feat: add feature update userpin

This commit is contained in:
pahmiudahgede 2025-02-05 12:43:14 +07:00
parent bb85fe64d7
commit 4f97664a6c
6 changed files with 105 additions and 3 deletions

View File

@ -37,6 +37,31 @@ func (r *RequestUserPinDTO) Validate() (map[string][]string, bool) {
return nil, true return nil, true
} }
type UpdateUserPinDTO struct {
OldPin string `json:"old_pin"`
NewPin string `json:"new_pin"`
}
func (r *UpdateUserPinDTO) Validate() (map[string][]string, bool) {
errors := make(map[string][]string)
if strings.TrimSpace(r.OldPin) == "" {
errors["old_pin"] = append(errors["old_pin"], "Old pin is required")
}
if strings.TrimSpace(r.NewPin) == "" {
errors["new_pin"] = append(errors["new_pin"], "New pin is required")
} else if len(r.NewPin) < 6 {
errors["new_pin"] = append(errors["new_pin"], "New pin must be at least 6 digits")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}
func isNumeric(s string) bool { func isNumeric(s string) bool {
re := regexp.MustCompile(`^[0-9]+$`) re := regexp.MustCompile(`^[0-9]+$`)
return re.MatchString(s) return re.MatchString(s)

View File

@ -77,3 +77,24 @@ func (h *UserPinHandler) CreateUserPin(c *fiber.Ctx) error {
return utils.LogResponse(c, userPinResponse, "User pin created successfully") return utils.LogResponse(c, userPinResponse, "User pin created successfully")
} }
func (h *UserPinHandler) UpdateUserPin(c *fiber.Ctx) error {
var requestUserPinDTO dto.UpdateUserPinDTO
if err := c.BodyParser(&requestUserPinDTO); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
}
errors, valid := requestUserPinDTO.Validate()
if !valid {
return utils.ValidationErrorResponse(c, errors)
}
userID := c.Locals("userID").(string)
userPinResponse, err := h.UserPinService.UpdateUserPin(userID, requestUserPinDTO.OldPin, requestUserPinDTO.NewPin)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusBadRequest, err.Error())
}
return utils.LogResponse(c, userPinResponse, "User pin updated successfully")
}

View File

@ -9,6 +9,7 @@ type UserPinRepository interface {
FindByUserID(userID string) (*model.UserPin, error) FindByUserID(userID string) (*model.UserPin, error)
FindByPin(userPin string) (*model.UserPin, error) FindByPin(userPin string) (*model.UserPin, error)
Create(userPin *model.UserPin) error Create(userPin *model.UserPin) error
Update(userPin *model.UserPin) error
} }
type userPinRepository struct { type userPinRepository struct {
@ -44,3 +45,11 @@ func (r *userPinRepository) Create(userPin *model.UserPin) error {
} }
return nil return nil
} }
func (r *userPinRepository) Update(userPin *model.UserPin) error {
err := r.DB.Save(userPin).Error
if err != nil {
return err
}
return nil
}

View File

@ -15,6 +15,7 @@ type UserPinService interface {
CreateUserPin(userID, pin string) (*dto.UserPinResponseDTO, error) CreateUserPin(userID, pin string) (*dto.UserPinResponseDTO, error)
VerifyUserPin(userID, pin string) (*dto.UserPinResponseDTO, error) VerifyUserPin(userID, pin string) (*dto.UserPinResponseDTO, error)
CheckPinStatus(userID string) (string, *dto.UserPinResponseDTO, error) CheckPinStatus(userID string) (string, *dto.UserPinResponseDTO, error)
UpdateUserPin(userID, oldPin, newPin string) (*dto.UserPinResponseDTO, error)
} }
type userPinService struct { type userPinService struct {
@ -115,3 +116,49 @@ func (s *userPinService) CreateUserPin(userID, pin string) (*dto.UserPinResponse
return userPinResponse, nil return userPinResponse, nil
} }
func (s *userPinService) UpdateUserPin(userID, oldPin, newPin string) (*dto.UserPinResponseDTO, error) {
userPin, err := s.UserPinRepo.FindByUserID(userID)
if err != nil {
return nil, fmt.Errorf("user pin not found")
}
err = bcrypt.CompareHashAndPassword([]byte(userPin.Pin), []byte(oldPin))
if err != nil {
return nil, fmt.Errorf("incorrect old pin")
}
hashedPin, err := bcrypt.GenerateFromPassword([]byte(newPin), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("error hashing the new pin: %v", err)
}
userPin.Pin = string(hashedPin)
err = s.UserPinRepo.Update(userPin)
if err != nil {
return nil, fmt.Errorf("error updating user pin: %v", err)
}
createdAt, _ := utils.FormatDateToIndonesianFormat(userPin.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(userPin.UpdatedAt)
userPinResponse := &dto.UserPinResponseDTO{
ID: userPin.ID,
UserID: userPin.UserID,
Pin: userPin.Pin,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
}
cacheKey := fmt.Sprintf("userpin:%s", userID)
cacheData := map[string]interface{}{
"data": userPinResponse,
}
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
if err != nil {
fmt.Printf("Error caching updated user pin to Redis: %v\n", err)
}
return userPinResponse, nil
}

View File

@ -16,6 +16,6 @@ func UserProfileRouter(api fiber.Router) {
api.Get("/user", middleware.AuthMiddleware, userProfileHandler.GetUserProfile) api.Get("/user", middleware.AuthMiddleware, userProfileHandler.GetUserProfile)
api.Put("/user/update-user", middleware.AuthMiddleware, userProfileHandler.UpdateUserProfile) api.Put("/user/update-user", middleware.AuthMiddleware, userProfileHandler.UpdateUserProfile)
api.Post("/user/update-user-password", middleware.AuthMiddleware, userProfileHandler.UpdateUserPassword) api.Patch("/user/update-user-password", middleware.AuthMiddleware, userProfileHandler.UpdateUserPassword)
api.Put("/user/upload-photoprofile", middleware.AuthMiddleware, userProfileHandler.UpdateUserAvatar) api.Patch("/user/upload-photoprofile", middleware.AuthMiddleware, userProfileHandler.UpdateUserAvatar)
} }

View File

@ -20,5 +20,5 @@ func UserPinRouter(api fiber.Router) {
api.Post("/user/set-pin", middleware.AuthMiddleware, userPinHandler.CreateUserPin) api.Post("/user/set-pin", middleware.AuthMiddleware, userPinHandler.CreateUserPin)
api.Post("/user/verif-pin", middleware.AuthMiddleware, userPinHandler.VerifyUserPin) api.Post("/user/verif-pin", middleware.AuthMiddleware, userPinHandler.VerifyUserPin)
api.Get("/user/cek-pin-status", middleware.AuthMiddleware, userPinHandler.CheckPinStatus) api.Get("/user/cek-pin-status", middleware.AuthMiddleware, userPinHandler.CheckPinStatus)
api.Patch("/user/update-pin", middleware.AuthMiddleware, userPinHandler.UpdateUserPin)
} }