Use message passing for changing permissions.
We used to handle permission change commands by directly mutating the permissions field from the source client's thread, which is racy. We now use message passing. Thanks to Vinayak Mishra.
This commit is contained in:
+37
-38
@@ -922,6 +922,10 @@ type pushClientAction struct {
|
||||
data map[string]interface{}
|
||||
}
|
||||
|
||||
type changePermissionsAction struct {
|
||||
kind string
|
||||
}
|
||||
|
||||
type permissionsChangedAction struct{}
|
||||
|
||||
type joinedAction struct {
|
||||
@@ -1222,6 +1226,29 @@ func handleAction(c *webClient, a any) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
case changePermissionsAction:
|
||||
switch a.kind {
|
||||
case "op":
|
||||
c.permissions = addnew("op", c.permissions)
|
||||
g := c.Group()
|
||||
if g != nil && g.Description().AllowRecording {
|
||||
c.permissions = addnew("record", c.permissions)
|
||||
}
|
||||
case "unop":
|
||||
c.permissions = remove("op", c.permissions)
|
||||
c.permissions = remove("record", c.permissions)
|
||||
case "present":
|
||||
c.permissions = addnew("present", c.permissions)
|
||||
case "unpresent":
|
||||
c.permissions = remove("present", c.permissions)
|
||||
case "shutup":
|
||||
c.permissions = remove("message", c.permissions)
|
||||
case "unshutup":
|
||||
c.permissions = addnew("message", c.permissions)
|
||||
default:
|
||||
return group.UserError("unknown permission")
|
||||
}
|
||||
c.action(permissionsChangedAction{})
|
||||
case permissionsChangedAction:
|
||||
g := c.Group()
|
||||
if g == nil {
|
||||
@@ -1338,41 +1365,6 @@ func closeDownConn(c *webClient, id string, message string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setPermissions(g *group.Group, id string, perm string) error {
|
||||
client := g.GetClient(id)
|
||||
if client == nil {
|
||||
return group.UserError("no such user")
|
||||
}
|
||||
|
||||
c, ok := client.(*webClient)
|
||||
if !ok {
|
||||
return group.UserError("this is not a real user")
|
||||
}
|
||||
|
||||
switch perm {
|
||||
case "op":
|
||||
c.permissions = addnew("op", c.permissions)
|
||||
if g.Description().AllowRecording {
|
||||
c.permissions = addnew("record", c.permissions)
|
||||
}
|
||||
case "unop":
|
||||
c.permissions = remove("op", c.permissions)
|
||||
c.permissions = remove("record", c.permissions)
|
||||
case "present":
|
||||
c.permissions = addnew("present", c.permissions)
|
||||
case "unpresent":
|
||||
c.permissions = remove("present", c.permissions)
|
||||
case "shutup":
|
||||
c.permissions = remove("message", c.permissions)
|
||||
case "unshutup":
|
||||
c.permissions = addnew("message", c.permissions)
|
||||
default:
|
||||
return group.UserError("unknown permission")
|
||||
}
|
||||
c.action(permissionsChangedAction{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *webClient) Kick(id string, user *string, message string) error {
|
||||
c.action(kickAction{id, user, message})
|
||||
return nil
|
||||
@@ -1912,10 +1904,17 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||
if !member("op", c.permissions) {
|
||||
return c.error(group.UserError("not authorised"))
|
||||
}
|
||||
err := setPermissions(g, m.Dest, m.Kind)
|
||||
if err != nil {
|
||||
return c.error(err)
|
||||
t := g.GetClient(m.Dest)
|
||||
if t == nil {
|
||||
return c.error(group.UserError("no suck user"))
|
||||
}
|
||||
target, ok := t.(*webClient)
|
||||
if !ok {
|
||||
return c.error(group.UserError(
|
||||
"this is not a real user",
|
||||
))
|
||||
}
|
||||
target.action(changePermissionsAction{m.Kind})
|
||||
case "identify":
|
||||
if !member("op", c.permissions) {
|
||||
return c.error(group.UserError("not authorised"))
|
||||
|
||||
Reference in New Issue
Block a user