Просмотр исходного кода

feat: add role-to-permission mapping utility

Add permissions.js with ROLE_PERMISSIONS mapping table, getEffectivePermissions(), hasPermission() with wildcard matching, and getRoleLabel(). Supports admin/teacher/nutritionist/article_manager/activity_manager roles.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sisyphus 3 месяцев назад
Родитель
Сommit
c789b7b4df
1 измененных файлов с 73 добавлено и 0 удалено
  1. 73 0
      cfc-web/src/utils/permissions.js

+ 73 - 0
cfc-web/src/utils/permissions.js

@@ -0,0 +1,73 @@
+/**
+ * 角色→权限映射表
+ * 每个角色映射一组权限标识,支持通配符 '*' 和前缀通配 'prefix:*'
+ */
+const ROLE_PERMISSIONS = {
+  admin: ['*'],
+  teacher: ['dashboard', 'service:*', 'growth:*', 'biz:*', 'assessment:*', 'messages'],
+  nutritionist: ['dashboard', 'service:family', 'health:*', 'assessment:dan', 'energy'],
+  article_manager: ['dashboard', 'articles:*'],
+  activity_manager: ['dashboard', 'activity:*'],
+}
+
+/**
+ * 获取用户有效权限列表
+ * @param {string[]} roles - 用户拥有的角色列表
+ * @returns {string[]} - 去重后的权限标识列表
+ */
+export function getEffectivePermissions(roles) {
+  if (!roles || roles.length === 0) return []
+  const permSet = new Set()
+  for (const role of roles) {
+    const perms = ROLE_PERMISSIONS[role]
+    if (perms) {
+      for (const p of perms) {
+        permSet.add(p)
+      }
+    }
+  }
+  return Array.from(permSet)
+}
+
+/**
+ * 判断是否拥有指定权限
+ * @param {string[]} userPerms - 用户的有效权限列表
+ * @param {string} required - 需要的权限标识(支持 'prefix:*' 通配匹配)
+ * @returns {boolean}
+ *
+ * 匹配规则:
+ * - 如果 userPerms 包含 '*' → 返回 true
+ * - 如果 required 是 'prefix:sub' 且 userPerms 包含 'prefix:*' → 返回 true
+ * - 如果 userPerms 包含 required → 返回 true
+ * - 否则返回 false
+ */
+export function hasPermission(userPerms, required) {
+  if (!userPerms || !required) return false
+  if (userPerms.includes('*')) return true
+
+  // 精确匹配
+  if (userPerms.includes(required)) return true
+
+  // 前缀通配匹配: required = 'articles:manage', 检查 'articles:*' 是否在 userPerms 中
+  const colonIndex = required.indexOf(':')
+  if (colonIndex > 0) {
+    const prefix = required.substring(0, colonIndex) + ':*'
+    if (userPerms.includes(prefix)) return true
+  }
+
+  return false
+}
+
+/**
+ * 获取角色中文名
+ */
+export function getRoleLabel(role) {
+  const labels = {
+    admin: '管理员',
+    teacher: '成长规划师',
+    nutritionist: '营养师',
+    article_manager: '文章管理员',
+    activity_manager: '活动管理员',
+  }
+  return labels[role] || role
+}