refactor permission checks

This commit is contained in:
Shivaram Lingamneni 2025-06-15 12:19:12 -04:00
parent 5da2ddbc07
commit e6aaaf1b88
4 changed files with 27 additions and 39 deletions

View file

@ -724,6 +724,7 @@ oper-classes:
- "history" # modify or delete history messages
- "defcon" # use the DEFCON command (restrict server capabilities)
- "massmessage" # message all users on the server
- "metadata" # modify arbitrary metadata on channels and users
# ircd operators
opers:

View file

@ -3155,7 +3155,7 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res
return
}
if !metadataCanIEditThisKey(client, target, key) {
if !metadataCanIEditThisKey(client, targetObj, key) {
noKeyPerms(key)
return
}
@ -3192,6 +3192,11 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res
}
case "get":
if !metadataCanISeeThisTarget(client, targetObj) {
noKeyPerms("*")
return
}
batchId := rb.StartNestedBatch("metadata")
defer rb.EndNestedBatch(batchId)
@ -3224,7 +3229,7 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res
}
case "clear":
if !metadataCanIEditThisTarget(client, target) {
if !metadataCanIEditThisTarget(client, targetObj) {
invalidTarget()
return
}

View file

@ -117,48 +117,29 @@ func metadataKeyIsEvil(key string) bool {
metadataEvilCharsRegexp.MatchString(key) // key can't contain the stuff it can't contain
}
func metadataCanIEditThisKey(client *Client, target string, _ string) bool {
if !metadataCanIEditThisTarget(client, target) { // you can't edit keys on targets you can't edit.
return false
}
// todo: we don't actually do anything regarding visibility yet so there's not much to do here
return true
func metadataCanIEditThisKey(client *Client, targetObj MetadataHaver, key string) bool {
// no key-specific logic as yet
return metadataCanIEditThisTarget(client, targetObj)
}
func metadataCanIEditThisTarget(client *Client, target string) bool {
if !metadataCanISeeThisTarget(client, target) { // you can't edit what you can't see. a wise man told me this once
return false
func metadataCanIEditThisTarget(client *Client, targetObj MetadataHaver) bool {
switch target := targetObj.(type) {
case *Client:
return client == target || client.HasRoleCapabs("metadata")
case *Channel:
return target.ClientIsAtLeast(client, modes.Operator) || client.HasRoleCapabs("metadata")
default:
return false // impossible
}
if client.HasRoleCapabs("sajoin") { // sajoin opers can do whatever they want
return true
}
if target == client.Nick() { // your right to swing your fist ends where my nose begins
return true
}
// if you're a channel operator, knock yourself out
channel := client.server.channels.Get(target)
if channel != nil && channel.ClientIsAtLeast(client, modes.Operator) {
return true
}
return false
}
func metadataCanISeeThisTarget(client *Client, target string) bool {
if client.HasRoleCapabs("sajoin") { // sajoin opers can do whatever they want
func metadataCanISeeThisTarget(client *Client, targetObj MetadataHaver) bool {
switch target := targetObj.(type) {
case *Client:
return true
case *Channel:
return target.hasClient(client) || client.HasRoleCapabs("metadata")
default:
return false // impossible
}
// check if the user is in the channel
channel := client.server.channels.Get(target)
if channel != nil && !channel.hasClient(client) {
return false
}
return true
}

View file

@ -695,6 +695,7 @@ oper-classes:
- "history" # modify or delete history messages
- "defcon" # use the DEFCON command (restrict server capabilities)
- "massmessage" # message all users on the server
- "metadata" # modify arbitrary metadata on channels and users
# ircd operators
opers: