fixing validation for username and full name
This commit is contained in:
parent
433512e3da
commit
f48d61d4e2
|
|
@ -16,10 +16,10 @@ const (
|
|||
)
|
||||
|
||||
type UserRegisterDTO struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password" validate:"required,min=6"`
|
||||
NomorInduk string `json:"nomor_induk" validate:"required"`
|
||||
Name string `json:"name" validate:"required,min=2,max=100,alphaspace"`
|
||||
Username string `json:"username" validate:"required,min=3,max=50,alphanumunderscore,nospace"`
|
||||
Password string `json:"password" validate:"required,min=6,max=100"`
|
||||
NomorInduk string `json:"nomor_induk" validate:"required,min=3,max=50,alphanum"`
|
||||
}
|
||||
|
||||
type UserLoginDTO struct {
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ const (
|
|||
|
||||
type User struct {
|
||||
ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"`
|
||||
NomorInduk *string `json:"nomor_induk,omitempty" gorm:"unique"` // Add this field
|
||||
NomorInduk *string `json:"nomor_induk,omitempty" gorm:"unique"`
|
||||
RoleID uuid.UUID `json:"role_id" gorm:"type:uuid"`
|
||||
Role Role `json:"role" gorm:"foreignKey:RoleID"`
|
||||
Name string `json:"name"`
|
||||
Name string `json:"name" gorm:"unique"`
|
||||
Username string `json:"username" gorm:"unique"`
|
||||
Password string `json:"password"`
|
||||
Status UserStatus `json:"status" gorm:"type:varchar(20);default:'pending'"` // Add status field
|
||||
Status UserStatus `json:"status" gorm:"type:varchar(20);default:'pending'"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ type UsersRepo interface {
|
|||
Post(user entity.User) error
|
||||
GetRoleByDepartment(departmentName string) (entity.Role, error)
|
||||
GetUserByUsername(username string) (entity.User, error)
|
||||
GetUserByNomorInduk(nomorInduk string) (entity.User, error) // Add this
|
||||
CreateUserFromExternal(user entity.User) error // Add this
|
||||
UpdateUserRole(nomorInduk string, roleID uuid.UUID) error // Add this
|
||||
GetAllUsers() ([]entity.User, error) // Add this
|
||||
GetUserByNomorInduk(nomorInduk string) (entity.User, error)
|
||||
CreateUserFromExternal(user entity.User) error
|
||||
UpdateUserRole(nomorInduk string, roleID uuid.UUID) error
|
||||
GetAllUsers() ([]entity.User, error)
|
||||
RegisterUser(user entity.User) error
|
||||
GetPendingUsers() ([]entity.User, error)
|
||||
UpdateUserStatus(userID uuid.UUID, status entity.UserStatus) error
|
||||
|
|
@ -23,6 +23,7 @@ type UsersRepo interface {
|
|||
CreateSuperAdminBypass(user entity.User) error
|
||||
UpdateUserRoleByID(userID uuid.UUID, roleID uuid.UUID) error
|
||||
UpdateUserRoleByUsername(username string, roleID uuid.UUID) error
|
||||
GetUserByName(name string) (entity.User, error)
|
||||
}
|
||||
|
||||
type usersRepo struct {
|
||||
|
|
@ -35,6 +36,13 @@ func NewUsersRepo(db *gorm.DB) UsersRepo {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *usersRepo) GetUserByName(name string) (entity.User, error) {
|
||||
var user entity.User
|
||||
// Use LOWER() function for case-insensitive comparison
|
||||
err := r.db.Where("LOWER(name) = LOWER(?)", name).Preload("Role").First(&user).Error
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (r *usersRepo) UpdateUserRoleByID(userID uuid.UUID, roleID uuid.UUID) error {
|
||||
return r.db.Model(&entity.User{}).Where("id = ?", userID).Update("role_id", roleID).Error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"users_management/m/model/entity"
|
||||
"users_management/m/repository"
|
||||
"users_management/m/utils"
|
||||
"users_management/m/utils/validation"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/google/uuid"
|
||||
|
|
@ -15,10 +16,10 @@ import (
|
|||
type UsersUsecase interface {
|
||||
GetRoleByDepartment(departmentName string) (uuid.UUID, error)
|
||||
GetUserByUsername(username string) (entity.User, error)
|
||||
GetUserByNomorInduk(nomorInduk string) (entity.User, error) // Add this
|
||||
CreateUserFromExternal(nomorInduk, name, roleName string) error // Add this
|
||||
UpdateUserRole(nomorInduk, roleName string) error // Add this
|
||||
GetAllUsers() ([]entity.User, error) // Add this
|
||||
GetUserByNomorInduk(nomorInduk string) (entity.User, error)
|
||||
CreateUserFromExternal(nomorInduk, name, roleName string) error
|
||||
UpdateUserRole(nomorInduk, roleName string) error
|
||||
GetAllUsers() ([]entity.User, error)
|
||||
RegisterUser(registerDTO dto.UserRegisterDTO) error
|
||||
GetPendingUsers() ([]dto.PendingUserResponse, error)
|
||||
ApproveUser(userID uuid.UUID) error
|
||||
|
|
@ -28,6 +29,7 @@ type UsersUsecase interface {
|
|||
UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error
|
||||
UpdateUserRoleByUsername(username, newRoleName string) error
|
||||
GetUserByID(userID uuid.UUID) (entity.User, error)
|
||||
GetUserByName(name string) (entity.User, error)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -37,12 +39,19 @@ type usersUsecase struct {
|
|||
}
|
||||
|
||||
func NewUsersUsecase(userRepo repository.UsersRepo) UsersUsecase {
|
||||
|
||||
validate := validator.New()
|
||||
validation.RegisterCustomValidators(validate)
|
||||
return &usersUsecase{
|
||||
userRepo: userRepo,
|
||||
validate: validator.New(),
|
||||
validate: validate,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *usersUsecase) GetUserByName(name string) (entity.User, error) {
|
||||
return u.userRepo.GetUserByName(name)
|
||||
}
|
||||
|
||||
|
||||
func (u *usersUsecase) CreateSuperAdminBypass(user entity.User) error {
|
||||
return u.userRepo.CreateSuperAdminBypass(user)
|
||||
|
|
@ -92,7 +101,6 @@ func (u *usersUsecase) RegisterUser(registerDTO dto.UserRegisterDTO) error {
|
|||
if err := u.validate.Struct(registerDTO); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if username already exists
|
||||
existingUser, err := u.userRepo.GetUserByUsernameWithStatus(registerDTO.Username)
|
||||
if err == nil && existingUser.ID != uuid.Nil {
|
||||
|
|
@ -107,6 +115,11 @@ func (u *usersUsecase) RegisterUser(registerDTO dto.UserRegisterDTO) error {
|
|||
}
|
||||
}
|
||||
|
||||
existingUserByName, err := u.userRepo.GetUserByName(registerDTO.Name)
|
||||
if err == nil && existingUserByName.ID != uuid.Nil {
|
||||
return errors.New("name already exists, please use a different name")
|
||||
}
|
||||
|
||||
// Hash password
|
||||
hashedPassword, err := utils.HashPassword(registerDTO.Password)
|
||||
if err != nil {
|
||||
|
|
@ -119,7 +132,6 @@ func (u *usersUsecase) RegisterUser(registerDTO dto.UserRegisterDTO) error {
|
|||
}
|
||||
|
||||
|
||||
|
||||
// Create user with pending status
|
||||
user := entity.User{
|
||||
ID: uuid.New(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package validation
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
// RegisterCustomValidators registers custom validation rules
|
||||
func RegisterCustomValidators(validate *validator.Validate) {
|
||||
validate.RegisterValidation("nospace", validateNoSpace)
|
||||
validate.RegisterValidation("alphanumunderscore", validateAlphaNumUnderscore)
|
||||
validate.RegisterValidation("alphaspace", validateAlphaSpace) // Add this
|
||||
validate.RegisterValidation("alphanum", validateAlphaNum) // Add this
|
||||
}
|
||||
|
||||
// validateNoSpace checks that the field contains no spaces
|
||||
func validateNoSpace(fl validator.FieldLevel) bool {
|
||||
value := fl.Field().String()
|
||||
return !strings.Contains(value, " ")
|
||||
}
|
||||
|
||||
// validateAlphaNumUnderscore allows alphanumeric characters and underscores only
|
||||
func validateAlphaNumUnderscore(fl validator.FieldLevel) bool {
|
||||
value := fl.Field().String()
|
||||
matched, _ := regexp.MatchString("^[a-zA-Z0-9_]+$", value)
|
||||
return matched
|
||||
}
|
||||
|
||||
// validateAlphaSpace allows alphabetic characters and spaces only (for names)
|
||||
func validateAlphaSpace(fl validator.FieldLevel) bool {
|
||||
value := fl.Field().String()
|
||||
for _, char := range value {
|
||||
if !unicode.IsLetter(char) && char != ' ' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// validateAlphaNum allows alphanumeric characters only
|
||||
func validateAlphaNum(fl validator.FieldLevel) bool {
|
||||
value := fl.Field().String()
|
||||
matched, _ := regexp.MatchString("^[a-zA-Z0-9]+$", value)
|
||||
return matched
|
||||
}
|
||||
Loading…
Reference in New Issue