diff --git a/.gitignore b/.gitignore index 7406241..807ea2e 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,5 @@ scripts/__pycache__/run_eveai_app.cpython-312.pyc /nginx/.parcel-cache/ /nginx/static/ /docker/build_logs/ +/content/.Ulysses-Group.plist +/content/.Ulysses-Settings.plist diff --git a/common/services/user/__init__.py b/common/services/user/__init__.py index f1e5463..703a2f6 100644 --- a/common/services/user/__init__.py +++ b/common/services/user/__init__.py @@ -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'] \ No newline at end of file +__all__ = ['UserServices', 'PartnerServices', 'TenantServices', 'ConsentServices'] \ No newline at end of file diff --git a/common/services/user/consent_service.py b/common/services/user/consent_services.py similarity index 93% rename from common/services/user/consent_service.py rename to common/services/user/consent_services.py index deb65e8..c7e0a6e 100644 --- a/common/services/user/consent_service.py +++ b/common/services/user/consent_services.py @@ -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, diff --git a/common/services/user/tenant_services.py b/common/services/user/tenant_services.py index 3f96472..44d18fd 100644 --- a/common/services/user/tenant_services.py +++ b/common/services/user/tenant_services.py @@ -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) diff --git a/common/services/utils/version_services.py b/common/services/utils/version_services.py new file mode 100644 index 0000000..10e64a4 --- /dev/null +++ b/common/services/utils/version_services.py @@ -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 diff --git a/config/config.py b/config/config.py index 5f9b9e8..8f7543e 100644 --- a/config/config.py +++ b/config/config.py @@ -316,6 +316,11 @@ class Config(object): # Type Definitions ---------------------------------------------------------------------------- TENANT_TYPES = ['Active', 'Demo', 'Inactive', 'Test'] CONSENT_TYPES = ["Data Privacy Agreement", "Terms & Conditions"] + # CONSENT_TYPE_MAP maps names with the actual base folders the consent documents are stored in + CONSENT_TYPE_MAP = { + "Data Privacy Agreement": "dpa", + "Terms & Conditions": "terms", + } # The maximum number of seconds allowed for audio compression (to save resources) MAX_COMPRESSION_DURATION = 60*10 # 10 minutes diff --git a/eveai_app/templates/basic/view_markdown.html b/eveai_app/templates/basic/view_markdown.html index c002c24..c167008 100644 --- a/eveai_app/templates/basic/view_markdown.html +++ b/eveai_app/templates/basic/view_markdown.html @@ -6,14 +6,14 @@ {% block content %}
-
+
-
+