from __future__ import annotations from pathlib import Path from govoplan_core.core.access import CAPABILITY_AUTH_PERMISSION_EVALUATOR, CAPABILITY_AUTH_PRINCIPAL_RESOLVER from govoplan_core.core.module_guards import persistent_table_uninstall_guard from govoplan_core.core.modules import ( DocumentationTopic, FrontendModule, FrontendRoute, MigrationSpec, ModuleContext, ModuleManifest, NavItem, PermissionDefinition, RoleTemplate, ) from govoplan_core.core.organizations import CAPABILITY_ORGANIZATION_DIRECTORY from govoplan_core.db.base import Base from govoplan_organizations.backend.db import models as organization_models # noqa: F401 - populate metadata ORGANIZATIONS_READ_SCOPES = ( "organizations:model:read", "organizations:unit:read", "organizations:function:read", "admin:settings:read", ) def _permission(scope: str, label: str, description: str) -> PermissionDefinition: module_id, resource, action = scope.split(":", 2) return PermissionDefinition( scope=scope, label=label, description=description, category="Organizations", level="tenant", module_id=module_id, resource=resource, action=action, ) PERMISSIONS = ( _permission("organizations:model:read", "View organization model", "Read organization meta-model definitions such as unit types, structures, and relation types."), _permission("organizations:model:write", "Manage organization model", "Create and edit organization meta-model definitions."), _permission("organizations:settings:read", "View organization settings", "Read organization governance, audit, and retention settings."), _permission("organizations:settings:write", "Manage organization settings", "Edit organization governance, audit, and retention settings."), _permission("organizations:unit:read", "View organization units", "Read concrete organization units and relations."), _permission("organizations:unit:write", "Manage organization units", "Create and edit concrete organization units and relations."), _permission("organizations:function:read", "View organization functions", "Read function definitions."), _permission("organizations:function:write", "Manage organization functions", "Create and edit function definitions."), ) ROLE_TEMPLATES = ( RoleTemplate( slug="organization_modeler", name="Organization modeler", description="Manage organization meta-model, concrete units, structures, and functions.", permissions=tuple(permission.scope for permission in PERMISSIONS), ), RoleTemplate( slug="organization_viewer", name="Organization viewer", description="Read organization model, organization units, and functions.", permissions=("organizations:model:read", "organizations:settings:read", "organizations:unit:read", "organizations:function:read"), ), ) def _route_factory(context: ModuleContext): del context from govoplan_organizations.backend.api.v1.routes import router return router def _organization_directory(context: ModuleContext) -> object: del context from govoplan_organizations.backend.directory import SqlOrganizationDirectory return SqlOrganizationDirectory() manifest = ModuleManifest( id="organizations", name="Organizations", version="0.1.8", required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR), optional_dependencies=("tenancy", "access", "audit", "policy"), permissions=PERMISSIONS, role_templates=ROLE_TEMPLATES, route_factory=_route_factory, nav_items=(NavItem(path="/organizations", label="Organizations", icon="users", required_any=ORGANIZATIONS_READ_SCOPES, order=70),), frontend=FrontendModule( module_id="organizations", package_name="@govoplan/organizations-webui", routes=(FrontendRoute(path="/organizations", component="OrganizationsPage", required_any=ORGANIZATIONS_READ_SCOPES, order=70),), nav_items=(NavItem(path="/organizations", label="Organizations", icon="users", required_any=ORGANIZATIONS_READ_SCOPES, order=70),), ), migration_spec=MigrationSpec( module_id="organizations", metadata=Base.metadata, script_location=str(Path(__file__).with_name("migrations") / "versions"), ), uninstall_guard_providers=( persistent_table_uninstall_guard( organization_models.OrganizationUnitType, organization_models.OrganizationTenantSettings, organization_models.OrganizationStructure, organization_models.OrganizationRelationType, organization_models.OrganizationRelation, organization_models.OrganizationUnit, organization_models.OrganizationFunctionType, organization_models.OrganizationFunction, label="Organizations", ), ), capability_factories={ CAPABILITY_ORGANIZATION_DIRECTORY: _organization_directory, }, documentation=( DocumentationTopic( id="organizations.model", title="Organization model", summary="Organizations owns units, hierarchy, and functions. IDM links identities to functions, and Access maps accepted facts to roles and rights.", body=( "Use organization unit types, structures, and relation types to model how the institution describes itself. " "A concrete organization unit can participate in several structures at the same time, such as an employer hierarchy and an academic structure. " "Functions describe responsibilities in organization units. IDM links identities to those functions, and Access maps accepted facts to roles and rights." ), layer="configured", documentation_types=("admin", "user"), audience=("tenant_admin", "access_admin", "operator"), order=25, ), ), ) def get_manifest() -> ModuleManifest: return manifest