Create access module package
This commit is contained in:
81
src/govoplan_access/backend/auth/roles.py
Normal file
81
src/govoplan_access/backend/auth/roles.py
Normal file
@@ -0,0 +1,81 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from govoplan_access.backend.db.models import Account, Group, GroupMembership, Membership, Role, RoleBinding
|
||||
from govoplan_access.backend.permissions.evaluator import expand_scopes
|
||||
from govoplan_core.core.modules import PermissionDefinition, SubjectType
|
||||
|
||||
|
||||
def membership_group_ids(session: Session, *, tenant_id: str, membership_id: str) -> frozenset[str]:
|
||||
rows = (
|
||||
session.query(Group.id)
|
||||
.join(GroupMembership, GroupMembership.group_id == Group.id)
|
||||
.filter(
|
||||
GroupMembership.tenant_id == tenant_id,
|
||||
GroupMembership.membership_id == membership_id,
|
||||
Group.is_active.is_(True),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
return frozenset(row[0] for row in rows)
|
||||
|
||||
|
||||
def roles_for_subject(
|
||||
session: Session,
|
||||
*,
|
||||
subject_type: SubjectType,
|
||||
subject_id: str,
|
||||
tenant_id: str | None,
|
||||
) -> list[Role]:
|
||||
query = (
|
||||
session.query(Role)
|
||||
.join(RoleBinding, RoleBinding.role_id == Role.id)
|
||||
.filter(
|
||||
RoleBinding.subject_type == subject_type,
|
||||
RoleBinding.subject_id == subject_id,
|
||||
)
|
||||
)
|
||||
if tenant_id is None:
|
||||
query = query.filter(RoleBinding.tenant_id.is_(None), Role.tenant_id.is_(None))
|
||||
else:
|
||||
query = query.filter(RoleBinding.tenant_id == tenant_id, Role.tenant_id == tenant_id)
|
||||
return query.order_by(Role.name.asc()).all()
|
||||
|
||||
|
||||
def membership_roles(session: Session, membership: Membership) -> list[Role]:
|
||||
roles_by_id = {
|
||||
role.id: role
|
||||
for role in roles_for_subject(
|
||||
session,
|
||||
subject_type="membership",
|
||||
subject_id=membership.id,
|
||||
tenant_id=membership.tenant_id,
|
||||
)
|
||||
}
|
||||
for group_id in membership_group_ids(session, tenant_id=membership.tenant_id, membership_id=membership.id):
|
||||
for role in roles_for_subject(session, subject_type="group", subject_id=group_id, tenant_id=membership.tenant_id):
|
||||
roles_by_id[role.id] = role
|
||||
return list(roles_by_id.values())
|
||||
|
||||
|
||||
def account_system_roles(session: Session, account: Account) -> list[Role]:
|
||||
return roles_for_subject(session, subject_type="account", subject_id=account.id, tenant_id=None)
|
||||
|
||||
|
||||
def principal_scopes(
|
||||
session: Session,
|
||||
*,
|
||||
account: Account,
|
||||
membership: Membership | None,
|
||||
include_system: bool,
|
||||
catalog: dict[str, PermissionDefinition],
|
||||
) -> list[str]:
|
||||
scopes: set[str] = set()
|
||||
if membership is not None:
|
||||
for role in membership_roles(session, membership):
|
||||
scopes.update(role.permissions or [])
|
||||
if include_system:
|
||||
for role in account_system_roles(session, account):
|
||||
scopes.update(role.permissions or [])
|
||||
return expand_scopes(scopes, catalog=catalog)
|
||||
Reference in New Issue
Block a user