瀏覽代碼

some tweaks to account/channel unregistration

tags/v0.12.0
Shivaram Lingamneni 6 年之前
父節點
當前提交
02a4aaf583
共有 4 個文件被更改,包括 45 次插入25 次删除
  1. 13
    9
      irc/chanserv.go
  2. 6
    3
      irc/modes.go
  3. 25
    12
      irc/nickserv.go
  4. 1
    1
      oragono.yaml

+ 13
- 9
irc/chanserv.go 查看文件

@@ -10,6 +10,7 @@ import (
10 10
 	"sort"
11 11
 	"strconv"
12 12
 	"strings"
13
+	"time"
13 14
 
14 15
 	"github.com/goshuirc/irc-go/ircfmt"
15 16
 	"github.com/oragono/oragono/irc/modes"
@@ -287,15 +288,10 @@ func csUnregisterHandler(server *Server, client *Client, command, params string,
287 288
 	}
288 289
 
289 290
 	info := channel.ExportRegistration(0)
290
-	// verification code is the crc32 of the name, plus the registration time
291
-	var codeInput bytes.Buffer
292
-	codeInput.WriteString(info.Name)
293
-	codeInput.WriteString(strconv.FormatInt(info.RegisteredAt.Unix(), 16))
294
-	expectedCode := int(crc32.ChecksumIEEE(codeInput.Bytes()))
295
-	receivedCode, err := strconv.Atoi(verificationCode)
296
-	if err != nil || expectedCode != receivedCode {
297
-		csNotice(rb, client.t("$bWarning:$b Unregistering this channel will remove all stored channel attributes."))
298
-		csNotice(rb, fmt.Sprintf(client.t("To confirm channel unregistration, type: /CS UNREGISTER %s %d"), channelKey, expectedCode))
291
+	expectedCode := unregisterConfirmationCode(info.Name, info.RegisteredAt)
292
+	if expectedCode != verificationCode {
293
+		csNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this channel will remove all stored channel attributes.$b")))
294
+		csNotice(rb, fmt.Sprintf(client.t("To confirm channel unregistration, type: /CS UNREGISTER %s %s"), channelKey, expectedCode))
299 295
 		return
300 296
 	}
301 297
 
@@ -303,3 +299,11 @@ func csUnregisterHandler(server *Server, client *Client, command, params string,
303 299
 	go server.channelRegistry.Delete(channelKey, info)
304 300
 	csNotice(rb, fmt.Sprintf(client.t("Channel %s is now unregistered"), channelKey))
305 301
 }
302
+
303
+// deterministically generates a confirmation code for unregistering a channel / account
304
+func unregisterConfirmationCode(name string, registeredAt time.Time) (code string) {
305
+	var codeInput bytes.Buffer
306
+	codeInput.WriteString(name)
307
+	codeInput.WriteString(strconv.FormatInt(registeredAt.Unix(), 16))
308
+	return strconv.Itoa(int(crc32.ChecksumIEEE(codeInput.Bytes())))
309
+}

+ 6
- 3
irc/modes.go 查看文件

@@ -255,7 +255,10 @@ func umodeGreaterThan(l modes.Mode, r modes.Mode) bool {
255 255
 
256 256
 // ProcessAccountToUmodeChange processes Add/Remove/List operations for channel persistent usermodes.
257 257
 func (channel *Channel) ProcessAccountToUmodeChange(client *Client, change modes.ModeChange) (results []modes.ModeChange, err error) {
258
-	umodeGEQ := func(l modes.Mode, r modes.Mode) bool {
258
+	hasPrivsOver := func(l modes.Mode, r modes.Mode) bool {
259
+		if l == modes.ChannelAdmin {
260
+			return umodeGreaterThan(l, r)
261
+		}
259 262
 		return l == r || umodeGreaterThan(l, r)
260 263
 	}
261 264
 
@@ -275,9 +278,9 @@ func (channel *Channel) ProcessAccountToUmodeChange(client *Client, change modes
275 278
 	// operators and founders can do anything
276 279
 	hasPrivs := isOperChange || (account != "" && account == channel.registeredFounder)
277 280
 	// halfop and up can list, and do add/removes at levels <= their own
278
-	if change.Op == modes.List && umodeGEQ(clientMode, modes.Halfop) {
281
+	if change.Op == modes.List && hasPrivsOver(clientMode, modes.Halfop) {
279 282
 		hasPrivs = true
280
-	} else if umodeGEQ(clientMode, modes.Halfop) && umodeGEQ(clientMode, targetModeNow) && umodeGEQ(clientMode, targetModeAfter) {
283
+	} else if hasPrivsOver(clientMode, modes.Halfop) && hasPrivsOver(clientMode, targetModeNow) && hasPrivsOver(clientMode, targetModeAfter) {
281 284
 		hasPrivs = true
282 285
 	}
283 286
 	if !hasPrivs {

+ 25
- 12
irc/nickserv.go 查看文件

@@ -7,6 +7,7 @@ import (
7 7
 	"fmt"
8 8
 	"strings"
9 9
 
10
+	"github.com/goshuirc/irc-go/ircfmt"
10 11
 	"github.com/oragono/oragono/irc/utils"
11 12
 )
12 13
 
@@ -98,10 +99,12 @@ SADROP forcibly de-links the given nickname from the attached user account.`,
98 99
 		},
99 100
 		"unregister": {
100 101
 			handler: nsUnregisterHandler,
101
-			help: `Syntax: $bUNREGISTER [username]$b
102
+			help: `Syntax: $bUNREGISTER <username> [code]$b
102 103
 
103
-UNREGISTER lets you delete your user account (or the given one, if you're an
104
-IRC operator with the correct permissions).`,
104
+UNREGISTER lets you delete your user account (or someone else's, if you're an
105
+IRC operator with the correct permissions). To prevent accidental
106
+unregistrations, a verification code is required; invoking the command without
107
+a code will display the necessary code.`,
105 108
 			helpShort: `$bUNREGISTER$b lets you delete your user account.`,
106 109
 		},
107 110
 		"verify": {
@@ -316,7 +319,7 @@ func nsRegisterHandler(server *Server, client *Client, command, params string, r
316 319
 }
317 320
 
318 321
 func nsUnregisterHandler(server *Server, client *Client, command, params string, rb *ResponseBuffer) {
319
-	username, _ := utils.ExtractParam(params)
322
+	username, verificationCode := utils.ExtractParam(params)
320 323
 
321 324
 	if !server.AccountConfig().Registration.Enabled {
322 325
 		nsNotice(rb, client.t("Account registration has been disabled"))
@@ -324,22 +327,32 @@ func nsUnregisterHandler(server *Server, client *Client, command, params string,
324 327
 	}
325 328
 
326 329
 	if username == "" {
327
-		username = client.Account()
328
-	}
329
-	if username == "" {
330
-		nsNotice(rb, client.t("You're not logged into an account"))
330
+		nsNotice(rb, client.t("You must specify an account"))
331 331
 		return
332 332
 	}
333
-	cfname, err := CasefoldName(username)
334
-	if err != nil {
335
-		nsNotice(rb, client.t("Invalid username"))
333
+
334
+	account, err := server.accounts.LoadAccount(username)
335
+	if err == errAccountDoesNotExist {
336
+		nsNotice(rb, client.t("Invalid account name"))
337
+		return
338
+	} else if err != nil {
339
+		nsNotice(rb, client.t("Internal error"))
336 340
 		return
337 341
 	}
338
-	if !(cfname == client.Account() || client.HasRoleCapabs("unregister")) {
342
+
343
+	cfname, _ := CasefoldName(username)
344
+	if !(cfname == client.Account() || client.HasRoleCapabs("accreg")) {
339 345
 		nsNotice(rb, client.t("Insufficient oper privs"))
340 346
 		return
341 347
 	}
342 348
 
349
+	expectedCode := unregisterConfirmationCode(account.Name, account.RegisteredAt)
350
+	if expectedCode != verificationCode {
351
+		nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this account will remove its stored privileges.$b")))
352
+		nsNotice(rb, fmt.Sprintf(client.t("To confirm account unregistration, type: /NS UNREGISTER %s %s"), cfname, expectedCode))
353
+		return
354
+	}
355
+
343 356
 	if cfname == client.Account() {
344 357
 		client.server.accounts.Logout(client)
345 358
 	}

+ 1
- 1
oragono.yaml 查看文件

@@ -280,7 +280,7 @@ oper-classes:
280 280
         capabilities:
281 281
             - "oper:rehash"
282 282
             - "oper:die"
283
-            - "unregister"
283
+            - "accreg"
284 284
             - "sajoin"
285 285
             - "samode"
286 286
             - "vhosts"

Loading…
取消
儲存