mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-22 18:52:41 +01:00
Merge pull request #274 from slingamn/chanunreg.1
add CHANSERV UNREGISTER
This commit is contained in:
commit
f4a284675d
@ -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()
|
||||
|
@ -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) {
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user