package api import ( "encoding/json" "net/http" "archivdms/internal/audit" ) type loginRequest struct { Username string `json:"username"` Password string `json:"password"` } func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) { var req loginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } ip := s.remoteIP(r) token, user, err := s.authMgr.LoginFrom(r.Context(), req.Username, req.Password, ip) if err != nil { s.audlog.Log(audit.Entry{ EventType: audit.EventLogin, Username: req.Username, IPAddress: ip, Success: false, Detail: "invalid_credentials", }) writeError(w, http.StatusUnauthorized, "invalid credentials") return } http.SetCookie(w, &http.Cookie{ Name: sessionCookieName, Value: token, Path: "/", HttpOnly: true, Secure: s.cfg.SecureCookies, SameSite: http.SameSiteLaxMode, MaxAge: 8 * 60 * 60, }) _ = s.users.UpdateLastLogin(user.ID) s.audlog.Log(audit.Entry{ EventType: audit.EventLogin, Username: user.Username, IPAddress: ip, TenantID: user.TenantID, Success: true, }) writeJSON(w, http.StatusOK, map[string]any{"token": token, "user": user}) } func (s *Server) handleMe(w http.ResponseWriter, r *http.Request) { sess := sessionFromCtx(r.Context()) user, err := s.users.GetByID(sess.UserID) if err != nil { writeError(w, http.StatusNotFound, "user not found") return } writeJSON(w, http.StatusOK, user) } func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) { sess := sessionFromCtx(r.Context()) token := "" if c, err := r.Cookie(sessionCookieName); err == nil { token = c.Value } if token == "" { token = extractBearerToken(r) } if token != "" { _ = s.authMgr.Logout(token) } http.SetCookie(w, &http.Cookie{ Name: sessionCookieName, Value: "", Path: "/", HttpOnly: true, MaxAge: -1, }) s.audlog.Log(audit.Entry{ EventType: audit.EventLogout, Username: sess.Username, IPAddress: s.remoteIP(r), TenantID: sess.TenantID, Success: true, }) writeJSON(w, http.StatusOK, map[string]string{"status": "logged out"}) }