349 lines
11 KiB
Go
349 lines
11 KiB
Go
|
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
|
||
|
}
|