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

@ -89,7 +89,6 @@ type ListenerWrapper struct {
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
@ -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()