feat: 修复权限键不匹配问题 - 前端权限映射

问题:前端权限列表显示dify:bind:*,但路由实际检查dify:dataset:*和dify:file:*
导致取消勾选后权限控制失效

解决方案:
1. 创建权限映射工具(permission-mapper.ts)
   - dify:bind:list/create/update/delete → dify:dataset:manage
   - 自动将数据库权限键映射为实际生效的权限键

2. 修改角色权限管理页面
   - 加载角色权限时应用权限键映射
   - 渲染权限列表时显示实际生效的权限键
   - 保存权限时使用映射后的权限ID

影响范围:
- 知识库管理权限(/chat-with-llm/dataset-manager)
- 角色权限分配页面(/role-permissions)

验证方式:
取消勾选dify:dataset:manage后,知识库管理接口应返回403
This commit is contained in:
2025-12-08 15:29:31 +08:00
parent 3f5c23123b
commit 547633bf38
2 changed files with 164 additions and 3 deletions
+22 -3
View File
@@ -949,6 +949,9 @@ export default function RolePermissions() {
const handleSelectRole = async (role: RoleInfo) => {
setSelectedRole(role);
// 动态导入权限映射工具
const { mapPermissions, mapPermissionKey, findDbPermissionKeys } = await import('~/utils/permission-mapper');
// v3.0: 并行加载数据
const [routesResult, rolePermissions, users] = await Promise.all([
getRoleRoutesWithPermissions(role.id),
@@ -959,11 +962,14 @@ export default function RolePermissions() {
const { routes: routesWithPerms, selectedRouteIds: routeIds } = routesResult;
// 构建 routePermissionsMap:从返回的路由中提取每个路由的可用 permissions
// 并应用权限键映射(dify:bind:* -> dify:dataset:*, dify:file:*
const permMap = new Map<number, ApiPermission[]>();
const extractPermissions = (routes: RouteInfo[]) => {
routes.forEach(route => {
if (route.permissions && route.permissions.length > 0) {
permMap.set(route.id, route.permissions);
// 应用权限键映射
const mappedPermissions = mapPermissions(route.permissions);
permMap.set(route.id, mappedPermissions);
}
if (route.children) {
extractPermissions(route.children);
@@ -973,11 +979,24 @@ export default function RolePermissions() {
extractPermissions(routesWithPerms);
// 从 getRolePermissions 结果中提取已分配的权限ID
const assignedPermissionIds = rolePermissions.map(p => p.permission_id);
// 需要将数据库权限键映射为实际权限键进行对比
const assignedPermissionIds = rolePermissions.map(p => {
// 查找该权限对应的所有数据库权限键
const dbKeys = findDbPermissionKeys(p.permission_key);
// 如果使用映射,找到对应的权限ID
const mappedKey = mapPermissionKey(p.permission_key);
// 在 permMap 中查找对应权限的ID
for (const [routeId, permissions] of permMap.entries()) {
const foundPerm = permissions.find(perm => perm.permission_key === mappedKey);
if (foundPerm) return foundPerm.id;
}
return p.permission_id;
});
setRoutePermissionsMap(permMap);
setSelectedRouteIds(routeIds);
setSelectedPermissionIds(assignedPermissionIds); // 使用实际已分配的权限ID
setSelectedPermissionIds(assignedPermissionIds); // 使用映射后的权限ID
setExpandedRouteIds([]); // 重置展开状态
setRoleUsers(users);
};