diff --git a/default.yaml b/default.yaml index b21a66c6..dec96b79 100644 --- a/default.yaml +++ b/default.yaml @@ -1150,6 +1150,8 @@ allow-environment-overrides: true metadata: # can clients store metadata? enabled: true + # if this is true, only server operators with the `metadata` capability can edit metadata: + operator-only-modification: false # how many keys can a client subscribe to? max-subs: 100 # how many keys can be stored per entity? diff --git a/irc/config.go b/irc/config.go index 43f7a421..d6d64cec 100644 --- a/irc/config.go +++ b/irc/config.go @@ -715,11 +715,12 @@ type Config struct { } Metadata struct { - Enabled bool - MaxSubs int `yaml:"max-subs"` - MaxKeys int `yaml:"max-keys"` - MaxValueBytes int `yaml:"max-value-length"` - ClientThrottle ThrottleConfig `yaml:"client-throttle"` + Enabled bool + OperatorOnlyModification bool `yaml:"operator-only-modification"` + MaxSubs int `yaml:"max-subs"` + MaxKeys int `yaml:"max-keys"` + MaxValueBytes int `yaml:"max-value-length"` + ClientThrottle ThrottleConfig `yaml:"client-throttle"` } WebPush struct { diff --git a/irc/handlers.go b/irc/handlers.go index b714f5db..8d657e6b 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -3148,7 +3148,7 @@ func markReadHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) (exiting bool) { config := server.Config() if !config.Metadata.Enabled { - rb.Add(nil, server.name, "FAIL", "METADATA", "FORBIDDEN", utils.SafeErrorParam(msg.Params[0]), "Metadata is disabled on this server") + rb.Add(nil, server.name, "FAIL", "METADATA", "FORBIDDEN", utils.SafeErrorParam(msg.Params[0]), client.t("Metadata is disabled on this server")) return } @@ -3163,7 +3163,13 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res case "sub", "unsub", "subs": // these are session-local and function the same whether or not the client is registered return metadataSubsHandler(client, subcommand, msg.Params, rb) - case "get", "set", "list", "clear", "sync": + case "set", "clear": + if config.Metadata.OperatorOnlyModification && !client.HasRoleCapabs("metadata") { + rb.Add(nil, server.name, "FAIL", "METADATA", "FORBIDDEN", utils.SafeErrorParam(msg.Params[0]), client.t("Only server operators can modify metadata")) + return + } + fallthrough + case "get", "list", "sync": if client.registered { return metadataRegisteredHandler(client, config, subcommand, msg.Params, rb) } else { diff --git a/traditional.yaml b/traditional.yaml index f326ef55..d54c0284 100644 --- a/traditional.yaml +++ b/traditional.yaml @@ -1121,6 +1121,8 @@ allow-environment-overrides: true metadata: # can clients store metadata? enabled: true + # if this is true, only server operators with the `metadata` capability can edit metadata: + operator-only-modification: false # how many keys can a client subscribe to? max-subs: 100 # how many keys can be stored per entity?