package usecase import ( "backend/pkg/library/errs/code" "context" "github.com/zeromicro/go-zero/core/logx" "go.mongodb.org/mongo-driver/v2/bson" "backend/pkg/library/errs" "backend/pkg/permission/domain/entity" "backend/pkg/permission/domain/repository" "backend/pkg/permission/domain/usecase" "github.com/casbin/casbin/v2" ) type PermissionUseCaseParam struct { Enforcer *casbin.Enforcer PermissionRepo repository.PermissionRepository RoleRepo repository.RoleRepository UserRoleRepo repository.UserRoleRepository } type PermissionUseCase struct { enforcer *casbin.Enforcer permissionRepo repository.PermissionRepository roleRepo repository.RoleRepository userRoleRepo repository.UserRoleRepository } // MustPermissionUseCase 創建權限用例實例 func MustPermissionUseCase(param PermissionUseCaseParam) usecase.PermissionUseCase { return &PermissionUseCase{ enforcer: param.Enforcer, permissionRepo: param.PermissionRepo, roleRepo: param.RoleRepo, userRoleRepo: param.UserRoleRepo, } } func (uc *PermissionUseCase) CreatePermission(ctx context.Context, req usecase.CreatePermissionRequest) (*entity.Permission, error) { // 驗證請求 if req.Name == "" { return nil, errs.InvalidFormat("permission name is required") } permission := &entity.Permission{ Name: req.Name, HTTPMethod: req.HTTPMethod, HTTPPath: req.HTTPPath, Status: req.Status, Type: req.Type, } if req.ParentID != nil { objID, err := bson.ObjectIDFromHex(*req.ParentID) if err != nil { e := errs.InvalidFormat(err.Error()) return nil, e } permission.ID = objID } if err := uc.permissionRepo.Create(ctx, permission); err != nil { return nil, err } return permission, nil } func (uc *PermissionUseCase) GetPermission(ctx context.Context, id string) (*entity.Permission, error) { return uc.permissionRepo.GetByID(ctx, id) } func (uc *PermissionUseCase) UpdatePermission(ctx context.Context, req usecase.UpdatePermissionRequest) (*entity.Permission, error) { // 獲取現有權限 permission, err := uc.permissionRepo.GetByID(ctx, req.ID) if err != nil { return nil, err } // 更新字段 if req.Name != nil { permission.Name = *req.Name } if req.HTTPMethod != nil { permission.HTTPMethod = *req.HTTPMethod } if req.HTTPPath != nil { permission.HTTPPath = *req.HTTPPath } if req.Status != nil { permission.Status = *req.Status } if req.Type != nil { permission.Type = *req.Type } if err := uc.permissionRepo.Update(ctx, req.ID, permission); err != nil { return nil, err } return permission, nil } func (uc *PermissionUseCase) DeletePermission(ctx context.Context, id string) error { return uc.permissionRepo.Delete(ctx, id) } func (uc *PermissionUseCase) ListPermissions(ctx context.Context, req usecase.ListPermissionsRequest) ([]*entity.Permission, error) { filter := repository.PermissionFilter{ Status: req.Status, Type: req.Type, ParentID: req.ParentID, Limit: req.Limit, Skip: req.Skip, } return uc.permissionRepo.List(ctx, filter) } // CheckUserPermission 使用 Casbin 檢查用戶權限 func (uc *PermissionUseCase) CheckUserPermission(ctx context.Context, uid, httpMethod, httpPath string) (bool, error) { // 使用 Casbin 進行權限檢查 // sub: 用戶ID, obj: 資源路徑, act: 行為 hasPermission, err := uc.enforcer.Enforce(uid, httpPath, httpMethod) if err != nil { return false, errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin enforce failed: "+err.Error()) } if !hasPermission { return false, errs.InsufficientPermission(httpMethod + ":" + httpPath) } return true, nil } // CheckRolePermission 使用 Casbin 檢查角色權限 func (uc *PermissionUseCase) CheckRolePermission(ctx context.Context, roleUID, httpMethod, httpPath string) (bool, error) { // 使用 Casbin 進行角色權限檢查 hasPermission, err := uc.enforcer.Enforce(roleUID, httpPath, httpMethod) if err != nil { return false, errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin enforce failed: "+err.Error()) } if !hasPermission { return false, errs.InsufficientPermission(httpMethod + ":" + httpPath) } return true, nil } // GetUserPermissions 獲取用戶的所有權限 func (uc *PermissionUseCase) GetUserPermissions(ctx context.Context, uid string) (map[string]int, error) { // 獲取用戶的所有角色 roles, err := uc.enforcer.GetRolesForUser(uid) if err != nil { return nil, errs.SystemInternalErrorScope(code.CloudEPPermission, "failed to get user permissions: "+err.Error()) } permissions := make(map[string]int) // 獲取用戶直接擁有的權限 userPolicies, err := uc.enforcer.GetPermissionsForUser(uid) if err != nil { logx.Infof("failed to get user permissions: " + err.Error()) } for _, policy := range userPolicies { if len(policy) >= 3 { key := policy[2] + ":" + policy[1] // method:path permissions[key] = 1 } } // 獲取通過角色繼承的權限 for _, role := range roles { rolePolicies, err := uc.enforcer.GetPermissionsForUser(role) if err != nil { logx.Infof("failed to get permissions for user: " + err.Error()) } for _, policy := range rolePolicies { if len(policy) >= 3 { key := policy[2] + ":" + policy[1] // method:path permissions[key] = 1 } } } return permissions, nil } // BatchCheckPermissions 批量檢查權限 func (uc *PermissionUseCase) BatchCheckPermissions(ctx context.Context, uid string, permissions []usecase.PermissionCheck) (map[string]bool, error) { results := make(map[string]bool) for _, perm := range permissions { key := perm.HTTPMethod + ":" + perm.HTTPPath hasPermission, err := uc.enforcer.Enforce(uid, perm.HTTPPath, perm.HTTPMethod) if err != nil { return nil, errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin enforce failed: "+err.Error()) } results[key] = hasPermission } return results, nil } // AddPolicyForUser 為用戶添加權限策略 func (uc *PermissionUseCase) AddPolicyForUser(ctx context.Context, uid, httpPath, httpMethod string) error { added, err := uc.enforcer.AddPolicy(uid, httpPath, httpMethod) if err != nil { return errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin add policy failed: "+err.Error()) } if !added { return errs.ResourceAlreadyExistWithScope(code.CloudEPPermission, "policy already exists") } return nil } // RemovePolicyForUser 移除用戶的權限策略 func (uc *PermissionUseCase) RemovePolicyForUser(ctx context.Context, uid, httpPath, httpMethod string) error { removed, err := uc.enforcer.RemovePolicy(uid, httpPath, httpMethod) if err != nil { return errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin remove policy failed: "+err.Error()) } if !removed { return errs.ResourceNotFoundWithScope(code.CloudEPPermission, 0, "policy not found") } return nil } // AddRoleForUser 為用戶分配角色 func (uc *PermissionUseCase) AddRoleForUser(ctx context.Context, uid, roleUID string) error { added, err := uc.enforcer.AddRoleForUser(uid, roleUID) if err != nil { return errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin add role failed: "+err.Error()) } if !added { return errs.ResourceAlreadyExistWithScope(code.CloudEPPermission, "role already assigned") } return nil } // RemoveRoleForUser 移除用戶的角色 func (uc *PermissionUseCase) RemoveRoleForUser(ctx context.Context, uid, roleUID string) error { removed, err := uc.enforcer.DeleteRoleForUser(uid, roleUID) if err != nil { return errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin remove role failed: "+err.Error()) } if !removed { return errs.ResourceNotFoundWithScope(code.CloudEPPermission, 0, "role assignment not found") } return nil } // GetUsersForRole 獲取角色下的所有用戶 func (uc *PermissionUseCase) GetUsersForRole(ctx context.Context, roleUID string) ([]string, error) { return uc.enforcer.GetUsersForRole(roleUID) } // GetRolesForUser 獲取用戶的所有角色 func (uc *PermissionUseCase) GetRolesForUser(ctx context.Context, uid string) ([]string, error) { return uc.enforcer.GetRolesForUser(uid) } // AddPermissionForRole 為角色添加權限 func (uc *PermissionUseCase) AddPermissionForRole(ctx context.Context, roleUID, httpPath, httpMethod string) error { added, err := uc.enforcer.AddPolicy(roleUID, httpPath, httpMethod) if err != nil { return errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin add policy failed: "+err.Error()) } if !added { return errs.ResourceAlreadyExistWithScope(code.CloudEPPermission, "policy already exists") } return nil } // RemovePermissionForRole 移除角色的權限 func (uc *PermissionUseCase) RemovePermissionForRole(ctx context.Context, roleUID, httpPath, httpMethod string) error { removed, err := uc.enforcer.RemovePolicy(roleUID, httpPath, httpMethod) if err != nil { return errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin remove policy failed: "+err.Error()) } if !removed { return errs.ResourceNotFoundWithScope(code.CloudEPPermission, 0, "policy not found") } return nil } // GetPermissionsForRole 獲取角色的所有權限 func (uc *PermissionUseCase) GetPermissionsForRole(ctx context.Context, roleUID string) (map[string]int, error) { policies, err := uc.enforcer.GetPermissionsForUser(roleUID) if err != nil { return nil, errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin get permissions failed: "+err.Error()) } permissions := make(map[string]int) for _, policy := range policies { if len(policy) >= 3 { key := policy[2] + ":" + policy[1] // method:path permissions[key] = 1 } } return permissions, nil } // CheckPatternPermission 檢查模式權限 (支援通配符) func (uc *PermissionUseCase) CheckPatternPermission(ctx context.Context, uid, pattern, action string) (bool, error) { hasPermission, err := uc.enforcer.Enforce(uid, pattern, action) if err != nil { return false, errs.SystemInternalErrorScope(code.CloudEPPermission, "casbin enforce failed: "+err.Error()) } return hasPermission, nil } // GetAllPolicies 獲取所有策略 func (uc *PermissionUseCase) GetAllPolicies(ctx context.Context) ([][]string, error) { policies, err := uc.enforcer.GetPolicy() if err != nil { return nil, errs.SystemInternalErrorScope(code.CloudEPPermission, "failed to get all policies: "+err.Error()) } return policies, nil } // GetFilteredPolicies 獲取過濾後的策略 func (uc *PermissionUseCase) GetFilteredPolicies(ctx context.Context, fieldIndex int, fieldValues ...string) ([][]string, error) { policies, err := uc.enforcer.GetFilteredPolicy(fieldIndex, fieldValues...) if err != nil { return nil, errs.SystemInternalErrorScope(code.CloudEPPermission, "failed to get filtered policies: "+err.Error()) } return policies, nil }