mirror of
https://github.com/jech/galene.git
synced 2024-11-09 18:25:58 +01:00
Add group permissions.
This commit is contained in:
parent
cb1782b6b2
commit
2890d21c98
5 changed files with 136 additions and 22 deletions
17
client.go
17
client.go
|
@ -89,6 +89,7 @@ type clientMessage struct {
|
|||
Id string `json:"id,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Permissions userPermission `json:"permissions,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
|
@ -149,7 +150,7 @@ func startClient(conn *websocket.Conn) (err error) {
|
|||
c.writerDone = make(chan struct{})
|
||||
go clientWriter(conn, c.writeCh, c.writerDone)
|
||||
|
||||
g, users, err := addClient(m.Group, c)
|
||||
g, users, err := addClient(m.Group, c, m.Username, m.Password)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -262,7 +263,7 @@ func addUpConn(c *client, id string) (*upConnection, error) {
|
|||
clients := c.group.getClients(c)
|
||||
for _, cc := range clients {
|
||||
cc.action(addTrackAction{id, local, u, done})
|
||||
if(done && u.label != "") {
|
||||
if done && u.label != "" {
|
||||
cc.action(addLabelAction{id, u.label})
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +390,7 @@ func delDownConn(c *client, id string) {
|
|||
log.Printf("Deleting unknown connection")
|
||||
return
|
||||
}
|
||||
conn := c.down[id];
|
||||
conn := c.down[id]
|
||||
if conn == nil {
|
||||
log.Printf("Deleting unknown connection")
|
||||
return
|
||||
|
@ -667,6 +668,11 @@ func clientLoop(c *client, conn *websocket.Conn) error {
|
|||
|
||||
g := c.group
|
||||
|
||||
c.write(clientMessage{
|
||||
Type: "permissions",
|
||||
Permissions: c.permissions,
|
||||
})
|
||||
|
||||
for _, cc := range g.getClients(c) {
|
||||
cc.action(pushTracksAction{c})
|
||||
}
|
||||
|
@ -721,7 +727,7 @@ func clientLoop(c *client, conn *websocket.Conn) error {
|
|||
for _, u := range c.up {
|
||||
var done bool
|
||||
for i, p := range u.pairs {
|
||||
done = i >= u.streamCount - 1
|
||||
done = i >= u.streamCount-1
|
||||
a.c.action(addTrackAction{
|
||||
u.id, p.local, u,
|
||||
done,
|
||||
|
@ -747,6 +753,9 @@ func clientLoop(c *client, conn *websocket.Conn) error {
|
|||
func handleClientMessage(c *client, m clientMessage) error {
|
||||
switch m.Type {
|
||||
case "offer":
|
||||
if !c.permissions.Present {
|
||||
return userError("not authorized")
|
||||
}
|
||||
if m.Offer == nil {
|
||||
return protocolError("null offer")
|
||||
}
|
||||
|
|
124
group.go
124
group.go
|
@ -6,7 +6,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/pion/webrtc/v2"
|
||||
|
@ -34,20 +37,21 @@ type downConnection struct {
|
|||
}
|
||||
|
||||
type client struct {
|
||||
group *group
|
||||
id string
|
||||
username string
|
||||
done chan struct{}
|
||||
writeCh chan interface{}
|
||||
writerDone chan struct{}
|
||||
actionCh chan interface{}
|
||||
down map[string]*downConnection
|
||||
up map[string]*upConnection
|
||||
group *group
|
||||
id string
|
||||
username string
|
||||
permissions userPermission
|
||||
done chan struct{}
|
||||
writeCh chan interface{}
|
||||
writerDone chan struct{}
|
||||
actionCh chan interface{}
|
||||
down map[string]*downConnection
|
||||
up map[string]*upConnection
|
||||
}
|
||||
|
||||
type group struct {
|
||||
name string
|
||||
public bool
|
||||
name string
|
||||
description *groupDescription
|
||||
|
||||
mu sync.Mutex
|
||||
clients []*client
|
||||
|
@ -102,8 +106,13 @@ func addGroup(name string) (*group, error) {
|
|||
g := groups.groups[name]
|
||||
|
||||
if g == nil {
|
||||
desc, err := getDescription(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g = &group{
|
||||
name: name,
|
||||
name: name,
|
||||
description: desc,
|
||||
}
|
||||
groups.groups[name] = g
|
||||
}
|
||||
|
@ -130,12 +139,18 @@ type userid struct {
|
|||
username string
|
||||
}
|
||||
|
||||
func addClient(name string, client *client) (*group, []userid, error) {
|
||||
func addClient(name string, client *client, user, pass string) (*group, []userid, error) {
|
||||
g, err := addGroup(name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
perms, err := getPermission(g.description, user, pass)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
client.permissions = perms
|
||||
|
||||
var users []userid
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
@ -182,8 +197,8 @@ func (g *group) Range(f func(c *client) bool) {
|
|||
defer g.mu.Unlock()
|
||||
for _, c := range g.clients {
|
||||
ok := f(c)
|
||||
if(!ok){
|
||||
break;
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +233,83 @@ func (c *client) action(m interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
type groupUser struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func matchUser(user, pass string, users []groupUser) (bool, bool) {
|
||||
for _, u := range users {
|
||||
if (u.Username == "" || u.Username == user) {
|
||||
return true, (u.Password == "" || u.Password == pass)
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
type groupDescription struct {
|
||||
Public bool `json:"public,omitempty"`
|
||||
AllowAnonymous bool `json:"allow-anonymous,omitempty"`
|
||||
Admin []groupUser `json:"admin,omitempty"`
|
||||
Presenter []groupUser `json:"presenter,omitempty"`
|
||||
Other []groupUser `json:"other,omitempty"`
|
||||
}
|
||||
|
||||
func getDescription(name string) (*groupDescription, error) {
|
||||
r, err := os.Open(filepath.Join(groupsDir, name+".json"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = userError("group does not exist")
|
||||
} else if os.IsPermission(err) {
|
||||
err = userError("unauthorised")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
var desc groupDescription
|
||||
d := json.NewDecoder(r)
|
||||
err = d.Decode(&desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &desc, nil
|
||||
}
|
||||
|
||||
type userPermission struct {
|
||||
Admin bool `json:"admin,omitempty"`
|
||||
Present bool `json:"present,omitempty"`
|
||||
}
|
||||
|
||||
func getPermission(desc *groupDescription, user, pass string) (userPermission, error) {
|
||||
var p userPermission
|
||||
if !desc.AllowAnonymous && user == "" {
|
||||
return p, userError("anonymous users not allowed in this group")
|
||||
}
|
||||
if found, good := matchUser(user, pass, desc.Admin); found {
|
||||
if good {
|
||||
p.Admin = true
|
||||
p.Present = true
|
||||
return p, nil
|
||||
}
|
||||
return p, userError("not authorized")
|
||||
}
|
||||
if found, good := matchUser(user, pass, desc.Presenter); found {
|
||||
if good {
|
||||
p.Present = true
|
||||
return p, nil
|
||||
}
|
||||
return p, userError("not authorized")
|
||||
}
|
||||
if found, good := matchUser(user, pass, desc.Other); found {
|
||||
if good {
|
||||
return p, nil
|
||||
}
|
||||
return p, userError("not authorized")
|
||||
}
|
||||
return p, userError("not authorized")
|
||||
}
|
||||
|
||||
type publicGroup struct {
|
||||
Name string `json:"name"`
|
||||
ClientCount int `json:"clientCount"`
|
||||
|
@ -228,7 +320,7 @@ func getPublicGroups() []publicGroup {
|
|||
groups.mu.Lock()
|
||||
defer groups.mu.Unlock()
|
||||
for _, g := range groups.groups {
|
||||
if g.public {
|
||||
if g.description.Public {
|
||||
gs = append(gs, publicGroup{
|
||||
Name: g.name,
|
||||
ClientCount: len(g.clients),
|
||||
|
|
3
sfu.go
3
sfu.go
|
@ -22,6 +22,7 @@ import (
|
|||
var httpAddr string
|
||||
var staticRoot string
|
||||
var dataDir string
|
||||
var groupsDir string
|
||||
var iceFilename string
|
||||
|
||||
func main() {
|
||||
|
@ -30,6 +31,8 @@ func main() {
|
|||
"web server root `directory`")
|
||||
flag.StringVar(&dataDir, "data", "./data/",
|
||||
"data `directory`")
|
||||
flag.StringVar(&groupsDir, "groups", "./groups/",
|
||||
"group description `directory`")
|
||||
flag.Parse()
|
||||
iceFilename = filepath.Join(staticRoot, "ice-servers.json")
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
|
||||
<div id="optionsdiv">
|
||||
<label for="presenterbox">Present:</label>
|
||||
<input id="presenterbox" type="checkbox"/>
|
||||
<input id="presenterbox" type="checkbox"/ disabled>
|
||||
<label for="sharebox">Share screen:</label>
|
||||
<input id="sharebox" type="checkbox"/>
|
||||
<input id="sharebox" type="checkbox"/ disabled>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -279,8 +279,10 @@ function serverConnect() {
|
|||
socket.onclose = function(e) {
|
||||
setConnected(false);
|
||||
document.getElementById('presenterbox').checked = false;
|
||||
document.getElementById('presenterbox').disabled = true;
|
||||
setLocalMedia();
|
||||
document.getElementById('sharebox').checked = false;
|
||||
document.getElementById('sharebox').disabled = true;
|
||||
setShareMedia();
|
||||
reject(new Error('websocket close ' + e.code + ' ' + e.reason));
|
||||
};
|
||||
|
@ -305,6 +307,9 @@ function serverConnect() {
|
|||
case 'label':
|
||||
gotLabel(m.id, m.value);
|
||||
break;
|
||||
case 'permissions':
|
||||
gotPermissions(m.permissions);
|
||||
break;
|
||||
case 'user':
|
||||
gotUser(m.id, m.username, m.del);
|
||||
break;
|
||||
|
@ -483,6 +488,11 @@ function gotUser(id, name, del) {
|
|||
addUser(id, name);
|
||||
}
|
||||
|
||||
function gotPermissions(permissions) {
|
||||
document.getElementById('presenterbox').disabled = !permissions.present;
|
||||
document.getElementById('sharebox').disabled = !permissions.present;
|
||||
}
|
||||
|
||||
const urlRegexp = /https?:\/\/[-a-zA-Z0-9@:%/._\+~#=?]+[-a-zA-Z0-9@:%/_\+~#=]/g;
|
||||
|
||||
function formatLine(line) {
|
||||
|
|
Loading…
Reference in a new issue