package handlers import ( // Added for context.Context "errors" "fmt" "net/http" "git.linuxforward.com/byop/byop-engine/auth" "git.linuxforward.com/byop/byop-engine/dbstore" // Keep for NewAuthHandler, but userStore is not directly used in handlers "git.linuxforward.com/byop/byop-engine/models" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" // Added for validation ) // AuthHandler handles authentication-related operations type AuthHandler struct { authService auth.Service validate *validator.Validate // Added for validation } // NewAuthHandler creates a new AuthHandler func NewAuthHandler(authService auth.Service, userStore *dbstore.SQLiteStore) *AuthHandler { return &AuthHandler{ authService: authService, validate: validator.New(), // Initialize validator } } // LoginRequest defines the structure for login requests. type LoginRequest struct { Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required"` } // Login handles user authentication func (h *AuthHandler) Login(c *gin.Context) { ctx := c.Request.Context() // Propagate context var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { models.RespondWithError(c, models.NewErrValidation("invalid_request_body", map[string]string{"body": "Invalid request body"}, err)) return } fmt.Println("Login request received:", req.Email) // Debugging line to check input // Validate input if err := h.validate.Struct(req); err != nil { validationErrors := models.ExtractValidationErrors(err) models.RespondWithError(c, models.NewErrValidation("input_validation_failed", validationErrors, err)) return } tokenResp, err := h.authService.Login(ctx, req.Email, req.Password) if err != nil { if errors.Is(err, auth.ErrInvalidCredentials) || errors.Is(err, auth.ErrUserNotFound) { models.RespondWithError(c, models.NewErrUnauthorized("login_failed", err)) } else { models.RespondWithError(c, models.NewErrInternalServer("login_token_generation_failed", err)) } return } c.JSON(http.StatusOK, tokenResp) // auth.TokenResponse is now the direct response } // RefreshTokenRequest defines the structure for refresh token requests. type RefreshTokenRequest struct { RefreshToken string `json:"refresh_token" validate:"required"` } // RefreshToken handles token refresh func (h *AuthHandler) RefreshToken(c *gin.Context) { ctx := c.Request.Context() // Propagate context var req RefreshTokenRequest if err := c.ShouldBindJSON(&req); err != nil { models.RespondWithError(c, models.NewErrValidation("invalid_request_body_refresh", map[string]string{"body": "Invalid request body"}, err)) return } if err := h.validate.Struct(req); err != nil { validationErrors := models.ExtractValidationErrors(err) models.RespondWithError(c, models.NewErrValidation("input_validation_failed_refresh", validationErrors, err)) return } resp, err := h.authService.RefreshToken(ctx, req.RefreshToken) if err != nil { if errors.Is(err, auth.ErrInvalidToken) || errors.Is(err, auth.ErrRefreshTokenNotFound) || errors.Is(err, auth.ErrTokenExpired) { models.RespondWithError(c, models.NewErrUnauthorized("invalid_refresh_token", err)) } else { models.RespondWithError(c, models.NewErrInternalServer("refresh_token_failed", err)) } return } c.JSON(http.StatusOK, resp) } // LogoutRequest defines the structure for logout requests. type LogoutRequest struct { Token string `json:"token" validate:"required"` // Assuming the client sends the token to be invalidated } // Logout handles user logout func (h *AuthHandler) Logout(c *gin.Context) { ctx := c.Request.Context() // Propagate context var req LogoutRequest if err := c.ShouldBindJSON(&req); err != nil { models.RespondWithError(c, models.NewErrValidation("invalid_request_body_logout", map[string]string{"body": "Invalid request body"}, err)) return } if err := h.validate.Struct(req); err != nil { validationErrors := models.ExtractValidationErrors(err) models.RespondWithError(c, models.NewErrValidation("input_validation_failed_logout", validationErrors, err)) return } err := h.authService.Logout(ctx, req.Token) if err != nil { if errors.Is(err, auth.ErrInvalidToken) { models.RespondWithError(c, models.NewErrBadRequest("logout_failed_invalid_token", err)) } else { models.RespondWithError(c, models.NewErrInternalServer("logout_failed", err)) } return } c.Status(http.StatusNoContent) }