diff --git a/default.yaml b/default.yaml index 6c32e95b..841820f6 100644 --- a/default.yaml +++ b/default.yaml @@ -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: diff --git a/irc/handlers.go b/irc/handlers.go index 11312bd4..6d6408a4 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -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 } diff --git a/irc/metadata.go b/irc/metadata.go index d7094065..629f3878 100644 --- a/irc/metadata.go +++ b/irc/metadata.go @@ -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 } diff --git a/traditional.yaml b/traditional.yaml index f32018c4..48c139f5 100644 --- a/traditional.yaml +++ b/traditional.yaml @@ -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: