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
}
// 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.
func (channel *Channel) IsRegistered() bool {
channel.stateMutex.RLock()

View File

@ -201,6 +201,20 @@ func (reg *ChannelRegistry) LoadChannel(nameCasefolded string) (info *Registered
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
// persisted under its new name, and the old name is cleaned up if necessary.
func (reg *ChannelRegistry) Rename(channel *Channel, casefoldedOldName string) {

View File

@ -4,8 +4,11 @@
package irc
import (
"bytes"
"fmt"
"hash/crc32"
"sort"
"strconv"
"strings"
"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:
%s`
func chanregEnabled(server *Server) bool {
return server.ChannelRegistrationEnabled()
}
var (
chanservCommands = map[string]*serviceCommand{
"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.`,
helpShort: `$bOP$b makes the given user (or yourself) a channel admin.`,
authRequired: true,
enabled: chanregEnabled,
},
"register": {
handler: csRegisterHandler,
@ -42,6 +50,17 @@ given admin privs on it. Modes set on the channel and the topic will also be
remembered.`,
helpShort: `$bREGISTER$b lets you own a given channel.`,
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": {
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
referenced by their registered account names, not their nicknames.`,
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) {
if !server.channelRegistrationEnabled {
csNotice(rb, client.t("Channel registration is not enabled"))
return
}
channelName := strings.TrimSpace(params)
if channelName == "" {
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 {
server.configurableStateMutex.RLock()
defer server.configurableStateMutex.RUnlock()
return server.channelRegistrationEnabled
return server.config.Channels.Registration.Enabled
}
func (server *Server) AccountConfig() *AccountConfig {

View File

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