package usecase import ( "context" "permission/reborn/config" "permission/reborn/domain/entity" "permission/reborn/domain/errors" "permission/reborn/domain/repository" "permission/reborn/domain/usecase" ) type rolePermissionUseCase struct { permRepo repository.PermissionRepository rolePermRepo repository.RolePermissionRepository roleRepo repository.RoleRepository userRoleRepo repository.UserRoleRepository permUseCase usecase.PermissionUseCase cache repository.CacheRepository config config.RoleConfig } // NewRolePermissionUseCase 建立角色權限 UseCase func NewRolePermissionUseCase( permRepo repository.PermissionRepository, rolePermRepo repository.RolePermissionRepository, roleRepo repository.RoleRepository, userRoleRepo repository.UserRoleRepository, permUseCase usecase.PermissionUseCase, cache repository.CacheRepository, cfg config.RoleConfig, ) usecase.RolePermissionUseCase { return &rolePermissionUseCase{ permRepo: permRepo, rolePermRepo: rolePermRepo, roleRepo: roleRepo, userRoleRepo: userRoleRepo, permUseCase: permUseCase, cache: cache, config: cfg, } } func (uc *rolePermissionUseCase) GetByRoleUID(ctx context.Context, roleUID string) (entity.Permissions, error) { // 檢查是否為管理員 if roleUID == uc.config.AdminRoleUID { return uc.getAllPermissions(ctx) } // 嘗試從快取取得 if uc.cache != nil { var permissions entity.Permissions cacheKey := repository.CacheKeyRolePermission(roleUID) err := uc.cache.GetObject(ctx, cacheKey, &permissions) if err == nil && len(permissions) > 0 { return permissions, nil } } // 取得角色 role, err := uc.roleRepo.GetByUID(ctx, roleUID) if err != nil { return nil, err } // 取得角色權限關聯 rolePerms, err := uc.rolePermRepo.GetByRoleID(ctx, role.ID) if err != nil { return nil, err } if len(rolePerms) == 0 { return make(entity.Permissions), nil } // 取得權限樹並建立權限集合 perms, err := uc.permRepo.ListActive(ctx) if err != nil { return nil, err } tree := NewPermissionTree(perms) // 取得權限 ID 列表 permIDs := make([]int64, len(rolePerms)) for i, rp := range rolePerms { permIDs[i] = rp.PermissionID } // 建立權限集合 (包含父權限) permissions := tree.BuildPermissionsFromIDs(permIDs) // 存入快取 if uc.cache != nil { cacheKey := repository.CacheKeyRolePermission(roleUID) _ = uc.cache.SetObject(ctx, cacheKey, permissions, 0) } return permissions, nil } func (uc *rolePermissionUseCase) GetByUserUID(ctx context.Context, userUID string) (*usecase.UserPermissionResponse, error) { // 嘗試從快取取得 if uc.cache != nil { var resp usecase.UserPermissionResponse cacheKey := repository.CacheKeyUserPermission(userUID) err := uc.cache.GetObject(ctx, cacheKey, &resp) if err == nil && resp.RoleUID != "" { return &resp, nil } } // 取得使用者角色 userRole, err := uc.userRoleRepo.Get(ctx, userUID) if err != nil { return nil, err } // 取得角色 role, err := uc.roleRepo.GetByUID(ctx, userRole.RoleID) if err != nil { return nil, err } // 取得角色權限 permissions, err := uc.GetByRoleUID(ctx, userRole.RoleID) if err != nil { return nil, err } resp := &usecase.UserPermissionResponse{ UserUID: userUID, RoleUID: role.UID, RoleName: role.Name, Permissions: permissions, } // 存入快取 if uc.cache != nil { cacheKey := repository.CacheKeyUserPermission(userUID) _ = uc.cache.SetObject(ctx, cacheKey, resp, 0) } return resp, nil } func (uc *rolePermissionUseCase) UpdateRolePermissions(ctx context.Context, roleUID string, permissions entity.Permissions) error { // 取得角色 role, err := uc.roleRepo.GetByUID(ctx, roleUID) if err != nil { return err } // 展開權限 (包含父權限) expandedPerms, err := uc.permUseCase.ExpandPermissions(ctx, permissions) if err != nil { return err } // 取得權限樹並轉換為 ID perms, err := uc.permRepo.ListActive(ctx) if err != nil { return err } tree := NewPermissionTree(perms) permIDs, err := tree.GetPermissionIDs(expandedPerms) if err != nil { return err } // 更新角色權限 if err := uc.rolePermRepo.Update(ctx, role.ID, permIDs); err != nil { return err } // 清除快取 if uc.cache != nil { // 清除角色權限快取 _ = uc.cache.Delete(ctx, repository.CacheKeyRolePermission(roleUID)) // 清除所有使用此角色的使用者權限快取 userRoles, _ := uc.userRoleRepo.GetByRoleID(ctx, roleUID) for _, ur := range userRoles { _ = uc.cache.Delete(ctx, repository.CacheKeyUserPermission(ur.UID)) } } return nil } func (uc *rolePermissionUseCase) CheckPermission(ctx context.Context, roleUID, path, method string) (*usecase.PermissionCheckResponse, error) { // 檢查是否為管理員 if roleUID == uc.config.AdminRoleUID { return &usecase.PermissionCheckResponse{ Allowed: true, PlainCode: true, }, nil } // 取得角色權限 permissions, err := uc.GetByRoleUID(ctx, roleUID) if err != nil { return nil, err } // 取得 API 權限 perm, err := uc.permRepo.GetByHTTP(ctx, path, method) if err != nil { if errors.Is(err, errors.ErrPermissionNotFound) { // 如果找不到對應的權限定義,預設拒絕 return &usecase.PermissionCheckResponse{ Allowed: false, }, nil } return nil, err } // 檢查是否有權限 allowed := permissions.HasPermission(perm.Name) resp := &usecase.PermissionCheckResponse{ Allowed: allowed, PermissionName: perm.Name, PlainCode: false, } // 檢查是否有 plain_code 權限 (特殊邏輯) if allowed && method == "GET" { plainCodePermName := perm.Name + ".plain_code" resp.PlainCode = permissions.HasPermission(plainCodePermName) } return resp, nil } // getAllPermissions 取得所有權限 (管理員用) func (uc *rolePermissionUseCase) getAllPermissions(ctx context.Context) (entity.Permissions, error) { perms, err := uc.permRepo.ListActive(ctx) if err != nil { return nil, err } permissions := make(entity.Permissions) for _, perm := range perms { permissions.AddPermission(perm.Name) } return permissions, nil }