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