mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-25 13:29:27 +01:00
commit
c2c5fe7cf8
@ -475,23 +475,6 @@ accounts:
|
||||
# (make sure any changes you make here are RFC-compliant)
|
||||
valid-regexp: '^[0-9A-Za-z.\-_/]+$'
|
||||
|
||||
# options controlling users requesting vhosts:
|
||||
user-requests:
|
||||
# can users request vhosts at all? if this is false, operators with the
|
||||
# 'vhosts' capability can still assign vhosts manually
|
||||
enabled: false
|
||||
|
||||
# if uncommented, all new vhost requests will be dumped into the given
|
||||
# channel, so opers can review them as they are sent in. ensure that you
|
||||
# have registered and restricted the channel appropriately before you
|
||||
# uncomment this.
|
||||
#channel: "#vhosts"
|
||||
|
||||
# after a user's vhost has been approved or rejected, they need to wait
|
||||
# this long (starting from the time of their original request)
|
||||
# before they can request a new one.
|
||||
cooldown: 168h
|
||||
|
||||
# modes that are set by default when a user connects
|
||||
# if unset, no user modes will be set by default
|
||||
# +i is invisible (a user's channels are hidden from whois replies)
|
||||
|
17
default.yaml
17
default.yaml
@ -503,23 +503,6 @@ accounts:
|
||||
# (make sure any changes you make here are RFC-compliant)
|
||||
valid-regexp: '^[0-9A-Za-z.\-_/]+$'
|
||||
|
||||
# options controlling users requesting vhosts:
|
||||
user-requests:
|
||||
# can users request vhosts at all? if this is false, operators with the
|
||||
# 'vhosts' capability can still assign vhosts manually
|
||||
enabled: false
|
||||
|
||||
# if uncommented, all new vhost requests will be dumped into the given
|
||||
# channel, so opers can review them as they are sent in. ensure that you
|
||||
# have registered and restricted the channel appropriately before you
|
||||
# uncomment this.
|
||||
#channel: "#vhosts"
|
||||
|
||||
# after a user's vhost has been approved or rejected, they need to wait
|
||||
# this long (starting from the time of their original request)
|
||||
# before they can request a new one.
|
||||
cooldown: 168h
|
||||
|
||||
# modes that are set by default when a user connects
|
||||
# if unset, no user modes will be set by default
|
||||
# +i is invisible (a user's channels are hidden from whois replies)
|
||||
|
204
irc/accounts.go
204
irc/accounts.go
@ -12,7 +12,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
@ -44,23 +43,14 @@ const (
|
||||
keyAccountModes = "account.modes %s" // user modes for the always-on client as a string
|
||||
keyAccountRealname = "account.realname %s" // client realname stored as string
|
||||
|
||||
keyVHostQueueAcctToId = "vhostQueue %s"
|
||||
vhostRequestIdx = "vhostQueue"
|
||||
|
||||
maxCertfpsPerAccount = 5
|
||||
)
|
||||
|
||||
// everything about accounts is persistent; therefore, the database is the authoritative
|
||||
// source of truth for all account information. anything on the heap is just a cache
|
||||
type AccountManager struct {
|
||||
// XXX these are up here so they can be aligned to a 64-bit boundary, please forgive me
|
||||
// autoincrementing ID for vhost requests:
|
||||
vhostRequestID uint64
|
||||
vhostRequestPendingCount uint64
|
||||
|
||||
sync.RWMutex // tier 2
|
||||
serialCacheUpdateMutex sync.Mutex // tier 3
|
||||
vHostUpdateMutex sync.Mutex // tier 3
|
||||
|
||||
server *Server
|
||||
// track clients logged in to accounts
|
||||
@ -80,7 +70,6 @@ func (am *AccountManager) Initialize(server *Server) {
|
||||
|
||||
config := server.Config()
|
||||
am.buildNickToAccountIndex(config)
|
||||
am.initVHostRequestQueue(config)
|
||||
am.createAlwaysOnClients(config)
|
||||
am.resetRegisterThrottle(config)
|
||||
}
|
||||
@ -225,44 +214,6 @@ func (am *AccountManager) buildNickToAccountIndex(config *Config) {
|
||||
}
|
||||
}
|
||||
|
||||
func (am *AccountManager) initVHostRequestQueue(config *Config) {
|
||||
if !config.Accounts.VHosts.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
am.vHostUpdateMutex.Lock()
|
||||
defer am.vHostUpdateMutex.Unlock()
|
||||
|
||||
// the db maps the account name to the autoincrementing integer ID of its request
|
||||
// create an numerically ordered index on ID, so we can list the oldest requests
|
||||
// finally, collect the integer id of the newest request and the total request count
|
||||
var total uint64
|
||||
var lastIDStr string
|
||||
err := am.server.store.Update(func(tx *buntdb.Tx) error {
|
||||
err := tx.CreateIndex(vhostRequestIdx, fmt.Sprintf(keyVHostQueueAcctToId, "*"), buntdb.IndexInt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Descend(vhostRequestIdx, func(key, value string) bool {
|
||||
if lastIDStr == "" {
|
||||
lastIDStr = value
|
||||
}
|
||||
total++
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", "could not create vhost queue index", err.Error())
|
||||
}
|
||||
|
||||
lastID, _ := strconv.ParseUint(lastIDStr, 10, 64)
|
||||
am.server.logger.Debug("services", fmt.Sprintf("vhost queue length is %d, autoincrementing id is %d", total, lastID))
|
||||
|
||||
atomic.StoreUint64(&am.vhostRequestID, lastID)
|
||||
atomic.StoreUint64(&am.vhostRequestPendingCount, total)
|
||||
}
|
||||
|
||||
func (am *AccountManager) NickToAccount(nick string) string {
|
||||
cfnick, err := CasefoldName(nick)
|
||||
if err != nil {
|
||||
@ -1394,7 +1345,6 @@ func (am *AccountManager) Unregister(account string, erase bool) error {
|
||||
nicksKey := fmt.Sprintf(keyAccountAdditionalNicks, casefoldedAccount)
|
||||
settingsKey := fmt.Sprintf(keyAccountSettings, casefoldedAccount)
|
||||
vhostKey := fmt.Sprintf(keyAccountVHost, casefoldedAccount)
|
||||
vhostQueueKey := fmt.Sprintf(keyVHostQueueAcctToId, casefoldedAccount)
|
||||
channelsKey := fmt.Sprintf(keyAccountChannels, casefoldedAccount)
|
||||
joinedChannelsKey := fmt.Sprintf(keyAccountJoinedChannels, casefoldedAccount)
|
||||
lastSeenKey := fmt.Sprintf(keyAccountLastSeen, casefoldedAccount)
|
||||
@ -1461,8 +1411,6 @@ func (am *AccountManager) Unregister(account string, erase bool) error {
|
||||
tx.Delete(modesKey)
|
||||
tx.Delete(realnameKey)
|
||||
|
||||
_, err := tx.Delete(vhostQueueKey)
|
||||
am.decrementVHostQueueCount(casefoldedAccount, err)
|
||||
return nil
|
||||
})
|
||||
|
||||
@ -1635,42 +1583,8 @@ func (am *AccountManager) ModifyAccountSettings(account string, munger settingsM
|
||||
|
||||
// represents someone's status in hostserv
|
||||
type VHostInfo struct {
|
||||
ApprovedVHost string
|
||||
Enabled bool
|
||||
RequestedVHost string
|
||||
RejectedVHost string
|
||||
RejectionReason string
|
||||
LastRequestTime time.Time
|
||||
}
|
||||
|
||||
// pair type, <VHostInfo, accountName>
|
||||
type PendingVHostRequest struct {
|
||||
VHostInfo
|
||||
Account string
|
||||
}
|
||||
|
||||
type vhostThrottleExceeded struct {
|
||||
timeRemaining time.Duration
|
||||
}
|
||||
|
||||
func (vhe *vhostThrottleExceeded) Error() string {
|
||||
return fmt.Sprintf("Wait at least %v and try again", vhe.timeRemaining)
|
||||
}
|
||||
|
||||
func (vh *VHostInfo) checkThrottle(cooldown time.Duration) (err error) {
|
||||
if cooldown == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
elapsed := now.Sub(vh.LastRequestTime)
|
||||
if elapsed > cooldown {
|
||||
// success
|
||||
vh.LastRequestTime = now
|
||||
return nil
|
||||
} else {
|
||||
return &vhostThrottleExceeded{timeRemaining: cooldown - elapsed}
|
||||
}
|
||||
ApprovedVHost string
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// callback type implementing the actual business logic of vhost operations
|
||||
@ -1687,52 +1601,6 @@ func (am *AccountManager) VHostSet(account string, vhost string) (result VHostIn
|
||||
return am.performVHostChange(account, munger)
|
||||
}
|
||||
|
||||
func (am *AccountManager) VHostRequest(account string, vhost string, cooldown time.Duration) (result VHostInfo, err error) {
|
||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||
output = input
|
||||
// you can update your existing request, but if you were approved or rejected,
|
||||
// you can't spam a new request
|
||||
if output.RequestedVHost == "" {
|
||||
err = output.checkThrottle(cooldown)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
output.RequestedVHost = vhost
|
||||
output.RejectedVHost = ""
|
||||
output.RejectionReason = ""
|
||||
output.LastRequestTime = time.Now().UTC()
|
||||
return
|
||||
}
|
||||
|
||||
return am.performVHostChange(account, munger)
|
||||
}
|
||||
|
||||
func (am *AccountManager) VHostApprove(account string) (result VHostInfo, err error) {
|
||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||
output = input
|
||||
output.Enabled = true
|
||||
output.ApprovedVHost = input.RequestedVHost
|
||||
output.RequestedVHost = ""
|
||||
output.RejectionReason = ""
|
||||
return
|
||||
}
|
||||
|
||||
return am.performVHostChange(account, munger)
|
||||
}
|
||||
|
||||
func (am *AccountManager) VHostReject(account string, reason string) (result VHostInfo, err error) {
|
||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||
output = input
|
||||
output.RejectedVHost = output.RequestedVHost
|
||||
output.RequestedVHost = ""
|
||||
output.RejectionReason = reason
|
||||
return
|
||||
}
|
||||
|
||||
return am.performVHostChange(account, munger)
|
||||
}
|
||||
|
||||
func (am *AccountManager) VHostSetEnabled(client *Client, enabled bool) (result VHostInfo, err error) {
|
||||
munger := func(input VHostInfo) (output VHostInfo, err error) {
|
||||
if input.ApprovedVHost == "" {
|
||||
@ -1759,9 +1627,6 @@ func (am *AccountManager) performVHostChange(account string, munger vhostMunger)
|
||||
return
|
||||
}
|
||||
|
||||
am.vHostUpdateMutex.Lock()
|
||||
defer am.vHostUpdateMutex.Unlock()
|
||||
|
||||
clientAccount, err := am.LoadAccount(account)
|
||||
if err != nil {
|
||||
err = errAccountDoesNotExist
|
||||
@ -1784,25 +1649,9 @@ func (am *AccountManager) performVHostChange(account string, munger vhostMunger)
|
||||
vhstr := string(vhtext)
|
||||
|
||||
key := fmt.Sprintf(keyAccountVHost, account)
|
||||
queueKey := fmt.Sprintf(keyVHostQueueAcctToId, account)
|
||||
err = am.server.store.Update(func(tx *buntdb.Tx) error {
|
||||
if _, _, err := tx.Set(key, vhstr, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update request queue
|
||||
if clientAccount.VHost.RequestedVHost == "" && result.RequestedVHost != "" {
|
||||
id := atomic.AddUint64(&am.vhostRequestID, 1)
|
||||
if _, _, err = tx.Set(queueKey, strconv.FormatUint(id, 10), nil); err != nil {
|
||||
return err
|
||||
}
|
||||
atomic.AddUint64(&am.vhostRequestPendingCount, 1)
|
||||
} else if clientAccount.VHost.RequestedVHost != "" && result.RequestedVHost == "" {
|
||||
_, err = tx.Delete(queueKey)
|
||||
am.decrementVHostQueueCount(account, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
_, _, err := tx.Set(key, vhstr, nil)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
@ -1814,51 +1663,6 @@ func (am *AccountManager) performVHostChange(account string, munger vhostMunger)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// XXX annoying helper method for keeping the queue count in sync with the DB
|
||||
// `err` is the buntdb error returned from deleting the queue key
|
||||
func (am *AccountManager) decrementVHostQueueCount(account string, err error) {
|
||||
if err == nil {
|
||||
// successfully deleted a queue entry, do a 2's complement decrement:
|
||||
atomic.AddUint64(&am.vhostRequestPendingCount, ^uint64(0))
|
||||
} else if err != buntdb.ErrNotFound {
|
||||
am.server.logger.Error("internal", "buntdb dequeue error", account, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (am *AccountManager) VHostListRequests(limit int) (requests []PendingVHostRequest, total int) {
|
||||
am.vHostUpdateMutex.Lock()
|
||||
defer am.vHostUpdateMutex.Unlock()
|
||||
|
||||
total = int(atomic.LoadUint64(&am.vhostRequestPendingCount))
|
||||
|
||||
prefix := fmt.Sprintf(keyVHostQueueAcctToId, "")
|
||||
accounts := make([]string, 0, limit)
|
||||
err := am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
return tx.Ascend(vhostRequestIdx, func(key, value string) bool {
|
||||
accounts = append(accounts, strings.TrimPrefix(key, prefix))
|
||||
return len(accounts) < limit
|
||||
})
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", "couldn't traverse vhost queue", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, account := range accounts {
|
||||
accountInfo, err := am.LoadAccount(account)
|
||||
if err == nil {
|
||||
requests = append(requests, PendingVHostRequest{
|
||||
Account: account,
|
||||
VHostInfo: accountInfo.VHost,
|
||||
})
|
||||
} else {
|
||||
am.server.logger.Error("internal", "corrupt account", account, err.Error())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (am *AccountManager) applyVHostInfo(client *Client, info VHostInfo) {
|
||||
// if hostserv is disabled in config, then don't grant vhosts
|
||||
// that were previously approved while it was enabled
|
||||
|
@ -316,12 +316,7 @@ type VHostConfig struct {
|
||||
Enabled bool
|
||||
MaxLength int `yaml:"max-length"`
|
||||
ValidRegexpRaw string `yaml:"valid-regexp"`
|
||||
ValidRegexp *regexp.Regexp
|
||||
UserRequests struct {
|
||||
Enabled bool
|
||||
Channel string
|
||||
Cooldown custime.Duration
|
||||
} `yaml:"user-requests"`
|
||||
validRegexp *regexp.Regexp
|
||||
}
|
||||
|
||||
type NickEnforcementMethod int
|
||||
@ -1109,13 +1104,13 @@ func LoadConfig(filename string) (config *Config, err error) {
|
||||
if rawRegexp != "" {
|
||||
regexp, err := regexp.Compile(rawRegexp)
|
||||
if err == nil {
|
||||
config.Accounts.VHosts.ValidRegexp = regexp
|
||||
config.Accounts.VHosts.validRegexp = regexp
|
||||
} else {
|
||||
log.Printf("invalid vhost regexp: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
if config.Accounts.VHosts.ValidRegexp == nil {
|
||||
config.Accounts.VHosts.ValidRegexp = defaultValidVhostRegex
|
||||
if config.Accounts.VHosts.validRegexp == nil {
|
||||
config.Accounts.VHosts.validRegexp = defaultValidVhostRegex
|
||||
}
|
||||
|
||||
config.Server.capValues[caps.SASL] = "PLAIN,EXTERNAL"
|
||||
|
@ -24,7 +24,7 @@ const (
|
||||
// 'version' of the database schema
|
||||
keySchemaVersion = "db.version"
|
||||
// latest schema of the db
|
||||
latestDbSchema = "16"
|
||||
latestDbSchema = "17"
|
||||
|
||||
keyCloakSecret = "crypto.cloak_secret"
|
||||
)
|
||||
@ -835,6 +835,24 @@ func schemaChangeV15ToV16(config *Config, tx *buntdb.Tx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// #1346: remove vhost request queue
|
||||
func schemaChangeV16ToV17(config *Config, tx *buntdb.Tx) error {
|
||||
prefix := "vhostQueue "
|
||||
var keys []string
|
||||
tx.AscendGreaterOrEqual("", prefix, func(key, value string) bool {
|
||||
if !strings.HasPrefix(key, prefix) {
|
||||
return false
|
||||
}
|
||||
keys = append(keys, key)
|
||||
return true
|
||||
})
|
||||
|
||||
for _, key := range keys {
|
||||
tx.Delete(key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
allChanges := []SchemaChange{
|
||||
{
|
||||
@ -912,6 +930,11 @@ func init() {
|
||||
TargetVersion: "16",
|
||||
Changer: schemaChangeV15ToV16,
|
||||
},
|
||||
{
|
||||
InitialVersion: "16",
|
||||
TargetVersion: "17",
|
||||
Changer: schemaChangeV16ToV17,
|
||||
},
|
||||
}
|
||||
|
||||
// build the index
|
||||
|
145
irc/hostserv.go
145
irc/hostserv.go
@ -7,11 +7,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/goshuirc/irc-go/ircfmt"
|
||||
|
||||
"github.com/oragono/oragono/irc/sno"
|
||||
"github.com/oragono/oragono/irc/utils"
|
||||
)
|
||||
|
||||
@ -32,10 +30,6 @@ func hostservEnabled(config *Config) bool {
|
||||
return config.Accounts.VHosts.Enabled
|
||||
}
|
||||
|
||||
func hostservRequestsEnabled(config *Config) bool {
|
||||
return config.Accounts.VHosts.Enabled && config.Accounts.VHosts.UserRequests.Enabled
|
||||
}
|
||||
|
||||
var (
|
||||
hostservCommands = map[string]*serviceCommand{
|
||||
"on": {
|
||||
@ -56,17 +50,6 @@ OFF disables your vhost, if you have one approved.`,
|
||||
authRequired: true,
|
||||
enabled: hostservEnabled,
|
||||
},
|
||||
"request": {
|
||||
handler: hsRequestHandler,
|
||||
help: `Syntax: $bREQUEST <vhost>$b
|
||||
|
||||
REQUEST requests that a new vhost by assigned to your account. The request must
|
||||
then be approved by a server operator.`,
|
||||
helpShort: `$bREQUEST$b requests a new vhost, pending operator approval.`,
|
||||
authRequired: true,
|
||||
enabled: hostservRequestsEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"status": {
|
||||
handler: hsStatusHandler,
|
||||
help: `Syntax: $bSTATUS [user]$b
|
||||
@ -96,39 +79,6 @@ DEL deletes a user's vhost.`,
|
||||
enabled: hostservEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"waiting": {
|
||||
handler: hsWaitingHandler,
|
||||
help: `Syntax: $bWAITING$b
|
||||
|
||||
WAITING shows a list of pending vhost requests, which can then be approved
|
||||
or rejected.`,
|
||||
helpShort: `$bWAITING$b shows a list of pending vhost requests.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
},
|
||||
"approve": {
|
||||
handler: hsApproveHandler,
|
||||
help: `Syntax: $bAPPROVE <user>$b
|
||||
|
||||
APPROVE approves a user's vhost request.`,
|
||||
helpShort: `$bAPPROVE$b approves a user's vhost request.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
minParams: 1,
|
||||
},
|
||||
"reject": {
|
||||
handler: hsRejectHandler,
|
||||
help: `Syntax: $bREJECT <user> [<reason>]$b
|
||||
|
||||
REJECT rejects a user's vhost request, optionally giving them a reason
|
||||
for the rejection.`,
|
||||
helpShort: `$bREJECT$b rejects a user's vhost request.`,
|
||||
capabs: []string{"vhosts"},
|
||||
enabled: hostservEnabled,
|
||||
minParams: 1,
|
||||
maxParams: 2,
|
||||
unsplitFinalParam: true,
|
||||
},
|
||||
"setcloaksecret": {
|
||||
handler: hsSetCloakSecretHandler,
|
||||
help: `Syntax: $bSETCLOAKSECRET$b <secret> [code]
|
||||
@ -150,19 +100,6 @@ func hsNotice(rb *ResponseBuffer, text string) {
|
||||
rb.Add(nil, hsNickMask, "NOTICE", rb.target.Nick(), text)
|
||||
}
|
||||
|
||||
// hsNotifyChannel notifies the designated channel of new vhost activity
|
||||
func hsNotifyChannel(server *Server, message string) {
|
||||
chname := server.Config().Accounts.VHosts.UserRequests.Channel
|
||||
channel := server.channels.Get(chname)
|
||||
if channel == nil {
|
||||
return
|
||||
}
|
||||
chname = channel.Name()
|
||||
for _, client := range channel.Members() {
|
||||
client.Send(nil, hsNickMask, "PRIVMSG", chname, message)
|
||||
}
|
||||
}
|
||||
|
||||
func hsOnOffHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
enable := false
|
||||
if command == "on" {
|
||||
@ -181,29 +118,6 @@ func hsOnOffHandler(server *Server, client *Client, command string, params []str
|
||||
}
|
||||
}
|
||||
|
||||
func hsRequestHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
vhost := params[0]
|
||||
if validateVhost(server, vhost, false) != nil {
|
||||
hsNotice(rb, client.t("Invalid vhost"))
|
||||
return
|
||||
}
|
||||
|
||||
accountName := client.Account()
|
||||
_, err := server.accounts.VHostRequest(accountName, vhost, time.Duration(server.Config().Accounts.VHosts.UserRequests.Cooldown))
|
||||
if err != nil {
|
||||
if throttled, ok := err.(*vhostThrottleExceeded); ok {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("You must wait an additional %v before making another request"), throttled.timeRemaining))
|
||||
} else {
|
||||
hsNotice(rb, client.t("An error occurred"))
|
||||
}
|
||||
} else {
|
||||
hsNotice(rb, client.t("Your vhost request will be reviewed by an administrator"))
|
||||
chanMsg := fmt.Sprintf("Account %s requests vhost %s", accountName, vhost)
|
||||
hsNotifyChannel(server, chanMsg)
|
||||
server.snomasks.Send(sno.LocalVhosts, chanMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func hsStatusHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
var accountName string
|
||||
if len(params) > 0 {
|
||||
@ -237,13 +151,6 @@ func hsStatusHandler(server *Server, client *Client, command string, params []st
|
||||
} else {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("Account %s has no vhost"), accountName))
|
||||
}
|
||||
if account.VHost.RequestedVHost != "" {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("A request is pending for vhost: %s"), account.VHost.RequestedVHost))
|
||||
}
|
||||
if account.VHost.RejectedVHost != "" {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("A request was previously made for vhost: %s"), account.VHost.RejectedVHost))
|
||||
hsNotice(rb, fmt.Sprintf(client.t("It was rejected for reason: %s"), account.VHost.RejectionReason))
|
||||
}
|
||||
}
|
||||
|
||||
func validateVhost(server *Server, vhost string, oper bool) error {
|
||||
@ -251,7 +158,7 @@ func validateVhost(server *Server, vhost string, oper bool) error {
|
||||
if len(vhost) > config.Accounts.VHosts.MaxLength {
|
||||
return errVHostTooLong
|
||||
}
|
||||
if !config.Accounts.VHosts.ValidRegexp.MatchString(vhost) {
|
||||
if !config.Accounts.VHosts.validRegexp.MatchString(vhost) {
|
||||
return errVHostBadCharacters
|
||||
}
|
||||
return nil
|
||||
@ -280,56 +187,6 @@ func hsSetHandler(server *Server, client *Client, command string, params []strin
|
||||
}
|
||||
}
|
||||
|
||||
func hsWaitingHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
requests, total := server.accounts.VHostListRequests(10)
|
||||
hsNotice(rb, fmt.Sprintf(client.t("There are %[1]d pending requests for vhosts (%[2]d displayed)"), total, len(requests)))
|
||||
for i, request := range requests {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("%[1]d. User %[2]s requests vhost: %[3]s"), i+1, request.Account, request.RequestedVHost))
|
||||
}
|
||||
}
|
||||
|
||||
func hsApproveHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
user := params[0]
|
||||
|
||||
vhostInfo, err := server.accounts.VHostApprove(user)
|
||||
if err != nil {
|
||||
hsNotice(rb, client.t("An error occurred"))
|
||||
} else {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("Successfully approved vhost request for %s"), user))
|
||||
chanMsg := fmt.Sprintf("Oper %[1]s approved vhost %[2]s for account %[3]s", client.Nick(), vhostInfo.ApprovedVHost, user)
|
||||
hsNotifyChannel(server, chanMsg)
|
||||
server.snomasks.Send(sno.LocalVhosts, chanMsg)
|
||||
for _, client := range server.accounts.AccountToClients(user) {
|
||||
client.Send(nil, hsNickMask, "NOTICE", client.Nick(), client.t("Your vhost request was approved by an administrator"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hsRejectHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
var reason string
|
||||
user := params[0]
|
||||
if len(params) > 1 {
|
||||
reason = params[1]
|
||||
}
|
||||
|
||||
vhostInfo, err := server.accounts.VHostReject(user, reason)
|
||||
if err != nil {
|
||||
hsNotice(rb, client.t("An error occurred"))
|
||||
} else {
|
||||
hsNotice(rb, fmt.Sprintf(client.t("Successfully rejected vhost request for %s"), user))
|
||||
chanMsg := fmt.Sprintf("Oper %s rejected vhost %s for account %s, with the reason: %v", client.Nick(), vhostInfo.RejectedVHost, user, reason)
|
||||
hsNotifyChannel(server, chanMsg)
|
||||
server.snomasks.Send(sno.LocalVhosts, chanMsg)
|
||||
for _, client := range server.accounts.AccountToClients(user) {
|
||||
if reason == "" {
|
||||
client.Send(nil, hsNickMask, "NOTICE", client.Nick(), client.t("Your vhost request was rejected by an administrator"))
|
||||
} else {
|
||||
client.Send(nil, hsNickMask, "NOTICE", client.Nick(), fmt.Sprintf(client.t("Your vhost request was rejected by an administrator. The reason given was: %s"), reason))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hsSetCloakSecretHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
|
||||
secret := params[0]
|
||||
expectedCode := utils.ConfirmationCode(secret, server.ctime)
|
||||
|
@ -69,8 +69,8 @@ func doImportDBGeneric(config *Config, dbImport databaseImport, credsType Creden
|
||||
// produce a hardcoded version of the database schema
|
||||
// XXX instead of referencing, e.g., keyAccountExists, we should write in the string literal
|
||||
// (to ensure that no matter what code changes happen elsewhere, we're still producing a
|
||||
// version 14 db)
|
||||
tx.Set(keySchemaVersion, "14", nil)
|
||||
// db of the hardcoded version)
|
||||
tx.Set(keySchemaVersion, "17", nil)
|
||||
tx.Set(keyCloakSecret, utils.GenerateSecretKey(), nil)
|
||||
|
||||
for username, userInfo := range dbImport.Users {
|
||||
|
@ -570,9 +570,6 @@ func (server *Server) applyConfig(config *Config) (err error) {
|
||||
if !oldConfig.Accounts.NickReservation.Enabled {
|
||||
server.accounts.buildNickToAccountIndex(config)
|
||||
}
|
||||
if !oldConfig.Accounts.VHosts.Enabled {
|
||||
server.accounts.initVHostRequestQueue(config)
|
||||
}
|
||||
if !oldConfig.Channels.Registration.Enabled {
|
||||
server.channels.loadRegisteredChannels(config)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user