package handler import ( "encoding/json" "errors" "log" "net/http" "strings" "time" "github.com/panelhosting/panel/internal/auth" "github.com/panelhosting/panel/internal/authsvc" "github.com/panelhosting/panel/internal/config" "github.com/panelhosting/panel/internal/httputil" "github.com/panelhosting/panel/internal/middleware" ) type AuthHandler struct { svc *authsvc.Service cfg *config.Config } func NewAuthHandler(svc *authsvc.Service, cfg *config.Config) *AuthHandler { return &AuthHandler{svc: svc, cfg: cfg} } type loginRequest struct { Username string `json:"username"` Password string `json:"password"` } func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { var req loginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid json") return } result, err := h.svc.Login(r.Context(), authsvc.LoginInput{ Username: strings.TrimSpace(req.Username), Password: req.Password, IP: httputil.ClientIP(r), UserAgent: r.UserAgent(), }) if err != nil { if errors.Is(err, auth.ErrInvalidCredentials) { writeError(w, http.StatusUnauthorized, "invalid credentials") return } log.Printf("login error: %v", err) writeError(w, http.StatusInternalServerError, "login failed") return } http.SetCookie(w, &http.Cookie{ Name: h.cfg.SessionCookieName, Value: result.Token, Path: "/", HttpOnly: true, SameSite: http.SameSiteLaxMode, MaxAge: h.cfg.SessionTTLHours * 3600, }) writeJSON(w, http.StatusOK, map[string]any{"user": result.User}) } func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { token := "" if c, err := r.Cookie(h.cfg.SessionCookieName); err == nil { token = c.Value } _ = h.svc.Logout(r.Context(), token) http.SetCookie(w, &http.Cookie{ Name: h.cfg.SessionCookieName, Value: "", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Unix(0, 0), }) writeJSON(w, http.StatusOK, map[string]string{"message": "logged out"}) } func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request) { user, ok := middleware.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } writeJSON(w, http.StatusOK, map[string]any{"user": user}) }