mirror of
https://github.com/jech/galene.git
synced 2024-11-22 08:35:57 +01:00
Send user permissions to client.
We now maintain the user list in the serverConnection.
This commit is contained in:
parent
d0ef6a2c0f
commit
f0a39fca48
8 changed files with 120 additions and 54 deletions
|
@ -47,10 +47,12 @@ from the server; the field `kind` indicates the kind of message.
|
||||||
|
|
||||||
Once you have joined a group (see below), the remaining callbacks may
|
Once you have joined a group (see below), the remaining callbacks may
|
||||||
trigger. The `onuser` callback is used to indicate that a user has joined
|
trigger. The `onuser` callback is used to indicate that a user has joined
|
||||||
or left the current group. The `onchat` callback indicates that a chat
|
or left the current group, or that their attributes have changed; the
|
||||||
message has been posted to the group, and `onclearchat` indicates that the
|
user's state can be found in the `users` dictionary. The `onchat`
|
||||||
chat history has been cleared. Finally, `ondownstream` is called when the
|
callback indicates that a chat message has been posted to the group, and
|
||||||
server pushes a stream to the client; see the section below about streams.
|
`onclearchat` indicates that the chat history has been cleared. Finally,
|
||||||
|
`ondownstream` is called when the server pushes a stream to the client;
|
||||||
|
see the section below about streams.
|
||||||
|
|
||||||
You may now connect to the server.
|
You may now connect to the server.
|
||||||
|
|
||||||
|
|
|
@ -115,9 +115,10 @@ users a `user` message:
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
type: 'user',
|
type: 'user',
|
||||||
kind: 'add' or 'delete',
|
kind: 'add' or 'change' or 'delete',
|
||||||
id: id,
|
id: id,
|
||||||
username: username
|
username: username,
|
||||||
|
permissions: permissions
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ func (client *Client) Permissions() group.ClientPermissions {
|
||||||
return group.ClientPermissions{}
|
return group.ClientPermissions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) PushClient(id, username string, add bool) error {
|
func (client *Client) PushClient(id, username string, permissions group.ClientPermissions, kind string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,6 @@ type Client interface {
|
||||||
SetPermissions(ClientPermissions)
|
SetPermissions(ClientPermissions)
|
||||||
OverridePermissions(*Group) bool
|
OverridePermissions(*Group) bool
|
||||||
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
|
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
|
||||||
PushClient(id, username string, add bool) error
|
PushClient(id, username string, permissions ClientPermissions, kind string) error
|
||||||
Kick(id, user, message string) error
|
Kick(id, user, message string) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,11 +485,13 @@ func AddClient(group string, c Client) (*Group, error) {
|
||||||
g.clients[c.Id()] = c
|
g.clients[c.Id()] = c
|
||||||
g.timestamp = time.Now()
|
g.timestamp = time.Now()
|
||||||
|
|
||||||
|
id := c.Id()
|
||||||
u := c.Username()
|
u := c.Username()
|
||||||
c.PushClient(c.Id(), u, true)
|
p := c.Permissions()
|
||||||
|
c.PushClient(c.Id(), u, p, "add")
|
||||||
for _, cc := range clients {
|
for _, cc := range clients {
|
||||||
c.PushClient(cc.Id(), cc.Username(), true)
|
c.PushClient(cc.Id(), cc.Username(), cc.Permissions(), "add")
|
||||||
cc.PushClient(c.Id(), u, true)
|
cc.PushClient(id, u, p, "add")
|
||||||
}
|
}
|
||||||
|
|
||||||
return g, nil
|
return g, nil
|
||||||
|
@ -535,7 +537,7 @@ func DelClient(c Client) {
|
||||||
|
|
||||||
go func(clients []Client) {
|
go func(clients []Client) {
|
||||||
for _, cc := range clients {
|
for _, cc := range clients {
|
||||||
cc.PushClient(c.Id(), c.Username(), false)
|
cc.PushClient(c.Id(), c.Username(), c.Permissions(), "delete")
|
||||||
}
|
}
|
||||||
}(clients)
|
}(clients)
|
||||||
|
|
||||||
|
|
|
@ -106,16 +106,13 @@ func (c *webClient) OverridePermissions(g *group.Group) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *webClient) PushClient(id, username string, add bool) error {
|
func (c *webClient) PushClient(id, username string, permissions group.ClientPermissions, kind string) error {
|
||||||
kind := "add"
|
|
||||||
if !add {
|
|
||||||
kind = "delete"
|
|
||||||
}
|
|
||||||
return c.write(clientMessage{
|
return c.write(clientMessage{
|
||||||
Type: "user",
|
Type: "user",
|
||||||
Kind: kind,
|
Kind: kind,
|
||||||
Id: id,
|
Id: id,
|
||||||
Username: username,
|
Username: username,
|
||||||
|
Permissions: &permissions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,6 +986,14 @@ func handleAction(c *webClient, a interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
id := c.Id()
|
||||||
|
user := c.Username()
|
||||||
|
clients := g.GetClients(nil)
|
||||||
|
go func(clients []group.Client) {
|
||||||
|
for _, cc := range clients {
|
||||||
|
cc.PushClient(id, user, perms, "change")
|
||||||
|
}
|
||||||
|
}(clients)
|
||||||
case kickAction:
|
case kickAction:
|
||||||
return group.KickError{
|
return group.KickError{
|
||||||
a.id, a.username, a.message,
|
a.id, a.username, a.message,
|
||||||
|
|
|
@ -293,13 +293,11 @@ function setConnected(connected) {
|
||||||
let userbox = document.getElementById('profile');
|
let userbox = document.getElementById('profile');
|
||||||
let connectionbox = document.getElementById('login-container');
|
let connectionbox = document.getElementById('login-container');
|
||||||
if(connected) {
|
if(connected) {
|
||||||
resetUsers();
|
|
||||||
clearChat();
|
clearChat();
|
||||||
userbox.classList.remove('invisible');
|
userbox.classList.remove('invisible');
|
||||||
connectionbox.classList.add('invisible');
|
connectionbox.classList.add('invisible');
|
||||||
displayUsername();
|
displayUsername();
|
||||||
} else {
|
} else {
|
||||||
resetUsers();
|
|
||||||
fillLogin();
|
fillLogin();
|
||||||
userbox.classList.add('invisible');
|
userbox.classList.add('invisible');
|
||||||
connectionbox.classList.remove('invisible');
|
connectionbox.classList.remove('invisible');
|
||||||
|
@ -1654,9 +1652,6 @@ function resizePeers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type{Object<string,string>} */
|
|
||||||
let users = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lexicographic order, with case differences secondary.
|
* Lexicographic order, with case differences secondary.
|
||||||
* @param{string} a
|
* @param{string} a
|
||||||
|
@ -1683,9 +1678,6 @@ function stringCompare(a, b) {
|
||||||
function addUser(id, name) {
|
function addUser(id, name) {
|
||||||
if(!name)
|
if(!name)
|
||||||
name = null;
|
name = null;
|
||||||
if(id in users)
|
|
||||||
throw new Error('Duplicate user id');
|
|
||||||
users[id] = name;
|
|
||||||
|
|
||||||
let div = document.getElementById('users');
|
let div = document.getElementById('users');
|
||||||
let user = document.createElement('div');
|
let user = document.createElement('div');
|
||||||
|
@ -1697,7 +1689,9 @@ function addUser(id, name) {
|
||||||
let us = div.children;
|
let us = div.children;
|
||||||
for(let i = 0; i < us.length; i++) {
|
for(let i = 0; i < us.length; i++) {
|
||||||
let child = us[i];
|
let child = us[i];
|
||||||
let childname = users[child.id.slice('user-'.length)] || null;
|
let childuser =
|
||||||
|
serverConnection.users[child.id.slice('user-'.length)] || null;
|
||||||
|
let childname = (childuser && childuser.username) || null;
|
||||||
if(!childname || stringCompare(childname, name) > 0) {
|
if(!childname || stringCompare(childname, name) > 0) {
|
||||||
div.insertBefore(user, child);
|
div.insertBefore(user, child);
|
||||||
return;
|
return;
|
||||||
|
@ -1711,36 +1705,38 @@ function addUser(id, name) {
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
*/
|
*/
|
||||||
function delUser(id, name) {
|
function changeUser(id, name) {
|
||||||
if(!name)
|
let user = document.getElementById('user-' + id);
|
||||||
name = null;
|
if(!user) {
|
||||||
if(!(id in users))
|
console.warn('Unknown user ' + id);
|
||||||
throw new Error('Unknown user id');
|
return;
|
||||||
if(users[id] !== name)
|
}
|
||||||
throw new Error('Inconsistent user name');
|
user.textContent = name ? name : '(anon)';
|
||||||
delete(users[id]);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} id
|
||||||
|
*/
|
||||||
|
function delUser(id) {
|
||||||
let div = document.getElementById('users');
|
let div = document.getElementById('users');
|
||||||
let user = document.getElementById('user-' + id);
|
let user = document.getElementById('user-' + id);
|
||||||
div.removeChild(user);
|
div.removeChild(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetUsers() {
|
|
||||||
for(let id in users)
|
|
||||||
delUser(id, users[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {string} kind
|
* @param {string} kind
|
||||||
* @param {string} name
|
|
||||||
*/
|
*/
|
||||||
function gotUser(id, kind, name) {
|
function gotUser(id, kind) {
|
||||||
switch(kind) {
|
switch(kind) {
|
||||||
case 'add':
|
case 'add':
|
||||||
addUser(id, name);
|
addUser(id, serverConnection.users[id].username);
|
||||||
break;
|
break;
|
||||||
case 'delete':
|
case 'delete':
|
||||||
delUser(id, name);
|
delUser(id);
|
||||||
|
break;
|
||||||
|
case 'change':
|
||||||
|
changeUser(id, serverConnection.users[id].username);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn('Unknown user kind', kind);
|
console.warn('Unknown user kind', kind);
|
||||||
|
@ -1986,8 +1982,10 @@ function addToChatbox(peerId, dest, nick, time, privileged, kind, message) {
|
||||||
let header = document.createElement('p');
|
let header = document.createElement('p');
|
||||||
if(peerId || nick || dest) {
|
if(peerId || nick || dest) {
|
||||||
let user = document.createElement('span');
|
let user = document.createElement('span');
|
||||||
|
let u = serverConnection.users[dest];
|
||||||
|
let name = (u && u.username);
|
||||||
user.textContent = dest ?
|
user.textContent = dest ?
|
||||||
`${nick||'(anon)'} \u2192 ${users[dest]||'(anon)'}` :
|
`${nick||'(anon)'} \u2192 ${name || '(anon)'}` :
|
||||||
(nick || '(anon)');
|
(nick || '(anon)');
|
||||||
user.classList.add('message-user');
|
user.classList.add('message-user');
|
||||||
header.appendChild(user);
|
header.appendChild(user);
|
||||||
|
@ -2246,11 +2244,12 @@ function parseCommand(line) {
|
||||||
* @param {string} user
|
* @param {string} user
|
||||||
*/
|
*/
|
||||||
function findUserId(user) {
|
function findUserId(user) {
|
||||||
if(user in users)
|
if(user in serverConnection.users)
|
||||||
return user;
|
return user;
|
||||||
|
|
||||||
for(let id in users) {
|
for(let id in serverConnection.users) {
|
||||||
if(users[id] === user)
|
let u = serverConnection.users[id];
|
||||||
|
if(u && u.username === user)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -60,6 +60,12 @@ function newLocalId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} user
|
||||||
|
* @property {string} username
|
||||||
|
* @property {Object<string,boolean>} permissions
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ServerConnection encapsulates a websocket connection to the server and
|
* ServerConnection encapsulates a websocket connection to the server and
|
||||||
* all the associated streams.
|
* all the associated streams.
|
||||||
|
@ -81,8 +87,16 @@ function ServerConnection() {
|
||||||
this.group = null;
|
this.group = null;
|
||||||
/**
|
/**
|
||||||
* The username we joined as.
|
* The username we joined as.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.username = null;
|
this.username = null;
|
||||||
|
/**
|
||||||
|
* The set of users in this group, including ourself.
|
||||||
|
*
|
||||||
|
* @type {Object<string,user>}
|
||||||
|
*/
|
||||||
|
this.users = {};
|
||||||
/**
|
/**
|
||||||
* The underlying websocket.
|
* The underlying websocket.
|
||||||
*
|
*
|
||||||
|
@ -136,9 +150,10 @@ function ServerConnection() {
|
||||||
*/
|
*/
|
||||||
this.onclose = null;
|
this.onclose = null;
|
||||||
/**
|
/**
|
||||||
* onuser is called whenever a user is added or removed from the group
|
* onuser is called whenever a user in the group changes. The users
|
||||||
|
* array has already been updated.
|
||||||
*
|
*
|
||||||
* @type{(this: ServerConnection, id: string, kind: string, username: string) => void}
|
* @type{(this: ServerConnection, id: string, kind: string) => void}
|
||||||
*/
|
*/
|
||||||
this.onuser = null;
|
this.onuser = null;
|
||||||
/**
|
/**
|
||||||
|
@ -260,6 +275,11 @@ ServerConnection.prototype.connect = async function(url) {
|
||||||
let c = sc.down[id];
|
let c = sc.down[id];
|
||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
|
for(let id in sc.users) {
|
||||||
|
delete(sc.users[id]);
|
||||||
|
if(sc.onuser)
|
||||||
|
sc.onuser.call(sc, id, 'delete');
|
||||||
|
}
|
||||||
if(sc.group && sc.onjoined)
|
if(sc.group && sc.onjoined)
|
||||||
sc.onjoined.call(sc, 'leave', sc.group, {}, '');
|
sc.onjoined.call(sc, 'leave', sc.group, {}, '');
|
||||||
sc.group = null;
|
sc.group = null;
|
||||||
|
@ -303,14 +323,51 @@ ServerConnection.prototype.connect = async function(url) {
|
||||||
sc.username = m.username;
|
sc.username = m.username;
|
||||||
sc.permissions = m.permissions || [];
|
sc.permissions = m.permissions || [];
|
||||||
sc.rtcConfiguration = m.rtcConfiguration || null;
|
sc.rtcConfiguration = m.rtcConfiguration || null;
|
||||||
|
if(m.kind == 'leave') {
|
||||||
|
for(let id in sc.users) {
|
||||||
|
delete(sc.users[id]);
|
||||||
|
if(sc.onuser)
|
||||||
|
sc.onuser.call(sc, id, 'delete');
|
||||||
|
}
|
||||||
|
}
|
||||||
if(sc.onjoined)
|
if(sc.onjoined)
|
||||||
sc.onjoined.call(sc, m.kind, m.group,
|
sc.onjoined.call(sc, m.kind, m.group,
|
||||||
m.permissions || {},
|
m.permissions || {},
|
||||||
m.value || null);
|
m.value || null);
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
|
switch(m.kind) {
|
||||||
|
case 'add':
|
||||||
|
if(m.id in sc.users)
|
||||||
|
console.warn(`Duplicate user ${m.id} ${m.username}`);
|
||||||
|
sc.users[m.id] = {
|
||||||
|
username: m.username,
|
||||||
|
permissions: m.permissions,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'change':
|
||||||
|
if(!(m.id in sc.users)) {
|
||||||
|
console.warn(`Unknown user ${m.id} ${m.username}`);
|
||||||
|
sc.users[m.id] = {
|
||||||
|
username: m.username,
|
||||||
|
permissions: m.permissions,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
sc.users[m.id].username = m.username;
|
||||||
|
sc.users[m.id].permissions = m.permissions;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
if(!(m.id in sc.users))
|
||||||
|
console.warn(`Unknown user ${m.id} ${m.username}`);
|
||||||
|
delete(sc.users[m.id]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn(`Unknown user action ${m.kind}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(sc.onuser)
|
if(sc.onuser)
|
||||||
sc.onuser.call(sc, m.id, m.kind, m.username);
|
sc.onuser.call(sc, m.id, m.kind);
|
||||||
break;
|
break;
|
||||||
case 'chat':
|
case 'chat':
|
||||||
if(sc.onchat)
|
if(sc.onchat)
|
||||||
|
|
Loading…
Reference in a new issue