Files
SEEN/backend/internal/api/handlers/auth_handler.go
T
2026-04-10 12:06:24 +02:00

137 lines
3.5 KiB
Go

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