Source code for src.share_kernel.settings

"""Default settings for django-multitenant, overridable in the consumer project's settings.py."""

from django.conf import settings

MULTITENANT_DEFAULTS: dict[str, object] = {
    # Isolation
    "ISOLATION_BACKEND": "schema",  # 'schema', 'rls', 'shared_fk'
    # Schema (schema backend only)
    "SHARED_SCHEMA_NAME": "public",
    "TENANT_SCHEMA_PREFIX": "tenant_",
    "SCHEMA_NAME_REGEX": r"^[a-z][a-z0-9_]{2,62}$",
    "RESERVED_SCHEMA_NAMES": [
        "public",
        "pg_catalog",
        "information_schema",
        "pg_toast",
        "pg_temp",
    ],
    # Tenant resolution
    "TENANT_HEADER": "X-Tenant-ID",
    "TENANT_JWT_CLAIM": "tenant_id",
    "TENANT_RESOLUTION_ORDER": ["jwt", "header"],
    # ABAC
    "ABAC_DEFAULT_EFFECT": "deny",
    "ABAC_CONDITION_ENGINE": "json",  # 'json', 'cedar', 'casbin'
    "ABAC_STATIC_POLICIES_MODULE": "src.module.authorization.domain.static_policies",
    "ABAC_CACHE_POLICIES": True,
    "ABAC_ENABLED": True,
    "ABAC_POLICY_CACHE_TTL": 300,
    "ABAC_MAX_CONDITION_DEPTH": 10,
    "ABAC_MAX_CONDITIONS_PER_POLICY": 50,
    "ABAC_REGEX_TIMEOUT_MS": 100,
    # Approval
    "APPROVAL_DEFAULT_EXPIRATION_HOURS": 72,
    "APPROVAL_DEFAULT_REQUIRED_APPROVALS": 1,
    "APPROVAL_AUTO_EXECUTE_DEFAULT": True,
    "APPROVAL_ENABLED": True,
    # JWT (claims only — token lifetime is managed via SIMPLE_JWT)
    "JWT_INCLUDE_TENANT_CLAIMS": True,
    # Async backend
    "ASYNC_BACKEND": "auto",  # 'celery', 'sync', 'auto'
    # Cache isolation
    "CACHE_KEY_FUNCTION": "src.share_kernel.infrastructure.cache.tenant_cache_key_func",
    "CACHE_ISOLATION_ENABLED": True,
    # Noisy neighbor
    "TENANT_STATEMENT_TIMEOUT_MS": 30000,
    "TENANT_RATE_THROTTLE": "100/minute",
    # Security
    "TENANT_SCHEMA_SAFE_IDENTIFIER": True,
    # OTP / Two-Factor Authentication
    "OTP_ENABLED": False,
    "OTP_EMAIL_ENABLED": True,
    "OTP_TOTP_ENABLED": True,
    "OTP_STATIC_ENABLED": True,
    "OTP_EMAIL_TOKEN_VALIDITY_SECONDS": 300,  # 5 minutes
    "OTP_TOTP_ISSUER_NAME": "django-multitenant",
    "OTP_STATIC_TOKEN_COUNT": 10,
    "OTP_REQUIRED_FOR_LOGIN": False,  # When True, login requires OTP verification
    # Email verification
    "EMAIL_VERIFICATION_ENABLED": False,
    "EMAIL_VERIFICATION_TOKEN_VALIDITY_HOURS": 48,
    # Tenant invitations
    "INVITATION_ENABLED": True,
    "INVITATION_EXPIRATION_HOURS": 168,  # 7 days
    "INVITATION_FROM_EMAIL": None,  # Falls back to DEFAULT_FROM_EMAIL
}


[docs] def get_setting(name: str) -> object: """Retrieve a multitenant setting, falling back to the default.""" user_settings = getattr(settings, "MULTITENANT", {}) if name in user_settings: return user_settings[name] return MULTITENANT_DEFAULTS[name]