- Show markdown when signing a document
- Introduce consent history - Centralise consent and content services and config
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from common.services.user.user_services import UserServices
|
||||
from common.services.user.partner_services import PartnerServices
|
||||
from common.services.user.tenant_services import TenantServices
|
||||
from common.services.user.consent_service import ConsentService
|
||||
from common.services.user.consent_services import ConsentServices
|
||||
|
||||
__all__ = ['UserServices', 'PartnerServices', 'TenantServices', 'ConsentService']
|
||||
__all__ = ['UserServices', 'PartnerServices', 'TenantServices', 'ConsentServices']
|
||||
@@ -20,7 +20,7 @@ class TypeStatus:
|
||||
last_version: Optional[str]
|
||||
|
||||
|
||||
class ConsentService:
|
||||
class ConsentServices:
|
||||
@staticmethod
|
||||
def get_required_consent_types() -> List[str]:
|
||||
return list(current_app.config.get("CONSENT_TYPES", []))
|
||||
@@ -50,12 +50,12 @@ class ConsentService:
|
||||
|
||||
@staticmethod
|
||||
def evaluate_type_status(tenant_id: int, consent_type: str) -> TypeStatus:
|
||||
active = ConsentService.get_active_consent_version(consent_type)
|
||||
active = ConsentServices.get_active_consent_version(consent_type)
|
||||
if not active:
|
||||
current_app.logger.error(f"No active ConsentVersion found for type {consent_type}")
|
||||
return TypeStatus(consent_type, ConsentStatus.UNKNOWN_CONSENT_VERSION, None, None)
|
||||
|
||||
last = ConsentService.get_tenant_last_consent(tenant_id, consent_type)
|
||||
last = ConsentServices.get_tenant_last_consent(tenant_id, consent_type)
|
||||
if not last:
|
||||
return TypeStatus(consent_type, ConsentStatus.NOT_CONSENTED, active.consent_version, None)
|
||||
|
||||
@@ -98,8 +98,8 @@ class ConsentService:
|
||||
|
||||
@staticmethod
|
||||
def get_consent_status(tenant_id: int) -> ConsentStatus:
|
||||
statuses = [ConsentService.evaluate_type_status(tenant_id, ct) for ct in ConsentService.get_required_consent_types()]
|
||||
return ConsentService.aggregate_status(statuses)
|
||||
statuses = [ConsentServices.evaluate_type_status(tenant_id, ct) for ct in ConsentServices.get_required_consent_types()]
|
||||
return ConsentServices.aggregate_status(statuses)
|
||||
|
||||
@staticmethod
|
||||
def _is_tenant_admin_for(tenant_id: int) -> bool:
|
||||
@@ -131,9 +131,9 @@ class ConsentService:
|
||||
@staticmethod
|
||||
def can_consent_on_behalf(tenant_id: int) -> Tuple[bool, str, Optional[int], Optional[int]]:
|
||||
# Returns: allowed, mode('tenant_admin'|'management_partner'), partner_id, partner_service_id
|
||||
if ConsentService._is_tenant_admin_for(tenant_id):
|
||||
if ConsentServices._is_tenant_admin_for(tenant_id):
|
||||
return True, 'tenant_admin', None, None
|
||||
allowed, partner_id, partner_service_id = ConsentService._is_management_partner_for(tenant_id)
|
||||
allowed, partner_id, partner_service_id = ConsentServices._is_management_partner_for(tenant_id)
|
||||
if allowed:
|
||||
return True, 'management_partner', partner_id, partner_service_id
|
||||
return False, 'none', None, None
|
||||
@@ -195,13 +195,13 @@ class ConsentService:
|
||||
@staticmethod
|
||||
def record_consent(tenant_id: int, consent_type: str) -> TenantConsent:
|
||||
# Validate type
|
||||
if consent_type not in ConsentService.get_required_consent_types():
|
||||
if consent_type not in ConsentServices.get_required_consent_types():
|
||||
raise ValueError(f"Unknown consent type: {consent_type}")
|
||||
active = ConsentService.get_active_consent_version(consent_type)
|
||||
active = ConsentServices.get_active_consent_version(consent_type)
|
||||
if not active:
|
||||
raise RuntimeError(f"No active ConsentVersion for type {consent_type}")
|
||||
|
||||
allowed, mode, partner_id, partner_service_id = ConsentService.can_consent_on_behalf(tenant_id)
|
||||
allowed, mode, partner_id, partner_service_id = ConsentServices.can_consent_on_behalf(tenant_id)
|
||||
if not allowed:
|
||||
raise PermissionError("Not authorized to record consent for this tenant")
|
||||
|
||||
@@ -216,7 +216,7 @@ class ConsentService:
|
||||
ip = request.headers.get('X-Forwarded-For', '').split(',')[0].strip() or request.remote_addr or ''
|
||||
ua = request.headers.get('User-Agent', '')
|
||||
locale = session.get('locale') or request.accept_languages.best or ''
|
||||
content_meta = ConsentService._resolve_consent_content(consent_type, active.consent_version)
|
||||
content_meta = ConsentServices._resolve_consent_content(consent_type, active.consent_version)
|
||||
consent_data = {
|
||||
'source_ip': ip,
|
||||
'user_agent': ua,
|
||||
@@ -178,5 +178,5 @@ class TenantServices:
|
||||
@staticmethod
|
||||
def get_consent_status(tenant_id: int) -> ConsentStatus:
|
||||
# Delegate to centralized ConsentService to ensure consistent logic
|
||||
from common.services.user.consent_service import ConsentService
|
||||
return ConsentService.get_consent_status(tenant_id)
|
||||
from common.services.user.consent_services import ConsentServices
|
||||
return ConsentServices.get_consent_status(tenant_id)
|
||||
|
||||
14
common/services/utils/version_services.py
Normal file
14
common/services/utils/version_services.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from flask import current_app
|
||||
|
||||
class VersionServices:
|
||||
@staticmethod
|
||||
def split_version(full_version: str) -> tuple[str, str]:
|
||||
parts = full_version.split(".")
|
||||
if len(parts) < 3:
|
||||
major_minor = '.'.join(parts[:2]) if len(parts) >= 2 else full_version
|
||||
patch = ''
|
||||
else:
|
||||
major_minor = '.'.join(parts[:2])
|
||||
patch = parts[2]
|
||||
|
||||
return major_minor, patch
|
||||
Reference in New Issue
Block a user