Release v0.1.6
This commit is contained in:
70
src/govoplan_core/tenancy/service.py
Normal file
70
src/govoplan_core/tenancy/service.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from govoplan_core.admin.common import AdminValidationError
|
||||
from govoplan_core.admin.settings import get_system_settings
|
||||
from govoplan_core.core.runtime import get_registry
|
||||
from govoplan_access.backend.db.models import ApiKey, Group, User
|
||||
from govoplan_tenancy.backend.db.models import Tenant
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class EffectiveTenantGovernance:
|
||||
allow_custom_groups: bool
|
||||
allow_custom_roles: bool
|
||||
allow_api_keys: bool
|
||||
|
||||
|
||||
def _narrowing_bool(system_allows: bool, tenant_override: bool | None) -> bool:
|
||||
if not system_allows:
|
||||
return False
|
||||
return tenant_override is not False
|
||||
|
||||
|
||||
def effective_tenant_governance(session: Session, tenant: Tenant) -> EffectiveTenantGovernance:
|
||||
defaults = get_system_settings(session)
|
||||
return EffectiveTenantGovernance(
|
||||
allow_custom_groups=_narrowing_bool(defaults.allow_tenant_custom_groups, tenant.allow_custom_groups),
|
||||
allow_custom_roles=_narrowing_bool(defaults.allow_tenant_custom_roles, tenant.allow_custom_roles),
|
||||
allow_api_keys=_narrowing_bool(defaults.allow_tenant_api_keys, tenant.allow_api_keys),
|
||||
)
|
||||
|
||||
|
||||
def assert_tenant_governance_override_allowed(session: Session, *, field: str, value: bool | None) -> None:
|
||||
if value is not True:
|
||||
return
|
||||
defaults = get_system_settings(session)
|
||||
blocked = {
|
||||
"allow_custom_groups": not defaults.allow_tenant_custom_groups,
|
||||
"allow_custom_roles": not defaults.allow_tenant_custom_roles,
|
||||
"allow_api_keys": not defaults.allow_tenant_api_keys,
|
||||
}
|
||||
if blocked.get(field):
|
||||
raise AdminValidationError("Tenant governance cannot explicitly allow a capability denied by system settings.")
|
||||
|
||||
|
||||
def _tenant_module_counts(session: Session, tenant_id: str) -> dict[str, int]:
|
||||
registry = get_registry()
|
||||
if registry is None or not hasattr(registry, "tenant_summary_providers"):
|
||||
return {}
|
||||
counts: dict[str, int] = {}
|
||||
for provider in registry.tenant_summary_providers().values():
|
||||
provided = provider(session, tenant_id)
|
||||
counts.update({str(key): int(value) for key, value in provided.items()})
|
||||
return counts
|
||||
|
||||
|
||||
def tenant_counts(session: Session, tenant_id: str) -> dict[str, int]:
|
||||
module_counts = _tenant_module_counts(session, tenant_id)
|
||||
|
||||
return {
|
||||
"users": session.query(User).filter(User.tenant_id == tenant_id).count(),
|
||||
"active_users": session.query(User).filter(User.tenant_id == tenant_id, User.is_active.is_(True)).count(),
|
||||
"groups": session.query(Group).filter(Group.tenant_id == tenant_id).count(),
|
||||
"campaigns": module_counts.get("campaigns", 0),
|
||||
"files": module_counts.get("files", 0),
|
||||
"api_keys": session.query(ApiKey).filter(ApiKey.tenant_id == tenant_id, ApiKey.revoked_at.is_(None)).count(),
|
||||
}
|
||||
Reference in New Issue
Block a user