package main import ( "encoding/json" "errors" "net/http" "time" "logjensticks/internal/auth" "logjensticks/internal/db" ) type loginRequest struct { Username string `json:"username"` Password string `json:"password"` } func handleLogin(dbc *db.Client, secureCookie bool) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", "method not allowed") return } var req loginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Username == "" || req.Password == "" { writeError(w, http.StatusBadRequest, "BAD_REQUEST", "username and password required") return } token, session, err := auth.Login(r.Context(), dbc, req.Username, req.Password) if errors.Is(err, auth.ErrInvalidCredentials) { writeError(w, http.StatusUnauthorized, "INVALID_CREDENTIALS", "invalid username or password") return } if err != nil { writeError(w, http.StatusInternalServerError, "SERVER_ERROR", "internal server error") return } http.SetCookie(w, &http.Cookie{ Name: auth.CookieName, Value: token, Path: "/", HttpOnly: true, Secure: secureCookie, SameSite: http.SameSiteStrictMode, MaxAge: int(db.SessionTTL / time.Second), }) writeSuccess(w, http.StatusOK, map[string]string{"role": session.Role}) } } func handleLogout(dbc *db.Client, secureCookie bool) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", "method not allowed") return } if cookie, err := r.Cookie(auth.CookieName); err == nil { auth.DeleteSession(r.Context(), dbc, cookie.Value) } http.SetCookie(w, &http.Cookie{ Name: auth.CookieName, Value: "", Path: "/", HttpOnly: true, Secure: secureCookie, SameSite: http.SameSiteStrictMode, MaxAge: -1, }) writeSuccess(w, http.StatusOK, nil) } }