fix: 修复权限映射的反向保存逻辑

问题:权限映射只在显示层面进行,但保存时还需要反向映射回数据库权限键

解决方案:
1. 分离显示权限和原始权限:
   - originalRoutePermissionsMap:存储未映射的原始权限(用于保存)
   - routePermissionsMap:存储映射后的权限(用于显示)
   - originalAllPermissions:存储所有原始权限的列表

2. 加载角色权限时:
   - 从API获取角色已分配的权限ID(原始ID)
   - 直接存储到 selectedPermissionIds
   - 不做任何映射转换

3. 显示权限列表时:
   - 从原始权限构建映射后的权限(合并相同的)
   - 用户看到的就是映射后的权限(如dify:dataset:manage)
   - 但勾选状态基于原始权限ID

4. 保存权限时:
   - 直接使用 selectedPermissionIds(原始ID)
   - 无需反向映射

验证方式:
1. 取消勾选 dify:dataset:manage → 数据库中4个bind权限被DENY → 接口返回403
2. 重新勾选 dify:dataset:manage → 数据库中4个bind权限被GRANT → 接口可访问
This commit is contained in:
2025-12-08 15:39:39 +08:00
parent 34029db395
commit d3418ef31b
2 changed files with 94 additions and 26 deletions
+56
View File
@@ -122,6 +122,62 @@ export function mapPermissions(permissions: Permission[]): Permission[] {
return Array.from(mappedMap.values());
}
/**
* 反向转换:将显示权限键转换为数据库权限键列表(用于保存权限)
* @param permissionKey 显示权限键(如 'dify:dataset:manage'
* @returns 对应的数据库权限键列表
*
* @example
* reverseMapPermissionKey('dify:dataset:manage')
* // 返回 ['dify:bind:list', 'dify:bind:create', 'dify:bind:update', 'dify:bind:delete']
*
* reverseMapPermissionKey('dify:file:read')
* // 返回 ['dify:file:read'](无映射)
*/
export function reverseMapPermissionKey(permissionKey: string): string[] {
// 查找所有映射到该权限键的原始权限键
const originalKeys: string[] = [];
for (const [key, mappedKey] of Object.entries(PERMISSION_KEY_MAP)) {
if (mappedKey === permissionKey) {
originalKeys.push(key);
}
}
return originalKeys.length > 0 ? originalKeys : [permissionKey];
}
/**
* 根据显示的权限ID查找对应的数据库权限ID(用于保存)
* 这是一个复杂操作,因为前端显示的权限ID是经过映射的
*
* @param displayPermissionId 前端显示的权限ID(映射后的)
* @param allMappedPermissions 所有映射后的权限列表(从路由获取的)
* @param originalPermissions 原始的权限列表(未映射的)
* @returns 对应的数据库权限ID列表
*/
export function findDbPermissionIds(
displayPermissionId: number,
allMappedPermissions: Permission[],
originalPermissions: Permission[]
): number[] {
// 查找显示权限对应的显示权限对象
const displayPerm = allMappedPermissions.find(p => p.id === displayPermissionId);
if (!displayPerm) return [];
// 将显示权限键反向映射为数据库权限键列表
const dbKeys = reverseMapPermissionKey(displayPerm.permission_key);
// 在原始权限列表中查找这些数据库权限键对应的ID
const dbIds: number[] = [];
for (const key of dbKeys) {
const originalPerm = originalPermissions.find(p => p.permission_key === key);
if (originalPerm) {
dbIds.push(originalPerm.id);
}
}
return dbIds;
}
/**
* 检查权限是否受映射影响
* @param permissionKey 权限键