Files
group_fqcd_jr/app/repository/identity_repository.py
T

51 lines
2.3 KiB
Python
Raw Normal View History

2026-09-09 21:55:37 +08:00
from datetime import UTC, datetime
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.contracts import RequestContext
from app.core.errors import UnauthorizedAgentError
class IdentityRepository:
"""Read existing RBAC tables; never authorize from client role claims."""
def __init__(self, session: AsyncSession) -> None:
self.session = session
async def load_context(self, identity: RequestContext) -> RequestContext:
now = datetime.now(UTC).replace(tzinfo=None)
params = {"user_id": int(identity.user_id), "now": now}
status = await self.session.scalar(
text("SELECT status FROM sys_user WHERE id=:user_id"), params
)
if status != "正常":
raise UnauthorizedAgentError("账号不存在或未启用")
rows = (await self.session.execute(text("""
SELECT r.role_code, p.permission_code, p.data_scope
FROM sys_user_role ur JOIN sys_role r ON r.id=ur.role_id
LEFT JOIN sys_role_permission rp ON rp.role_id=r.id
LEFT JOIN sys_permission p ON p.id=rp.permission_id
WHERE ur.user_id=:user_id AND r.status='active'
AND ur.assigned_at<=:now AND (ur.expires_at IS NULL OR ur.expires_at>:now)
"""), params)).mappings().all()
roles = tuple(sorted({str(row["role_code"]) for row in rows}))
scopes: dict[str, str] = {}
rank = {"self": 0, "own_customers": 1, "all": 2}
for row in rows:
if row["permission_code"] and row["data_scope"] in rank:
code, scope = str(row["permission_code"]), str(row["data_scope"])
if code not in scopes or rank[scope] > rank[scopes[code]]:
scopes[code] = scope
customers = (await self.session.scalars(text("""
SELECT customer_id FROM sys_customer_assignment
WHERE employee_id=:user_id AND assigned_at<=:now
AND (unassigned_at IS NULL OR unassigned_at>:now)
"""), params)).all()
return identity.model_copy(update={
"roles": roles, "permissions": tuple(sorted(scopes)),
"permission_scopes": scopes, "data_scope": "self",
"customer_ids": tuple(str(value) for value in customers),
"portal": "api",
})