You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

63 lines
1.6 KiB

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},
})
}
}