mirror of
https://github.com/jech/galene.git
synced 2024-11-22 00:25:58 +01:00
Implement user statuses.
The server now maintains a set of statuses for each user that are not interpreted by the server but communicated to the other members of the group using 'user' messages.
This commit is contained in:
parent
f0a39fca48
commit
3ba2394be7
7 changed files with 87 additions and 15 deletions
|
@ -118,7 +118,8 @@ users a `user` message:
|
|||
kind: 'add' or 'change' or 'delete',
|
||||
id: id,
|
||||
username: username,
|
||||
permissions: permissions
|
||||
permissions: permissions,
|
||||
status: status
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -277,8 +278,8 @@ A user action requests that the server act upon a user.
|
|||
value: value
|
||||
}
|
||||
```
|
||||
Currently defined kinds include `op`, `unop`, `present`, `unpresent`, and
|
||||
`kick`.
|
||||
Currently defined kinds include `op`, `unop`, `present`, `unpresent`,
|
||||
`kick` and `setstatus`.
|
||||
|
||||
Finally, a group action requests that the server act on the current group.
|
||||
|
||||
|
|
|
@ -71,7 +71,11 @@ func (client *Client) Permissions() group.ClientPermissions {
|
|||
return group.ClientPermissions{}
|
||||
}
|
||||
|
||||
func (client *Client) PushClient(id, username string, permissions group.ClientPermissions, kind string) error {
|
||||
func (client *Client) Status() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *Client) PushClient(id, username string, permissions group.ClientPermissions, status map[string]interface{}, kind string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -98,8 +98,9 @@ type Client interface {
|
|||
Challengeable
|
||||
Permissions() ClientPermissions
|
||||
SetPermissions(ClientPermissions)
|
||||
Status() map[string]interface{}
|
||||
OverridePermissions(*Group) bool
|
||||
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
|
||||
PushClient(id, username string, permissions ClientPermissions, kind string) error
|
||||
PushClient(id, username string, permissions ClientPermissions, status map[string]interface{}, kind string) error
|
||||
Kick(id, user, message string) error
|
||||
}
|
||||
|
|
|
@ -488,10 +488,14 @@ func AddClient(group string, c Client) (*Group, error) {
|
|||
id := c.Id()
|
||||
u := c.Username()
|
||||
p := c.Permissions()
|
||||
c.PushClient(c.Id(), u, p, "add")
|
||||
s := c.Status()
|
||||
c.PushClient(c.Id(), u, p, s, "add")
|
||||
for _, cc := range clients {
|
||||
c.PushClient(cc.Id(), cc.Username(), cc.Permissions(), "add")
|
||||
cc.PushClient(id, u, p, "add")
|
||||
c.PushClient(
|
||||
cc.Id(), cc.Username(), cc.Permissions(), cc.Status(),
|
||||
"add",
|
||||
)
|
||||
cc.PushClient(id, u, p, s, "add")
|
||||
}
|
||||
|
||||
return g, nil
|
||||
|
@ -537,7 +541,7 @@ func DelClient(c Client) {
|
|||
|
||||
go func(clients []Client) {
|
||||
for _, cc := range clients {
|
||||
cc.PushClient(c.Id(), c.Username(), c.Permissions(), "delete")
|
||||
cc.PushClient(c.Id(), c.Username(), c.Permissions(), c.Status(), "delete")
|
||||
}
|
||||
}(clients)
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ type webClient struct {
|
|||
username string
|
||||
password string
|
||||
permissions group.ClientPermissions
|
||||
status map[string]interface{}
|
||||
requested map[string]uint32
|
||||
done chan struct{}
|
||||
writeCh chan interface{}
|
||||
|
@ -98,6 +99,10 @@ func (c *webClient) Permissions() group.ClientPermissions {
|
|||
return c.permissions
|
||||
}
|
||||
|
||||
func (c *webClient) Status() map[string]interface{} {
|
||||
return c.status
|
||||
}
|
||||
|
||||
func (c *webClient) SetPermissions(perms group.ClientPermissions) {
|
||||
c.permissions = perms
|
||||
}
|
||||
|
@ -106,13 +111,14 @@ func (c *webClient) OverridePermissions(g *group.Group) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *webClient) PushClient(id, username string, permissions group.ClientPermissions, kind string) error {
|
||||
func (c *webClient) PushClient(id, username string, permissions group.ClientPermissions, status map[string]interface{}, kind string) error {
|
||||
return c.write(clientMessage{
|
||||
Type: "user",
|
||||
Kind: kind,
|
||||
Id: id,
|
||||
Username: username,
|
||||
Permissions: &permissions,
|
||||
Status: status,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -174,6 +180,7 @@ type clientMessage struct {
|
|||
Password string `json:"password,omitempty"`
|
||||
Privileged bool `json:"privileged,omitempty"`
|
||||
Permissions *group.ClientPermissions `json:"permissions,omitempty"`
|
||||
Status map[string]interface{} `json:"status,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
NoEcho bool `json:"noecho,omitempty"`
|
||||
|
@ -988,10 +995,11 @@ func handleAction(c *webClient, a interface{}) error {
|
|||
}
|
||||
id := c.Id()
|
||||
user := c.Username()
|
||||
s := c.Status()
|
||||
clients := g.GetClients(nil)
|
||||
go func(clients []group.Client) {
|
||||
for _, cc := range clients {
|
||||
cc.PushClient(id, user, perms, "change")
|
||||
cc.PushClient(id, user, perms, s, "change")
|
||||
}
|
||||
}(clients)
|
||||
case kickAction:
|
||||
|
@ -1042,6 +1050,7 @@ func leaveGroup(c *webClient) {
|
|||
|
||||
group.DelClient(c)
|
||||
c.permissions = group.ClientPermissions{}
|
||||
c.status = nil
|
||||
c.requested = map[string]uint32{}
|
||||
c.group = nil
|
||||
}
|
||||
|
@ -1454,6 +1463,36 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
if err != nil {
|
||||
return c.error(err)
|
||||
}
|
||||
case "setstatus":
|
||||
if m.Dest != c.Id() {
|
||||
return c.error(group.UserError("not authorised"))
|
||||
}
|
||||
s, ok := m.Value.(map[string]interface{})
|
||||
if !ok {
|
||||
return c.error(group.UserError(
|
||||
"Bad value in setstatus",
|
||||
))
|
||||
}
|
||||
if c.status == nil {
|
||||
c.status = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range s {
|
||||
if v == nil {
|
||||
delete(c.status, k)
|
||||
} else {
|
||||
c.status[k] = v
|
||||
}
|
||||
}
|
||||
id := c.Id()
|
||||
user := c.Username()
|
||||
perms := c.Permissions()
|
||||
status := c.Status()
|
||||
go func(clients []group.Client) {
|
||||
for _, cc := range clients {
|
||||
cc.PushClient(id, user, perms, status,
|
||||
"change")
|
||||
}
|
||||
}(g.GetClients(nil))
|
||||
default:
|
||||
return group.ProtocolError("unknown user action")
|
||||
}
|
||||
|
|
|
@ -2365,6 +2365,24 @@ commands.wall = {
|
|||
},
|
||||
};
|
||||
|
||||
commands.raise = {
|
||||
description: 'raise hand',
|
||||
f: (c, r) => {
|
||||
serverConnection.userAction(
|
||||
"setstatus", serverConnection.id, {"raisehand": true},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
commands.unraise = {
|
||||
description: 'unraise hand',
|
||||
f: (c, r) => {
|
||||
serverConnection.userAction(
|
||||
"setstatus", serverConnection.id, {"raisehand": null},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loopback through a TURN relay.
|
||||
*
|
||||
|
|
|
@ -64,6 +64,7 @@ function newLocalId() {
|
|||
* @typedef {Object} user
|
||||
* @property {string} username
|
||||
* @property {Object<string,boolean>} permissions
|
||||
* @property {Object<string,any>} status
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -205,6 +206,7 @@ function ServerConnection() {
|
|||
* @property {string} [password]
|
||||
* @property {boolean} [privileged]
|
||||
* @property {Object<string,boolean>} [permissions]
|
||||
* @property {Object<string,any>} [status]
|
||||
* @property {string} [group]
|
||||
* @property {unknown} [value]
|
||||
* @property {boolean} [noecho]
|
||||
|
@ -342,7 +344,8 @@ ServerConnection.prototype.connect = async function(url) {
|
|||
console.warn(`Duplicate user ${m.id} ${m.username}`);
|
||||
sc.users[m.id] = {
|
||||
username: m.username,
|
||||
permissions: m.permissions,
|
||||
permissions: m.permissions || {},
|
||||
status: m.status || {},
|
||||
};
|
||||
break;
|
||||
case 'change':
|
||||
|
@ -350,11 +353,13 @@ ServerConnection.prototype.connect = async function(url) {
|
|||
console.warn(`Unknown user ${m.id} ${m.username}`);
|
||||
sc.users[m.id] = {
|
||||
username: m.username,
|
||||
permissions: m.permissions,
|
||||
permissions: m.permissions || {},
|
||||
status: m.status || {},
|
||||
};
|
||||
} else {
|
||||
sc.users[m.id].username = m.username;
|
||||
sc.users[m.id].permissions = m.permissions;
|
||||
sc.users[m.id].permissions = m.permissions || {};
|
||||
sc.users[m.id].status = m.status || {};
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
|
@ -562,7 +567,7 @@ ServerConnection.prototype.chat = function(kind, dest, value) {
|
|||
*
|
||||
* @param {string} kind - One of "op", "unop", "kick", "present", "unpresent".
|
||||
* @param {string} dest - The id of the user to act upon.
|
||||
* @param {string} [value] - An optional user-readable message.
|
||||
* @param {any} [value] - An action-dependent parameter.
|
||||
*/
|
||||
ServerConnection.prototype.userAction = function(kind, dest, value) {
|
||||
this.send({
|
||||
|
|
Loading…
Reference in a new issue