1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-22 00:25:58 +01:00

Add new "caption" permission.

It is required for displaying captions.
This commit is contained in:
Juliusz Chroboczek 2024-11-08 13:08:11 +01:00
parent a9e269e979
commit 07f4aab9b1
5 changed files with 56 additions and 12 deletions

View file

@ -310,7 +310,7 @@ A chat message may be sent using a `chat` message.
```javascript ```javascript
{ {
type: 'chat', type: 'chat',
kind: '' or 'me', kind: null or 'me' or 'caption',
source: source-id, source: source-id,
username: username, username: username,
dest: dest-id, dest: dest-id,
@ -321,6 +321,13 @@ A chat message may be sent using a `chat` message.
} }
``` ```
The field `kind` can have one of the following values:
- `null` or the empty string, a normal chat message;
- `'me'`, an IRC-style first-person message;
- `'caption'`, a caption or subtitle (this requires the sender to have
the `caption` permission).
If `dest` is empty, the message is a broadcast message, destined to all of If `dest` is empty, the message is a broadcast message, destined to all of
the clients in the group. If `source` is empty, then the message was the clients in the group. If `source` is empty, then the message was
originated by the server. The message is forwarded by the server without originated by the server. The message is forwarded by the server without

View file

@ -42,7 +42,7 @@ func TestMakePassword(t *testing.T) {
func TestFormatPermissions(t *testing.T) { func TestFormatPermissions(t *testing.T) {
tests := []struct{ j, v, p string }{ tests := []struct{ j, v, p string }{
{`"op"`, "op", "[mopt]"}, {`"op"`, "op", "[cmopt]"},
{`"present"`, "present", "[mp]"}, {`"present"`, "present", "[mp]"},
{`"observe"`, "observe", "[]"}, {`"observe"`, "observe", "[]"},
{`"admin"`, "admin", "[a]"}, {`"admin"`, "admin", "[a]"},

View file

@ -26,10 +26,11 @@ type Permissions struct {
} }
var permissionsMap = map[string][]string{ var permissionsMap = map[string][]string{
"op": {"op", "present", "message", "token"}, "op": {"op", "present", "message", "caption", "token"},
"present": {"present", "message"}, "present": {"present", "message"},
"message": {"message"}, "message": {"message"},
"observe": {}, "observe": {},
"caption": {"caption"},
"admin": {"admin"}, "admin": {"admin"},
} }

View file

@ -90,7 +90,7 @@ func TestChatHistory(t *testing.T) {
if lh := len(g.GetChatHistory()); lh != l*3/4 { if lh := len(g.GetChatHistory()); lh != l*3/4 {
t.Errorf("Expected %v, got %v", l*3/4, lh) t.Errorf("Expected %v, got %v", l*3/4, lh)
} }
g.ClearChatHistory("", ""); g.ClearChatHistory("", "")
if lh := len(g.GetChatHistory()); lh != 0 { if lh := len(g.GetChatHistory()); lh != 0 {
t.Errorf("Expected 0, got %v", lh) t.Errorf("Expected 0, got %v", lh)
} }
@ -125,6 +125,8 @@ var john = "john"
var james = "james" var james = "james"
var paul = "paul" var paul = "paul"
var peter = "peter" var peter = "peter"
var admin = "admin"
var stt = "speech-to-text"
var badClients = []ClientCredentials{ var badClients = []ClientCredentials{
{Username: &jch, Password: "foo"}, {Username: &jch, Password: "foo"},
@ -137,10 +139,27 @@ type credPerm struct {
p []string p []string
} }
var desc2JSON = `
{
"max-history-age": 10,
"auto-subgroups": true,
"users": {
"jch": {"password": "topsecret", "permissions": "op"},
"john": {"password": "secret", "permissions": "present"},
"james": {"password": "secret2", "permissions": "message"},
"peter": {"password": "secret4"},
"admin": {"password": "admin", "permissions": "admin"},
"speech-to-text": {"password": {"type": "wildcard"},
"permissions": "caption"}
},
"wildcard-user":
{"permissions": "message", "password": {"type":"wildcard"}}
}`
var goodClients = []credPerm{ var goodClients = []credPerm{
{ {
ClientCredentials{Username: &jch, Password: "topsecret"}, ClientCredentials{Username: &jch, Password: "topsecret"},
[]string{"op", "present", "message", "token"}, []string{"op", "present", "message", "caption", "token"},
}, },
{ {
ClientCredentials{Username: &john, Password: "secret"}, ClientCredentials{Username: &john, Password: "secret"},
@ -158,11 +177,19 @@ var goodClients = []credPerm{
ClientCredentials{Username: &peter, Password: "secret4"}, ClientCredentials{Username: &peter, Password: "secret4"},
[]string{}, []string{},
}, },
{
ClientCredentials{Username: &admin, Password: "admin"},
[]string{"admin"},
},
{
ClientCredentials{Username: &stt},
[]string{"caption"},
},
} }
func TestPermissions(t *testing.T) { func TestPermissions(t *testing.T) {
var g Group var g Group
err := json.Unmarshal([]byte(descJSON), &g.description) err := json.Unmarshal([]byte(desc2JSON), &g.description)
if err != nil { if err != nil {
t.Fatalf("unmarshal: %v", err) t.Fatalf("unmarshal: %v", err)
} }
@ -209,41 +236,46 @@ func TestExtraPermissions(t *testing.T) {
} }
doit := func(u string, p []string) { doit := func(u string, p []string) {
t.Helper()
pu := d.Users[u].Permissions.Permissions(&d) pu := d.Users[u].Permissions.Permissions(&d)
if !permissionsEqual(pu, p) { if !permissionsEqual(pu, p) {
t.Errorf("%v: expected %v, got %v", u, p, pu) t.Errorf("%v: expected %v, got %v", u, p, pu)
} }
} }
doit("jch", []string{"op", "token", "present", "message"}) doit("jch", []string{"op", "token", "present", "message", "caption"})
doit("john", []string{"present", "message"}) doit("john", []string{"present", "message"})
doit("james", []string{}) doit("james", []string{})
d.AllowRecording = true d.AllowRecording = true
d.UnrestrictedTokens = false d.UnrestrictedTokens = false
doit("jch", []string{"op", "record", "token", "present", "message"}) doit("jch", []string{
"op", "record", "token", "present", "message", "caption",
})
doit("john", []string{"present", "message"}) doit("john", []string{"present", "message"})
doit("james", []string{}) doit("james", []string{})
d.AllowRecording = false d.AllowRecording = false
d.UnrestrictedTokens = true d.UnrestrictedTokens = true
doit("jch", []string{"op", "token", "present", "message"}) doit("jch", []string{"op", "token", "present", "message", "caption"})
doit("john", []string{"token", "present", "message"}) doit("john", []string{"token", "present", "message"})
doit("james", []string{}) doit("james", []string{})
d.AllowRecording = true d.AllowRecording = true
d.UnrestrictedTokens = true d.UnrestrictedTokens = true
doit("jch", []string{"op", "record", "token", "present", "message"}) doit("jch", []string{
"op", "record", "token", "present", "message", "caption",
})
doit("john", []string{"token", "present", "message"}) doit("john", []string{"token", "present", "message"})
doit("james", []string{}) doit("james", []string{})
} }
func TestUsernameTaken(t *testing.T) { func TestUsernameTaken(t *testing.T) {
var g Group var g Group
err := json.Unmarshal([]byte(descJSON), &g.description) err := json.Unmarshal([]byte(desc2JSON), &g.description)
if err != nil { if err != nil {
t.Fatalf("unmarshal: %v", err) t.Fatalf("unmarshal: %v", err)
} }

View file

@ -1572,7 +1572,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
return c.error(group.UserError("join a group first")) return c.error(group.UserError("join a group first"))
} }
if !member("message", c.permissions) { required := "message"
if m.Type == "chat" && m.Kind == "caption" {
required = "caption"
}
if !member(required, c.permissions) {
return c.error(group.UserError("not authorised")) return c.error(group.UserError("not authorised"))
} }