package handlers import ( "errors" "net/http" "github.com/gin-gonic/gin" "github.com/tdvorak/seen/backend/internal/services/auth" "github.com/tdvorak/seen/backend/pkg/httpx" ) type AuthHandler struct { service *auth.Service } func NewAuthHandler(service *auth.Service) *AuthHandler { return &AuthHandler{service: service} } type registerRequest struct { Email string `json:"email"` Password string `json:"password"` DisplayName string `json:"displayName"` } type loginRequest struct { Email string `json:"email"` Password string `json:"password"` } type refreshRequest struct { RefreshToken string `json:"refreshToken"` } func (h *AuthHandler) Me(c *gin.Context) { accessToken, ok := bearerToken(c.GetHeader("Authorization")) if !ok { httpx.JSONError(c, http.StatusUnauthorized, "missing bearer token") return } user, err := h.service.UserFromAccessToken(c.Request.Context(), accessToken) if err != nil { switch { case errors.Is(err, auth.ErrInvalidToken): httpx.JSONError(c, http.StatusUnauthorized, err.Error()) default: httpx.JSONError(c, http.StatusInternalServerError, "failed to resolve user") } return } httpx.JSON(c, http.StatusOK, user) } func (h *AuthHandler) Register(c *gin.Context) { var request registerRequest if err := c.ShouldBindJSON(&request); err != nil { httpx.JSONError(c, http.StatusBadRequest, "invalid request body") return } result, err := h.service.Register(c.Request.Context(), auth.RegisterInput{ Email: request.Email, Password: request.Password, DisplayName: request.DisplayName, }) if err != nil { switch { case errors.Is(err, auth.ErrInvalidInput): httpx.JSONError(c, http.StatusBadRequest, err.Error()) case errors.Is(err, auth.ErrEmailTaken): httpx.JSONError(c, http.StatusConflict, err.Error()) default: httpx.JSONError(c, http.StatusInternalServerError, "register failed") } return } httpx.JSON(c, http.StatusCreated, result) } func (h *AuthHandler) Login(c *gin.Context) { var request loginRequest if err := c.ShouldBindJSON(&request); err != nil { httpx.JSONError(c, http.StatusBadRequest, "invalid request body") return } result, err := h.service.Login(c.Request.Context(), auth.LoginInput{ Email: request.Email, Password: request.Password, UserAgent: c.GetHeader("User-Agent"), IP: c.ClientIP(), }) if err != nil { switch { case errors.Is(err, auth.ErrInvalidInput): httpx.JSONError(c, http.StatusBadRequest, err.Error()) case errors.Is(err, auth.ErrInvalidCredentials): httpx.JSONError(c, http.StatusUnauthorized, err.Error()) default: httpx.JSONError(c, http.StatusInternalServerError, "login failed") } return } httpx.JSON(c, http.StatusOK, result) } func (h *AuthHandler) Refresh(c *gin.Context) { var request refreshRequest if err := c.ShouldBindJSON(&request); err != nil { httpx.JSONError(c, http.StatusBadRequest, "invalid request body") return } result, err := h.service.Refresh(c.Request.Context(), auth.RefreshInput{ RefreshToken: request.RefreshToken, UserAgent: c.GetHeader("User-Agent"), IP: c.ClientIP(), }) if err != nil { switch { case errors.Is(err, auth.ErrInvalidInput): httpx.JSONError(c, http.StatusBadRequest, err.Error()) case errors.Is(err, auth.ErrInvalidSession): httpx.JSONError(c, http.StatusUnauthorized, err.Error()) default: httpx.JSONError(c, http.StatusInternalServerError, "refresh failed") } return } httpx.JSON(c, http.StatusOK, result) }