fix: 开启自助注册须先有 8-64 字符安全码
This commit is contained in:
@@ -25,6 +25,9 @@ const (
|
||||
settingRegistrationEnabled = "registration_enabled"
|
||||
settingRegistrationCode = "registration_code"
|
||||
|
||||
minRegistrationCodeLen = 8
|
||||
maxRegistrationCodeLen = 64
|
||||
|
||||
sourceSelf = "self"
|
||||
|
||||
idAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
@@ -144,6 +147,11 @@ func (h *RegisterHandler) register(ctx context.Context, req *protocol.RegisterRe
|
||||
if !enabled {
|
||||
return RegisterResult{}, apiErr(http.StatusForbidden, protocol.CodeRegistrationClosed, "registration closed")
|
||||
}
|
||||
// 存储码不是 8–64 字符时视为关闭(含开启+空码的旧库)。放在锁定检查之前,不计入锁定。
|
||||
if n := utf8.RuneCountInString(storedCode); n < minRegistrationCodeLen || n > maxRegistrationCodeLen {
|
||||
h.cfg.Logger.Warn("register", "result", protocol.CodeRegistrationClosed, "reason", "unusable_code", "ip", ip)
|
||||
return RegisterResult{}, apiErr(http.StatusForbidden, protocol.CodeRegistrationClosed, "registration closed")
|
||||
}
|
||||
|
||||
lockKey := auth.LockKey{Kind: auth.LockRegisterIP, IP: ip}
|
||||
if locked, _ := h.cfg.Locks.Check(lockKey); locked {
|
||||
|
||||
@@ -141,6 +141,33 @@ func openTestEnv(t *testing.T) *testEnv {
|
||||
return env
|
||||
}
|
||||
|
||||
func (e *testEnv) setEnabledOnly(t *testing.T, enabled bool) {
|
||||
t.Helper()
|
||||
en := "0"
|
||||
if enabled {
|
||||
en = "1"
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
err := e.db.Queue.Do(context.Background(), func(tx *sql.Tx) error {
|
||||
if _, err := tx.Exec(`INSERT INTO settings(key, value, updated_at) VALUES(?, ?, ?)
|
||||
ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at`,
|
||||
settingRegistrationEnabled, en, now); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(`DELETE FROM settings WHERE key = ?`, settingRegistrationCode)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *registerIPLocker) failCount(ip string) int {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return len(l.fails[ip])
|
||||
}
|
||||
|
||||
func (e *testEnv) setRegistration(t *testing.T, enabled bool, code string) {
|
||||
t.Helper()
|
||||
en := "0"
|
||||
@@ -233,6 +260,43 @@ func TestRegisterF23_ClosedFails(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegister_EnabledWithoutUsableCodeIsClosed(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
prep func(*testEnv, *testing.T)
|
||||
}{
|
||||
{"no_code_row", func(env *testEnv, t *testing.T) { env.setEnabledOnly(t, true) }},
|
||||
{"empty_code", func(env *testEnv, t *testing.T) { env.setRegistration(t, true, "") }},
|
||||
{"short_code", func(env *testEnv, t *testing.T) { env.setRegistration(t, true, "short") }},
|
||||
}
|
||||
bodies := []string{
|
||||
`{"registration_code":"","id":"ep_empty","login_password":"password1"}`,
|
||||
`{"registration_code":"anything1","id":"ep_any","login_password":"password1"}`,
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
env := openTestEnv(t)
|
||||
tc.prep(env, t)
|
||||
for _, body := range bodies {
|
||||
code, resp, _ := env.doRegister(t, body)
|
||||
if code != http.StatusForbidden || resp.Error == nil || resp.Error.Code != protocol.CodeRegistrationClosed {
|
||||
t.Fatalf("body=%s status=%d resp=%+v", body, code, resp)
|
||||
}
|
||||
}
|
||||
if env.locks.failCount(env.fixedIP) != 0 {
|
||||
t.Fatalf("unusable code must not count as lock fail: %d", env.locks.failCount(env.fixedIP))
|
||||
}
|
||||
logged := env.logBuf.String()
|
||||
if strings.Contains(logged, "anything1") || strings.Contains(logged, "short") {
|
||||
t.Fatalf("log leaked code: %s", logged)
|
||||
}
|
||||
if !strings.Contains(logged, "unusable_code") {
|
||||
t.Fatalf("missing warn: %s", logged)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterF23_WrongCodeFails_RightCodeOK(t *testing.T) {
|
||||
env := openTestEnv(t)
|
||||
env.setRegistration(t, true, "good-code-01")
|
||||
|
||||
Reference in New Issue
Block a user