80 lines
2.1 KiB
Go
80 lines
2.1 KiB
Go
package useCases
|
|
|
|
import (
|
|
"RenewCMS/internal/domain/audit"
|
|
"RenewCMS/internal/domain/contenttype"
|
|
"RenewCMS/internal/domain/role"
|
|
"RenewCMS/internal/domain/user"
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
type RemoveUserUseCase struct {
|
|
users user.Repository
|
|
roles role.Repository
|
|
contentTypes contenttype.Repository
|
|
recorder audit.Recorder
|
|
}
|
|
|
|
type RemoveUserCommand struct {
|
|
Caller ContentCaller
|
|
TargetID uint32
|
|
ExpectedRoleID uint32
|
|
}
|
|
|
|
func NewRemoveUserUseCase(users user.Repository, roles role.Repository, contentTypes contenttype.Repository, recorder audit.Recorder) *RemoveUserUseCase {
|
|
return &RemoveUserUseCase{users: users, roles: roles, contentTypes: contentTypes, recorder: recorder}
|
|
}
|
|
|
|
func (u *RemoveUserUseCase) Remove(ctx context.Context, command RemoveUserCommand) error {
|
|
if command.ExpectedRoleID == 0 {
|
|
return role.ErrUnknownRole
|
|
}
|
|
target, err := u.users.Get(command.TargetID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := u.check(command, target); err != nil {
|
|
return err
|
|
}
|
|
event := audit.NewEvent(audit.ActionUserRemove, audit.CategoryUsers)
|
|
event.Target = audit.NewTarget(audit.TargetUser, target.ID, target.Username)
|
|
if err := u.users.DeleteIfRole(target.ID, command.ExpectedRoleID); err != nil {
|
|
u.recordWriteFailure(ctx, event, err)
|
|
return err
|
|
}
|
|
u.recorder.Record(ctx, event)
|
|
return nil
|
|
}
|
|
|
|
func (u *RemoveUserUseCase) check(command RemoveUserCommand, target user.User) error {
|
|
if target.ID == command.Caller.UserID {
|
|
return role.ErrOwnRole
|
|
}
|
|
if target.RoleID != command.ExpectedRoleID {
|
|
return user.ErrRoleChanged
|
|
}
|
|
held, err := resolveRole(u.roles, target)
|
|
if errors.Is(err, role.ErrRoleNotFound) {
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if held.Locked {
|
|
return role.ErrRoleLocked
|
|
}
|
|
typeKeys, err := allowedTypeKeys(u.contentTypes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ensureCoveredBy(command.Caller, typeKeys, held)
|
|
}
|
|
|
|
func (u *RemoveUserUseCase) recordWriteFailure(ctx context.Context, event audit.Event, err error) {
|
|
if errors.Is(err, user.ErrRoleChanged) || errors.Is(err, user.ErrUserNotFound) {
|
|
return
|
|
}
|
|
recordFailure(ctx, u.recorder, event, err)
|
|
}
|