Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
galene
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
galene
Commits
f0a39fca
Commit
f0a39fca
authored
Apr 27, 2021
by
Juliusz Chroboczek
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Send user permissions to client.
We now maintain the user list in the serverConnection.
parent
d0ef6a2c
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
120 additions
and
54 deletions
+120
-54
README.FRONTEND
README.FRONTEND
+6
-4
README.PROTOCOL
README.PROTOCOL
+3
-2
diskwriter/diskwriter.go
diskwriter/diskwriter.go
+1
-1
group/client.go
group/client.go
+1
-1
group/group.go
group/group.go
+6
-4
rtpconn/webclient.go
rtpconn/webclient.go
+14
-9
static/galene.js
static/galene.js
+29
-30
static/protocol.js
static/protocol.js
+60
-3
No files found.
README.FRONTEND
View file @
f0a39fca
...
...
@@ -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
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
message has been posted to the group, and `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.
or left the current group, or that their attributes have changed; the
user's state can be found in the `users` dictionary. The `onchat`
callback indicates that a chat message has been posted to the group, and
`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.
...
...
README.PROTOCOL
View file @
f0a39fca
...
...
@@ -115,9 +115,10 @@ users a `user` message:
```javascript
{
type: 'user',
kind: 'add' or 'delete',
kind: 'add' or '
change' or '
delete',
id: id,
username: username
username: username,
permissions: permissions
}
```
...
...
diskwriter/diskwriter.go
View file @
f0a39fca
...
...
@@ -71,7 +71,7 @@ func (client *Client) Permissions() 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
}
...
...
group/client.go
View file @
f0a39fca
...
...
@@ -100,6 +100,6 @@ type Client interface {
SetPermissions
(
ClientPermissions
)
OverridePermissions
(
*
Group
)
bool
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
}
group/group.go
View file @
f0a39fca
...
...
@@ -485,11 +485,13 @@ func AddClient(group string, c Client) (*Group, error) {
g
.
clients
[
c
.
Id
()]
=
c
g
.
timestamp
=
time
.
Now
()
id
:=
c
.
Id
()
u
:=
c
.
Username
()
c
.
PushClient
(
c
.
Id
(),
u
,
true
)
p
:=
c
.
Permissions
()
c
.
PushClient
(
c
.
Id
(),
u
,
p
,
"add"
)
for
_
,
cc
:=
range
clients
{
c
.
PushClient
(
cc
.
Id
(),
cc
.
Username
(),
true
)
cc
.
PushClient
(
c
.
Id
(),
u
,
true
)
c
.
PushClient
(
cc
.
Id
(),
cc
.
Username
(),
cc
.
Permissions
(),
"add"
)
cc
.
PushClient
(
id
,
u
,
p
,
"add"
)
}
return
g
,
nil
...
...
@@ -535,7 +537,7 @@ func DelClient(c Client) {
go
func
(
clients
[]
Client
)
{
for
_
,
cc
:=
range
clients
{
cc
.
PushClient
(
c
.
Id
(),
c
.
Username
(),
false
)
cc
.
PushClient
(
c
.
Id
(),
c
.
Username
(),
c
.
Permissions
(),
"delete"
)
}
}(
clients
)
...
...
rtpconn/webclient.go
View file @
f0a39fca
...
...
@@ -106,16 +106,13 @@ func (c *webClient) OverridePermissions(g *group.Group) bool {
return
false
}
func
(
c
*
webClient
)
PushClient
(
id
,
username
string
,
add
bool
)
error
{
kind
:=
"add"
if
!
add
{
kind
=
"delete"
}
func
(
c
*
webClient
)
PushClient
(
id
,
username
string
,
permissions
group
.
ClientPermissions
,
kind
string
)
error
{
return
c
.
write
(
clientMessage
{
Type
:
"user"
,
Kind
:
kind
,
Id
:
id
,
Username
:
username
,
Type
:
"user"
,
Kind
:
kind
,
Id
:
id
,
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
:
return
group
.
KickError
{
a
.
id
,
a
.
username
,
a
.
message
,
...
...
static/galene.js
View file @
f0a39fca
...
...
@@ -293,13 +293,11 @@ function setConnected(connected) {
let
userbox
=
document
.
getElementById
(
'
profile
'
);
let
connectionbox
=
document
.
getElementById
(
'
login-container
'
);
if
(
connected
)
{
resetUsers
();
clearChat
();
userbox
.
classList
.
remove
(
'
invisible
'
);
connectionbox
.
classList
.
add
(
'
invisible
'
);
displayUsername
();
}
else
{
resetUsers
();
fillLogin
();
userbox
.
classList
.
add
(
'
invisible
'
);
connectionbox
.
classList
.
remove
(
'
invisible
'
);
...
...
@@ -1654,9 +1652,6 @@ function resizePeers() {
}
}
/** @type{Object<string,string>} */
let
users
=
{};
/**
* Lexicographic order, with case differences secondary.
* @param{string} a
...
...
@@ -1683,9 +1678,6 @@ function stringCompare(a, b) {
function
addUser
(
id
,
name
)
{
if
(
!
name
)
name
=
null
;
if
(
id
in
users
)
throw
new
Error
(
'
Duplicate user id
'
);
users
[
id
]
=
name
;
let
div
=
document
.
getElementById
(
'
users
'
);
let
user
=
document
.
createElement
(
'
div
'
);
...
...
@@ -1697,7 +1689,9 @@ function addUser(id, name) {
let
us
=
div
.
children
;
for
(
let
i
=
0
;
i
<
us
.
length
;
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
)
{
div
.
insertBefore
(
user
,
child
);
return
;
...
...
@@ -1711,36 +1705,38 @@ function addUser(id, name) {
* @param {string} id
* @param {string} name
*/
function
delUser
(
id
,
name
)
{
if
(
!
name
)
name
=
null
;
if
(
!
(
id
in
users
))
throw
new
Error
(
'
Unknown user id
'
);
if
(
users
[
id
]
!==
name
)
throw
new
Error
(
'
Inconsistent user name
'
);
delete
(
users
[
id
]);
let
div
=
document
.
getElementById
(
'
users
'
);
function
changeUser
(
id
,
name
)
{
let
user
=
document
.
getElementById
(
'
user-
'
+
id
);
div
.
removeChild
(
user
);
if
(
!
user
)
{
console
.
warn
(
'
Unknown user
'
+
id
);
return
;
}
user
.
textContent
=
name
?
name
:
'
(anon)
'
;
}
function
resetUsers
()
{
for
(
let
id
in
users
)
delUser
(
id
,
users
[
id
]);
/**
* @param {string} id
*/
function
delUser
(
id
)
{
let
div
=
document
.
getElementById
(
'
users
'
);
let
user
=
document
.
getElementById
(
'
user-
'
+
id
);
div
.
removeChild
(
user
);
}
/**
* @param {string} id
* @param {string} kind
* @param {string} name
*/
function
gotUser
(
id
,
kind
,
name
)
{
function
gotUser
(
id
,
kind
)
{
switch
(
kind
)
{
case
'
add
'
:
addUser
(
id
,
name
);
addUser
(
id
,
serverConnection
.
users
[
id
].
user
name
);
break
;
case
'
delete
'
:
delUser
(
id
,
name
);
delUser
(
id
);
break
;
case
'
change
'
:
changeUser
(
id
,
serverConnection
.
users
[
id
].
username
);
break
;
default
:
console
.
warn
(
'
Unknown user kind
'
,
kind
);
...
...
@@ -1986,8 +1982,10 @@ function addToChatbox(peerId, dest, nick, time, privileged, kind, message) {
let
header
=
document
.
createElement
(
'
p
'
);
if
(
peerId
||
nick
||
dest
)
{
let
user
=
document
.
createElement
(
'
span
'
);
let
u
=
serverConnection
.
users
[
dest
];
let
name
=
(
u
&&
u
.
username
);
user
.
textContent
=
dest
?
`
${
nick
||
'
(anon)
'
}
\u2192
${
users
[
dest
]
||
'
(anon)
'
}
`
:
`
${
nick
||
'
(anon)
'
}
\u2192
${
name
||
'
(anon)
'
}
`
:
(
nick
||
'
(anon)
'
);
user
.
classList
.
add
(
'
message-user
'
);
header
.
appendChild
(
user
);
...
...
@@ -2246,11 +2244,12 @@ function parseCommand(line) {
* @param {string} user
*/
function
findUserId
(
user
)
{
if
(
user
in
users
)
if
(
user
in
serverConnection
.
users
)
return
user
;
for
(
let
id
in
users
)
{
if
(
users
[
id
]
===
user
)
for
(
let
id
in
serverConnection
.
users
)
{
let
u
=
serverConnection
.
users
[
id
];
if
(
u
&&
u
.
username
===
user
)
return
id
;
}
return
null
;
...
...
static/protocol.js
View file @
f0a39fca
...
...
@@ -60,6 +60,12 @@ function newLocalId() {
return
id
;
}
/**
* @typedef {Object} user
* @property {string} username
* @property {Object<string,boolean>} permissions
*/
/**
* ServerConnection encapsulates a websocket connection to the server and
* all the associated streams.
...
...
@@ -81,8 +87,16 @@ function ServerConnection() {
this
.
group
=
null
;
/**
* The username we joined as.
*
* @type {string}
*/
this
.
username
=
null
;
/**
* The set of users in this group, including ourself.
*
* @type {Object<string,user>}
*/
this
.
users
=
{};
/**
* The underlying websocket.
*
...
...
@@ -136,9 +150,10 @@ function ServerConnection() {
*/
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
;
/**
...
...
@@ -260,6 +275,11 @@ ServerConnection.prototype.connect = async function(url) {
let
c
=
sc
.
down
[
id
];
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
)
sc
.
onjoined
.
call
(
sc
,
'
leave
'
,
sc
.
group
,
{},
''
);
sc
.
group
=
null
;
...
...
@@ -303,14 +323,51 @@ ServerConnection.prototype.connect = async function(url) {
sc
.
username
=
m
.
username
;
sc
.
permissions
=
m
.
permissions
||
[];
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
)
sc
.
onjoined
.
call
(
sc
,
m
.
kind
,
m
.
group
,
m
.
permissions
||
{},
m
.
value
||
null
);
break
;
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
)
sc
.
onuser
.
call
(
sc
,
m
.
id
,
m
.
kind
,
m
.
username
);
sc
.
onuser
.
call
(
sc
,
m
.
id
,
m
.
kind
);
break
;
case
'
chat
'
:
if
(
sc
.
onchat
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment