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:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user