package handlers import ( "errors" "log/slog" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication" jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator" "github.com/gofiber/fiber/v2" ) type loginCustomerReq struct { Email string `json:"email" example:"john.doe@example.com"` PhoneNumber string `json:"phone_number" example:"1234567890"` Password string `json:"password" example:"password123"` } type loginCustomerRes struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` Role string `json:"role"` } // LoginCustomer godoc // @Summary Login customer // @Description Login customer // @Tags auth // @Accept json // @Produce json // @Param login body loginCustomerReq true "Login customer" // @Success 200 {object} loginCustomerRes // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /auth/login [post] func LoginCustomer( logger *slog.Logger, authSvc *authentication.Service, validator *customvalidator.CustomValidator, JwtConfig jwtutil.JwtConfig) fiber.Handler { return func(c *fiber.Ctx) error { var req loginCustomerReq if err := c.BodyParser(&req); err != nil { logger.Error("Login failed", "error", err) response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } successRes, err := authSvc.Login(c.Context(), req.Email, req.PhoneNumber, req.Password) if err != nil { logger.Info("Login failed", "error", err) if errors.Is(err, authentication.ErrInvalidPassword) { response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid password or not registered", nil, nil) return nil } if errors.Is(err, authentication.ErrUserNotFound) { response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid password or not registered", nil, nil) return nil } logger.Error("Login failed", "error", err) response.WriteJSON(c, fiber.StatusInternalServerError, "Internal server error", nil, nil) return nil } accessToken, err := jwtutil.CreateJwt(successRes.UserId, successRes.Role, JwtConfig.JwtAccessKey, JwtConfig.JwtAccessExpiry) res := loginCustomerRes{ AccessToken: accessToken, RefreshToken: successRes.RfToken, Role: string(successRes.Role), } return response.WriteJSON(c, fiber.StatusOK, "Login successful", res, nil) } } type refreshToken struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` } // RefreshToken godoc // @Summary Refresh token // @Description Refresh token // @Tags auth // @Accept json // @Produce json // @Param refresh body refreshToken true "tokens" // @Success 200 {object} loginCustomerRes // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /auth/refresh [post] func RefreshToken(logger *slog.Logger, authSvc *authentication.Service, validator *customvalidator.CustomValidator, JwtConfig jwtutil.JwtConfig) fiber.Handler { return func(c *fiber.Ctx) error { var req refreshToken if err := c.BodyParser(&req); err != nil { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } rf, err := authSvc.RefreshToken(c.Context(), req.RefreshToken) if err != nil { logger.Info("Refresh token failed", "error", err) if errors.Is(err, authentication.ErrExpiredToken) { response.WriteJSON(c, fiber.StatusUnauthorized, "The refresh token has expired", nil, nil) return nil } if errors.Is(err, authentication.ErrRefreshTokenNotFound) { response.WriteJSON(c, fiber.StatusUnauthorized, "Refresh token not found", nil, nil) return nil } logger.Error("Refresh token failed", "error", err) response.WriteJSON(c, fiber.StatusInternalServerError, "Internal server error", nil, nil) return nil } accessToken, err := jwtutil.CreateJwt(0, "", JwtConfig.JwtAccessKey, JwtConfig.JwtAccessExpiry) if err != nil { logger.Error("Create jwt failed", "error", err) response.WriteJSON(c, fiber.StatusInternalServerError, "Internal server error", nil, nil) return nil } res := loginCustomerRes{ AccessToken: accessToken, RefreshToken: rf, } return response.WriteJSON(c, fiber.StatusOK, "refresh successful", res, nil) } } type logoutReq struct { RefreshToken string `json:"refresh_token"` } // LogOutCustomer godoc // @Summary Logout customer // @Description Logout customer // @Tags auth // @Accept json // @Produce json // @Param logout body logoutReq true "Logout customer" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /auth/logout [post] func LogOutCustomer( logger *slog.Logger, authSvc *authentication.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { var req logoutReq if err := c.BodyParser(&req); err != nil { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } err := authSvc.Logout(c.Context(), req.RefreshToken) if err != nil { logger.Info("Logout failed", "error", err) if errors.Is(err, authentication.ErrExpiredToken) { response.WriteJSON(c, fiber.StatusUnauthorized, "The refresh token has expired", nil, nil) return nil } if errors.Is(err, authentication.ErrRefreshTokenNotFound) { response.WriteJSON(c, fiber.StatusUnauthorized, "Refresh token not found", nil, nil) return nil } logger.Error("Logout failed", "error", err) response.WriteJSON(c, fiber.StatusInternalServerError, "Internal server error", nil, nil) return nil } return response.WriteJSON(c, fiber.StatusOK, "Logout successful", nil, nil) } }