181 lines
6.0 KiB
Python
181 lines
6.0 KiB
Python
"""Compatibility facade for privacy retention policy.
|
|
|
|
Policy-owned behavior is provided by ``govoplan-policy`` through the
|
|
``policy.privacyRetention`` capability. This module keeps legacy imports stable
|
|
without importing policy implementation code from core.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any, Mapping
|
|
|
|
from govoplan_core.core.policy import CAPABILITY_POLICY_PRIVACY_RETENTION, PrivacyRetentionService
|
|
from govoplan_core.core.runtime import get_registry
|
|
from govoplan_core.privacy.schemas import (
|
|
RETENTION_DAY_KEYS as RETENTION_DAY_KEYS,
|
|
RETENTION_POLICY_FIELD_KEYS,
|
|
default_allow_lower_level_limits as default_allow_lower_level_limits,
|
|
normalize_allow_lower_level_limits,
|
|
)
|
|
|
|
|
|
PRIVACY_POLICY_SETTINGS_KEY = "privacy_retention_policy"
|
|
_DEFAULT_POLICY = {
|
|
"store_raw_campaign_json": True,
|
|
"raw_campaign_json_retention_days": None,
|
|
"generated_eml_retention_days": None,
|
|
"stored_report_detail_retention_days": None,
|
|
"mock_mailbox_retention_days": None,
|
|
"audit_detail_retention_days": None,
|
|
"audit_detail_level": "full",
|
|
}
|
|
|
|
_EXPORTS = (
|
|
"PRIVACY_POLICY_SETTINGS_KEY",
|
|
"RETENTION_DAY_KEYS",
|
|
"RETENTION_POLICY_FIELD_KEYS",
|
|
"PrivacyRetentionPolicy",
|
|
"PrivacyRetentionPolicyPatch",
|
|
"PrivacyPolicyError",
|
|
"default_allow_lower_level_limits",
|
|
"privacy_policy_from_settings",
|
|
"privacy_policy_from_session",
|
|
"set_privacy_policy",
|
|
"effective_privacy_policy",
|
|
"parent_privacy_policy",
|
|
"effective_privacy_policy_sources",
|
|
"parent_privacy_policy_sources",
|
|
"get_privacy_policy_for_scope",
|
|
"set_privacy_policy_for_scope",
|
|
"sanitize_audit_details_for_policy",
|
|
"apply_retention_policy",
|
|
)
|
|
|
|
|
|
class PrivacyPolicyError(RuntimeError):
|
|
pass
|
|
|
|
|
|
class _UnavailablePolicyModel:
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
del args, kwargs
|
|
_raise_unavailable()
|
|
|
|
@classmethod
|
|
def model_validate(cls, value: Any) -> Any:
|
|
del value
|
|
_raise_unavailable()
|
|
|
|
|
|
PrivacyRetentionPolicy = _UnavailablePolicyModel
|
|
PrivacyRetentionPolicyPatch = _UnavailablePolicyModel
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class _SystemPrivacyPolicy:
|
|
payload: Mapping[str, Any]
|
|
|
|
def model_dump(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
del args, kwargs
|
|
return dict(self.payload)
|
|
|
|
|
|
def _raise_unavailable() -> None:
|
|
raise PrivacyPolicyError("Privacy retention policy requires the active govoplan-policy module.")
|
|
|
|
|
|
def _runtime_service() -> PrivacyRetentionService | None:
|
|
registry = get_registry()
|
|
if registry is None or not hasattr(registry, "has_capability") or not registry.has_capability(CAPABILITY_POLICY_PRIVACY_RETENTION):
|
|
return None
|
|
capability = registry.require_capability(CAPABILITY_POLICY_PRIVACY_RETENTION)
|
|
if not isinstance(capability, PrivacyRetentionService):
|
|
raise PrivacyPolicyError("Privacy retention policy capability is invalid")
|
|
return capability
|
|
|
|
|
|
def _service() -> PrivacyRetentionService:
|
|
service = _runtime_service()
|
|
if service is None:
|
|
_raise_unavailable()
|
|
return service
|
|
|
|
|
|
def _settings_payload(item: object) -> dict[str, Any]:
|
|
settings = getattr(item, "settings", None)
|
|
return dict(settings or {}) if isinstance(settings, Mapping) else {}
|
|
|
|
|
|
def _policy_data(settings_payload: Mapping[str, Any] | None) -> dict[str, Any]:
|
|
raw = settings_payload.get(PRIVACY_POLICY_SETTINGS_KEY) if isinstance(settings_payload, Mapping) else None
|
|
if not isinstance(raw, Mapping):
|
|
raw = {}
|
|
payload = dict(_DEFAULT_POLICY)
|
|
for key in RETENTION_POLICY_FIELD_KEYS:
|
|
if key in raw:
|
|
payload[key] = raw[key]
|
|
payload["allow_lower_level_limits"] = normalize_allow_lower_level_limits(raw.get("allow_lower_level_limits"), fill_defaults=True)
|
|
return payload
|
|
|
|
|
|
def privacy_policy_from_settings(item: object) -> Any:
|
|
service = _runtime_service()
|
|
if service is not None:
|
|
return service.privacy_policy_from_settings(item)
|
|
return _SystemPrivacyPolicy(_policy_data(_settings_payload(item)))
|
|
|
|
|
|
def privacy_policy_from_session(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().privacy_policy_from_session(*args, **kwargs)
|
|
|
|
|
|
def set_privacy_policy(item: object, policy: Any) -> Any:
|
|
service = _runtime_service()
|
|
if service is not None:
|
|
return service.set_privacy_policy(item, policy)
|
|
value = policy.model_dump(mode="json") if hasattr(policy, "model_dump") else dict(policy or {})
|
|
next_settings = _settings_payload(item)
|
|
next_settings[PRIVACY_POLICY_SETTINGS_KEY] = _policy_data({PRIVACY_POLICY_SETTINGS_KEY: value})
|
|
setattr(item, "settings", next_settings)
|
|
return _SystemPrivacyPolicy(next_settings[PRIVACY_POLICY_SETTINGS_KEY])
|
|
|
|
|
|
def effective_privacy_policy(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().effective_privacy_policy(*args, **kwargs)
|
|
|
|
|
|
def parent_privacy_policy(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().parent_privacy_policy(*args, **kwargs)
|
|
|
|
|
|
def effective_privacy_policy_sources(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().effective_privacy_policy_sources(*args, **kwargs)
|
|
|
|
|
|
def parent_privacy_policy_sources(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().parent_privacy_policy_sources(*args, **kwargs)
|
|
|
|
|
|
def get_privacy_policy_for_scope(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().get_privacy_policy_for_scope(*args, **kwargs)
|
|
|
|
|
|
def set_privacy_policy_for_scope(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().set_privacy_policy_for_scope(*args, **kwargs)
|
|
|
|
|
|
def sanitize_audit_details_for_policy(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
service = _runtime_service()
|
|
if service is not None:
|
|
return dict(service.sanitize_audit_details_for_policy(*args, **kwargs))
|
|
details = args[1] if len(args) > 1 else kwargs.get("details")
|
|
return dict(details or {})
|
|
|
|
|
|
def apply_retention_policy(*args: Any, **kwargs: Any) -> Any:
|
|
return _service().apply_retention_policy(*args, **kwargs)
|
|
|
|
|
|
__all__ = list(_EXPORTS)
|