252 lines
7.4 KiB
Go
252 lines
7.4 KiB
Go
package usecase
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
"users_management/m/model/dto"
|
|
"users_management/m/model/entity"
|
|
"users_management/m/repository"
|
|
"users_management/m/utils"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
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
|
|
RegisterUser(registerDTO dto.UserRegisterDTO) error
|
|
GetPendingUsers() ([]dto.PendingUserResponse, error)
|
|
ApproveUser(userID uuid.UUID) error
|
|
RejectUser(userID uuid.UUID) error
|
|
GetUserByUsernameWithStatus(username string) (entity.User, error)
|
|
CreateSuperAdminBypass(user entity.User) error
|
|
UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error
|
|
UpdateUserRoleByUsername(username, newRoleName string) error
|
|
GetUserByID(userID uuid.UUID) (entity.User, error)
|
|
|
|
}
|
|
|
|
type usersUsecase struct {
|
|
userRepo repository.UsersRepo
|
|
validate *validator.Validate
|
|
}
|
|
|
|
func NewUsersUsecase(userRepo repository.UsersRepo) UsersUsecase {
|
|
return &usersUsecase{
|
|
userRepo: userRepo,
|
|
validate: validator.New(),
|
|
}
|
|
}
|
|
|
|
|
|
func (u *usersUsecase) CreateSuperAdminBypass(user entity.User) error {
|
|
return u.userRepo.CreateSuperAdminBypass(user)
|
|
}
|
|
|
|
// Add these implementations to the usersUsecase struct
|
|
func (u *usersUsecase) UpdateUserRoleByID(userID uuid.UUID, newRoleName string) error {
|
|
// Get the new role ID
|
|
newRoleID, err := u.GetRoleByDepartment(newRoleName)
|
|
if err != nil {
|
|
return errors.New("invalid role name: " + err.Error())
|
|
}
|
|
|
|
// Check if user exists
|
|
_, err = u.userRepo.GetUserByID(userID)
|
|
if err != nil {
|
|
return errors.New("user not found")
|
|
}
|
|
|
|
// Update user role
|
|
return u.userRepo.UpdateUserRoleByID(userID, newRoleID)
|
|
}
|
|
|
|
func (u *usersUsecase) UpdateUserRoleByUsername(username, newRoleName string) error {
|
|
// Get the new role ID
|
|
newRoleID, err := u.GetRoleByDepartment(newRoleName)
|
|
if err != nil {
|
|
return errors.New("invalid role name: " + err.Error())
|
|
}
|
|
|
|
// Check if user exists
|
|
_, err = u.userRepo.GetUserByUsernameWithStatus(username)
|
|
if err != nil {
|
|
return errors.New("user not found")
|
|
}
|
|
|
|
// Update user role by username
|
|
return u.userRepo.UpdateUserRoleByUsername(username, newRoleID)
|
|
}
|
|
|
|
func (u *usersUsecase) GetUserByID(userID uuid.UUID) (entity.User, error) {
|
|
return u.userRepo.GetUserByID(userID)
|
|
}
|
|
|
|
func (u *usersUsecase) RegisterUser(registerDTO dto.UserRegisterDTO) error {
|
|
// Validate input
|
|
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 {
|
|
return errors.New("username already exists")
|
|
}
|
|
|
|
// Check if nomor_induk already exists
|
|
if registerDTO.NomorInduk != "" {
|
|
existingUser, err := u.userRepo.GetUserByNomorInduk(registerDTO.NomorInduk)
|
|
if err == nil && existingUser.ID != uuid.Nil {
|
|
return errors.New("nomor induk already exists")
|
|
}
|
|
}
|
|
|
|
// Hash password
|
|
hashedPassword, err := utils.HashPassword(registerDTO.Password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
teknisiRoleID, err := u.GetRoleByDepartment("Teknisi")
|
|
if err != nil {
|
|
return errors.New("failed to get Teknisi role: " + err.Error())
|
|
}
|
|
|
|
|
|
|
|
// Create user with pending status
|
|
user := entity.User{
|
|
ID: uuid.New(),
|
|
Name: registerDTO.Name,
|
|
Username: registerDTO.Username,
|
|
Password: hashedPassword,
|
|
NomorInduk: ®isterDTO.NomorInduk,
|
|
RoleID: teknisiRoleID,
|
|
Status: entity.UserStatusPending, // Set status to pending
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
return u.userRepo.RegisterUser(user)
|
|
}
|
|
|
|
func (u *usersUsecase) GetPendingUsers() ([]dto.PendingUserResponse, error) {
|
|
users, err := u.userRepo.GetPendingUsers()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
|
|
var responses []dto.PendingUserResponse
|
|
for _, user := range users {
|
|
response := dto.PendingUserResponse{
|
|
ID: user.ID,
|
|
Name: user.Name,
|
|
Username: user.Username,
|
|
NomorInduk: user.NomorInduk,
|
|
RoleName: user.Role.Name,
|
|
Status: dto.UserStatus(user.Status),
|
|
CreatedAt: user.CreatedAt,
|
|
UpdatedAt: user.UpdatedAt,
|
|
}
|
|
responses = append(responses, response)
|
|
}
|
|
|
|
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
func (u *usersUsecase) ApproveUser(userID uuid.UUID) error {
|
|
// Check if user exists and is pending
|
|
user, err := u.userRepo.GetUserByID(userID)
|
|
if err != nil {
|
|
return errors.New("user not found")
|
|
}
|
|
|
|
if user.Status != entity.UserStatusPending {
|
|
return errors.New("user is not in pending status")
|
|
}
|
|
|
|
return u.userRepo.UpdateUserStatus(userID, entity.UserStatusApproved)
|
|
}
|
|
|
|
func (u *usersUsecase) RejectUser(userID uuid.UUID) error {
|
|
// Check if user exists and is pending
|
|
user, err := u.userRepo.GetUserByID(userID)
|
|
if err != nil {
|
|
return errors.New("user not found")
|
|
}
|
|
|
|
if user.Status != entity.UserStatusPending {
|
|
return errors.New("user is not in pending status")
|
|
}
|
|
|
|
return u.userRepo.UpdateUserStatus(userID, entity.UserStatusRejected)
|
|
}
|
|
|
|
func (u *usersUsecase) GetUserByUsernameWithStatus(username string) (entity.User, error) {
|
|
return u.userRepo.GetUserByUsernameWithStatus(username)
|
|
}
|
|
|
|
func (u *usersUsecase) GetRoleByDepartment(departmentName string) (uuid.UUID, error) {
|
|
role, err := u.userRepo.GetRoleByDepartment(departmentName)
|
|
if err != nil {
|
|
return uuid.Nil, err
|
|
}
|
|
return role.Id, nil
|
|
}
|
|
|
|
func (u *usersUsecase) GetUserByUsername(username string) (entity.User, error) {
|
|
users, err := u.userRepo.GetUserByUsername(username)
|
|
if err != nil {
|
|
return users, err
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
// New methods for RBAC
|
|
func (u *usersUsecase) GetUserByNomorInduk(nomorInduk string) (entity.User, error) {
|
|
return u.userRepo.GetUserByNomorInduk(nomorInduk)
|
|
}
|
|
|
|
func (u *usersUsecase) CreateUserFromExternal(nomorInduk, name, roleName string) error {
|
|
// Get role ID
|
|
roleID, err := u.GetRoleByDepartment(roleName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create user
|
|
user := entity.User{
|
|
ID: uuid.New(),
|
|
NomorInduk: &nomorInduk,
|
|
RoleID: roleID,
|
|
Name: name,
|
|
Username: nomorInduk, // Use nomor_induk as username
|
|
Password: "", // External auth, no local password needed
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
return u.userRepo.CreateUserFromExternal(user)
|
|
}
|
|
|
|
func (u *usersUsecase) UpdateUserRole(nomorInduk, roleName string) error {
|
|
roleID, err := u.GetRoleByDepartment(roleName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return u.userRepo.UpdateUserRole(nomorInduk, roleID)
|
|
}
|
|
|
|
func (u *usersUsecase) GetAllUsers() ([]entity.User, error) {
|
|
return u.userRepo.GetAllUsers()
|
|
} |