Skip to content

createReactivePermission

基于响应式系统的权限管理函数,支持角色切换时的自动权限更新。

函数签名

typescript
function createReactivePermission(
  config: PermissionConfig,
  deps: PermissionDeps
): PermissionInstance

interface PermissionConfig {
  /** 默认角色 */
  defaultRole: string
  /** 所有权限定义 */
  permissions: Permission[]
  /** 所有角色定义 */
  roles: Role[]
  /** 是否严格模式(检查未定义的权限时抛出错误) */
  strict?: boolean
}

interface PermissionDeps {
  /** 创建响应式对象 */
  createReactive: CreateReactive
  /** 控制台日志函数 */
  log: (...args: any[]) => void
  /** 控制台警告函数 */
  warn: (...args: any[]) => void
}

interface Permission {
  /** 权限代码 */
  code: string
  /** 权限名称 */
  name: string
  /** 权限描述 */
  description?: string
}

interface Role {
  /** 角色代码 */
  code: string
  /** 角色名称 */
  name: string
  /** 角色拥有的权限代码列表 */
  permissions: string[]
  /** 角色描述 */
  description?: string
}

前置依赖

依赖参数

参数名类型说明
deps.createReactiveCreateReactive创建响应式对象的函数,用于实现角色切换的自动更新
deps.log(...args: any[]) => void日志输出函数,用于记录角色切换等操作
deps.warn(...args: any[]) => void警告输出函数,用于记录权限检查警告信息

环境要求

  • createReactive: 需要先导入 createReactive 函数
bash
# 确保已安装相关依赖
npm install shared

参数

参数名类型必填说明
configPermissionConfig权限配置对象
config.defaultRolestring默认角色代码
config.permissionsPermission[]所有权限定义列表
config.rolesRole[]所有角色定义列表
config.strictboolean是否启用严格模式,默认 false
depsPermissionDeps环境依赖,包含响应式函数和日志函数

返回值

类型说明
PermissionInstance权限管理实例,包含权限检查和角色管理方法

工作原理

  1. 响应式状态管理:使用 createReactive 创建响应式的角色状态
  2. 权限检查:根据当前角色的权限列表进行权限验证
  3. 多种检查模式:支持单个权限、全部权限(AND)、任一权限(OR)的检查
  4. 订阅通知:角色变化时自动通知所有订阅者
  5. 动态管理:支持运行时添加角色和权限
  6. 严格模式:可选的权限定义检查,避免检查未定义的权限

核心特性

  • 角色切换时所有权限检查自动更新
  • 灵活的权限检查方式(单个/全部/任一)
  • 支持动态添加角色和权限
  • 响应式订阅机制
  • 可选的严格模式

异常

错误类型触发条件错误信息
Error缺少默认角色defaultRole is required
Error角色列表为空roles is required and cannot be empty
Error默认角色不存在Default role "xxx" not found in roles

完整示例

typescript
import { createReactivePermission } from 'zcw-shared/reactive/createReactivePermission'
import { createReactive } from 'zcw-shared/reactive/createReactive'

// 创建权限管理实例
const permission = createReactivePermission({
  defaultRole: 'user',
  permissions: [
    { code: 'user.view', name: '查看用户', description: '查看用户列表和详情' },
    { code: 'user.create', name: '创建用户', description: '创建新用户' },
    { code: 'user.edit', name: '编辑用户', description: '编辑用户信息' },
    { code: 'user.delete', name: '删除用户', description: '删除用户账户' },
    { code: 'post.view', name: '查看文章', description: '查看文章列表' },
    { code: 'post.create', name: '创建文章', description: '创建新文章' },
    { code: 'post.edit', name: '编辑文章', description: '编辑文章内容' },
    { code: 'post.delete', name: '删除文章', description: '删除文章' },
    { code: 'post.publish', name: '发布文章', description: '发布文章' }
  ],
  roles: [
    {
      code: 'guest',
      name: '访客',
      description: '未登录用户',
      permissions: ['post.view']
    },
    {
      code: 'user',
      name: '普通用户',
      description: '已注册的普通用户',
      permissions: ['user.view', 'post.view', 'post.create']
    },
    {
      code: 'editor',
      name: '编辑',
      description: '内容编辑',
      permissions: ['user.view', 'post.view', 'post.create', 'post.edit', 'post.publish']
    },
    {
      code: 'admin',
      name: '管理员',
      description: '系统管理员',
      permissions: ['user.view', 'user.create', 'user.edit', 'user.delete', 'post.view', 'post.create', 'post.edit', 'post.delete', 'post.publish']
    }
  ],
  strict: true
}, {
  createReactive,
  log: console.log,
  warn: console.warn
})

// 单个权限检查
console.log(permission.hasPermission('user.view'))  // true
console.log(permission.hasPermission('user.edit'))  // false

// 多个权限检查 (AND)
console.log(permission.hasAllPermissions(['user.view', 'post.create']))  // true
console.log(permission.hasAllPermissions(['user.view', 'user.edit']))  // false

// 多个权限检查 (OR)
console.log(permission.hasAnyPermission(['user.edit', 'post.create']))  // true
console.log(permission.hasAnyPermission(['user.edit', 'user.delete']))  // false

// 切换角色
permission.setRole('admin')
console.log(permission.hasPermission('user.edit'))  // true
console.log(permission.hasPermission('user.delete'))  // true

// 订阅角色变化
const unsubscribe = permission.subscribe(() => {
  console.log('角色已切换到:', permission.currentRole)
  // 更新 UI 显示
  updateUI()
})

// 获取当前角色信息
const currentRole = permission.getCurrentRole()
console.log(currentRole?.name)  // 管理员
console.log(currentRole?.permissions)  // ['user.view', 'user.create', ...]

// 获取当前角色的所有权限对象
const currentPermissions = permission.getCurrentPermissions()
console.log(currentPermissions)  // [{ code: 'user.view', name: '查看用户' }, ...]

// 动态添加角色
permission.addRole({
  code: 'moderator',
  name: '版主',
  description: '内容审核',
  permissions: ['post.view', 'post.edit', 'post.delete']
})

// 动态添加权限
permission.addPermission({
  code: 'comment.moderate',
  name: '审核评论',
  description: '审核和管理评论'
})

// 为角色添加权限
permission.addPermissionToRole('moderator', 'comment.moderate')

// 从角色移除权限
permission.removePermissionFromRole('moderator', 'post.delete')

// 检查角色是否存在
console.log(permission.hasRole('moderator'))  // true

// 获取所有角色
const allRoles = permission.getRoles()
console.log(allRoles)  // [{ code: 'guest', ... }, { code: 'user', ... }, ...]

// 获取所有权限
const allPermissions = permission.getPermissions()
console.log(allPermissions)  // [{ code: 'user.view', ... }, { code: 'user.create', ... }, ...]

// 清理订阅
unsubscribe()

实际应用场景

Vue 组件中使用

typescript
import { createReactivePermission } from 'zcw-shared/reactive/createReactivePermission'
import { createReactive } from 'zcw-shared/reactive/createReactive'
import { ref, computed } from 'vue'

const permission = createReactivePermission(config, { 
  createReactive, 
  log: console.log, 
  warn: console.warn 
})

export default {
  setup() {
    const currentRole = ref(permission.currentRole)
    
    // 订阅角色变化
    permission.subscribe(() => {
      currentRole.value = permission.currentRole
    })
    
    // 计算属性
    const canEdit = computed(() => permission.hasPermission('post.edit'))
    const canDelete = computed(() => permission.hasPermission('post.delete'))
    
    return {
      currentRole,
      canEdit,
      canDelete,
      hasPermission: permission.hasPermission,
      setRole: permission.setRole
    }
  }
}

React Hook 中使用

typescript
function usePermission() {
  const [currentRole, setCurrentRole] = useState(permission.currentRole)
  
  useEffect(() => {
    const unsubscribe = permission.subscribe(() => {
      setCurrentRole(permission.currentRole)
    })
    
    return unsubscribe
  }, [])
  
  return {
    currentRole,
    hasPermission: permission.hasPermission,
    hasAllPermissions: permission.hasAllPermissions,
    hasAnyPermission: permission.hasAnyPermission,
    setRole: permission.setRole
  }
}

路由守卫

typescript
// Vue Router 守卫
router.beforeEach((to, from, next) => {
  const requiredPermissions = to.meta.permissions as string[]
  
  if (requiredPermissions && requiredPermissions.length > 0) {
    if (permission.hasAllPermissions(requiredPermissions)) {
      next()
    } else {
      next('/403')  // 无权限,跳转到 403 页面
    }
  } else {
    next()
  }
})

UI 条件渲染

vue
<template>
  <div>
    <!-- 单个权限检查 -->
    <button v-if="permission.hasPermission('user.create')">
      创建用户
    </button>
    
    <!-- 多个权限检查 (AND) -->
    <button v-if="permission.hasAllPermissions(['post.edit', 'post.publish'])">
      编辑并发布
    </button>
    
    <!-- 多个权限检查 (OR) -->
    <button v-if="permission.hasAnyPermission(['post.edit', 'post.delete'])">
      管理文章
    </button>
    
    <!-- 角色切换 -->
    <select v-model="permission.currentRole">
      <option v-for="role in permission.getRoles()" :key="role.code" :value="role.code">
        {{ role.name }}
      </option>
    </select>
  </div>
</template>

高级用法

自定义权限检查函数

typescript
// 基于资源的权限检查
function canAccessResource(resourceType: string, action: string): boolean {
  const permissionCode = `${resourceType}.${action}`
  return permission.hasPermission(permissionCode)
}

// 使用示例
if (canAccessResource('user', 'edit')) {
  // 允许编辑用户
}

权限组合

typescript
// 定义权限组
const ADMIN_PERMISSIONS = [
  'user.view', 'user.create', 'user.edit', 'user.delete',
  'post.view', 'post.create', 'post.edit', 'post.delete', 'post.publish'
]

const EDITOR_PERMISSIONS = [
  'post.view', 'post.create', 'post.edit', 'post.publish'
]

// 检查是否具有管理员权限组
function isAdmin(): boolean {
  return permission.hasAllPermissions(ADMIN_PERMISSIONS)
}

// 检查是否具有编辑权限组
function isEditor(): boolean {
  return permission.hasAllPermissions(EDITOR_PERMISSIONS)
}

权限继承

typescript
// 定义角色层级
const ROLE_HIERARCHY = {
  guest: [],
  user: ['guest'],
  editor: ['user'],
  admin: ['editor']
}

// 扩展角色权限(继承父角色权限)
function extendRolePermissions(role: Role, allRoles: Role[]): string[] {
  const permissions = [...role.permissions]
  const parents = ROLE_HIERARCHY[role.code as keyof typeof ROLE_HIERARCHY] || []
  
  parents.forEach(parentCode => {
    const parentRole = allRoles.find(r => r.code === parentCode)
    if (parentRole) {
      permissions.push(...extendRolePermissions(parentRole, allRoles))
    }
  })
  
  return [...new Set(permissions)]  // 去重
}

动态权限加载

typescript
// 从服务器加载权限配置
async function loadPermissionsFromServer() {
  const response = await fetch('/api/permissions')
  const data = await response.json()
  
  // 添加新权限
  data.permissions.forEach((p: Permission) => {
    permission.addPermission(p)
  })
  
  // 添加新角色
  data.roles.forEach((r: Role) => {
    permission.addRole(r)
  })
}

// 根据用户信息设置角色
async function setupUserPermissions(userId: string) {
  const response = await fetch(`/api/users/${userId}/role`)
  const { roleCode } = await response.json()
  
  permission.setRole(roleCode)
}

基于响应式系统的权限管理解决方案,让权限控制变得简单而高效!