package auth import ( "encoding/json" "net/http" "github.com/jackc/pgx/v5/pgxpool" ) type loginRequest struct { Username string `json:"username"` Password string `json:"password"` } type userResponse struct { ID int64 `json:"id"` Username string `json:"username"` Role string `json:"role"` } type loginResponse struct { Token string `json:"token"` User userResponse `json:"user"` } // NewLoginHandler returns the handler for POST /api/auth/login. func NewLoginHandler(db *pgxpool.Pool, jwtSecret string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req loginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Username == "" || req.Password == "" { http.Error(w, "invalid input", http.StatusBadRequest) return } var id int64 var username, role, passwordHash string err := db.QueryRow(r.Context(), `SELECT id, username, role, password FROM users WHERE username = $1`, req.Username, ).Scan(&id, &username, &role, &passwordHash) if err != nil { http.Error(w, "invalid username or password", http.StatusUnauthorized) return } if err := VerifyPassword(passwordHash, req.Password); err != nil { http.Error(w, "invalid username or password", http.StatusUnauthorized) return } token, err := GenerateJWT(jwtSecret, id, username, role) if err != nil { http.Error(w, "internal server error", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(loginResponse{ Token: token, User: userResponse{ID: id, Username: username, Role: role}, }) } }