fix(auth): серверная проверка длины пароля, loading-guard и различение ошибок на auth-страницах

This commit is contained in:
2026-07-03 21:33:03 +07:00
parent 5a4d560e70
commit 901eb51e2a
5 changed files with 126 additions and 8 deletions
+6
View File
@@ -60,6 +60,12 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
writeErr(w, http.StatusBadRequest, "email and password are required")
return
}
// Server-side minimum length is the source of truth: the client-side
// zod min(8) check is UX only and can be bypassed with a direct POST.
if len(req.Password) < 8 {
writeErr(w, http.StatusBadRequest, "password must be at least 8 characters")
return
}
hash, err := auth.HashPassword(req.Password)
if err != nil {
+36
View File
@@ -165,6 +165,42 @@ func TestAuthRegister_NormalizesEmail(t *testing.T) {
}
}
// TestAuthRegister_ShortPasswordReturns400 verifies the server-side password
// length floor: the client's zod min(8) is UX only and can be bypassed with a
// direct POST, so the handler itself must reject a password under 8 chars
// before ever calling RegisterUser.
func TestAuthRegister_ShortPasswordReturns400(t *testing.T) {
a, authStore, _ := newTestAuthAPI()
registerCalled := false
authStore.registerUserFn = func(context.Context, string, string) (store.User, store.Project, error) {
registerCalled = true
return store.User{}, store.Project{}, nil
}
router := NewRouter(a)
body := `{"email":"alice@example.com","password":"short"}`
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/register", strings.NewReader(body))
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Fatalf("status %d, body %s", w.Code, w.Body.String())
}
var got map[string]string
if err := json.Unmarshal(w.Body.Bytes(), &got); err != nil {
t.Fatal(err)
}
if got["error"] != "password must be at least 8 characters" {
t.Fatalf(`expected error "password must be at least 8 characters", got %q`, got["error"])
}
if registerCalled {
t.Fatal("expected RegisterUser not to be called for a too-short password")
}
if findCookie(w.Result(), sessionCookieName) != nil {
t.Fatal("expected no session cookie on rejected register")
}
}
// TestAuthRegister_DuplicateEmailReturns409 verifies the fix for the
// duplicate-registration gap: RegisterUser reporting store.ErrEmailTaken
// must surface as 409, not a generic 500.