mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 03:49:27 +01:00
Only stage some metadata changes for now, not the vendor update
This commit is contained in:
parent
512d89ba18
commit
060d06ba6a
44
default.yaml
44
default.yaml
@ -364,6 +364,50 @@ server:
|
|||||||
# the default value of 512. DO NOT change this on a public server:
|
# the default value of 512. DO NOT change this on a public server:
|
||||||
# max-line-len: 512
|
# max-line-len: 512
|
||||||
|
|
||||||
|
# metadata options
|
||||||
|
metadata:
|
||||||
|
# maximum number of keys users can have set.
|
||||||
|
# this excludes admin-set keys which users cannot set or view
|
||||||
|
max-keys: 16
|
||||||
|
|
||||||
|
# maximum number of keys users can subscribe to at one time.
|
||||||
|
# opers can subscribe to more than this though
|
||||||
|
max-subs: 16
|
||||||
|
|
||||||
|
users:
|
||||||
|
# uncomment this if you ONLY want these keys to be settable
|
||||||
|
# allowed-keys:
|
||||||
|
# - avatar
|
||||||
|
# - color
|
||||||
|
# - display-name
|
||||||
|
# - homepage
|
||||||
|
# - status
|
||||||
|
|
||||||
|
# uncomment this if you want all BUT these keys to be settable
|
||||||
|
# blocked-keys:
|
||||||
|
# - example-bad-key
|
||||||
|
# - another-bad-example
|
||||||
|
|
||||||
|
# these keys are restricted to opers
|
||||||
|
restricted-keys:
|
||||||
|
- admin:*
|
||||||
|
- server:*
|
||||||
|
|
||||||
|
channels:
|
||||||
|
# uncomment this if you ONLY want these keys to be settable
|
||||||
|
# allowed-keys:
|
||||||
|
# - url
|
||||||
|
|
||||||
|
# uncomment this if you want all BUT these keys to be settable
|
||||||
|
# blocked-keys:
|
||||||
|
# - example-bad-key
|
||||||
|
# - another-bad-example
|
||||||
|
|
||||||
|
# these keys are restricted to opers
|
||||||
|
restricted-keys:
|
||||||
|
- admin:*
|
||||||
|
- server:*
|
||||||
|
|
||||||
# account options
|
# account options
|
||||||
accounts:
|
accounts:
|
||||||
# is account authentication enabled, i.e., can users log into existing accounts?
|
# is account authentication enabled, i.e., can users log into existing accounts?
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/ergochat/irc-go/ircfmt"
|
"github.com/ergochat/irc-go/ircfmt"
|
||||||
"github.com/ergochat/irc-go/ircmsg"
|
"github.com/ergochat/irc-go/ircmsg"
|
||||||
"github.com/ergochat/irc-go/ircreader"
|
"github.com/ergochat/irc-go/ircreader"
|
||||||
|
"github.com/soroushj/menge"
|
||||||
"github.com/xdg-go/scram"
|
"github.com/xdg-go/scram"
|
||||||
|
|
||||||
"github.com/ergochat/ergo/irc/caps"
|
"github.com/ergochat/ergo/irc/caps"
|
||||||
@ -174,6 +175,9 @@ type Session struct {
|
|||||||
capState caps.State
|
capState caps.State
|
||||||
capVersion caps.Version
|
capVersion caps.Version
|
||||||
|
|
||||||
|
stateMutex sync.RWMutex // tier 1
|
||||||
|
subscribedMetadataKeys menge.StringSet
|
||||||
|
|
||||||
registrationMessages int
|
registrationMessages int
|
||||||
|
|
||||||
zncPlaybackTimes *zncPlaybackTimes
|
zncPlaybackTimes *zncPlaybackTimes
|
||||||
@ -359,6 +363,7 @@ func (server *Server) RunClient(conn IRCConn) {
|
|||||||
proxiedIP: proxiedIP,
|
proxiedIP: proxiedIP,
|
||||||
isTor: wConn.Config.Tor,
|
isTor: wConn.Config.Tor,
|
||||||
hideSTS: wConn.Config.Tor || wConn.Config.HideSTS,
|
hideSTS: wConn.Config.Tor || wConn.Config.HideSTS,
|
||||||
|
subscribedMetadataKeys: menge.NewStringSet(),
|
||||||
}
|
}
|
||||||
client.sessions = []*Session{session}
|
client.sessions = []*Session{session}
|
||||||
|
|
||||||
|
@ -178,6 +178,10 @@ func init() {
|
|||||||
handler: lusersHandler,
|
handler: lusersHandler,
|
||||||
minParams: 0,
|
minParams: 0,
|
||||||
},
|
},
|
||||||
|
"METADATA": {
|
||||||
|
handler: metadataHandler,
|
||||||
|
minParams: 2,
|
||||||
|
},
|
||||||
"MODE": {
|
"MODE": {
|
||||||
handler: modeHandler,
|
handler: modeHandler,
|
||||||
minParams: 1,
|
minParams: 1,
|
||||||
|
@ -300,6 +300,38 @@ func (t *ThrottleConfig) UnmarshalYAML(unmarshal func(interface{}) error) (err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MetadataKeyConfig struct {
|
||||||
|
AllowedKeys []string `yaml:"allowed-keys"`
|
||||||
|
AllowedKeysMatcher *regexp.Regexp
|
||||||
|
BlockedKeys []string `yaml:"blocked-keys"`
|
||||||
|
BlockedKeysMatcher *regexp.Regexp
|
||||||
|
RestrictedKeys []string `yaml:"restricted-keys"`
|
||||||
|
RestrictedKeysMatcher *regexp.Regexp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mkc *MetadataKeyConfig) compileMatchers() (err error) {
|
||||||
|
mkc.AllowedKeysMatcher, err = utils.CompileMasks(mkc.AllowedKeys)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("allowed-keys")
|
||||||
|
}
|
||||||
|
mkc.BlockedKeysMatcher, err = utils.CompileMasks(mkc.BlockedKeys)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("blocked-keys")
|
||||||
|
}
|
||||||
|
mkc.RestrictedKeysMatcher, err = utils.CompileMasks(mkc.RestrictedKeys)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("restricted-keys")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetadataConfig struct {
|
||||||
|
MaxKeys int `yaml:"max-keys"`
|
||||||
|
MaxSubs int `yaml:"max-subs"`
|
||||||
|
Users MetadataKeyConfig
|
||||||
|
Channels MetadataKeyConfig
|
||||||
|
}
|
||||||
|
|
||||||
type AccountConfig struct {
|
type AccountConfig struct {
|
||||||
Registration AccountRegistrationConfig
|
Registration AccountRegistrationConfig
|
||||||
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
AuthenticationEnabled bool `yaml:"authentication-enabled"`
|
||||||
@ -621,6 +653,8 @@ type Config struct {
|
|||||||
MySQL mysql.Config
|
MySQL mysql.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Metadata MetadataConfig
|
||||||
|
|
||||||
Accounts AccountConfig
|
Accounts AccountConfig
|
||||||
|
|
||||||
Channels struct {
|
Channels struct {
|
||||||
@ -1228,6 +1262,26 @@ func LoadConfig(filename string) (config *Config, err error) {
|
|||||||
config.Server.capValues[caps.Multiline] = multilineCapValue
|
config.Server.capValues[caps.Multiline] = multilineCapValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// confirm that we don't have both allowed and blocked metadata keys set
|
||||||
|
config.Server.capValues[caps.Metadata] = fmt.Sprintf("maxsub=%d,maxkey=%d", config.Metadata.MaxSubs, config.Metadata.MaxKeys)
|
||||||
|
|
||||||
|
if len(config.Metadata.Users.AllowedKeys) > 0 && len(config.Metadata.Users.BlockedKeys) > 0 {
|
||||||
|
return nil, errors.New("You can only set either allowed-keys or blocked-keys in metadata.users, not both")
|
||||||
|
}
|
||||||
|
if len(config.Metadata.Channels.AllowedKeys) > 0 && len(config.Metadata.Channels.BlockedKeys) > 0 {
|
||||||
|
return nil, errors.New("You can only set either allowed-keys or blocked-keys in metadata.channels, not both")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.Metadata.Users.compileMatchers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not compile metadata.users.%s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.Metadata.Channels.compileMatchers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not compile metadata.channels.%s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// handle legacy name 'bouncer' for 'multiclient' section:
|
// handle legacy name 'bouncer' for 'multiclient' section:
|
||||||
if config.Accounts.Bouncer != nil {
|
if config.Accounts.Bouncer != nil {
|
||||||
config.Accounts.Multiclient = *config.Accounts.Bouncer
|
config.Accounts.Multiclient = *config.Accounts.Bouncer
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
@ -1709,6 +1710,95 @@ func lusersHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// METADATA <Target> <Subcommand> [<Param 1> ... [<Param n>]]
|
||||||
|
func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool {
|
||||||
|
// target := msg.Params[0]
|
||||||
|
subCommand := strings.ToUpper(msg.Params[1])
|
||||||
|
|
||||||
|
config := server.Config().Metadata
|
||||||
|
|
||||||
|
//TODO: do this once when the server boots?
|
||||||
|
keyNameMatcher, _ := regexp.Compile(`^[a-z0-9_.-][a-z0-9_.\-:]*$`)
|
||||||
|
|
||||||
|
switch subCommand {
|
||||||
|
// these subcommands affect the client itself, or other targets
|
||||||
|
//
|
||||||
|
|
||||||
|
// these subcommands affect the current session
|
||||||
|
//
|
||||||
|
case "SUB":
|
||||||
|
var addedKeys []string
|
||||||
|
|
||||||
|
rb.session.stateMutex.Lock()
|
||||||
|
defer rb.session.stateMutex.Unlock()
|
||||||
|
for i, key := range msg.Params {
|
||||||
|
if i < 2 {
|
||||||
|
// skip target and subcommand
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rb.session.subscribedMetadataKeys)+len(addedKeys) > config.MaxSubs {
|
||||||
|
rb.Add(nil, server.name, ERR_METADATATOOMANYSUBS, client.nick, key)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !keyNameMatcher.MatchString(key) {
|
||||||
|
rb.Add(nil, server.name, ERR_KEYINVALID, client.nick, key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if key is restricted
|
||||||
|
if client.Oper() == nil && (config.Users.RestrictedKeysMatcher.MatchString(key) || config.Channels.RestrictedKeysMatcher.MatchString(key)) {
|
||||||
|
rb.Add(nil, server.name, ERR_KEYNOPERMISSION, client.nick, "*", key, "permission denied")
|
||||||
|
// still let the user subscribe to the key, don't continue on to the next one
|
||||||
|
}
|
||||||
|
|
||||||
|
addedKeys = append(addedKeys, key)
|
||||||
|
}
|
||||||
|
rb.session.subscribedMetadataKeys.Add(addedKeys...)
|
||||||
|
|
||||||
|
if len(addedKeys) > 0 {
|
||||||
|
rb.Add(nil, server.name, RPL_METADATASUBOK, client.nick, strings.Join(addedKeys, " "))
|
||||||
|
}
|
||||||
|
rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata")
|
||||||
|
|
||||||
|
case "UNSUB":
|
||||||
|
var removedKeys []string
|
||||||
|
|
||||||
|
rb.session.stateMutex.Lock()
|
||||||
|
defer rb.session.stateMutex.Unlock()
|
||||||
|
for i, key := range msg.Params {
|
||||||
|
if i < 2 {
|
||||||
|
// skip target and subcommand
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !keyNameMatcher.MatchString(key) {
|
||||||
|
rb.Add(nil, server.name, ERR_KEYINVALID, client.nick, key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
removedKeys = append(removedKeys, key)
|
||||||
|
}
|
||||||
|
rb.session.subscribedMetadataKeys.Remove(removedKeys...)
|
||||||
|
|
||||||
|
if len(removedKeys) > 0 {
|
||||||
|
rb.Add(nil, server.name, RPL_METADATAUNSUBOK, client.nick, strings.Join(removedKeys, " "))
|
||||||
|
}
|
||||||
|
rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata")
|
||||||
|
|
||||||
|
case "SUBS":
|
||||||
|
rb.session.stateMutex.RLock()
|
||||||
|
defer rb.session.stateMutex.RUnlock()
|
||||||
|
if rb.session.subscribedMetadataKeys.Size() > 0 {
|
||||||
|
//TODO: loop and return subscriptions with multiple numerics if we need to
|
||||||
|
rb.Add(nil, server.name, RPL_METADATASUBS, client.nick, strings.Join(rb.session.subscribedMetadataKeys.AsSlice(), " "))
|
||||||
|
}
|
||||||
|
rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// MODE <target> [<modestring> [<mode arguments>...]]
|
// MODE <target> [<modestring> [<mode arguments>...]]
|
||||||
func modeHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool {
|
func modeHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool {
|
||||||
if 0 < len(msg.Params[0]) && msg.Params[0][0] == '#' {
|
if 0 < len(msg.Params[0]) && msg.Params[0][0] == '#' {
|
||||||
|
@ -347,6 +347,14 @@ Lists all the nicknames you are currently monitoring.
|
|||||||
|
|
||||||
MONITOR S
|
MONITOR S
|
||||||
Lists whether each nick in your MONITOR list is online or offline.`,
|
Lists whether each nick in your MONITOR list is online or offline.`,
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
text: `METADATA <target> <subcmd>
|
||||||
|
|
||||||
|
Lets you add metadata to yourself and channels, as well as subscribe
|
||||||
|
to metadata changes. The subcommands are:
|
||||||
|
|
||||||
|
//TODO`,
|
||||||
},
|
},
|
||||||
"motd": {
|
"motd": {
|
||||||
text: `MOTD [server]
|
text: `MOTD [server]
|
||||||
|
4
irc/metadata.go
Normal file
4
irc/metadata.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Copyright (c) 2021 Daniel Oaks <daniel@danieloaks.net>
|
||||||
|
// released under the MIT license
|
||||||
|
|
||||||
|
package irc
|
@ -337,6 +337,50 @@ server:
|
|||||||
# the default value of 512. DO NOT change this on a public server:
|
# the default value of 512. DO NOT change this on a public server:
|
||||||
# max-line-len: 512
|
# max-line-len: 512
|
||||||
|
|
||||||
|
# metadata options
|
||||||
|
metadata:
|
||||||
|
# maximum number of keys users can have set.
|
||||||
|
# this excludes admin-set keys which users cannot set or view
|
||||||
|
max-keys: 16
|
||||||
|
|
||||||
|
# maximum number of keys users can subscribe to at one time.
|
||||||
|
# opers can subscribe to more than this though
|
||||||
|
max-subs: 16
|
||||||
|
|
||||||
|
users:
|
||||||
|
# uncomment this if you ONLY want these keys to be settable
|
||||||
|
# allowed-keys:
|
||||||
|
# - avatar
|
||||||
|
# - color
|
||||||
|
# - display-name
|
||||||
|
# - homepage
|
||||||
|
# - status
|
||||||
|
|
||||||
|
# uncomment this if you want all BUT these keys to be settable
|
||||||
|
# blocked-keys:
|
||||||
|
# - example-bad-key
|
||||||
|
# - another-bad-example
|
||||||
|
|
||||||
|
# these keys are restricted to opers
|
||||||
|
restricted-keys:
|
||||||
|
- admin:*
|
||||||
|
- server:*
|
||||||
|
|
||||||
|
channels:
|
||||||
|
# uncomment this if you ONLY want these keys to be settable
|
||||||
|
# allowed-keys:
|
||||||
|
# - url
|
||||||
|
|
||||||
|
# uncomment this if you want all BUT these keys to be settable
|
||||||
|
# blocked-keys:
|
||||||
|
# - example-bad-key
|
||||||
|
# - another-bad-example
|
||||||
|
|
||||||
|
# these keys are restricted to opers
|
||||||
|
restricted-keys:
|
||||||
|
- admin:*
|
||||||
|
- server:*
|
||||||
|
|
||||||
# account options
|
# account options
|
||||||
accounts:
|
accounts:
|
||||||
# is account authentication enabled, i.e., can users log into existing accounts?
|
# is account authentication enabled, i.e., can users log into existing accounts?
|
||||||
|
Loading…
Reference in New Issue
Block a user