mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
Refactor nickserv.go to better support NS HELP and translations
This commit is contained in:
parent
a39c46d470
commit
7b8c4e7e91
548
irc/nickserv.go
548
irc/nickserv.go
@ -5,51 +5,124 @@ package irc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goshuirc/irc-go/ircfmt"
|
||||||
|
|
||||||
|
"github.com/oragono/oragono/irc/modes"
|
||||||
|
"github.com/oragono/oragono/irc/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: "email" is an oversimplification here; it's actually any callback, e.g.,
|
// TODO: "email" is an oversimplification here; it's actually any callback, e.g.,
|
||||||
// person@example.com, mailto:person@example.com, tel:16505551234.
|
// person@example.com, mailto:person@example.com, tel:16505551234.
|
||||||
const nickservHelp = `NickServ lets you register and log into a user account.
|
const nickservHelp = `NickServ lets you register and login to an account.
|
||||||
|
|
||||||
To register an account:
|
To see in-depth help for a specific NickServ command, try:
|
||||||
/NS REGISTER username email [password]
|
$b/NS HELP <command>$b
|
||||||
Leave out [password] if you're registering using your client certificate fingerprint.
|
|
||||||
The server may or may not allow you to register anonymously (by sending * as your
|
|
||||||
email address).
|
|
||||||
|
|
||||||
To verify an account (if you were sent a verification code):
|
Here are the commands you can use:
|
||||||
/NS VERIFY username code
|
%s`
|
||||||
|
|
||||||
To unregister an account:
|
type nsCommand struct {
|
||||||
/NS UNREGISTER [username]
|
capabs []string // oper capabs the given user has to have to access this command
|
||||||
Leave out [username] if you're unregistering the user you're currently logged in as.
|
handler func(server *Server, client *Client, command, params string, rb *ResponseBuffer)
|
||||||
|
help string
|
||||||
|
helpShort string
|
||||||
|
nickReservation bool // nick reservation must be enabled to use this command
|
||||||
|
oper bool // true if the user has to be an oper to use this command
|
||||||
|
}
|
||||||
|
|
||||||
To login to an account:
|
var (
|
||||||
/NS IDENTIFY [username password]
|
nickservCommands = map[string]*nsCommand{
|
||||||
Leave out [username password] to use your client certificate fingerprint. Otherwise,
|
"drop": {
|
||||||
the given username and password will be used.
|
handler: nsDropHandler,
|
||||||
|
help: `Syntax: $bDROP [nickname]$b
|
||||||
|
|
||||||
To see account information:
|
DROP de-links the given (or your current) nickname from your user account.`,
|
||||||
/NS INFO [username]
|
helpShort: `$bDROP$b de-links your current (or the given) nickname from your user account.`,
|
||||||
Leave out [username] to see your own account information.
|
nickReservation: true,
|
||||||
|
},
|
||||||
|
"ghost": {
|
||||||
|
handler: nsGhostHandler,
|
||||||
|
help: `Syntax: $bGHOST <nickname>$b
|
||||||
|
|
||||||
To associate your current nick with the account you're logged into:
|
GHOST disconnects the given user from the network if they're logged in with the
|
||||||
/NS GROUP
|
same user account, letting you reclaim your nickname.`,
|
||||||
|
helpShort: `$bGHOST$b reclaims your nickname.`,
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
handler: nsGroupHandler,
|
||||||
|
help: `Syntax: $bGROUP$b
|
||||||
|
|
||||||
To disassociate a nick with the account you're logged into:
|
GROUP links your current nickname with your logged-in account, preventing other
|
||||||
/NS DROP [nickname]
|
users from changing to it (or forcing them to rename).`,
|
||||||
Leave out [nickname] to drop your association with your current nickname.`
|
helpShort: `$bGROUP$b links your current nickname to your user account.`,
|
||||||
|
nickReservation: true,
|
||||||
|
},
|
||||||
|
"help": {
|
||||||
|
help: `Syntax: $bHELP [command]$b
|
||||||
|
|
||||||
// extractParam extracts a parameter from the given string, returning the param and the rest of the string.
|
HELP returns information on the given command.`,
|
||||||
func extractParam(line string) (string, string) {
|
helpShort: `$bHELP$b shows in-depth information about commands.`,
|
||||||
rawParams := strings.SplitN(strings.TrimSpace(line), " ", 2)
|
},
|
||||||
param0 := rawParams[0]
|
"identify": {
|
||||||
var param1 string
|
handler: nsIdentifyHandler,
|
||||||
if 1 < len(rawParams) {
|
help: `Syntax: $bIDENTIFY <username> [password]$b
|
||||||
param1 = strings.TrimSpace(rawParams[1])
|
|
||||||
|
IDENTIFY lets you login to the given username using either password auth, or
|
||||||
|
certfp (your client certificate) if a password is not given.`,
|
||||||
|
helpShort: `$bIDENTIFY$b lets you login to your account.`,
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
handler: nsInfoHandler,
|
||||||
|
help: `Syntax: $bINFO [username]$b
|
||||||
|
|
||||||
|
INFO gives you information about the given (or your own) user account.`,
|
||||||
|
helpShort: `$bINFO$b gives you information on a user account.`,
|
||||||
|
},
|
||||||
|
"register": {
|
||||||
|
handler: nsRegisterHandler,
|
||||||
|
help: `Syntax: $bREGISTER <username> <email> [password]$b
|
||||||
|
|
||||||
|
REGISTER lets you register a user account. If the server allows anonymous
|
||||||
|
registration, you can send an asterisk (*) as the email address.
|
||||||
|
|
||||||
|
If the password is left out, your account will be registered to your TLS client
|
||||||
|
certificate (and you will need to use that certificate to login in future).`,
|
||||||
|
helpShort: `$bREGISTER$b lets you register a user account.`,
|
||||||
|
},
|
||||||
|
"sadrop": {
|
||||||
|
handler: nsDropHandler,
|
||||||
|
help: `Syntax: $bSADROP <nickname>$b
|
||||||
|
|
||||||
|
SADROP foribly de-links the given nickname from the attached user account.`,
|
||||||
|
helpShort: `$bSADROP$b forcibly de-links the given nickname from its user account.`,
|
||||||
|
nickReservation: true,
|
||||||
|
capabs: []string{"unregister"},
|
||||||
|
},
|
||||||
|
"unregister": {
|
||||||
|
handler: nsUnregisterHandler,
|
||||||
|
help: `Syntax: $bUNREGISTER [username]$b
|
||||||
|
|
||||||
|
UNREGISTER lets you delete your user account (or the given one, if you're an
|
||||||
|
IRC operator with the correct permissions).`,
|
||||||
|
helpShort: `$bUNREGISTER$b lets you delete your user account.`,
|
||||||
|
},
|
||||||
|
"verify": {
|
||||||
|
handler: nsVerifyHandler,
|
||||||
|
help: `Syntax: $bVERIFY <username> <code>$b
|
||||||
|
|
||||||
|
VERIFY lets you complete an account registration, if the server requires email
|
||||||
|
or other verification.`,
|
||||||
|
helpShort: `$bVERIFY$b lets you complete account registration.`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return param0, param1
|
)
|
||||||
|
|
||||||
|
// send a notice from the NickServ "nick"
|
||||||
|
func nsNotice(rb *ResponseBuffer, text string) {
|
||||||
|
rb.Add(nil, "NickServ", "NOTICE", rb.target.Nick(), text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nickservNoticeHandler handles NOTICEs that NickServ receives.
|
// nickservNoticeHandler handles NOTICEs that NickServ receives.
|
||||||
@ -57,109 +130,217 @@ func (server *Server) nickservNoticeHandler(client *Client, message string, rb *
|
|||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a notice from the NickServ "nick"
|
|
||||||
func nsNotice(rb *ResponseBuffer, text string) {
|
|
||||||
rb.Add(nil, "NickServ", "NOTICE", rb.target.Nick(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// nickservPrivmsgHandler handles PRIVMSGs that NickServ receives.
|
// nickservPrivmsgHandler handles PRIVMSGs that NickServ receives.
|
||||||
func (server *Server) nickservPrivmsgHandler(client *Client, message string, rb *ResponseBuffer) {
|
func (server *Server) nickservPrivmsgHandler(client *Client, message string, rb *ResponseBuffer) {
|
||||||
command, params := extractParam(message)
|
commandName, params := utils.ExtractParam(message)
|
||||||
command = strings.ToLower(command)
|
commandName = strings.ToLower(commandName)
|
||||||
|
|
||||||
if command == "help" {
|
commandInfo := nickservCommands[commandName]
|
||||||
for _, line := range strings.Split(nickservHelp, "\n") {
|
if commandInfo == nil {
|
||||||
nsNotice(rb, line)
|
nsNotice(rb, client.t("Unknown command. To see available commands, run /NS HELP"))
|
||||||
}
|
return
|
||||||
} else if command == "register" {
|
|
||||||
// get params
|
|
||||||
username, afterUsername := extractParam(params)
|
|
||||||
email, passphrase := extractParam(afterUsername)
|
|
||||||
server.nickservRegisterHandler(client, username, email, passphrase, rb)
|
|
||||||
} else if command == "verify" {
|
|
||||||
username, code := extractParam(params)
|
|
||||||
server.nickservVerifyHandler(client, username, code, rb)
|
|
||||||
} else if command == "identify" {
|
|
||||||
username, passphrase := extractParam(params)
|
|
||||||
server.nickservIdentifyHandler(client, username, passphrase, rb)
|
|
||||||
} else if command == "unregister" {
|
|
||||||
username, _ := extractParam(params)
|
|
||||||
server.nickservUnregisterHandler(client, username, rb)
|
|
||||||
} else if command == "ghost" {
|
|
||||||
nick, _ := extractParam(params)
|
|
||||||
server.nickservGhostHandler(client, nick, rb)
|
|
||||||
} else if command == "info" {
|
|
||||||
nick, _ := extractParam(params)
|
|
||||||
server.nickservInfoHandler(client, nick, rb)
|
|
||||||
} else if command == "group" {
|
|
||||||
server.nickservGroupHandler(client, rb)
|
|
||||||
} else if command == "drop" {
|
|
||||||
nick, _ := extractParam(params)
|
|
||||||
server.nickservDropHandler(client, nick, false, rb)
|
|
||||||
} else if command == "sadrop" {
|
|
||||||
nick, _ := extractParam(params)
|
|
||||||
server.nickservDropHandler(client, nick, true, rb)
|
|
||||||
} else {
|
|
||||||
nsNotice(rb, client.t("Command not recognised. To see the available commands, run /NS HELP"))
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) nickservUnregisterHandler(client *Client, username string, rb *ResponseBuffer) {
|
if commandInfo.oper && !client.HasMode(modes.Operator) {
|
||||||
if !server.AccountConfig().Registration.Enabled {
|
nsNotice(rb, client.t("Command restricted"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 < len(commandInfo.capabs) && !client.HasRoleCapabs(commandInfo.capabs...) {
|
||||||
|
nsNotice(rb, client.t("Command restricted"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if commandInfo.nickReservation && !server.AccountConfig().Registration.Enabled {
|
||||||
nsNotice(rb, client.t("Account registration has been disabled"))
|
nsNotice(rb, client.t("Account registration has been disabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if username == "" {
|
// custom help handling here to prevent recursive init loop
|
||||||
username = client.Account()
|
if commandName == "help" {
|
||||||
|
nsHelpHandler(server, client, commandName, params, rb)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if username == "" {
|
|
||||||
|
if commandInfo.handler == nil {
|
||||||
|
nsNotice(rb, client.t("Command error. Please report this to the developers"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
commandInfo.handler(server, client, commandName, params, rb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsDropHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
|
sadrop := command == "sadrop"
|
||||||
|
nick, _ := utils.ExtractParam(params)
|
||||||
|
|
||||||
|
err := server.accounts.SetNickReserved(client, nick, sadrop, false)
|
||||||
|
if err == nil {
|
||||||
|
nsNotice(rb, fmt.Sprintf(client.t("Successfully ungrouped nick %s with your account"), nick))
|
||||||
|
} else if err == errAccountNotLoggedIn {
|
||||||
|
nsNotice(rb, client.t("You're not logged into an account"))
|
||||||
|
} else if err == errAccountCantDropPrimaryNick {
|
||||||
|
nsNotice(rb, client.t("You can't ungroup your primary nickname (try unregistering your account instead)"))
|
||||||
|
} else if err == errNicknameReserved {
|
||||||
|
nsNotice(rb, client.t("That nickname is already reserved by someone else"))
|
||||||
|
} else {
|
||||||
|
nsNotice(rb, client.t("Could not ungroup nick"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsGhostHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
|
nick, _ := utils.ExtractParam(params)
|
||||||
|
|
||||||
|
account := client.Account()
|
||||||
|
if account == "" || server.accounts.NickToAccount(nick) != account {
|
||||||
|
nsNotice(rb, client.t("You don't own that nick"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ghost := server.clients.Get(nick)
|
||||||
|
if ghost == nil {
|
||||||
|
nsNotice(rb, client.t("No such nick"))
|
||||||
|
return
|
||||||
|
} else if ghost == client {
|
||||||
|
nsNotice(rb, client.t("You can't GHOST yourself (try /QUIT instead)"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ghost.Quit(fmt.Sprintf(ghost.t("GHOSTed by %s"), client.Nick()))
|
||||||
|
ghost.destroy(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsGroupHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
|
account := client.Account()
|
||||||
|
if account == "" {
|
||||||
nsNotice(rb, client.t("You're not logged into an account"))
|
nsNotice(rb, client.t("You're not logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cfname, err := CasefoldName(username)
|
|
||||||
if err != nil {
|
|
||||||
nsNotice(rb, client.t("Invalid username"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !(cfname == client.Account() || client.HasRoleCapabs("unregister")) {
|
|
||||||
nsNotice(rb, client.t("Insufficient oper privs"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfname == client.Account() {
|
nick := client.NickCasefolded()
|
||||||
client.server.accounts.Logout(client)
|
err := server.accounts.SetNickReserved(client, nick, false, true)
|
||||||
}
|
if err == nil {
|
||||||
|
nsNotice(rb, fmt.Sprintf(client.t("Successfully grouped nick %s with your account"), nick))
|
||||||
err = server.accounts.Unregister(cfname)
|
} else if err == errAccountTooManyNicks {
|
||||||
if err == errAccountDoesNotExist {
|
nsNotice(rb, client.t("You have too many nicks reserved already (you can remove some with /NS DROP)"))
|
||||||
nsNotice(rb, client.t(err.Error()))
|
} else if err == errNicknameReserved {
|
||||||
} else if err != nil {
|
nsNotice(rb, client.t("That nickname is already reserved by someone else"))
|
||||||
nsNotice(rb, client.t("Error while unregistering account"))
|
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully unregistered account %s"), cfname))
|
nsNotice(rb, client.t("Error reserving nickname"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) nickservVerifyHandler(client *Client, username string, code string, rb *ResponseBuffer) {
|
func nsHelpHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
err := server.accounts.Verify(client, username, code)
|
nsNotice(rb, ircfmt.Unescape(client.t("*** $bNickServ HELP$b ***")))
|
||||||
|
|
||||||
var errorMessage string
|
if params == "" {
|
||||||
if err == errAccountVerificationInvalidCode || err == errAccountAlreadyVerified {
|
// show general help
|
||||||
errorMessage = err.Error()
|
var shownHelpLines sort.StringSlice
|
||||||
} else if err != nil {
|
for _, commandInfo := range nickservCommands {
|
||||||
errorMessage = errAccountVerificationFailed.Error()
|
// skip commands user can't access
|
||||||
|
if commandInfo.oper && !client.HasMode(modes.Operator) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if 0 < len(commandInfo.capabs) && !client.HasRoleCapabs(commandInfo.capabs...) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if commandInfo.nickReservation && !server.AccountConfig().Registration.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
shownHelpLines = append(shownHelpLines, " "+client.t(commandInfo.helpShort))
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort help lines
|
||||||
|
sort.Sort(shownHelpLines)
|
||||||
|
|
||||||
|
// assemble help text
|
||||||
|
assembledHelpLines := strings.Join(shownHelpLines, "\n")
|
||||||
|
fullHelp := ircfmt.Unescape(fmt.Sprintf(client.t(nickservHelp), assembledHelpLines))
|
||||||
|
|
||||||
|
// push out help text
|
||||||
|
for _, line := range strings.Split(fullHelp, "\n") {
|
||||||
|
nsNotice(rb, line)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commandInfo := nickservCommands[strings.ToLower(strings.TrimSpace(params))]
|
||||||
|
if commandInfo == nil {
|
||||||
|
nsNotice(rb, client.t("Unknown command. To see available commands, run /NS HELP"))
|
||||||
|
} else {
|
||||||
|
for _, line := range strings.Split(ircfmt.Unescape(client.t(commandInfo.help)), "\n") {
|
||||||
|
nsNotice(rb, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if errorMessage != "" {
|
nsNotice(rb, ircfmt.Unescape(client.t("*** $bEnd of NickServ HELP$b ***")))
|
||||||
nsNotice(rb, client.t(errorMessage))
|
}
|
||||||
|
|
||||||
|
func nsIdentifyHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
|
// fail out if we need to
|
||||||
|
if !server.AccountConfig().AuthenticationEnabled {
|
||||||
|
nsNotice(rb, client.t("Login has been disabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSuccessfulRegResponse(client, rb, true)
|
loginSuccessful := false
|
||||||
|
|
||||||
|
username, passphrase := utils.ExtractParam(params)
|
||||||
|
|
||||||
|
// try passphrase
|
||||||
|
if username != "" && passphrase != "" {
|
||||||
|
err := server.accounts.AuthenticateByPassphrase(client, username, passphrase)
|
||||||
|
loginSuccessful = (err == nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// try certfp
|
||||||
|
if !loginSuccessful && client.certfp != "" {
|
||||||
|
err := server.accounts.AuthenticateByCertFP(client)
|
||||||
|
loginSuccessful = (err == nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if loginSuccessful {
|
||||||
|
sendSuccessfulSaslAuth(client, rb, true)
|
||||||
|
} else {
|
||||||
|
nsNotice(rb, client.t("Could not login with your TLS certificate or supplied username/password"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) nickservRegisterHandler(client *Client, username, email, passphrase string, rb *ResponseBuffer) {
|
func nsInfoHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
|
nick, _ := utils.ExtractParam(params)
|
||||||
|
|
||||||
|
if nick == "" {
|
||||||
|
nick = client.Nick()
|
||||||
|
}
|
||||||
|
|
||||||
|
accountName := nick
|
||||||
|
if server.AccountConfig().NickReservation.Enabled {
|
||||||
|
accountName = server.accounts.NickToAccount(nick)
|
||||||
|
if accountName == "" {
|
||||||
|
nsNotice(rb, client.t("That nickname is not registered"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := server.accounts.LoadAccount(accountName)
|
||||||
|
if err != nil || !account.Verified {
|
||||||
|
nsNotice(rb, client.t("Account does not exist"))
|
||||||
|
}
|
||||||
|
|
||||||
|
nsNotice(rb, fmt.Sprintf(client.t("Account: %s"), account.Name))
|
||||||
|
registeredAt := account.RegisteredAt.Format("Jan 02, 2006 15:04:05Z")
|
||||||
|
nsNotice(rb, fmt.Sprintf(client.t("Registered at: %s"), registeredAt))
|
||||||
|
// TODO nicer formatting for this
|
||||||
|
for _, nick := range account.AdditionalNicks {
|
||||||
|
nsNotice(rb, fmt.Sprintf(client.t("Additional grouped nick: %s"), nick))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsRegisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
|
// get params
|
||||||
|
username, afterUsername := utils.ExtractParam(params)
|
||||||
|
email, passphrase := utils.ExtractParam(afterUsername)
|
||||||
|
|
||||||
if !server.AccountConfig().Registration.Enabled {
|
if !server.AccountConfig().Registration.Enabled {
|
||||||
nsNotice(rb, client.t("Account registration has been disabled"))
|
nsNotice(rb, client.t("Account registration has been disabled"))
|
||||||
return
|
return
|
||||||
@ -236,130 +417,61 @@ func (server *Server) nickservRegisterHandler(client *Client, username, email, p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) nickservIdentifyHandler(client *Client, username, passphrase string, rb *ResponseBuffer) {
|
func nsUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
// fail out if we need to
|
username, _ := utils.ExtractParam(params)
|
||||||
if !server.AccountConfig().AuthenticationEnabled {
|
|
||||||
nsNotice(rb, client.t("Login has been disabled"))
|
if !server.AccountConfig().Registration.Enabled {
|
||||||
|
nsNotice(rb, client.t("Account registration has been disabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loginSuccessful := false
|
if username == "" {
|
||||||
|
username = client.Account()
|
||||||
// try passphrase
|
|
||||||
if username != "" && passphrase != "" {
|
|
||||||
err := server.accounts.AuthenticateByPassphrase(client, username, passphrase)
|
|
||||||
loginSuccessful = (err == nil)
|
|
||||||
}
|
}
|
||||||
|
if username == "" {
|
||||||
// try certfp
|
|
||||||
if !loginSuccessful && client.certfp != "" {
|
|
||||||
err := server.accounts.AuthenticateByCertFP(client)
|
|
||||||
loginSuccessful = (err == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if loginSuccessful {
|
|
||||||
sendSuccessfulSaslAuth(client, rb, true)
|
|
||||||
} else {
|
|
||||||
nsNotice(rb, client.t("Could not login with your TLS certificate or supplied username/password"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) nickservGhostHandler(client *Client, nick string, rb *ResponseBuffer) {
|
|
||||||
if !server.AccountConfig().NickReservation.Enabled {
|
|
||||||
nsNotice(rb, client.t("Nickname reservation is disabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
account := client.Account()
|
|
||||||
if account == "" || server.accounts.NickToAccount(nick) != account {
|
|
||||||
nsNotice(rb, client.t("You don't own that nick"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ghost := server.clients.Get(nick)
|
|
||||||
if ghost == nil {
|
|
||||||
nsNotice(rb, client.t("No such nick"))
|
|
||||||
return
|
|
||||||
} else if ghost == client {
|
|
||||||
nsNotice(rb, client.t("You can't GHOST yourself (try /QUIT instead)"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ghost.Quit(fmt.Sprintf(ghost.t("GHOSTed by %s"), client.Nick()))
|
|
||||||
ghost.destroy(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) nickservGroupHandler(client *Client, rb *ResponseBuffer) {
|
|
||||||
if !server.AccountConfig().NickReservation.Enabled {
|
|
||||||
nsNotice(rb, client.t("Nickname reservation is disabled"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
account := client.Account()
|
|
||||||
if account == "" {
|
|
||||||
nsNotice(rb, client.t("You're not logged into an account"))
|
nsNotice(rb, client.t("You're not logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cfname, err := CasefoldName(username)
|
||||||
|
if err != nil {
|
||||||
|
nsNotice(rb, client.t("Invalid username"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !(cfname == client.Account() || client.HasRoleCapabs("unregister")) {
|
||||||
|
nsNotice(rb, client.t("Insufficient oper privs"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
nick := client.NickCasefolded()
|
if cfname == client.Account() {
|
||||||
err := server.accounts.SetNickReserved(client, nick, false, true)
|
client.server.accounts.Logout(client)
|
||||||
if err == nil {
|
}
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully grouped nick %s with your account"), nick))
|
|
||||||
} else if err == errAccountTooManyNicks {
|
err = server.accounts.Unregister(cfname)
|
||||||
nsNotice(rb, client.t("You have too many nicks reserved already (you can remove some with /NS DROP)"))
|
if err == errAccountDoesNotExist {
|
||||||
} else if err == errNicknameReserved {
|
nsNotice(rb, client.t(err.Error()))
|
||||||
nsNotice(rb, client.t("That nickname is already reserved by someone else"))
|
} else if err != nil {
|
||||||
|
nsNotice(rb, client.t("Error while unregistering account"))
|
||||||
} else {
|
} else {
|
||||||
nsNotice(rb, client.t("Error reserving nickname"))
|
nsNotice(rb, fmt.Sprintf(client.t("Successfully unregistered account %s"), cfname))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) nickservInfoHandler(client *Client, nick string, rb *ResponseBuffer) {
|
func nsVerifyHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
|
||||||
if nick == "" {
|
username, code := utils.ExtractParam(params)
|
||||||
nick = client.Nick()
|
|
||||||
|
err := server.accounts.Verify(client, username, code)
|
||||||
|
|
||||||
|
var errorMessage string
|
||||||
|
if err == errAccountVerificationInvalidCode || err == errAccountAlreadyVerified {
|
||||||
|
errorMessage = err.Error()
|
||||||
|
} else if err != nil {
|
||||||
|
errorMessage = errAccountVerificationFailed.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
accountName := nick
|
if errorMessage != "" {
|
||||||
if server.AccountConfig().NickReservation.Enabled {
|
nsNotice(rb, client.t(errorMessage))
|
||||||
accountName = server.accounts.NickToAccount(nick)
|
return
|
||||||
if accountName == "" {
|
|
||||||
nsNotice(rb, client.t("That nickname is not registered"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
account, err := server.accounts.LoadAccount(accountName)
|
sendSuccessfulRegResponse(client, rb, true)
|
||||||
if err != nil || !account.Verified {
|
|
||||||
nsNotice(rb, client.t("Account does not exist"))
|
|
||||||
}
|
|
||||||
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Account: %s"), account.Name))
|
|
||||||
registeredAt := account.RegisteredAt.Format("Jan 02, 2006 15:04:05Z")
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Registered at: %s"), registeredAt))
|
|
||||||
// TODO nicer formatting for this
|
|
||||||
for _, nick := range account.AdditionalNicks {
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Additional grouped nick: %s"), nick))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) nickservDropHandler(client *Client, nick string, sadrop bool, rb *ResponseBuffer) {
|
|
||||||
if sadrop {
|
|
||||||
if !client.HasRoleCapabs("unregister") {
|
|
||||||
nsNotice(rb, client.t("Insufficient oper privs"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := server.accounts.SetNickReserved(client, nick, sadrop, false)
|
|
||||||
if err == nil {
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("Successfully ungrouped nick %s with your account"), nick))
|
|
||||||
} else if err == errAccountNotLoggedIn {
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("You're not logged into an account")))
|
|
||||||
} else if err == errAccountCantDropPrimaryNick {
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("You can't ungroup your primary nickname (try unregistering your account instead)")))
|
|
||||||
} else if err == errNicknameReserved {
|
|
||||||
nsNotice(rb, fmt.Sprintf(client.t("That nickname is already reserved by someone else")))
|
|
||||||
} else {
|
|
||||||
nsNotice(rb, client.t("Error ungrouping nick"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -175,6 +175,14 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// confirm help entries for NickServ exist.
|
||||||
|
// this forces people to write help entries for every single NS command.
|
||||||
|
for commandName, commandInfo := range nickservCommands {
|
||||||
|
if commandInfo.help == "" || commandInfo.helpShort == "" {
|
||||||
|
return nil, fmt.Errorf("Help entry does not exist for NickServ command %s", commandName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to clean up when receiving these signals.
|
// Attempt to clean up when receiving these signals.
|
||||||
signal.Notify(server.signals, ServerExitSignals...)
|
signal.Notify(server.signals, ServerExitSignals...)
|
||||||
signal.Notify(server.rehashSignal, syscall.SIGHUP)
|
signal.Notify(server.rehashSignal, syscall.SIGHUP)
|
||||||
|
@ -3,6 +3,19 @@
|
|||||||
|
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// ExtractParam extracts a parameter from the given string, returning the param and the rest of the string.
|
||||||
|
func ExtractParam(line string) (string, string) {
|
||||||
|
rawParams := strings.SplitN(strings.TrimSpace(line), " ", 2)
|
||||||
|
param0 := rawParams[0]
|
||||||
|
var param1 string
|
||||||
|
if 1 < len(rawParams) {
|
||||||
|
param1 = strings.TrimSpace(rawParams[1])
|
||||||
|
}
|
||||||
|
return param0, param1
|
||||||
|
}
|
||||||
|
|
||||||
// ArgsToStrings takes the arguments and splits them into a series of strings,
|
// ArgsToStrings takes the arguments and splits them into a series of strings,
|
||||||
// each argument separated by delim and each string bounded by maxLength.
|
// each argument separated by delim and each string bounded by maxLength.
|
||||||
func ArgsToStrings(maxLength int, arguments []string, delim string) []string {
|
func ArgsToStrings(maxLength int, arguments []string, delim string) []string {
|
||||||
|
Loading…
Reference in New Issue
Block a user