fix: harden login validation with proper JSON error responses

Change LoginHandler validation error from http.Error (plain text, mismatched Content-Type) to mw.RespondError (proper JSON {error:...} response). Add TestLogin_EmptyFields and TestLogin_MissingEmail tests verifying JSON error format.
This commit is contained in:
2026-08-22 00:34:48 +01:00
parent 5ed24f263a
commit 6567ff4904
2 changed files with 54 additions and 3 deletions
+51
View File
@@ -21,6 +21,7 @@ package auth
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
@@ -713,6 +714,56 @@ func TestLogin_InvalidRequest(t *testing.T) {
}
}
// TestLogin_EmptyFields verifies that sending login with empty email/password
// returns HTTP 400 with a JSON error body containing an error field.
func TestLogin_EmptyFields(t *testing.T) {
_, _ = resetTestData(t)
handler := http.HandlerFunc(LoginHandler)
body := map[string]string{
"email": "",
"password": "",
}
w := testutils.MakeRequestNoAuth(handler, "POST", "/api/login", body, context.Background())
if w.Code != http.StatusBadRequest {
t.Errorf("expected status 400, got %d", w.Code)
}
var resp map[string]string
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatalf("expected JSON error body, got: %s (parse error: %v)", w.Body.String(), err)
}
if _, ok := resp["error"]; !ok {
t.Errorf("expected JSON response with 'error' field, got: %v", resp)
}
}
// TestLogin_MissingEmail verifies that login without email field returns 400.
func TestLogin_MissingEmail(t *testing.T) {
_, _ = resetTestData(t)
handler := http.HandlerFunc(LoginHandler)
body := map[string]string{
"password": "secret123",
}
w := testutils.MakeRequestNoAuth(handler, "POST", "/api/login", body, context.Background())
if w.Code != http.StatusBadRequest {
t.Errorf("expected status 400, got %d", w.Code)
}
var resp map[string]string
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatalf("expected JSON error body, got: %s (parse error: %v)", w.Body.String(), err)
}
if _, ok := resp["error"]; !ok {
t.Errorf("expected JSON response with 'error' field, got: %v", resp)
}
}
// TestRegister_NameTooLong tests that registration fails when the first name
// exceeds 50 characters (the maximum allowed length).
func TestRegister_NameTooLong(t *testing.T) {
+3 -3
View File
@@ -313,13 +313,13 @@ func ValidateUKPhoneNumber(phone string) (string, error) {
func LoginHandler(w http.ResponseWriter, r *http.Request) {
var req LoginRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid request", http.StatusBadRequest)
mw.RespondError(w, http.StatusBadRequest, "invalid request")
return
}
if err := validators.Validate.Struct(&req); err != nil {
log.Printf("Failed to process request: %v", err)
http.Error(w, "Invalid request", http.StatusBadRequest)
log.Printf("Login validation failed: %v", err)
mw.RespondError(w, http.StatusBadRequest, "Email and password are required")
return
}