Merge pull request #799 from slingamn/issue725_deoper.1

fix #725
This commit is contained in:
Shivaram Lingamneni 2020-02-22 20:07:29 -08:00 committed by GitHub
commit fec27cc7c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 16 deletions

View File

@ -116,6 +116,11 @@ func init() {
minParams: 1, minParams: 1,
oper: true, oper: true,
}, },
"DEOPER": {
handler: deoperHandler,
minParams: 0,
oper: true,
},
"DLINE": { "DLINE": {
handler: dlineHandler, handler: dlineHandler,
minParams: 1, minParams: 1,

View File

@ -2141,35 +2141,49 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
return false return false
} }
// applies operator status to a client, who MUST NOT already be an operator // adds or removes operator status
// XXX: to add oper, this calls into ApplyUserModeChanges, but to remove oper,
// ApplyUserModeChanges calls into this, because the commands are asymmetric
// (/OPER to add, /MODE self -o to remove)
func applyOper(client *Client, oper *Oper, rb *ResponseBuffer) { func applyOper(client *Client, oper *Oper, rb *ResponseBuffer) {
details := client.Details() details := client.Details()
oldNickmask := details.nickMask
client.SetOper(oper) client.SetOper(oper)
newNickmask := client.NickMaskString() newDetails := client.Details()
if newNickmask != oldNickmask { if details.nickMask != newDetails.nickMask {
client.sendChghost(oldNickmask, oper.Vhost) client.sendChghost(details.nickMask, newDetails.hostname)
} }
// set new modes: modes.Operator, plus anything specified in the config if oper != nil {
modeChanges := make([]modes.ModeChange, len(oper.Modes)+1) // set new modes: modes.Operator, plus anything specified in the config
modeChanges[0] = modes.ModeChange{ modeChanges := make([]modes.ModeChange, len(oper.Modes)+1)
Mode: modes.Operator, modeChanges[0] = modes.ModeChange{
Op: modes.Add, Mode: modes.Operator,
Op: modes.Add,
}
copy(modeChanges[1:], oper.Modes)
applied := ApplyUserModeChanges(client, modeChanges, true)
client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), newDetails.nickMask, oper.Name))
rb.Broadcast(nil, client.server.name, RPL_YOUREOPER, details.nick, client.t("You are now an IRC operator"))
rb.Broadcast(nil, client.server.name, "MODE", details.nick, applied.String())
} else {
client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client deopered $c[grey][$r%s$c[grey]]"), newDetails.nickMask))
} }
copy(modeChanges[1:], oper.Modes)
applied := ApplyUserModeChanges(client, modeChanges, true)
client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, oper.Name))
rb.Broadcast(nil, client.server.name, RPL_YOUREOPER, details.nick, client.t("You are now an IRC operator"))
rb.Broadcast(nil, client.server.name, "MODE", details.nick, applied.String())
for _, session := range client.Sessions() { for _, session := range client.Sessions() {
// client may now be unthrottled by the fakelag system // client may now be unthrottled by the fakelag system
session.resetFakelag() session.resetFakelag()
} }
} }
// DEOPER
func deoperHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
// pretend they sent /MODE $nick -o
fakeModeMsg := ircmsg.MakeMessage(nil, "", "MODE", client.Nick(), "-o")
return umodeHandler(server, client, fakeModeMsg, rb)
}
// PART <channel>{,<channel>} [<reason>] // PART <channel>{,<channel>} [<reason>]
func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
channels := strings.Split(msg.Params[0], ",") channels := strings.Split(msg.Params[0], ",")

View File

@ -160,6 +160,12 @@ Prints debug information about the IRCd. <option> can be one of:
* STARTCPUPROFILE: Starts the CPU profiler. * STARTCPUPROFILE: Starts the CPU profiler.
* STOPCPUPROFILE: Stops the CPU profiler. * STOPCPUPROFILE: Stops the CPU profiler.
* PROFILEHEAP: Writes out the CPU profiler info.`, * PROFILEHEAP: Writes out the CPU profiler info.`,
},
"deoper": {
oper: true,
text: `DEOPER
DEOPER removes the IRCop privileges granted to you by a successful /OPER.`,
}, },
"dline": { "dline": {
oper: true, oper: true,

View File

@ -45,13 +45,26 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool)
} }
case modes.Remove: case modes.Remove:
var removedSnomasks string
if client.SetMode(change.Mode, false) { if client.SetMode(change.Mode, false) {
if change.Mode == modes.Invisible { if change.Mode == modes.Invisible {
client.server.stats.ChangeInvisible(-1) client.server.stats.ChangeInvisible(-1)
} else if change.Mode == modes.Operator || change.Mode == modes.LocalOperator { } else if change.Mode == modes.Operator || change.Mode == modes.LocalOperator {
removedSnomasks = client.server.snomasks.String(client)
client.server.stats.ChangeOperators(-1) client.server.stats.ChangeOperators(-1)
applyOper(client, nil, nil)
if removedSnomasks != "" {
client.server.snomasks.RemoveClient(client)
}
} }
applied = append(applied, change) applied = append(applied, change)
if removedSnomasks != "" {
applied = append(applied, modes.ModeChange{
Mode: modes.ServerNotice,
Op: modes.Remove,
Arg: removedSnomasks,
})
}
} }
} }