first commit
This commit is contained in:
233
internal/modules/user/service.go
Normal file
233
internal/modules/user/service.go
Normal file
@@ -0,0 +1,233 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"cardverse/internal/pkg/utils"
|
||||
)
|
||||
|
||||
var ErrEmailTaken = errors.New("email sudah terdaftar")
|
||||
var ErrUserNotFound = errors.New("user tidak ditemukan")
|
||||
var ErrUserSuspended = errors.New("akun anda sedang disuspensi")
|
||||
var ErrForbiddenRoleCreation = errors.New("hanya superadmin yang dapat membuat atau mengubah akun dengan role admin atau superadmin")
|
||||
|
||||
type Service interface {
|
||||
Create(creatorID *uint, req CreateUserRequest) (*User, error)
|
||||
GetAll() ([]User, error)
|
||||
GetAllPaginated(query ListUserQuery) ([]User, int64, error)
|
||||
GetByID(id uint) (*User, error)
|
||||
Update(modifierID uint, id uint, req UpdateUserRequest) (*User, error)
|
||||
UpdateProfile(userID uint, req UpdateProfileRequest) (*User, error)
|
||||
UpdateAvatar(userID uint, avatarURL string) (*User, error)
|
||||
SuspendUser(modifierID uint, id uint) (*User, error)
|
||||
UnsuspendUser(modifierID uint, id uint) (*User, error)
|
||||
Delete(id uint) error
|
||||
}
|
||||
|
||||
type service struct {
|
||||
repo Repository
|
||||
}
|
||||
|
||||
func NewService(repo Repository) Service {
|
||||
return &service{repo: repo}
|
||||
}
|
||||
|
||||
func (s *service) Create(creatorID *uint, req CreateUserRequest) (*User, error) {
|
||||
existing, _ := s.repo.FindByEmail(req.Email)
|
||||
if existing != nil {
|
||||
return nil, ErrEmailTaken
|
||||
}
|
||||
|
||||
role := req.Role
|
||||
if role == "" {
|
||||
role = RoleUser
|
||||
}
|
||||
|
||||
// Batasan role: Hanya Superadmin yang boleh membuat akun dengan role admin atau superadmin
|
||||
if role == RoleAdmin || role == RoleSuperAdmin {
|
||||
if creatorID == nil {
|
||||
return nil, ErrForbiddenRoleCreation
|
||||
}
|
||||
creator, err := s.repo.FindByID(*creatorID)
|
||||
if err != nil || creator.Role != RoleSuperAdmin {
|
||||
return nil, ErrForbiddenRoleCreation
|
||||
}
|
||||
}
|
||||
|
||||
hashedPassword, err := utils.HashPassword(req.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newUser := &User{
|
||||
Name: req.Name,
|
||||
Email: req.Email,
|
||||
Password: hashedPassword,
|
||||
Role: role,
|
||||
Status: StatusActive,
|
||||
IsEmailVerified: true,
|
||||
CreatedBy: creatorID,
|
||||
}
|
||||
|
||||
if err := s.repo.Create(newUser); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newUser, nil
|
||||
}
|
||||
|
||||
func (s *service) GetAll() ([]User, error) {
|
||||
return s.repo.FindAll()
|
||||
}
|
||||
|
||||
func (s *service) GetAllPaginated(query ListUserQuery) ([]User, int64, error) {
|
||||
page := query.Page
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
limit := query.Limit
|
||||
if limit < 1 {
|
||||
limit = 20
|
||||
}
|
||||
|
||||
return s.repo.FindAllPaginated(page, limit, query)
|
||||
}
|
||||
|
||||
func (s *service) GetByID(id uint) (*User, error) {
|
||||
u, err := s.repo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *service) Update(modifierID uint, id uint, req UpdateUserRequest) (*User, error) {
|
||||
u, err := s.repo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
u.Name = req.Name
|
||||
}
|
||||
if req.Email != "" && req.Email != u.Email {
|
||||
existing, _ := s.repo.FindByEmail(req.Email)
|
||||
if existing != nil {
|
||||
return nil, ErrEmailTaken
|
||||
}
|
||||
u.Email = req.Email
|
||||
}
|
||||
if req.AvatarURL != "" {
|
||||
if u.AvatarURL != nil && *u.AvatarURL != "" && *u.AvatarURL != req.AvatarURL {
|
||||
utils.DeleteLocalFile(*u.AvatarURL)
|
||||
}
|
||||
u.AvatarURL = &req.AvatarURL
|
||||
}
|
||||
if req.Role != "" && req.Role != u.Role {
|
||||
// Batasan role: Hanya Superadmin yang boleh mengubah role ke admin atau superadmin
|
||||
if req.Role == RoleAdmin || req.Role == RoleSuperAdmin {
|
||||
creator, err := s.repo.FindByID(modifierID)
|
||||
if err != nil || creator.Role != RoleSuperAdmin {
|
||||
return nil, ErrForbiddenRoleCreation
|
||||
}
|
||||
}
|
||||
u.Role = req.Role
|
||||
}
|
||||
if req.Status != "" {
|
||||
u.Status = req.Status
|
||||
}
|
||||
|
||||
u.UpdatedBy = &modifierID
|
||||
|
||||
if err := s.repo.Update(u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *service) UpdateProfile(userID uint, req UpdateProfileRequest) (*User, error) {
|
||||
u, err := s.repo.FindByID(userID)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
u.Name = req.Name
|
||||
}
|
||||
if req.AvatarURL != "" {
|
||||
if u.AvatarURL != nil && *u.AvatarURL != "" && *u.AvatarURL != req.AvatarURL {
|
||||
utils.DeleteLocalFile(*u.AvatarURL)
|
||||
}
|
||||
u.AvatarURL = &req.AvatarURL
|
||||
}
|
||||
|
||||
u.UpdatedBy = &userID
|
||||
|
||||
if err := s.repo.Update(u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *service) UpdateAvatar(userID uint, avatarURL string) (*User, error) {
|
||||
u, err := s.repo.FindByID(userID)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
// Hapus file avatar lama jika ada
|
||||
if u.AvatarURL != nil && *u.AvatarURL != "" && *u.AvatarURL != avatarURL {
|
||||
utils.DeleteLocalFile(*u.AvatarURL)
|
||||
}
|
||||
|
||||
u.AvatarURL = &avatarURL
|
||||
u.UpdatedBy = &userID
|
||||
|
||||
if err := s.repo.Update(u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *service) SuspendUser(modifierID uint, id uint) (*User, error) {
|
||||
u, err := s.repo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
u.Status = StatusSuspended
|
||||
u.UpdatedBy = &modifierID
|
||||
|
||||
if err := s.repo.Update(u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *service) UnsuspendUser(modifierID uint, id uint) (*User, error) {
|
||||
u, err := s.repo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
u.Status = StatusActive
|
||||
u.UpdatedBy = &modifierID
|
||||
|
||||
if err := s.repo.Update(u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *service) Delete(id uint) error {
|
||||
_, err := s.repo.FindByID(id)
|
||||
if err != nil {
|
||||
return ErrUserNotFound
|
||||
}
|
||||
return s.repo.Delete(id)
|
||||
}
|
||||
Reference in New Issue
Block a user