Shivaram Lingamneni пре 4 година
родитељ
комит
3363076689
4 измењених фајлова са 66 додато и 23 уклоњено
  1. 19
    5
      irc/accounts.go
  2. 1
    0
      irc/errors.go
  3. 1
    1
      irc/handlers.go
  4. 45
    17
      irc/nickserv.go

+ 19
- 5
irc/accounts.go Прегледај датотеку

@@ -24,6 +24,7 @@ import (
24 24
 const (
25 25
 	keyAccountExists           = "account.exists %s"
26 26
 	keyAccountVerified         = "account.verified %s"
27
+	keyAccountUnregistered     = "account.unregistered %s"
27 28
 	keyAccountCallback         = "account.callback %s"
28 29
 	keyAccountVerificationCode = "account.verificationcode %s"
29 30
 	keyAccountName             = "account.name %s" // stores the 'preferred name' of the account, not casemapped
@@ -363,6 +364,7 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
363 364
 	}
364 365
 
365 366
 	accountKey := fmt.Sprintf(keyAccountExists, casefoldedAccount)
367
+	unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
366 368
 	accountNameKey := fmt.Sprintf(keyAccountName, casefoldedAccount)
367 369
 	callbackKey := fmt.Sprintf(keyAccountCallback, casefoldedAccount)
368 370
 	registeredTimeKey := fmt.Sprintf(keyAccountRegTime, casefoldedAccount)
@@ -401,7 +403,11 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
401 403
 		}
402 404
 
403 405
 		return am.server.store.Update(func(tx *buntdb.Tx) error {
404
-			_, err := am.loadRawAccount(tx, casefoldedAccount)
406
+			if _, err := tx.Get(unregisteredKey); err == nil {
407
+				return errAccountAlreadyUnregistered
408
+			}
409
+
410
+			_, err = am.loadRawAccount(tx, casefoldedAccount)
405 411
 			if err != errAccountDoesNotExist {
406 412
 				return errAccountAlreadyRegistered
407 413
 			}
@@ -432,7 +438,7 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
432 438
 
433 439
 	code, err := am.dispatchCallback(client, casefoldedAccount, callbackNamespace, callbackValue)
434 440
 	if err != nil {
435
-		am.Unregister(casefoldedAccount)
441
+		am.Unregister(casefoldedAccount, true)
436 442
 		return errCallbackFailed
437 443
 	} else {
438 444
 		return am.server.store.Update(func(tx *buntdb.Tx) error {
@@ -1063,7 +1069,7 @@ func (am *AccountManager) loadRawAccount(tx *buntdb.Tx, casefoldedAccount string
1063 1069
 	return
1064 1070
 }
1065 1071
 
1066
-func (am *AccountManager) Unregister(account string) error {
1072
+func (am *AccountManager) Unregister(account string, erase bool) error {
1067 1073
 	config := am.server.Config()
1068 1074
 	casefoldedAccount, err := CasefoldName(account)
1069 1075
 	if err != nil {
@@ -1084,6 +1090,7 @@ func (am *AccountManager) Unregister(account string) error {
1084 1090
 	channelsKey := fmt.Sprintf(keyAccountChannels, casefoldedAccount)
1085 1091
 	joinedChannelsKey := fmt.Sprintf(keyAccountJoinedChannels, casefoldedAccount)
1086 1092
 	lastSeenKey := fmt.Sprintf(keyAccountLastSeen, casefoldedAccount)
1093
+	unregisteredKey := fmt.Sprintf(keyAccountUnregistered, casefoldedAccount)
1087 1094
 
1088 1095
 	var clients []*Client
1089 1096
 
@@ -1104,6 +1111,13 @@ func (am *AccountManager) Unregister(account string) error {
1104 1111
 	var accountName string
1105 1112
 	var channelsStr string
1106 1113
 	am.server.store.Update(func(tx *buntdb.Tx) error {
1114
+		if erase {
1115
+			tx.Delete(unregisteredKey)
1116
+		} else {
1117
+			if _, err := tx.Get(accountKey); err == nil {
1118
+				tx.Set(unregisteredKey, "1", nil)
1119
+			}
1120
+		}
1107 1121
 		tx.Delete(accountKey)
1108 1122
 		accountName, _ = tx.Get(accountNameKey)
1109 1123
 		tx.Delete(accountNameKey)
@@ -1129,7 +1143,7 @@ func (am *AccountManager) Unregister(account string) error {
1129 1143
 
1130 1144
 	if err == nil {
1131 1145
 		var creds AccountCredentials
1132
-		if err = json.Unmarshal([]byte(credText), &creds); err == nil {
1146
+		if err := json.Unmarshal([]byte(credText), &creds); err == nil {
1133 1147
 			for _, cert := range creds.Certfps {
1134 1148
 				certFPKey := fmt.Sprintf(keyCertToAccount, cert)
1135 1149
 				am.server.store.Update(func(tx *buntdb.Tx) error {
@@ -1169,7 +1183,7 @@ func (am *AccountManager) Unregister(account string) error {
1169 1183
 		}
1170 1184
 	}
1171 1185
 
1172
-	if err != nil {
1186
+	if err != nil && !erase {
1173 1187
 		return errAccountDoesNotExist
1174 1188
 	}
1175 1189
 

+ 1
- 0
irc/errors.go Прегледај датотеку

@@ -13,6 +13,7 @@ import (
13 13
 // Runtime Errors
14 14
 var (
15 15
 	errAccountAlreadyRegistered       = errors.New(`Account already exists`)
16
+	errAccountAlreadyUnregistered     = errors.New(`That account name was registered previously and can't be reused`)
16 17
 	errAccountAlreadyVerified         = errors.New(`Account is already verified`)
17 18
 	errAccountCantDropPrimaryNick     = errors.New("Can't unreserve primary nickname")
18 19
 	errAccountCreation                = errors.New("Account could not be created")

+ 1
- 1
irc/handlers.go Прегледај датотеку

@@ -66,7 +66,7 @@ func registrationErrorToMessageAndCode(err error) (message, code string) {
66 66
 	case errAccountBadPassphrase:
67 67
 		code = "REG_INVALID_CREDENTIAL"
68 68
 		message = err.Error()
69
-	case errAccountAlreadyRegistered, errAccountAlreadyVerified:
69
+	case errAccountAlreadyRegistered, errAccountAlreadyVerified, errAccountAlreadyUnregistered:
70 70
 		message = err.Error()
71 71
 	case errAccountCreation, errAccountMustHoldNick, errAccountBadPassphrase, errCertfpAlreadyExists, errFeatureDisabled:
72 72
 		message = err.Error()

+ 45
- 17
irc/nickserv.go Прегледај датотеку

@@ -164,6 +164,20 @@ a code will display the necessary code.`,
164 164
 			enabled:   servCmdRequiresAuthEnabled,
165 165
 			minParams: 1,
166 166
 		},
167
+		"erase": {
168
+			handler: nsUnregisterHandler,
169
+			help: `Syntax: $bERASE <username> [code]$b
170
+
171
+ERASE deletes all records of an account, allowing it to be re-registered.
172
+This should be used with caution, because it violates an expectation that
173
+account names are permanent identifiers. Typically, UNREGISTER should be
174
+used instead. A confirmation code is required; invoking the command
175
+without a code will display the necessary code.`,
176
+			helpShort: `$bERASE$b erases all records of an account, allowing reuse.`,
177
+			enabled:   servCmdRequiresAuthEnabled,
178
+			capabs:    []string{"accreg"},
179
+			minParams: 1,
180
+		},
167 181
 		"verify": {
168 182
 			handler: nsVerifyHandler,
169 183
 			help: `Syntax: $bVERIFY <username> <code>$b
@@ -815,6 +829,8 @@ func nsSaregisterHandler(server *Server, client *Client, command string, params
815 829
 }
816 830
 
817 831
 func nsUnregisterHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
832
+	erase := command == "erase"
833
+
818 834
 	username := params[0]
819 835
 	var verificationCode string
820 836
 	if len(params) > 1 {
@@ -826,39 +842,51 @@ func nsUnregisterHandler(server *Server, client *Client, command string, params
826 842
 		return
827 843
 	}
828 844
 
829
-	account, err := server.accounts.LoadAccount(username)
830
-	if err == errAccountDoesNotExist {
831
-		nsNotice(rb, client.t("Invalid account name"))
832
-		return
833
-	} else if err != nil {
834
-		nsNotice(rb, client.t("Internal error"))
835
-		return
845
+	var accountName string
846
+	var registeredAt time.Time
847
+	if erase {
848
+		// account may not be in a loadable state, e.g., if it was unregistered
849
+		accountName = username
850
+	} else {
851
+		account, err := server.accounts.LoadAccount(username)
852
+		if err == errAccountDoesNotExist {
853
+			nsNotice(rb, client.t("Invalid account name"))
854
+			return
855
+		} else if err != nil {
856
+			nsNotice(rb, client.t("Internal error"))
857
+			return
858
+		}
859
+		accountName = account.Name
860
+		registeredAt = account.RegisteredAt
836 861
 	}
837 862
 
838
-	cfname, _ := CasefoldName(username)
839
-	if !(cfname == client.Account() || client.HasRoleCapabs("accreg")) {
863
+	if !(accountName == client.AccountName() || client.HasRoleCapabs("accreg")) {
840 864
 		nsNotice(rb, client.t("Insufficient oper privs"))
841 865
 		return
842 866
 	}
843 867
 
844
-	expectedCode := utils.ConfirmationCode(account.Name, account.RegisteredAt)
868
+	expectedCode := utils.ConfirmationCode(accountName, registeredAt)
845 869
 	if expectedCode != verificationCode {
846
-		nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this account will remove its stored privileges.$b")))
847
-		nsNotice(rb, fmt.Sprintf(client.t("To confirm account unregistration, type: /NS UNREGISTER %[1]s %[2]s"), cfname, expectedCode))
870
+		if erase {
871
+			nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: erasing this account will allow it to be re-registered; consider UNREGISTER instead.$b")))
872
+			nsNotice(rb, fmt.Sprintf(client.t("To confirm account erase, type: /NS ERASE %[1]s %[2]s"), accountName, expectedCode))
873
+		} else {
874
+			nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this account will remove its stored privileges.$b")))
875
+			nsNotice(rb, fmt.Sprintf(client.t("To confirm account unregistration, type: /NS UNREGISTER %[1]s %[2]s"), accountName, expectedCode))
876
+		}
848 877
 		return
849 878
 	}
850 879
 
851
-	err = server.accounts.Unregister(cfname)
880
+	err := server.accounts.Unregister(accountName, erase)
852 881
 	if err == errAccountDoesNotExist {
853 882
 		nsNotice(rb, client.t(err.Error()))
854 883
 	} else if err != nil {
855 884
 		nsNotice(rb, client.t("Error while unregistering account"))
856 885
 	} else {
857
-		nsNotice(rb, fmt.Sprintf(client.t("Successfully unregistered account %s"), cfname))
858
-		server.logger.Info("accounts", "client", client.Nick(), "unregistered account", cfname)
886
+		nsNotice(rb, fmt.Sprintf(client.t("Successfully unregistered account %s"), accountName))
887
+		server.logger.Info("accounts", "client", client.Nick(), "unregistered account", accountName)
888
+		client.server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] unregistered account $c[grey][$r%s$c[grey]]"), client.NickMaskString(), accountName))
859 889
 	}
860
-
861
-	client.server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Client $c[grey][$r%s$c[grey]] unregistered account $c[grey][$r%s$c[grey]]"), client.NickMaskString(), account.Name))
862 890
 }
863 891
 
864 892
 func nsVerifyHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {

Loading…
Откажи
Сачувај