This commit is contained in:
Your Name
2026-08-07 17:51:57 +08:00
parent 6119fdd767
commit 327a0bc42f
29 changed files with 1610 additions and 579 deletions
+33 -11
View File
@@ -12,7 +12,7 @@ from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from models.models import Role, User
from .permissions import ALL_PERMISSIONS, normalize_permissions
from .permissions import ALL_PERMISSIONS, expand_paired_permissions, normalize_permissions
from .roles import (
ROLE_ADMIN,
RoleRecord,
@@ -48,7 +48,11 @@ def _decode_permissions(raw: str | None) -> list[str]:
def role_to_record(row: Role) -> RoleRecord:
perms = list(ALL_PERMISSIONS) if row.is_admin else _decode_permissions(row.permissions)
perms = (
list(ALL_PERMISSIONS)
if row.is_admin
else expand_paired_permissions(_decode_permissions(row.permissions))
)
return RoleRecord(
code=row.code,
label=row.label,
@@ -70,7 +74,7 @@ async def refresh_role_cache(db: AsyncSession) -> list[RoleRecord]:
async def seed_builtin_roles(db: AsyncSession) -> None:
"""Insert missing built-in roles and keep admin permissions complete."""
"""Insert missing built-in roles and keep system role permissions in sync."""
seeds = {seed.code: seed for seed in default_role_seeds()}
result = await db.execute(select(Role))
existing = {row.code: row for row in result.scalars().all()}
@@ -92,17 +96,35 @@ async def seed_builtin_roles(db: AsyncSession) -> None:
)
changed = True
continue
# Keep system flags and admin full permission set in sync.
# Keep system flags and built-in permission sets in sync with code.
if not row.is_system:
row.is_system = True
changed = True
if seed.is_admin and (not row.is_admin or row.permissions != payload):
row.is_admin = True
row.permissions = payload
row.label = seed.label
changed = True
elif not row.label:
row.label = seed.label
if seed.is_admin:
if not row.is_admin or row.permissions != payload or row.label != seed.label:
row.is_admin = True
row.permissions = payload
row.label = seed.label
if seed.description and row.description != seed.description:
row.description = seed.description
changed = True
else:
# operator / viewer: resync catalog so new menu/action codes ship.
desired = _encode_permissions(expand_paired_permissions(seed.permissions))
if row.permissions != desired or row.label != seed.label:
row.permissions = desired
row.label = seed.label
row.is_admin = False
changed = True
# Repair custom roles that have unpaired menu/action selections.
for row in existing.values():
if row.code in seeds or row.is_admin:
continue
repaired = expand_paired_permissions(_decode_permissions(row.permissions))
encoded = _encode_permissions(repaired)
if row.permissions != encoded:
row.permissions = encoded
changed = True
if changed: