Fix Bug 3+4+6: permission_version bump, denied_permissions, soft-delete

This commit is contained in:
2026-07-20 23:13:45 +00:00
parent 26850801fd
commit 7bb72f6b9e
+29 -6
View File
@@ -3,6 +3,7 @@
from __future__ import annotations from __future__ import annotations
import uuid import uuid
from datetime import UTC, datetime
from typing import Any from typing import Any
from sqlalchemy import select from sqlalchemy import select
@@ -20,7 +21,7 @@ class RoleService:
tenant_id: uuid.UUID, tenant_id: uuid.UUID,
) -> list[dict[str, Any]]: ) -> list[dict[str, Any]]:
"""List all roles in a tenant.""" """List all roles in a tenant."""
q = select(Role).where(Role.tenant_id == tenant_id) q = select(Role).where(Role.tenant_id == tenant_id, Role.deleted_at.is_(None))
result = await db.execute(q) result = await db.execute(q)
roles = result.scalars().all() roles = result.scalars().all()
return [self._role_to_dict(r) for r in roles] return [self._role_to_dict(r) for r in roles]
@@ -31,6 +32,7 @@ class RoleService:
tenant_id: uuid.UUID, tenant_id: uuid.UUID,
name: str, name: str,
permissions: dict[str, Any], permissions: dict[str, Any],
denied_permissions: list[str] | None = None,
field_permissions: dict[str, Any] | None = None, field_permissions: dict[str, Any] | None = None,
) -> Role: ) -> Role:
"""Create a new custom role.""" """Create a new custom role."""
@@ -38,6 +40,7 @@ class RoleService:
tenant_id=tenant_id, tenant_id=tenant_id,
name=name, name=name,
permissions=permissions, permissions=permissions,
denied_permissions=denied_permissions or [],
field_permissions=field_permissions or {}, field_permissions=field_permissions or {},
) )
db.add(role) db.add(role)
@@ -51,21 +54,35 @@ class RoleService:
role_id: uuid.UUID, role_id: uuid.UUID,
name: str | None = None, name: str | None = None,
permissions: dict[str, Any] | None = None, permissions: dict[str, Any] | None = None,
denied_permissions: list[str] | None = None,
field_permissions: dict[str, Any] | None = None, field_permissions: dict[str, Any] | None = None,
) -> Role | None: ) -> Role | None:
"""Update a role.""" """Update a role. Increments permission_version on permission changes."""
q = select(Role).where(Role.id == role_id, Role.tenant_id == tenant_id) q = select(Role).where(
Role.id == role_id,
Role.tenant_id == tenant_id,
Role.deleted_at.is_(None),
)
result = await db.execute(q) result = await db.execute(q)
role = result.scalar_one_or_none() role = result.scalar_one_or_none()
if role is None: if role is None:
return None return None
version_bump = False
if name is not None: if name is not None:
role.name = name role.name = name
if permissions is not None: if permissions is not None:
role.permissions = permissions role.permissions = permissions
version_bump = True
if denied_permissions is not None:
role.denied_permissions = denied_permissions
version_bump = True
if field_permissions is not None: if field_permissions is not None:
role.field_permissions = field_permissions role.field_permissions = field_permissions
version_bump = True
if version_bump:
role.permission_version += 1
await db.flush() await db.flush()
return role return role
@@ -76,14 +93,18 @@ class RoleService:
tenant_id: uuid.UUID, tenant_id: uuid.UUID,
role_id: uuid.UUID, role_id: uuid.UUID,
) -> bool: ) -> bool:
"""Delete a role.""" """Soft-delete a role."""
q = select(Role).where(Role.id == role_id, Role.tenant_id == tenant_id) q = select(Role).where(
Role.id == role_id,
Role.tenant_id == tenant_id,
Role.deleted_at.is_(None),
)
result = await db.execute(q) result = await db.execute(q)
role = result.scalar_one_or_none() role = result.scalar_one_or_none()
if role is None: if role is None:
return False return False
await db.delete(role) role.deleted_at = datetime.now(UTC)
await db.flush() await db.flush()
return True return True
@@ -93,7 +114,9 @@ class RoleService:
"id": str(role.id), "id": str(role.id),
"name": role.name, "name": role.name,
"permissions": role.permissions, "permissions": role.permissions,
"denied_permissions": role.denied_permissions,
"field_permissions": role.field_permissions, "field_permissions": role.field_permissions,
"permission_version": role.permission_version,
} }