backend/pkg/permission/usecase/role_permission_usecase.go

206 lines
4.9 KiB
Go

package usecase
import (
"backend/pkg/permission/domain/permission"
"backend/pkg/permission/domain/repository"
"backend/pkg/permission/domain/usecase"
"context"
"go.mongodb.org/mongo-driver/v2/bson"
)
type RolePermissionUseCaseParam struct {
PermRepo repository.PermissionRepository
RolePermRepo repository.RolePermissionRepository
RoleRepo repository.RoleRepository
UserRoleRepo repository.UserRoleRepository
PermUseCase usecase.PermissionUseCase
AdminRoleUID string // 管理員角色 UID
}
type rolePermissionUseCase struct {
RolePermissionUseCaseParam
}
// NewRolePermissionUseCase 建立角色權限 UseCase
func NewRolePermissionUseCase(param RolePermissionUseCaseParam) usecase.RolePermissionUseCase {
return &rolePermissionUseCase{
RolePermissionUseCaseParam: param,
}
}
func (uc *rolePermissionUseCase) GetByRoleUID(ctx context.Context, roleUID string) (permission.Permissions, error) {
// 檢查是否為管理員
if uc.AdminRoleUID != "" && roleUID == uc.AdminRoleUID {
return uc.getAllPermissions(ctx)
}
// 取得角色
role, err := uc.RoleRepo.GetByUID(ctx, roleUID)
if err != nil {
return nil, err
}
// 取得角色權限關聯
roleID := ConvertOIDToInt64(role.ID)
rolePerms, err := uc.RolePermRepo.GetByRoleID(ctx, roleID)
if err != nil {
return nil, err
}
if len(rolePerms) == 0 {
return make(permission.Permissions), nil
}
// 取得權限樹並建立權限集合
perms, err := uc.PermRepo.ListActive(ctx)
if err != nil {
return nil, err
}
tree := NewPermissionTree(perms)
// 取得權限 ObjectID 列表
permOIDs := make([]bson.ObjectID, len(rolePerms))
for i, rp := range rolePerms {
permOIDs[i] = rp.PermissionID
}
// 建立權限集合 (包含父權限)
permissions := tree.BuildPermissionsFromIDs(permOIDs)
return permissions, nil
}
func (uc *rolePermissionUseCase) GetByUserUID(ctx context.Context, userUID string) (*usecase.UserPermissionResponse, error) {
// 取得使用者角色
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,
}
return resp, nil
}
func (uc *rolePermissionUseCase) UpdateRolePermissions(ctx context.Context, roleUID string, permissions permission.Permissions) error {
// 取得角色
role, err := uc.RoleRepo.GetByUID(ctx, roleUID)
if err != nil {
return err
}
// 展開權限 (包含父權限)
var expandedPerms permission.Permissions
if uc.PermUseCase != nil {
expandedPerms, err = uc.PermUseCase.ExpandPermissions(ctx, permissions)
if err != nil {
return err
}
} else {
expandedPerms = permissions
}
// 取得權限樹並轉換為 ID
perms, err := uc.PermRepo.ListActive(ctx)
if err != nil {
return err
}
tree := NewPermissionTree(perms)
permOIDs, err := tree.GetPermissionIDs(expandedPerms)
if err != nil {
return err
}
// 轉換 ObjectID 為 int64
permIDs := make([]int64, len(permOIDs))
for i, oid := range permOIDs {
permIDs[i] = ConvertOIDToInt64(oid)
}
// 更新角色權限
roleID := ConvertOIDToInt64(role.ID)
if err := uc.RolePermRepo.Update(ctx, roleID, permIDs); err != nil {
return err
}
return nil
}
func (uc *rolePermissionUseCase) CheckPermission(ctx context.Context, roleUID, path, method string) (*usecase.PermissionCheckResponse, error) {
// 檢查是否為管理員
if uc.AdminRoleUID != "" && roleUID == uc.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.FindByHTTP(ctx, path, method)
if err != nil {
// 如果找不到對應的權限定義,預設拒絕
return &usecase.PermissionCheckResponse{
Allowed: false,
}, nil
}
// 檢查是否有權限
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) (permission.Permissions, error) {
perms, err := uc.PermRepo.ListActive(ctx)
if err != nil {
return nil, err
}
permissions := make(permission.Permissions)
for _, perm := range perms {
permissions.AddPermission(perm.Name)
}
return permissions, nil
}