3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-12-23 03:02:48 +01:00

Merge pull request #274 from slingamn/chanunreg.1

add CHANSERV UNREGISTER
This commit is contained in:
Daniel Oaks 2018-06-05 19:34:12 +10:00 committed by GitHub
commit f4a284675d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 54 deletions

View File

@ -157,6 +157,17 @@ func (channel *Channel) SetRegistered(founder string) error {
return nil return nil
} }
// SetUnregistered deletes the channel's registration information.
func (channel *Channel) SetUnregistered() {
channel.stateMutex.Lock()
defer channel.stateMutex.Unlock()
channel.registeredFounder = ""
var zeroTime time.Time
channel.registeredTime = zeroTime
channel.accountToUMode = make(map[string]modes.Mode)
}
// IsRegistered returns whether the channel is registered. // IsRegistered returns whether the channel is registered.
func (channel *Channel) IsRegistered() bool { func (channel *Channel) IsRegistered() bool {
channel.stateMutex.RLock() channel.stateMutex.RLock()

View File

@ -201,6 +201,20 @@ func (reg *ChannelRegistry) LoadChannel(nameCasefolded string) (info *Registered
return info return info
} }
func (reg *ChannelRegistry) Delete(casefoldedName string, info RegisteredChannel) {
if !reg.server.ChannelRegistrationEnabled() {
return
}
reg.Lock()
defer reg.Unlock()
reg.server.store.Update(func(tx *buntdb.Tx) error {
reg.deleteChannel(tx, casefoldedName, info)
return nil
})
}
// Rename handles the persistence part of a channel rename: the channel is // Rename handles the persistence part of a channel rename: the channel is
// persisted under its new name, and the old name is cleaned up if necessary. // persisted under its new name, and the old name is cleaned up if necessary.
func (reg *ChannelRegistry) Rename(channel *Channel, casefoldedOldName string) { func (reg *ChannelRegistry) Rename(channel *Channel, casefoldedOldName string) {

View File

@ -4,8 +4,11 @@
package irc package irc
import ( import (
"bytes"
"fmt" "fmt"
"hash/crc32"
"sort" "sort"
"strconv"
"strings" "strings"
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
@ -22,6 +25,10 @@ To see in-depth help for a specific ChanServ command, try:
Here are the commands you can use: Here are the commands you can use:
%s` %s`
func chanregEnabled(server *Server) bool {
return server.ChannelRegistrationEnabled()
}
var ( var (
chanservCommands = map[string]*serviceCommand{ chanservCommands = map[string]*serviceCommand{
"op": { "op": {
@ -32,6 +39,7 @@ OP makes the given nickname, or yourself, a channel admin. You can only use
this command if you're the founder of the channel.`, this command if you're the founder of the channel.`,
helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`, helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`,
authRequired: true, authRequired: true,
enabled: chanregEnabled,
}, },
"register": { "register": {
handler: csRegisterHandler, handler: csRegisterHandler,
@ -42,6 +50,17 @@ given admin privs on it. Modes set on the channel and the topic will also be
remembered.`, remembered.`,
helpShort: `$bREGISTER$b lets you own a given channel.`, helpShort: `$bREGISTER$b lets you own a given channel.`,
authRequired: true, authRequired: true,
enabled: chanregEnabled,
},
"unregister": {
handler: csUnregisterHandler,
help: `Syntax: $bUNREGISTER #channel [code]$b
UNREGISTER deletes a channel registration, allowing someone else to claim it.
To prevent accidental unregistrations, a verification code is required;
invoking the command without a code will display the necessary code.`,
helpShort: `$bUNREGISTER$b deletes a channel registration.`,
enabled: chanregEnabled,
}, },
"amode": { "amode": {
handler: csAmodeHandler, handler: csAmodeHandler,
@ -53,6 +72,7 @@ account the +o operator mode every time they join #channel. To list current
accounts and modes, use $bAMODE #channel$b. Note that users are always accounts and modes, use $bAMODE #channel$b. Note that users are always
referenced by their registered account names, not their nicknames.`, referenced by their registered account names, not their nicknames.`,
helpShort: `$bAMODE$b modifies persistent mode settings for channel members.`, helpShort: `$bAMODE$b modifies persistent mode settings for channel members.`,
enabled: chanregEnabled,
}, },
} }
) )
@ -197,11 +217,6 @@ func csOpHandler(server *Server, client *Client, command, params string, rb *Res
} }
func csRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) { func csRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
if !server.channelRegistrationEnabled {
csNotice(rb, client.t("Channel registration is not enabled"))
return
}
channelName := strings.TrimSpace(params) channelName := strings.TrimSpace(params)
if channelName == "" { if channelName == "" {
csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bREGISTER #channel$b"))) csNotice(rb, ircfmt.Unescape(client.t("Syntax: $bREGISTER #channel$b")))
@ -246,3 +261,45 @@ func csRegisterHandler(server *Server, client *Client, command, params string, r
} }
} }
} }
func csUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
channelName, verificationCode := utils.ExtractParam(params)
channelKey, err := CasefoldChannel(channelName)
if channelKey == "" || err != nil {
csNotice(rb, client.t("Channel name is not valid"))
return
}
channel := server.channels.Get(channelKey)
if channel == nil {
csNotice(rb, client.t("No such channel"))
return
}
hasPrivs := client.HasRoleCapabs("chanreg")
if !hasPrivs {
founder := channel.Founder()
hasPrivs = founder != "" && founder == client.Account()
}
if !hasPrivs {
csNotice(rb, client.t("Insufficient privileges"))
return
}
info := channel.ExportRegistration(0)
// verification code is the crc32 of the name, plus the registration time
var codeInput bytes.Buffer
codeInput.WriteString(info.Name)
codeInput.WriteString(strconv.FormatInt(info.RegisteredAt.Unix(), 16))
expectedCode := int(crc32.ChecksumIEEE(codeInput.Bytes()))
receivedCode, err := strconv.Atoi(verificationCode)
if err != nil || expectedCode != receivedCode {
csNotice(rb, client.t("$bWarning:$b Unregistering this channel will remove all stored channel attributes."))
csNotice(rb, fmt.Sprintf(client.t("To confirm channel unregistration, type: /CS UNREGISTER %s %d"), channelKey, expectedCode))
return
}
channel.SetUnregistered()
go server.channelRegistry.Delete(channelKey, info)
csNotice(rb, fmt.Sprintf(client.t("Channel %s is now unregistered"), channelKey))
}

View File

@ -62,7 +62,7 @@ func (server *Server) DefaultChannelModes() modes.Modes {
func (server *Server) ChannelRegistrationEnabled() bool { func (server *Server) ChannelRegistrationEnabled() bool {
server.configurableStateMutex.RLock() server.configurableStateMutex.RLock()
defer server.configurableStateMutex.RUnlock() defer server.configurableStateMutex.RUnlock()
return server.channelRegistrationEnabled return server.config.Channels.Registration.Enabled
} }
func (server *Server) AccountConfig() *AccountConfig { func (server *Server) AccountConfig() *AccountConfig {

View File

@ -87,51 +87,50 @@ type ListenerWrapper struct {
// Server is the main Oragono server. // Server is the main Oragono server.
type Server struct { type Server struct {
accounts *AccountManager accounts *AccountManager
batches *BatchManager batches *BatchManager
channelRegistrationEnabled bool channels *ChannelManager
channels *ChannelManager channelRegistry *ChannelRegistry
channelRegistry *ChannelRegistry checkIdent bool
checkIdent bool clients *ClientManager
clients *ClientManager config *Config
config *Config configFilename string
configFilename string configurableStateMutex sync.RWMutex // tier 1; generic protection for server state modified by rehash()
configurableStateMutex sync.RWMutex // tier 1; generic protection for server state modified by rehash() connectionLimiter *connection_limits.Limiter
connectionLimiter *connection_limits.Limiter connectionThrottler *connection_limits.Throttler
connectionThrottler *connection_limits.Throttler ctime time.Time
ctime time.Time defaultChannelModes modes.Modes
defaultChannelModes modes.Modes dlines *DLineManager
dlines *DLineManager loggingRawIO bool
loggingRawIO bool isupport *isupport.List
isupport *isupport.List klines *KLineManager
klines *KLineManager languages *languages.Manager
languages *languages.Manager limits Limits
limits Limits listeners map[string]*ListenerWrapper
listeners map[string]*ListenerWrapper logger *logger.Manager
logger *logger.Manager maxSendQBytes uint32
maxSendQBytes uint32 monitorManager *MonitorManager
monitorManager *MonitorManager motdLines []string
motdLines []string name string
name string nameCasefolded string
nameCasefolded string networkName string
networkName string operators map[string]*Oper
operators map[string]*Oper operclasses map[string]*OperClass
operclasses map[string]*OperClass password []byte
password []byte passwords *passwd.SaltedManager
passwords *passwd.SaltedManager recoverFromErrors bool
recoverFromErrors bool rehashMutex sync.Mutex // tier 4
rehashMutex sync.Mutex // tier 4 rehashSignal chan os.Signal
rehashSignal chan os.Signal pprofServer *http.Server
pprofServer *http.Server proxyAllowedFrom []string
proxyAllowedFrom []string signals chan os.Signal
signals chan os.Signal snomasks *SnoManager
snomasks *SnoManager store *buntdb.DB
store *buntdb.DB stsEnabled bool
stsEnabled bool webirc []webircConfig
webirc []webircConfig whoWas *WhoWasList
whoWas *WhoWasList stats *Stats
stats *Stats semaphores *ServerSemaphores
semaphores *ServerSemaphores
} }
var ( var (
@ -955,9 +954,6 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
server.operators = opers server.operators = opers
server.checkIdent = config.Server.CheckIdent server.checkIdent = config.Server.CheckIdent
// registration
server.channelRegistrationEnabled = config.Channels.Registration.Enabled
server.defaultChannelModes = ParseDefaultChannelModes(config) server.defaultChannelModes = ParseDefaultChannelModes(config)
server.configurableStateMutex.Unlock() server.configurableStateMutex.Unlock()