refact: fixing userpin statement

This commit is contained in:
pahmiudahgede 2025-02-14 16:12:21 +07:00
parent b741120918
commit 170fc79148
4 changed files with 75 additions and 103 deletions

View File

@ -1,18 +1,11 @@
package dto
import (
"fmt"
"regexp"
"strings"
)
type UserPinResponseDTO struct {
ID string `json:"id"`
UserID string `json:"userId"`
Pin string `json:"userpin"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type RequestUserPinDTO struct {
Pin string `json:"userpin"`
}
@ -24,10 +17,8 @@ func (r *RequestUserPinDTO) Validate() (map[string][]string, bool) {
errors["pin"] = append(errors["pin"], "Pin is required")
}
if len(r.Pin) != 6 {
errors["pin"] = append(errors["pin"], "Pin harus terdiri dari 6 digit")
} else if !isNumeric(r.Pin) {
errors["pin"] = append(errors["pin"], "Pin harus berupa angka")
if err := validatePin(r.Pin); err != nil {
errors["pin"] = append(errors["pin"], err.Error())
}
if len(errors) > 0 {
@ -42,17 +33,15 @@ type UpdateUserPinDTO struct {
NewPin string `json:"new_pin"`
}
func (r *UpdateUserPinDTO) Validate() (map[string][]string, bool) {
func (u *UpdateUserPinDTO) Validate() (map[string][]string, bool) {
errors := make(map[string][]string)
if strings.TrimSpace(r.OldPin) == "" {
if strings.TrimSpace(u.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 err := validatePin(u.NewPin); err != nil {
errors["new_pin"] = append(errors["new_pin"], err.Error())
}
if len(errors) > 0 {
@ -66,3 +55,12 @@ func isNumeric(s string) bool {
re := regexp.MustCompile(`^[0-9]+$`)
return re.MatchString(s)
}
func validatePin(pin string) error {
if len(pin) != 6 {
return fmt.Errorf("pin harus terdiri dari 6 digit")
} else if !isNumeric(pin) {
return fmt.Errorf("pin harus berupa angka")
}
return nil
}

View File

@ -21,6 +21,7 @@ func (h *UserPinHandler) VerifyUserPin(c *fiber.Ctx) error {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
}
// Validasi input pin
errors, valid := requestUserPinDTO.Validate()
if !valid {
return utils.ValidationErrorResponse(c, errors)
@ -31,12 +32,12 @@ func (h *UserPinHandler) VerifyUserPin(c *fiber.Ctx) error {
return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
}
_, err := h.UserPinService.VerifyUserPin(requestUserPinDTO.Pin, userID)
message, err := h.UserPinService.VerifyUserPin(userID, requestUserPinDTO.Pin)
if err != nil {
return utils.GenericResponse(c, fiber.StatusUnauthorized, "pin yang anda masukkan salah")
return utils.GenericResponse(c, fiber.StatusUnauthorized, err.Error())
}
return utils.SuccessResponse(c, map[string]string{"data": "pin yang anda masukkan benar"}, "Pin verification successful")
return utils.GenericResponse(c, fiber.StatusOK, message)
}
func (h *UserPinHandler) CheckPinStatus(c *fiber.Ctx) error {
@ -45,16 +46,16 @@ func (h *UserPinHandler) CheckPinStatus(c *fiber.Ctx) error {
return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
}
status, _, err := h.UserPinService.CheckPinStatus(userID)
status, err := h.UserPinService.CheckPinStatus(userID)
if err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
}
if status == "Pin not created" {
return utils.GenericResponse(c, fiber.StatusBadRequest, "pin belum dibuat")
return utils.GenericResponse(c, fiber.StatusBadRequest, "Pin belum dibuat")
}
return utils.SuccessResponse(c, map[string]string{"data": "pin sudah dibuat"}, "Pin status retrieved successfully")
return utils.GenericResponse(c, fiber.StatusOK, "Pin sudah dibuat")
}
func (h *UserPinHandler) CreateUserPin(c *fiber.Ctx) error {
@ -70,12 +71,13 @@ func (h *UserPinHandler) CreateUserPin(c *fiber.Ctx) error {
userID := c.Locals("userID").(string)
userPinResponse, err := h.UserPinService.CreateUserPin(userID, requestUserPinDTO.Pin)
message, err := h.UserPinService.CreateUserPin(userID, requestUserPinDTO.Pin)
if err != nil {
return utils.GenericResponse(c, fiber.StatusConflict, err.Error())
}
return utils.CreateResponse(c, userPinResponse, "User pin created successfully")
return utils.GenericResponse(c, fiber.StatusCreated, message)
}
func (h *UserPinHandler) UpdateUserPin(c *fiber.Ctx) error {
@ -91,10 +93,10 @@ func (h *UserPinHandler) UpdateUserPin(c *fiber.Ctx) error {
userID := c.Locals("userID").(string)
userPinResponse, err := h.UserPinService.UpdateUserPin(userID, requestUserPinDTO.OldPin, requestUserPinDTO.NewPin)
message, err := h.UserPinService.UpdateUserPin(userID, requestUserPinDTO.OldPin, requestUserPinDTO.NewPin)
if err != nil {
return utils.GenericResponse(c, fiber.StatusBadRequest, err.Error())
}
return utils.SuccessResponse(c, userPinResponse, "User pin updated successfully")
return utils.GenericResponse(c, fiber.StatusOK, message)
}

View File

@ -24,6 +24,10 @@ func (r *userPinRepository) FindByUserID(userID string) (*model.UserPin, error)
var userPin model.UserPin
err := r.DB.Where("user_id = ?", userID).First(&userPin).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, err
}
return &userPin, nil
@ -52,4 +56,4 @@ func (r *userPinRepository) Update(userPin *model.UserPin) error {
return err
}
return nil
}
}

View File

@ -4,7 +4,6 @@ import (
"fmt"
"time"
"github.com/pahmiudahgede/senggoldong/dto"
"github.com/pahmiudahgede/senggoldong/internal/repositories"
"github.com/pahmiudahgede/senggoldong/model"
"github.com/pahmiudahgede/senggoldong/utils"
@ -12,10 +11,10 @@ import (
)
type UserPinService interface {
CreateUserPin(userID, pin string) (*dto.UserPinResponseDTO, error)
VerifyUserPin(userID, pin string) (*dto.UserPinResponseDTO, error)
CheckPinStatus(userID string) (string, *dto.UserPinResponseDTO, error)
UpdateUserPin(userID, oldPin, newPin string) (*dto.UserPinResponseDTO, error)
CreateUserPin(userID, pin string) (string, error)
VerifyUserPin(userID, pin string) (string, error)
CheckPinStatus(userID string) (string, error)
UpdateUserPin(userID, oldPin, newPin string) (string, error)
}
type userPinService struct {
@ -26,62 +25,53 @@ func NewUserPinService(userPinRepo repositories.UserPinRepository) UserPinServic
return &userPinService{UserPinRepo: userPinRepo}
}
func (s *userPinService) VerifyUserPin(pin string, userID string) (*dto.UserPinResponseDTO, error) {
func (s *userPinService) VerifyUserPin(userID, pin string) (string, error) {
if pin == "" {
return "", fmt.Errorf("pin tidak boleh kosong")
}
userPin, err := s.UserPinRepo.FindByUserID(userID)
if err != nil {
return nil, fmt.Errorf("user pin not found")
return "", fmt.Errorf("error fetching user pin: %v", err)
}
if userPin == nil {
return "", fmt.Errorf("user pin not found")
}
err = bcrypt.CompareHashAndPassword([]byte(userPin.Pin), []byte(pin))
if err != nil {
return nil, fmt.Errorf("incorrect pin")
return "", fmt.Errorf("incorrect pin")
}
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,
}
return userPinResponse, nil
return "Pin yang anda masukkan benar", nil
}
func (s *userPinService) CheckPinStatus(userID string) (string, *dto.UserPinResponseDTO, error) {
func (s *userPinService) CheckPinStatus(userID string) (string, error) {
userPin, err := s.UserPinRepo.FindByUserID(userID)
if err != nil {
return "Pin not created", nil, nil
return "", fmt.Errorf("error checking pin status: %v", err)
}
if userPin == nil {
return "Pin not created", nil
}
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,
}
return "Pin already created", userPinResponse, nil
return "Pin already created", nil
}
func (s *userPinService) CreateUserPin(userID, pin string) (*dto.UserPinResponseDTO, error) {
func (s *userPinService) CreateUserPin(userID, pin string) (string, error) {
existingPin, err := s.UserPinRepo.FindByUserID(userID)
if err != nil && existingPin != nil {
return nil, fmt.Errorf("you have already created a pin, you don't need to create another one")
if err != nil {
return "", fmt.Errorf("error checking existing pin: %v", err)
}
if existingPin != nil {
return "", fmt.Errorf("you have already created a pin, you don't need to create another one")
}
hashedPin, err := bcrypt.GenerateFromPassword([]byte(pin), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("error hashing the pin: %v", err)
return "", fmt.Errorf("error hashing the pin: %v", err)
}
newPin := model.UserPin{
@ -91,74 +81,52 @@ func (s *userPinService) CreateUserPin(userID, pin string) (*dto.UserPinResponse
err = s.UserPinRepo.Create(&newPin)
if err != nil {
return nil, fmt.Errorf("error creating user pin: %v", err)
}
createdAt, _ := utils.FormatDateToIndonesianFormat(newPin.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(newPin.UpdatedAt)
userPinResponse := &dto.UserPinResponseDTO{
ID: newPin.ID,
UserID: newPin.UserID,
Pin: newPin.Pin,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
return "", fmt.Errorf("error creating user pin: %v", err)
}
cacheKey := fmt.Sprintf("userpin:%s", userID)
cacheData := map[string]interface{}{
"data": userPinResponse,
}
cacheData := map[string]interface{}{"data": newPin}
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
if err != nil {
fmt.Printf("Error caching new user pin to Redis: %v\n", err)
}
return userPinResponse, nil
return "Pin berhasil dibuat", nil
}
func (s *userPinService) UpdateUserPin(userID, oldPin, newPin string) (*dto.UserPinResponseDTO, error) {
func (s *userPinService) UpdateUserPin(userID, oldPin, newPin string) (string, error) {
userPin, err := s.UserPinRepo.FindByUserID(userID)
if err != nil {
return nil, fmt.Errorf("user pin not found")
return "", fmt.Errorf("error fetching user pin: %v", err)
}
if userPin == nil {
return "", fmt.Errorf("user pin not found")
}
err = bcrypt.CompareHashAndPassword([]byte(userPin.Pin), []byte(oldPin))
if err != nil {
return nil, fmt.Errorf("incorrect old pin")
return "", 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)
return "", 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,
return "", fmt.Errorf("error updating user pin: %v", err)
}
cacheKey := fmt.Sprintf("userpin:%s", userID)
cacheData := map[string]interface{}{
"data": userPinResponse,
}
cacheData := map[string]interface{}{"data": userPin}
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
return "Pin berhasil diperbarui", nil
}