ferrosoft.apps.ferrobase.middleware package¶
Submodules¶
ferrosoft.apps.ferrobase.middleware.appmeta module¶
- class ferrosoft.apps.ferrobase.middleware.appmeta.AppMetaMiddleware(get_response)[source]¶
Bases:
objectSet APP_META dict in request object.
This dict includes information about the application: NAME and ICON_PATH. The app is determined by HTTP Host header, allowing different branding per app.
- HOST_NAME_MAX_LENGTH = 255¶
- SETTINGS_KEY = 'FERROBASE_APP_HOSTS'¶
- async_capable = True¶
- sync_capable = False¶
ferrosoft.apps.ferrobase.middleware.asgi module¶
- class ferrosoft.apps.ferrobase.middleware.asgi.TenantASGIMiddleware(inner)[source]¶
Bases:
BaseMiddlewareThis middleware is like TenantMiddleware but for ASGI applications.
Only query parameters and cookies are inspected for tenant ID.
Well, not exactly the same thing. The resolved tenant is stored in scope field “tenant”. The thread-local variable is not written, because it cannot be guaranteed that the ASGI consumer is actually in the same thread. Thus, consumers need to explicitly use the context manager activate_tenant_database.
ferrosoft.apps.ferrobase.middleware.cache module¶
- class ferrosoft.apps.ferrobase.middleware.cache.CacheControlMiddleware(get_response)[source]¶
Bases:
objectMiddleware that ensures every response carries a
Cache-Controlheader.If the upstream view already set the header, it is left untouched. Otherwise the value is taken from
settings.CACHE_CONTROL, falling back to"no-store"so sensitive platform responses are never cached by default.- async_capable = True¶
- sync_capable = False¶
ferrosoft.apps.ferrobase.middleware.language module¶
- class ferrosoft.apps.ferrobase.middleware.language.UserLanguageMiddleware(get_response)[source]¶
Bases:
objectMiddleware that activates the authenticated user’s preferred language for each request.
Reads
user.language.iso_codeand callsdjango.utils.translation.activateso that all subsequentgettextcalls in the request–response cycle use the user’s chosen locale. Unauthenticated or language-less users receive Django’s default language.- async_capable = True¶
- sync_capable = True¶
ferrosoft.apps.ferrobase.middleware.tenant module¶
- exception ferrosoft.apps.ferrobase.middleware.tenant.BaseError[source]¶
Bases:
ExceptionBase class for all tenant-resolution errors.
- class ferrosoft.apps.ferrobase.middleware.tenant.GlobalRouter[source]¶
Bases:
objectSend queries for Django’s built-in apps and some of Ferrobase to default database.
- exception ferrosoft.apps.ferrobase.middleware.tenant.TenantChoiceRequired[source]¶
Bases:
BaseErrorRaised when no tenant has been chosen and user interaction is required to select one.
- class ferrosoft.apps.ferrobase.middleware.tenant.TenantMiddleware(get_response)[source]¶
Bases:
objectASGI-capable middleware that resolves and persists the active tenant per request.
Reads the tenant ID from POST → GET → cookie (in that order of priority). When the ID arrives via POST or GET, it is written back to the cookie so subsequent requests do not need to repeat it. The resolved
Tenantinstance is stored onrequest.current_tenantand in theactive_tenantcontext variable so ORM queries are automatically routed to the correct database.Unauthenticated requests and the tenant-selection view itself bypass resolution to avoid redirect loops.
- TENANT_REQUEST_KEY = 'fptid'¶
Name of the cookie and GET/POST parameter that carries the tenant ID.
- async_capable = True¶
- sync_capable = False¶
- exception ferrosoft.apps.ferrobase.middleware.tenant.TenantNotAllowed[source]¶
Bases:
BaseErrorRaised when the authenticated user is not authorised to access the requested tenant.
- exception ferrosoft.apps.ferrobase.middleware.tenant.TenantNotFound[source]¶
Bases:
BaseErrorRaised when the requested tenant ID does not exist or is inactive.
- class ferrosoft.apps.ferrobase.middleware.tenant.TenantRouter[source]¶
Bases:
objectSend queries to tenant database.
If no tenant is available, None is returned. TenantMiddleware makes sure to plug all holes so that no user can accidentally write Ferrosoft Platform objects to the default database.
- async ferrosoft.apps.ferrobase.middleware.tenant.aget_validated_tenant(tenant_id, user)[source]¶
Async variant of
get_validated_tenant.- Parameters:
- Returns:
The validated, active
Tenantinstance.- Return type:
- Raises:
TenantNotFound – If no active tenant with the given ID exists.
TenantNotAllowed – If the user is not permitted to use this tenant.
- async ferrosoft.apps.ferrobase.middleware.tenant.avalidate_chosen_tenant(tenant_id, user, organization)[source]¶
Async variant of
validate_chosen_tenant.- Parameters:
tenant_id (
str|None) – Tenant primary key string, orNone.user (
User|None) – Currently authenticated user for authorisation checks.organization (
Organization) – The user’s organisation.
- Returns:
The resolved
Tenantinstance.- Return type:
- Raises:
TenantChoiceRequired – When the tenant cannot be resolved automatically.
- ferrosoft.apps.ferrobase.middleware.tenant.get_validated_tenant(tenant_id, user)[source]¶
Look up and authorise a tenant synchronously.
- Parameters:
- Returns:
The validated, active
Tenantinstance.- Return type:
- Raises:
TenantNotFound – If no active tenant with the given ID exists.
TenantNotAllowed – If the user is not permitted to use this tenant.
- ferrosoft.apps.ferrobase.middleware.tenant.validate_chosen_tenant(tenant_id, user, organization)[source]¶
Resolve the tenant to use for an organisation, redirecting when no choice is made.
If
tenant_idis provided, it is validated; otherwise the organisation’s single tenant is used automatically. When the organisation has multiple tenants and none is specified, or when the requested tenant is invalid,TenantChoiceRequiredis raised so the caller can redirect to the selection page.- Parameters:
tenant_id (
str|None) – Tenant primary key string, orNone.user (
User|None) – Currently authenticated user for authorisation checks.organization (
Organization) – The user’s organisation used to enumerate available tenants.
- Returns:
The resolved
Tenantinstance.- Return type:
- Raises:
TenantChoiceRequired – When the tenant cannot be resolved automatically.