mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-20 10:10:08 -08:00
uniformize limit handling
* max-keys is enforced for channels as well * remove unlimited configurations * maintain the limit exactly without off-by-one cases
This commit is contained in:
parent
f85222f5f5
commit
c82d324a83
6 changed files with 31 additions and 28 deletions
|
|
@ -1093,10 +1093,9 @@ metadata:
|
||||||
# can clients store metadata?
|
# can clients store metadata?
|
||||||
enabled: true
|
enabled: true
|
||||||
# how many keys can a client subscribe to?
|
# how many keys can a client subscribe to?
|
||||||
# set to 0 to disable subscriptions or -1 to allow unlimited subscriptions.
|
|
||||||
max-subs: 100
|
max-subs: 100
|
||||||
# how many keys can a user store about themselves? set to -1 to allow unlimited keys.
|
# how many keys can be stored per entity?
|
||||||
max-keys: 1000
|
max-keys: 100
|
||||||
|
|
||||||
# experimental support for mobile push notifications
|
# experimental support for mobile push notifications
|
||||||
# see the manual for potential security, privacy, and performance implications.
|
# see the manual for potential security, privacy, and performance implications.
|
||||||
|
|
|
||||||
|
|
@ -1649,19 +1649,20 @@ func LoadConfig(filename string) (config *Config, err error) {
|
||||||
config.Server.supportedCaps.Disable(caps.Metadata)
|
config.Server.supportedCaps.Disable(caps.Metadata)
|
||||||
} else {
|
} else {
|
||||||
var metadataValues []string
|
var metadataValues []string
|
||||||
if config.Metadata.MaxSubs >= 0 {
|
// these are required for normal operation, so set sane defaults:
|
||||||
metadataValues = append(metadataValues, fmt.Sprintf("max-subs=%d", config.Metadata.MaxSubs))
|
if config.Metadata.MaxSubs == 0 {
|
||||||
|
config.Metadata.MaxSubs = 10
|
||||||
}
|
}
|
||||||
if config.Metadata.MaxKeys > 0 {
|
metadataValues = append(metadataValues, fmt.Sprintf("max-subs=%d", config.Metadata.MaxSubs))
|
||||||
metadataValues = append(metadataValues, fmt.Sprintf("max-keys=%d", config.Metadata.MaxKeys))
|
if config.Metadata.MaxKeys == 0 {
|
||||||
|
config.Metadata.MaxKeys = 10
|
||||||
}
|
}
|
||||||
|
metadataValues = append(metadataValues, fmt.Sprintf("max-keys=%d", config.Metadata.MaxKeys))
|
||||||
|
// this is not required since we enforce a hardcoded upper bound on key+value
|
||||||
if config.Metadata.MaxValueBytes > 0 {
|
if config.Metadata.MaxValueBytes > 0 {
|
||||||
metadataValues = append(metadataValues, fmt.Sprintf("max-value-bytes=%d", config.Metadata.MaxValueBytes))
|
metadataValues = append(metadataValues, fmt.Sprintf("max-value-bytes=%d", config.Metadata.MaxValueBytes))
|
||||||
}
|
}
|
||||||
if len(metadataValues) != 0 {
|
config.Server.capValues[caps.Metadata] = strings.Join(metadataValues, ",")
|
||||||
config.Server.capValues[caps.Metadata] = strings.Join(metadataValues, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.processExtjwt()
|
err = config.processExtjwt()
|
||||||
|
|
|
||||||
|
|
@ -894,7 +894,7 @@ func (channel *Channel) GetMetadata(key string) (string, bool) {
|
||||||
return val, ok
|
return val, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) SetMetadata(key string, value string) (updated bool) {
|
func (channel *Channel) SetMetadata(key string, value string, limit int) (updated bool, err error) {
|
||||||
defer channel.MarkDirty(IncludeAllAttrs)
|
defer channel.MarkDirty(IncludeAllAttrs)
|
||||||
|
|
||||||
channel.stateMutex.Lock()
|
channel.stateMutex.Lock()
|
||||||
|
|
@ -905,11 +905,14 @@ func (channel *Channel) SetMetadata(key string, value string) (updated bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
existing, ok := channel.metadata[key]
|
existing, ok := channel.metadata[key]
|
||||||
|
if !ok && len(channel.metadata) >= limit {
|
||||||
|
return false, errLimitExceeded
|
||||||
|
}
|
||||||
updated = !ok || value != existing
|
updated = !ok || value != existing
|
||||||
if updated {
|
if updated {
|
||||||
channel.metadata[key] = value
|
channel.metadata[key] = value
|
||||||
}
|
}
|
||||||
return updated
|
return updated, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) ListMetadata() map[string]string {
|
func (channel *Channel) ListMetadata() map[string]string {
|
||||||
|
|
@ -958,7 +961,7 @@ func (client *Client) GetMetadata(key string) (string, bool) {
|
||||||
return val, ok
|
return val, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) SetMetadata(key string, value string) (updated bool) {
|
func (client *Client) SetMetadata(key string, value string, limit int) (updated bool, err error) {
|
||||||
client.stateMutex.Lock()
|
client.stateMutex.Lock()
|
||||||
defer client.stateMutex.Unlock()
|
defer client.stateMutex.Unlock()
|
||||||
|
|
||||||
|
|
@ -967,11 +970,14 @@ func (client *Client) SetMetadata(key string, value string) (updated bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
existing, ok := client.metadata[key]
|
existing, ok := client.metadata[key]
|
||||||
|
if !ok && len(client.metadata) >= limit {
|
||||||
|
return false, errLimitExceeded
|
||||||
|
}
|
||||||
updated = !ok || value != existing
|
updated = !ok || value != existing
|
||||||
if updated {
|
if updated {
|
||||||
client.metadata[key] = value
|
client.metadata[key] = value
|
||||||
}
|
}
|
||||||
return updated
|
return updated, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) ListMetadata() map[string]string {
|
func (client *Client) ListMetadata() map[string]string {
|
||||||
|
|
|
||||||
|
|
@ -3175,19 +3175,17 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
maxKeys := config.Metadata.MaxKeys
|
updated, err := targetObj.SetMetadata(key, value, config.Metadata.MaxKeys)
|
||||||
isSelf := targetClient != nil && client == targetClient
|
if err != nil {
|
||||||
|
// errLimitExceeded is the only possible error
|
||||||
if isSelf && maxKeys > 0 && targetObj.CountMetadata() >= maxKeys {
|
rb.Add(nil, server.name, "FAIL", "METADATA", "LIMIT_REACHED", client.t("Too many metadata keys"))
|
||||||
rb.Add(nil, server.name, "FAIL", "METADATA", "LIMIT_REACHED", client.t("You have too many keys set on yourself"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if updated := targetObj.SetMetadata(key, value); updated {
|
|
||||||
notifySubscribers(server, rb.session, targetObj, target, key, value)
|
|
||||||
}
|
|
||||||
// echo the value to the client whether or not there was a real update
|
// echo the value to the client whether or not there was a real update
|
||||||
rb.Add(nil, server.name, RPL_KEYVALUE, client.Nick(), target, key, "*", value)
|
rb.Add(nil, server.name, RPL_KEYVALUE, client.Nick(), target, key, "*", value)
|
||||||
|
if updated {
|
||||||
|
notifySubscribers(server, rb.session, targetObj, target, key, value)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if updated := targetObj.DeleteMetadata(key); updated {
|
if updated := targetObj.DeleteMetadata(key); updated {
|
||||||
notifySubscribers(server, rb.session, targetObj, target, key, "")
|
notifySubscribers(server, rb.session, targetObj, target, key, "")
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MetadataHaver = interface {
|
type MetadataHaver = interface {
|
||||||
SetMetadata(key string, value string) (updated bool)
|
SetMetadata(key string, value string, limit int) (updated bool, err error)
|
||||||
GetMetadata(key string) (string, bool)
|
GetMetadata(key string) (string, bool)
|
||||||
DeleteMetadata(key string) (updated bool)
|
DeleteMetadata(key string) (updated bool)
|
||||||
ListMetadata() map[string]string
|
ListMetadata() map[string]string
|
||||||
|
|
|
||||||
|
|
@ -1064,10 +1064,9 @@ metadata:
|
||||||
# can clients store metadata?
|
# can clients store metadata?
|
||||||
enabled: true
|
enabled: true
|
||||||
# how many keys can a client subscribe to?
|
# how many keys can a client subscribe to?
|
||||||
# set to 0 to disable subscriptions or -1 to allow unlimited subscriptions.
|
|
||||||
max-subs: 100
|
max-subs: 100
|
||||||
# how many keys can a user store about themselves? set to -1 to allow unlimited keys.
|
# how many keys can be stored per entity?
|
||||||
max-keys: 1000
|
max-keys: 100
|
||||||
|
|
||||||
# experimental support for mobile push notifications
|
# experimental support for mobile push notifications
|
||||||
# see the manual for potential security, privacy, and performance implications.
|
# see the manual for potential security, privacy, and performance implications.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue