fix:[FL-197][角色管理 - 修复数据库表 user_role 不存在错误]

修复角色创建功能在使用现代表结构(roles)时因硬编码查询 user_role 表而导致的数据库错误。

问题分析:
- admin.py:72 直接硬编码查询 user_role 表检查角色是否存在
- legacy_admin_rbac_service.py:201 也硬编码查询 user_role 表
- 实际项目使用的是现代表结构 roles(定义在 rbac.py)
- 导致 psycopg.errors.UndefinedTable: relation "user_role" does not exist

修复方案:
1. 移除 admin.py 中的硬编码表查询,将重复检查逻辑委托给 create_role 服务函数
2. 在 create_role 函数中添加 role_source 检测逻辑
3. 根据检测结果使用正确的表名(user_role 或 roles)和字段
4. 确保 legacy 和 modern 模式下都能正常工作

影响范围:
- 角色创建功能现在支持两种表结构
- 保持向后兼容性(legacy 模式仍使用 user_role)
- 修复 modern 模式下的角色创建功能

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-18 12:35:32 +08:00
parent 80cf981fdb
commit 96f83923f6
2 changed files with 42 additions and 25 deletions
+1 -7
View File
@@ -67,15 +67,9 @@ def create_role_endpoint(
current_user: CurrentUser = Depends(require_permission("role.manage")),
db: Session = Depends(get_db),
) -> RolePublic:
from sqlalchemy import text
# Check if role code already exists
existing = db.scalar(text("SELECT id FROM user_role WHERE id = :id"), {"id": payload.code.strip()})
if existing:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="角色编码已存在,请使用其他编码")
created = create_role(db, payload, actor_user_id=current_user.user.id)
if not created:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="创建角色失败,请检查菜单权限配置是否正确")
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="创建角色失败,角色编码已存在或菜单权限配置正确")
return created
+41 -18
View File
@@ -198,32 +198,55 @@ def create_role(db: Session, payload: RoleCreateRequest, *, actor_user_id: str |
role_name = payload.name.strip()
if not role_name:
return None
existing = db.scalar(text("SELECT id FROM user_role WHERE id = :id"), {"id": role_id})
role_source = "legacy" if _legacy_role_table_exists(db) else "modern"
# Check if role code already exists
if role_source == "legacy":
existing = db.scalar(text("SELECT id FROM user_role WHERE id = :id"), {"id": role_id})
else:
existing = db.scalar(text("SELECT id FROM roles WHERE code = :code"), {"code": role_id})
if existing:
return None
menu_ids = sorted(set(menu_id.strip() for menu_id in payload.menu_ids if menu_id.strip()))
if not _menu_ids_exist(db, menu_ids):
if not _menu_ids_exist(db, menu_ids, role_source=role_source):
return None
now = datetime.now()
try:
db.execute(
text(
"""
INSERT INTO user_role (id, name, descr, state, create_date, update_date)
VALUES (:id, :name, :descr, 'ENABLED', :create_date, :update_date)
"""
),
{
"id": role_id,
"name": role_name,
"descr": role_name,
"create_date": now,
"update_date": now,
},
)
_replace_role_menus_internal(db, role_id, menu_ids)
if role_source == "legacy":
db.execute(
text(
"""
INSERT INTO user_role (id, name, descr, state, create_date, update_date)
VALUES (:id, :name, :descr, 'ENABLED', :create_date, :update_date)
"""
),
{
"id": role_id,
"name": role_name,
"descr": role_name,
"create_date": now,
"update_date": now,
},
)
else:
db.execute(
text(
"""
INSERT INTO roles (code, name)
VALUES (:code, :name)
"""
),
{
"code": role_id,
"name": role_name,
},
)
_replace_role_menus_internal(db, role_id, menu_ids, role_source=role_source)
write_audit_log(
db,
action="role.create",