630 lines
21 KiB
Go
630 lines
21 KiB
Go
package handlers
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
type CheckPhoneEmailExistReq struct {
|
|
Email string `json:"email" example:"john.doe@example.com"`
|
|
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
|
}
|
|
type CheckPhoneEmailExistRes struct {
|
|
EmailExist bool `json:"email_exist"`
|
|
PhoneNumberExist bool `json:"phone_number_exist"`
|
|
}
|
|
|
|
// CheckPhoneEmailExist godoc
|
|
// @Summary Check if phone number or email exist
|
|
// @Description Check if phone number or email exist
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param checkPhoneEmailExist body CheckPhoneEmailExistReq true "Check phone number or email exist"
|
|
// @Success 200 {object} CheckPhoneEmailExistRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/checkPhoneEmailExist [post]
|
|
func (h *Handler) CheckPhoneEmailExist(c *fiber.Ctx) error {
|
|
|
|
var req CheckPhoneEmailExistReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse CheckPhoneEmailExist request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
emailExist, phoneExist, err := h.userSvc.CheckPhoneEmailExist(c.Context(), req.PhoneNumber, req.Email)
|
|
if err != nil {
|
|
h.logger.Error("Failed to check phone/email existence", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check phone/email existence")
|
|
}
|
|
|
|
res := CheckPhoneEmailExistRes{
|
|
EmailExist: emailExist,
|
|
PhoneNumberExist: phoneExist,
|
|
}
|
|
return response.WriteJSON(c, fiber.StatusOK, "Check successful", res, nil)
|
|
}
|
|
|
|
type RegisterCodeReq struct {
|
|
Email string `json:"email" example:"john.doe@example.com"`
|
|
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
|
}
|
|
|
|
// SendRegisterCode godoc
|
|
// @Summary Send register code
|
|
// @Description Send register code
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param registerCode body RegisterCodeReq true "Send register code"
|
|
// @Success 200 {object} response.APIResponse
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/sendRegisterCode [post]
|
|
func (h *Handler) SendRegisterCode(c *fiber.Ctx) error {
|
|
|
|
var req RegisterCodeReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse SendRegisterCode request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
var sentTo string
|
|
var medium domain.OtpMedium
|
|
if req.Email != "" {
|
|
sentTo = req.Email
|
|
medium = domain.OtpMediumEmail
|
|
} else if req.PhoneNumber != "" {
|
|
sentTo = req.PhoneNumber
|
|
medium = domain.OtpMediumSms
|
|
} else {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
|
}
|
|
|
|
if err := h.userSvc.SendRegisterCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
|
h.logger.Error("Failed to send register code", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send register code")
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
|
}
|
|
|
|
type RegisterUserReq struct {
|
|
FirstName string `json:"first_name" example:"John"`
|
|
LastName string `json:"last_name" example:"Doe"`
|
|
Email string `json:"email" example:"john.doe@example.com"`
|
|
PhoneNumber string `json:"phone_number" example:"1234567890"`
|
|
Password string `json:"password" example:"password123"`
|
|
Otp string `json:"otp" example:"123456"`
|
|
ReferalCode string `json:"referal_code" example:"ABC123"`
|
|
}
|
|
|
|
// RegisterUser godoc
|
|
// @Summary Register user
|
|
// @Description Register user
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param registerUser body RegisterUserReq true "Register user"
|
|
// @Success 200 {object} response.APIResponse
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/register [post]
|
|
func (h *Handler) RegisterUser(c *fiber.Ctx) error {
|
|
|
|
var req RegisterUserReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse RegisterUser request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
user := domain.RegisterUserReq{
|
|
FirstName: req.FirstName,
|
|
LastName: req.LastName,
|
|
Email: req.Email,
|
|
PhoneNumber: req.PhoneNumber,
|
|
Password: req.Password,
|
|
Otp: req.Otp,
|
|
ReferralCode: req.ReferalCode,
|
|
OtpMedium: domain.OtpMediumEmail,
|
|
}
|
|
medium, err := getMedium(req.Email, req.PhoneNumber)
|
|
if err != nil {
|
|
h.logger.Error("RegisterUser failed", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
}
|
|
|
|
user.OtpMedium = medium
|
|
|
|
newUser, err := h.userSvc.RegisterUser(c.Context(), user)
|
|
if err != nil {
|
|
if errors.Is(err, domain.ErrOtpAlreadyUsed) {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Otp already used")
|
|
}
|
|
if errors.Is(err, domain.ErrOtpExpired) {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Otp expired")
|
|
}
|
|
if errors.Is(err, domain.ErrInvalidOtp) {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid otp")
|
|
}
|
|
if errors.Is(err, domain.ErrOtpNotFound) {
|
|
return fiber.NewError(fiber.StatusBadRequest, "User already exist")
|
|
}
|
|
h.logger.Error("RegisterUser failed", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Unknown Error")
|
|
}
|
|
|
|
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
|
|
UserID: newUser.ID,
|
|
IsWithdraw: true,
|
|
IsBettable: true,
|
|
})
|
|
if err != nil {
|
|
h.logger.Error("Failed to create wallet for user", "userID", newUser.ID, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create user wallet")
|
|
}
|
|
|
|
if req.ReferalCode != "" {
|
|
err = h.referralSvc.ProcessReferral(c.Context(), req.PhoneNumber, req.ReferalCode)
|
|
if err != nil {
|
|
h.logger.Warn("Failed to process referral during registration", "phone", req.PhoneNumber, "code", req.ReferalCode, "error", err)
|
|
}
|
|
}
|
|
|
|
// TODO: Remove later
|
|
_, err = h.walletSvc.AddToWallet(
|
|
c.Context(), newWallet.ID, domain.ToCurrency(100.0), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{})
|
|
|
|
if err != nil {
|
|
h.logger.Error("Failed to update wallet for user", "userID", newUser.ID, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user wallet")
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Registration successful", nil, nil)
|
|
}
|
|
|
|
type ResetCodeReq struct {
|
|
Email string `json:"email" example:"john.doe@example.com"`
|
|
PhoneNumber string `json:"phone_number" validate:"required_without=Email" example:"1234567890"`
|
|
// Provider domain.OtpProvider `json:"provider" validate:"required" example:"twilio"`
|
|
}
|
|
|
|
// SendResetCode godoc
|
|
// @Summary Send reset code
|
|
// @Description Send reset code
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param resetCode body ResetCodeReq true "Send reset code"
|
|
// @Success 200 {object} response.APIResponse
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/sendResetCode [post]
|
|
func (h *Handler) SendResetCode(c *fiber.Ctx) error {
|
|
|
|
var req ResetCodeReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse SendResetCode request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
var sentTo string
|
|
var medium domain.OtpMedium
|
|
if req.Email != "" {
|
|
sentTo = req.Email
|
|
medium = domain.OtpMediumEmail
|
|
} else if req.PhoneNumber != "" {
|
|
sentTo = req.PhoneNumber
|
|
medium = domain.OtpMediumSms
|
|
} else {
|
|
return fiber.NewError(fiber.StatusBadRequest, "Email or PhoneNumber must be provided")
|
|
}
|
|
|
|
if err := h.userSvc.SendResetCode(c.Context(), medium, sentTo, "twilio"); err != nil {
|
|
h.logger.Error("Failed to send reset code", "error", err)
|
|
fmt.Println(err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to send reset code")
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Code sent successfully", nil, nil)
|
|
}
|
|
|
|
type ResetPasswordReq struct {
|
|
Email string `json:"email,omitempty" validate:"required_without=PhoneNumber,omitempty,email" example:"john.doe@example.com"`
|
|
PhoneNumber string `json:"phone_number,omitempty" validate:"required_without=Email,omitempty" example:"1234567890"`
|
|
Password string `json:"password" validate:"required,min=8" example:"newpassword123"`
|
|
Otp string `json:"otp" validate:"required" example:"123456"`
|
|
}
|
|
|
|
// ResetPassword godoc
|
|
// @Summary Reset password
|
|
// @Description Reset password
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param resetPassword body ResetPasswordReq true "Reset password"
|
|
// @Success 200 {object} response.APIResponse
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/resetPassword [post]
|
|
func (h *Handler) ResetPassword(c *fiber.Ctx) error {
|
|
|
|
var req ResetPasswordReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse ResetPassword request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
medium, err := getMedium(req.Email, req.PhoneNumber)
|
|
if err != nil {
|
|
h.logger.Error("Failed to determine medium for ResetPassword", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
}
|
|
|
|
resetReq := domain.ResetPasswordReq{
|
|
Email: req.Email,
|
|
PhoneNumber: req.PhoneNumber,
|
|
Password: req.Password,
|
|
Otp: req.Otp,
|
|
OtpMedium: medium,
|
|
}
|
|
|
|
if err := h.userSvc.ResetPassword(c.Context(), resetReq); err != nil {
|
|
h.logger.Error("Failed to reset password", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset password")
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "Password reset successful", nil, nil)
|
|
}
|
|
|
|
type UserProfileRes struct {
|
|
ID int64 `json:"id"`
|
|
FirstName string `json:"first_name"`
|
|
LastName string `json:"last_name"`
|
|
Email string `json:"email"`
|
|
PhoneNumber string `json:"phone_number"`
|
|
Role domain.Role `json:"role"`
|
|
EmailVerified bool `json:"email_verified"`
|
|
PhoneVerified bool `json:"phone_verified"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
LastLogin time.Time `json:"last_login"`
|
|
SuspendedAt time.Time `json:"suspended_at"`
|
|
Suspended bool `json:"suspended"`
|
|
}
|
|
|
|
// UserProfile godoc
|
|
// @Summary Get user profile
|
|
// @Description Get user profile
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Success 200 {object} UserProfileRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Security Bearer
|
|
// @Router /user/profile [get]
|
|
func (h *Handler) UserProfile(c *fiber.Ctx) error {
|
|
|
|
userID, ok := c.Locals("user_id").(int64)
|
|
if !ok || userID == 0 {
|
|
h.logger.Error("Invalid user ID in context")
|
|
return fiber.NewError(fiber.StatusUnauthorized, "Invalid user identification")
|
|
}
|
|
|
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to get user profile", "userID", userID, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user profile")
|
|
}
|
|
|
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
|
if err != nil {
|
|
if err != authentication.ErrRefreshTokenNotFound {
|
|
h.logger.Error("Failed to get user last login", "userID", userID, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
|
}
|
|
|
|
lastLogin = &user.CreatedAt
|
|
}
|
|
res := UserProfileRes{
|
|
ID: user.ID,
|
|
FirstName: user.FirstName,
|
|
LastName: user.LastName,
|
|
Email: user.Email,
|
|
PhoneNumber: user.PhoneNumber,
|
|
Role: user.Role,
|
|
EmailVerified: user.EmailVerified,
|
|
PhoneVerified: user.PhoneVerified,
|
|
CreatedAt: user.CreatedAt,
|
|
UpdatedAt: user.UpdatedAt,
|
|
SuspendedAt: user.SuspendedAt,
|
|
Suspended: user.Suspended,
|
|
LastLogin: *lastLogin,
|
|
}
|
|
return response.WriteJSON(c, fiber.StatusOK, "User profile retrieved successfully", res, nil)
|
|
}
|
|
|
|
// Helper function (unchanged)
|
|
func getMedium(email, phoneNumber string) (domain.OtpMedium, error) {
|
|
if email != "" {
|
|
return domain.OtpMediumEmail, nil
|
|
}
|
|
if phoneNumber != "" {
|
|
return domain.OtpMediumSms, nil
|
|
}
|
|
return "", errors.New("both email and phone number are empty")
|
|
}
|
|
|
|
type SearchUserByNameOrPhoneReq struct {
|
|
SearchString string `json:"query"`
|
|
Role *domain.Role `json:"role,omitempty"`
|
|
}
|
|
|
|
// SearchUserByNameOrPhone godoc
|
|
// @Summary Search for user using name or phone
|
|
// @Description Search for user using name or phone
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param searchUserByNameOrPhone body SearchUserByNameOrPhoneReq true "Search for using his name or phone"
|
|
// @Success 200 {object} UserProfileRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/search [post]
|
|
func (h *Handler) SearchUserByNameOrPhone(c *fiber.Ctx) error {
|
|
// TODO: Add filtering by role based on which user is calling this
|
|
var req SearchUserByNameOrPhoneReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "Invalid request",
|
|
})
|
|
}
|
|
valErrs, ok := h.validator.Validate(c, req)
|
|
if !ok {
|
|
response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
return nil
|
|
}
|
|
companyID := c.Locals("company_id").(domain.ValidInt64)
|
|
|
|
users, err := h.userSvc.SearchUserByNameOrPhone(c.Context(), req.SearchString, req.Role, companyID)
|
|
if err != nil {
|
|
h.logger.Error("SearchUserByNameOrPhone failed", "error", err)
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Internal server error",
|
|
})
|
|
}
|
|
var res []UserProfileRes = make([]UserProfileRes, 0, len(users))
|
|
for _, user := range users {
|
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
|
if err != nil {
|
|
if err != authentication.ErrRefreshTokenNotFound {
|
|
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
|
}
|
|
|
|
lastLogin = &user.CreatedAt
|
|
}
|
|
res = append(res, UserProfileRes{
|
|
ID: user.ID,
|
|
FirstName: user.FirstName,
|
|
LastName: user.LastName,
|
|
Email: user.Email,
|
|
PhoneNumber: user.PhoneNumber,
|
|
Role: user.Role,
|
|
EmailVerified: user.EmailVerified,
|
|
PhoneVerified: user.PhoneVerified,
|
|
CreatedAt: user.CreatedAt,
|
|
UpdatedAt: user.UpdatedAt,
|
|
SuspendedAt: user.SuspendedAt,
|
|
Suspended: user.Suspended,
|
|
LastLogin: *lastLogin,
|
|
})
|
|
}
|
|
return response.WriteJSON(c, fiber.StatusOK, "Search Successful", res, nil)
|
|
|
|
}
|
|
|
|
// GetUserByID godoc
|
|
// @Summary Get user by id
|
|
// @Description Get a single user by id
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path int true "User ID"
|
|
// @Success 200 {object} UserProfileRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 401 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/single/{id} [get]
|
|
func (h *Handler) GetUserByID(c *fiber.Ctx) error {
|
|
// branchId := int64(12) //c.Locals("branch_id").(int64)
|
|
// filter := user.Filter{
|
|
// Role: string(domain.RoleUser),
|
|
// BranchId: user.ValidBranchId{
|
|
// Value: branchId,
|
|
// Valid: true,
|
|
// },
|
|
// Page: c.QueryInt("page", 1),
|
|
// PageSize: c.QueryInt("page_size", 10),
|
|
// }
|
|
// valErrs, ok := validator.Validate(c, filter)
|
|
// if !ok {
|
|
// return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
// }
|
|
|
|
userIDstr := c.Params("id")
|
|
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
|
if err != nil {
|
|
h.logger.Error("failed to fetch user using UserID", "error", err)
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid cashier ID", nil, nil)
|
|
}
|
|
|
|
user, err := h.userSvc.GetUserByID(c.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Get User By ID failed", "error", err)
|
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil)
|
|
}
|
|
|
|
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
|
|
if err != nil {
|
|
if err != authentication.ErrRefreshTokenNotFound {
|
|
h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
|
|
}
|
|
|
|
lastLogin = &user.CreatedAt
|
|
}
|
|
|
|
res := UserProfileRes{
|
|
ID: user.ID,
|
|
FirstName: user.FirstName,
|
|
LastName: user.LastName,
|
|
Email: user.Email,
|
|
PhoneNumber: user.PhoneNumber,
|
|
Role: user.Role,
|
|
EmailVerified: user.EmailVerified,
|
|
PhoneVerified: user.PhoneVerified,
|
|
CreatedAt: user.CreatedAt,
|
|
UpdatedAt: user.UpdatedAt,
|
|
SuspendedAt: user.SuspendedAt,
|
|
Suspended: user.Suspended,
|
|
LastLogin: *lastLogin,
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil)
|
|
|
|
}
|
|
|
|
// DeleteUser godoc
|
|
// @Summary Delete user by ID
|
|
// @Description Delete a user by their ID
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path int true "User ID"
|
|
// @Success 200 {object} response.APIResponse
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/delete/{id} [delete]
|
|
func (h *Handler) DeleteUser(c *fiber.Ctx) error {
|
|
userIDstr := c.Params("id")
|
|
userID, err := strconv.ParseInt(userIDstr, 10, 64)
|
|
if err != nil {
|
|
h.logger.Error("DeleteUser failed", "error", err)
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", nil, nil)
|
|
}
|
|
|
|
err = h.userSvc.DeleteUser(c.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to delete user", "userID", userID, "error", err)
|
|
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to delete user", nil, nil)
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "User deleted successfully", nil, nil)
|
|
}
|
|
|
|
type UpdateUserSuspendReq struct {
|
|
UserID int64 `json:"user_id" validate:"required" example:"123"`
|
|
Suspended bool `json:"suspended" validate:"required" example:"true"`
|
|
}
|
|
type UpdateUserSuspendRes struct {
|
|
UserID int64 `json:"user_id"`
|
|
Suspended bool `json:"suspended"`
|
|
}
|
|
|
|
// UpdateUserSuspend godoc
|
|
// @Summary Suspend or unsuspend a user
|
|
// @Description Suspend or unsuspend a user
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param updateUserSuspend body UpdateUserSuspendReq true "Suspend or unsuspend a user"
|
|
// @Success 200 {object} UpdateUserSuspendRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/suspend [post]
|
|
func (h *Handler) UpdateUserSuspend(c *fiber.Ctx) error {
|
|
var req UpdateUserSuspendReq
|
|
if err := c.BodyParser(&req); err != nil {
|
|
h.logger.Error("Failed to parse UpdateUserSuspend request", "error", err)
|
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
}
|
|
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
|
|
}
|
|
|
|
err := h.userSvc.UpdateUserSuspend(c.Context(), req.UserID, req.Suspended)
|
|
if err != nil {
|
|
h.logger.Error("Failed to update user suspend status", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update user suspend status")
|
|
}
|
|
|
|
res := UpdateUserSuspendRes{
|
|
UserID: req.UserID,
|
|
Suspended: req.Suspended,
|
|
}
|
|
return response.WriteJSON(c, fiber.StatusOK, "User suspend status updated successfully", res, nil)
|
|
}
|
|
|
|
// GetBetByUserID godoc
|
|
// @Summary Gets user bets
|
|
// @Description Gets user bets
|
|
// @Tags user
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Success 200 {array} domain.BetRes
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /user/bets [get]
|
|
func (h *Handler) GetBetByUserID(c *fiber.Ctx) error {
|
|
userID, ok := c.Locals("user_id").(int64)
|
|
if !ok || userID == 0 {
|
|
h.logger.Error("Invalid user ID in context")
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user identification")
|
|
}
|
|
|
|
bets, err := h.betSvc.GetBetByUserID(c.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to get bets", "error", err)
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve bets")
|
|
}
|
|
|
|
res := make([]domain.BetRes, len(bets))
|
|
for i, bet := range bets {
|
|
res[i] = domain.ConvertBet(bet)
|
|
}
|
|
|
|
return response.WriteJSON(c, fiber.StatusOK, "User bets retrieved successfully", res, nil)
|
|
}
|