fixing validation for username and full name
This commit is contained in:
parent
433512e3da
commit
f48d61d4e2
|
|
@ -16,10 +16,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserRegisterDTO struct {
|
type UserRegisterDTO struct {
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required,min=2,max=100,alphaspace"`
|
||||||
Username string `json:"username" validate:"required"`
|
Username string `json:"username" validate:"required,min=3,max=50,alphanumunderscore,nospace"`
|
||||||
Password string `json:"password" validate:"required,min=6"`
|
Password string `json:"password" validate:"required,min=6,max=100"`
|
||||||
NomorInduk string `json:"nomor_induk" validate:"required"`
|
NomorInduk string `json:"nomor_induk" validate:"required,min=3,max=50,alphanum"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserLoginDTO struct {
|
type UserLoginDTO struct {
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ const (
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"`
|
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"`
|
RoleID uuid.UUID `json:"role_id" gorm:"type:uuid"`
|
||||||
Role Role `json:"role" gorm:"foreignKey:RoleID"`
|
Role Role `json:"role" gorm:"foreignKey:RoleID"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name" gorm:"unique"`
|
||||||
Username string `json:"username" gorm:"unique"`
|
Username string `json:"username" gorm:"unique"`
|
||||||
Password string `json:"password"`
|
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"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ type UsersRepo interface {
|
||||||
Post(user entity.User) error
|
Post(user entity.User) error
|
||||||
GetRoleByDepartment(departmentName string) (entity.Role, error)
|
GetRoleByDepartment(departmentName string) (entity.Role, error)
|
||||||
GetUserByUsername(username string) (entity.User, error)
|
GetUserByUsername(username string) (entity.User, error)
|
||||||
GetUserByNomorInduk(nomorInduk string) (entity.User, error) // Add this
|
GetUserByNomorInduk(nomorInduk string) (entity.User, error)
|
||||||
CreateUserFromExternal(user entity.User) error // Add this
|
CreateUserFromExternal(user entity.User) error
|
||||||
UpdateUserRole(nomorInduk string, roleID uuid.UUID) error // Add this
|
UpdateUserRole(nomorInduk string, roleID uuid.UUID) error
|
||||||
GetAllUsers() ([]entity.User, error) // Add this
|
GetAllUsers() ([]entity.User, error)
|
||||||
RegisterUser(user entity.User) error
|
RegisterUser(user entity.User) error
|
||||||
GetPendingUsers() ([]entity.User, error)
|
GetPendingUsers() ([]entity.User, error)
|
||||||
UpdateUserStatus(userID uuid.UUID, status entity.UserStatus) error
|
UpdateUserStatus(userID uuid.UUID, status entity.UserStatus) error
|
||||||
|
|
@ -23,6 +23,7 @@ type UsersRepo interface {
|
||||||
CreateSuperAdminBypass(user entity.User) error
|
CreateSuperAdminBypass(user entity.User) error
|
||||||
UpdateUserRoleByID(userID uuid.UUID, roleID uuid.UUID) error
|
UpdateUserRoleByID(userID uuid.UUID, roleID uuid.UUID) error
|
||||||
UpdateUserRoleByUsername(username string, roleID uuid.UUID) error
|
UpdateUserRoleByUsername(username string, roleID uuid.UUID) error
|
||||||
|
GetUserByName(name string) (entity.User, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type usersRepo struct {
|
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 {
|
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
|
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/model/entity"
|
||||||
"users_management/m/repository"
|
"users_management/m/repository"
|
||||||
"users_management/m/utils"
|
"users_management/m/utils"
|
||||||
|
"users_management/m/utils/validation"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
@ -15,10 +16,10 @@ import (
|
||||||
type UsersUsecase interface {
|
type UsersUsecase interface {
|
||||||
GetRoleByDepartment(departmentName string) (uuid.UUID, error)
|
GetRoleByDepartment(departmentName string) (uuid.UUID, error)
|
||||||
GetUserByUsername(username string) (entity.User, error)
|
GetUserByUsername(username string) (entity.User, error)
|
||||||
GetUserByNomorInduk(nomorInduk string) (entity.User, error) // Add this
|
GetUserByNomorInduk(nomorInduk string) (entity.User, error)
|
||||||
CreateUserFromExternal(nomorInduk, name, roleName string) error // Add this
|
CreateUserFromExternal(nomorInduk, name, roleName string) error
|
||||||
UpdateUserRole(nomorInduk, roleName string) error // Add this
|
UpdateUserRole(nomorInduk, roleName string) error
|
||||||
GetAllUsers() ([]entity.User, error) // Add this
|
GetAllUsers() ([]entity.User, error)
|
||||||
RegisterUser(registerDTO dto.UserRegisterDTO) error
|
RegisterUser(registerDTO dto.UserRegisterDTO) error
|
||||||
GetPendingUsers() ([]dto.PendingUserResponse, error)
|
GetPendingUsers() ([]dto.PendingUserResponse, error)
|
||||||
ApproveUser(userID uuid.UUID) error
|
ApproveUser(userID uuid.UUID) error
|
||||||
|
|
@ -28,6 +29,7 @@ type UsersUsecase interface {
|
||||||
UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error
|
UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error
|
||||||
UpdateUserRoleByUsername(username, newRoleName string) error
|
UpdateUserRoleByUsername(username, newRoleName string) error
|
||||||
GetUserByID(userID uuid.UUID) (entity.User, 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 {
|
func NewUsersUsecase(userRepo repository.UsersRepo) UsersUsecase {
|
||||||
|
|
||||||
|
validate := validator.New()
|
||||||
|
validation.RegisterCustomValidators(validate)
|
||||||
return &usersUsecase{
|
return &usersUsecase{
|
||||||
userRepo: userRepo,
|
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 {
|
func (u *usersUsecase) CreateSuperAdminBypass(user entity.User) error {
|
||||||
return u.userRepo.CreateSuperAdminBypass(user)
|
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 {
|
if err := u.validate.Struct(registerDTO); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if username already exists
|
// Check if username already exists
|
||||||
existingUser, err := u.userRepo.GetUserByUsernameWithStatus(registerDTO.Username)
|
existingUser, err := u.userRepo.GetUserByUsernameWithStatus(registerDTO.Username)
|
||||||
if err == nil && existingUser.ID != uuid.Nil {
|
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
|
// Hash password
|
||||||
hashedPassword, err := utils.HashPassword(registerDTO.Password)
|
hashedPassword, err := utils.HashPassword(registerDTO.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -119,7 +132,6 @@ func (u *usersUsecase) RegisterUser(registerDTO dto.UserRegisterDTO) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Create user with pending status
|
// Create user with pending status
|
||||||
user := entity.User{
|
user := entity.User{
|
||||||
ID: uuid.New(),
|
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