From 937bad6717357379691bdeab1dba23d56f7c3fc1 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Tue, 17 Mar 2026 11:33:11 -0700 Subject: [PATCH] fix #2287 (#2369) Allow restricting metadata modification to server operators --- default.yaml | 2 ++ irc/config.go | 11 ++++++----- irc/handlers.go | 10 ++++++++-- traditional.yaml | 2 ++ 4 files changed, 18 insertions(+), 7 deletions(-) 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?