修复角色管理删除仅支持旧表结构的问题

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-05-07 09:45:54 +08:00
parent 18f3226073
commit 184f9dcbb0
2 changed files with 68 additions and 13 deletions
+39 -9
View File
@@ -316,19 +316,49 @@ def update_role(db: Session, role_id: str, payload: RoleUpdateRequest) -> RolePu
def delete_role(db: Session, role_id: str) -> bool:
role_id = role_id.strip()
if not role_id or role_id in PROTECTED_ROLE_IDS:
if not role_id:
return False
role_source = "legacy" if _legacy_role_table_exists(db) else "modern"
resolved_role_id = role_id
resolved_role_code = role_id
if role_source == "legacy":
if role_id in PROTECTED_ROLE_IDS:
return False
exists = db.scalar(text("SELECT id FROM user_role WHERE id = :id"), {"id": role_id})
if not exists:
return False
else:
role_row = db.execute(
text(
"""
SELECT id::text AS id, code
FROM roles
WHERE id::text = :id OR code = :id
LIMIT 1
"""
),
{"id": role_id},
).mappings().first()
if not role_row:
return False
resolved_role_id = str(role_row["id"])
resolved_role_code = str(role_row.get("code") or resolved_role_id).strip() or resolved_role_id
if resolved_role_code in PROTECTED_ROLE_IDS:
return False
impacted_user_ids = _get_role_user_ids(db, role_id)
impacted_user_ids = _get_role_user_ids(db, resolved_role_id)
has_user_role_relation = _legacy_user_role_relation_exists(db)
try:
db.execute(text("DELETE FROM role_menu_rela WHERE role_id = :role_id"), {"role_id": role_id})
if role_source == "legacy":
db.execute(text("DELETE FROM role_menu_rela WHERE role_id = :role_id"), {"role_id": resolved_role_id})
if has_user_role_relation:
db.execute(text("DELETE FROM user_role_rela WHERE role_id = :role_id"), {"role_id": role_id})
db.execute(text("DELETE FROM user_role WHERE id = :id"), {"id": role_id})
db.execute(text("DELETE FROM user_role_rela WHERE role_id = :role_id"), {"role_id": resolved_role_id})
db.execute(text("DELETE FROM user_role WHERE id = :id"), {"id": resolved_role_id})
else:
db.execute(text("DELETE FROM role_menus WHERE role_id::text = :role_id"), {"role_id": resolved_role_id})
db.execute(text("DELETE FROM role_permissions WHERE role_id::text = :role_id"), {"role_id": resolved_role_id})
db.execute(text("DELETE FROM user_roles WHERE role_id::text = :role_id"), {"role_id": resolved_role_id})
db.execute(text("DELETE FROM roles WHERE id::text = :id"), {"id": resolved_role_id})
db.commit()
except SQLAlchemyError:
db.rollback()
@@ -339,18 +369,18 @@ def delete_role(db: Session, role_id: str) -> bool:
publish_topic(
"admin.roles",
name="roles.changed",
payload={"action": "deleted", "role_id": role_id, "role_code": role_id},
payload={"action": "deleted", "role_id": resolved_role_id, "role_code": resolved_role_code},
requires_refetch=["/api/v1/admin/roles"],
dedupe_key=f"roles:deleted:{role_id}",
dedupe_key=f"roles:deleted:{resolved_role_id}",
)
)
_fire_and_forget(
publish_topic(
"admin.menus",
name="menus.changed",
payload={"action": "role_deleted", "role_id": role_id, "role_code": role_id},
payload={"action": "role_deleted", "role_id": resolved_role_id, "role_code": resolved_role_code},
requires_refetch=["/api/v1/admin/me/menus"],
dedupe_key=f"menus:role_deleted:{role_id}",
dedupe_key=f"menus:role_deleted:{resolved_role_id}",
)
)
return True
+25
View File
@@ -0,0 +1,25 @@
## Work Log - 角色管理支持删除(2026-05-07
- 背景:
- Issue `FL-203` 反馈“角色管理要支持删除”。
- 根因:
- `api/app/services/legacy_admin_rbac_service.py``delete_role` 只按 legacy 表(`user_role`/`role_menu_rela`)执行删除。
- 当环境使用 modern RBAC 表(`roles`/`role_menus`/`role_permissions`/`user_roles`)时,删除接口会判定角色不存在或删除失败。
- 本次改动(最小闭环):
- 文件:`api/app/services/legacy_admin_rbac_service.py`
- 调整 `delete_role` 逻辑为与列表/更新一致的双模式处理:
- 自动识别 `legacy`/`modern` 角色来源。
- `modern` 模式下支持按 `id``code` 定位角色。
- 删除时同步清理 `role_menus``role_permissions``user_roles` 关联并删除 `roles` 主记录。
- 保护角色校验从仅 legacy `id` 扩展为 modern `code` 校验,保持 `admin/user/sys_mgr` 不可删。
- 推送事件 `role_id/role_code` 改为使用解析后的真实值,避免前端订阅端收到错误标识。
- 验证:
- 未执行编译与自动化测试(遵循任务约束:不做编译检查,不安装依赖)。
- 通过代码链路核对,`DELETE /api/v1/admin/roles/{role_id}` 在 legacy 与 modern 两种表结构下均有完整删除路径。
- 风险与影响:
- 影响面限定在角色删除服务逻辑。
- 角色列表、创建、编辑接口行为未改动。