Prefer canonical identity and organization directories
This commit is contained in:
@@ -27,8 +27,9 @@ from govoplan_access.backend.semantic import (
|
||||
identity_id_for_account,
|
||||
)
|
||||
from govoplan_core.core.access import AccessDecisionProvenance, AccessExplanationService, PrincipalRef, ResourceAccessExplanationProvider
|
||||
from govoplan_core.core.identity import IdentityDirectory
|
||||
from govoplan_core.core.idm import IdmDirectory, OrganizationFunctionAssignmentRef
|
||||
from govoplan_core.core.organizations import OrganizationDirectory
|
||||
from govoplan_core.core.organizations import ORGANIZATIONS_MODULE_ID, OrganizationDirectory
|
||||
from govoplan_core.db.session import get_database
|
||||
from govoplan_access.backend.permissions.catalog import expand_scopes, scopes_grant
|
||||
|
||||
@@ -159,10 +160,12 @@ class SqlAccessExplanationService(AccessExplanationService):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
identity_directory: IdentityDirectory | None = None,
|
||||
idm_directory: IdmDirectory | None = None,
|
||||
organization_directory: OrganizationDirectory | None = None,
|
||||
resource_explanation_providers: Iterable[ResourceAccessExplanationProvider] = (),
|
||||
) -> None:
|
||||
self._identity_directory = identity_directory
|
||||
self._idm_directory = idm_directory
|
||||
self._organization_directory = organization_directory
|
||||
self._resource_explanation_providers = tuple(resource_explanation_providers)
|
||||
@@ -178,6 +181,7 @@ class SqlAccessExplanationService(AccessExplanationService):
|
||||
session,
|
||||
principal,
|
||||
required_scope,
|
||||
identity_directory=self._identity_directory,
|
||||
idm_directory=self._idm_directory,
|
||||
organization_directory=self._organization_directory,
|
||||
)
|
||||
@@ -196,6 +200,7 @@ class SqlAccessExplanationService(AccessExplanationService):
|
||||
session,
|
||||
principal,
|
||||
action,
|
||||
identity_directory=self._identity_directory,
|
||||
idm_directory=self._idm_directory,
|
||||
organization_directory=self._organization_directory,
|
||||
)
|
||||
@@ -250,12 +255,17 @@ def _scope_provenance(
|
||||
principal: PrincipalRef,
|
||||
required_scope: str,
|
||||
*,
|
||||
identity_directory: IdentityDirectory | None = None,
|
||||
idm_directory: IdmDirectory | None = None,
|
||||
organization_directory: OrganizationDirectory | None = None,
|
||||
) -> list[AccessDecisionProvenance]:
|
||||
items: list[AccessDecisionProvenance] = []
|
||||
account = session.get(Account, principal.account_id)
|
||||
identity_id = principal.identity_id or identity_id_for_account(session, principal.account_id)
|
||||
identity_id = principal.identity_id or identity_id_for_account(
|
||||
session,
|
||||
principal.account_id,
|
||||
identity_directory=identity_directory,
|
||||
)
|
||||
if identity_id:
|
||||
items.append(AccessDecisionProvenance(kind="identity", id=identity_id, source="identity_account_link"))
|
||||
items.append(
|
||||
@@ -421,6 +431,12 @@ def _idm_function_role_sources(
|
||||
for assignment in idm_directory.organization_function_assignments_for_account(user.account_id, tenant_id=user.tenant_id)
|
||||
if assignment.tenant_id == user.tenant_id and assignment.status == "active"
|
||||
]
|
||||
if organization_directory is not None:
|
||||
assignments = [
|
||||
assignment
|
||||
for assignment in assignments
|
||||
if _organization_function_active(organization_directory, assignment)
|
||||
]
|
||||
if not assignments:
|
||||
return [], []
|
||||
function_ids = sorted({assignment.function_id for assignment in assignments})
|
||||
@@ -429,6 +445,7 @@ def _idm_function_role_sources(
|
||||
.join(Role, ExternalFunctionRoleAssignment.role_id == Role.id)
|
||||
.filter(
|
||||
ExternalFunctionRoleAssignment.tenant_id == user.tenant_id,
|
||||
ExternalFunctionRoleAssignment.source_module == ORGANIZATIONS_MODULE_ID,
|
||||
ExternalFunctionRoleAssignment.function_id.in_(function_ids),
|
||||
Role.tenant_id == user.tenant_id,
|
||||
)
|
||||
@@ -446,7 +463,7 @@ def _idm_function_role_sources(
|
||||
mappings = mappings_by_function.get(assignment.function_id, [])
|
||||
function_facts.append(
|
||||
FunctionFactExplanation(
|
||||
source_module="organizations",
|
||||
source_module=ORGANIZATIONS_MODULE_ID,
|
||||
assignment_id=assignment.id,
|
||||
tenant_id=assignment.tenant_id,
|
||||
identity_id=assignment.identity_id,
|
||||
@@ -501,6 +518,14 @@ def _organization_labels(
|
||||
return (function.name if function is not None else None, unit.name if unit is not None else None)
|
||||
|
||||
|
||||
def _organization_function_active(
|
||||
organization_directory: OrganizationDirectory,
|
||||
assignment: OrganizationFunctionAssignmentRef,
|
||||
) -> bool:
|
||||
function = organization_directory.get_function(assignment.function_id)
|
||||
return function is not None and function.tenant_id == assignment.tenant_id and function.status == "active"
|
||||
|
||||
|
||||
def _system_role_sources(session: Session, account: Account) -> list[AccessRoleSourceExplanation]:
|
||||
roles = (
|
||||
session.query(Role)
|
||||
|
||||
Reference in New Issue
Block a user