backend/tmp/reborn/usecase/role_usecase.go

244 lines
5.8 KiB
Go
Raw Normal View History

2025-10-07 09:29:47 +00:00
package usecase
import (
"context"
"fmt"
"permission/reborn/config"
"permission/reborn/domain/entity"
"permission/reborn/domain/errors"
"permission/reborn/domain/repository"
"permission/reborn/domain/usecase"
"time"
)
type roleUseCase struct {
roleRepo repository.RoleRepository
userRoleRepo repository.UserRoleRepository
rolePermUseCase usecase.RolePermissionUseCase
cache repository.CacheRepository
config config.RoleConfig
}
// NewRoleUseCase 建立角色 UseCase
func NewRoleUseCase(
roleRepo repository.RoleRepository,
userRoleRepo repository.UserRoleRepository,
rolePermUseCase usecase.RolePermissionUseCase,
cache repository.CacheRepository,
cfg config.RoleConfig,
) usecase.RoleUseCase {
return &roleUseCase{
roleRepo: roleRepo,
userRoleRepo: userRoleRepo,
rolePermUseCase: rolePermUseCase,
cache: cache,
config: cfg,
}
}
func (uc *roleUseCase) Create(ctx context.Context, req usecase.CreateRoleRequest) (*usecase.RoleResponse, error) {
// 生成 UID
nextID, err := uc.roleRepo.NextID(ctx)
if err != nil {
return nil, errors.Wrap(errors.ErrCodeInternal, "failed to generate role id", err)
}
uid := fmt.Sprintf("%s%0*d", uc.config.UIDPrefix, uc.config.UIDLength, nextID)
// 建立角色
role := &entity.Role{
UID: uid,
ClientID: req.ClientID,
Name: req.Name,
Status: entity.StatusActive,
}
if err := uc.roleRepo.Create(ctx, role); err != nil {
return nil, err
}
// 設定權限
if len(req.Permissions) > 0 {
if err := uc.rolePermUseCase.UpdateRolePermissions(ctx, uid, req.Permissions); err != nil {
return nil, err
}
}
// 查詢完整角色資訊
return uc.Get(ctx, uid)
}
func (uc *roleUseCase) Update(ctx context.Context, uid string, req usecase.UpdateRoleRequest) (*usecase.RoleResponse, error) {
// 檢查角色是否存在
role, err := uc.roleRepo.GetByUID(ctx, uid)
if err != nil {
return nil, err
}
// 更新欄位
if req.Name != nil {
role.Name = *req.Name
}
if req.Status != nil {
role.Status = *req.Status
}
if err := uc.roleRepo.Update(ctx, role); err != nil {
return nil, err
}
// 更新權限
if req.Permissions != nil {
if err := uc.rolePermUseCase.UpdateRolePermissions(ctx, uid, req.Permissions); err != nil {
return nil, err
}
}
// 清除快取
if uc.cache != nil {
_ = uc.cache.Delete(ctx, repository.CacheKeyRolePermission(uid))
}
return uc.Get(ctx, uid)
}
func (uc *roleUseCase) Delete(ctx context.Context, uid string) error {
// 檢查是否有使用者使用此角色
users, err := uc.userRoleRepo.GetByRoleID(ctx, uid)
if err != nil {
return err
}
if len(users) > 0 {
return errors.ErrRoleHasUsers
}
// 刪除角色
if err := uc.roleRepo.Delete(ctx, uid); err != nil {
return err
}
// 清除快取
if uc.cache != nil {
_ = uc.cache.Delete(ctx, repository.CacheKeyRolePermission(uid))
}
return nil
}
func (uc *roleUseCase) Get(ctx context.Context, uid string) (*usecase.RoleResponse, error) {
role, err := uc.roleRepo.GetByUID(ctx, uid)
if err != nil {
return nil, err
}
// 取得權限
permissions, err := uc.rolePermUseCase.GetByRoleUID(ctx, uid)
if err != nil && !errors.Is(err, errors.ErrPermissionNotFound) {
return nil, err
}
return uc.toResponse(role, permissions), nil
}
func (uc *roleUseCase) List(ctx context.Context, filter usecase.RoleFilterRequest) ([]*usecase.RoleResponse, error) {
repoFilter := repository.RoleFilter{
ClientID: filter.ClientID,
Name: filter.Name,
Status: filter.Status,
}
roles, err := uc.roleRepo.List(ctx, repoFilter)
if err != nil {
return nil, err
}
return uc.toResponseList(ctx, roles), nil
}
func (uc *roleUseCase) Page(ctx context.Context, filter usecase.RoleFilterRequest, page, size int) (*usecase.RolePageResponse, error) {
repoFilter := repository.RoleFilter{
ClientID: filter.ClientID,
Name: filter.Name,
Status: filter.Status,
}
roles, total, err := uc.roleRepo.Page(ctx, repoFilter, page, size)
if err != nil {
return nil, err
}
// 取得所有角色的使用者數量 (批量查詢,避免 N+1)
roleUIDs := make([]string, len(roles))
for i, role := range roles {
roleUIDs[i] = role.UID
}
userCounts, err := uc.userRoleRepo.CountByRoleID(ctx, roleUIDs)
if err != nil {
return nil, err
}
// 組裝回應
list := make([]*usecase.RoleWithUserCountResponse, 0, len(roles))
for _, role := range roles {
// 取得權限
permissions, _ := uc.rolePermUseCase.GetByRoleUID(ctx, role.UID)
// 權限過濾 (如果有指定)
if len(filter.Permissions) > 0 {
hasPermission := false
for _, reqPerm := range filter.Permissions {
if permissions.HasPermission(reqPerm) {
hasPermission = true
break
}
}
if !hasPermission {
continue
}
}
resp := &usecase.RoleWithUserCountResponse{
RoleResponse: *uc.toResponse(role, permissions),
UserCount: userCounts[role.UID],
}
list = append(list, resp)
}
return &usecase.RolePageResponse{
List: list,
Total: total,
Page: page,
Size: size,
}, nil
}
func (uc *roleUseCase) toResponse(role *entity.Role, permissions entity.Permissions) *usecase.RoleResponse {
if permissions == nil {
permissions = make(entity.Permissions)
}
return &usecase.RoleResponse{
ID: role.ID,
UID: role.UID,
ClientID: role.ClientID,
Name: role.Name,
Status: role.Status,
Permissions: permissions,
CreateTime: role.CreateTime.UTC().Format(time.RFC3339),
UpdateTime: role.UpdateTime.UTC().Format(time.RFC3339),
}
}
func (uc *roleUseCase) toResponseList(ctx context.Context, roles []*entity.Role) []*usecase.RoleResponse {
result := make([]*usecase.RoleResponse, 0, len(roles))
for _, role := range roles {
permissions, _ := uc.rolePermUseCase.GetByRoleUID(ctx, role.UID)
result = append(result, uc.toResponse(role, permissions))
}
return result
}