Skip to content

Middleware

The core.middleware layer provides lightweight request preprocessing for the backend.

Its role is to prepare request-scoped context early in the lifecycle, without embedding business logic in the middleware itself.


Purpose

Middleware exists to:

  • initialize request-level context
  • attach the active organization to the request when possible
  • keep downstream permission and view logic simple
  • centralize early request preparation

In the current system, middleware is intentionally minimal.


Current Middleware

CurrentOrgMiddleware

This middleware initializes organization context for the request.

It:

  • sets request.org
  • sets request.organization
  • delegates actual resolution to the request context service

It does not perform business logic directly.


Why Middleware Is Lightweight

The architecture avoids putting complex behavior into middleware.

Instead:

  • middleware sets up request state
  • services resolve org/customer context
  • permissions enforce access
  • views remain thin

This keeps middleware:

  • testable
  • reusable
  • easy to reason about

Request Flow

flowchart LR
    A[Incoming Request] --> B[CurrentOrgMiddleware]
    B --> C[attach_current_org]
    C --> D[request.org set or None]
    D --> E[Permission Layer]

Responsibilities

CurrentOrgMiddleware

On every request:

  1. Initialize:
  2. request.org = None
  3. request.organization = None

  4. Call:

  5. attach_current_org(request)

  6. Continue request processing


Delegation to Request Context Service

The middleware does not know:

  • how orgs are resolved
  • how headers are interpreted
  • how memberships are checked

That logic is delegated to:

  • core.services.request_context

This is an intentional design decision.


What Middleware Does NOT Do

Middleware should not:

  • perform authorization logic
  • decide business permissions
  • query unrelated domain objects
  • return feature-specific responses
  • replace DRF permissions

Interaction with Permissions

Middleware is helpful, but permissions are still the source of enforcement.

Example:

  • middleware may set request.org
  • HasCurrentOrg confirms the request is valid
  • if resolution failed, permission denies access

This means the system remains safe even if middleware does not resolve an org.


Why Both Middleware and Permissions Exist

Middleware

  • improves ergonomics
  • attaches org early
  • simplifies downstream code

Permissions

  • enforce access
  • guarantee endpoint safety
  • prevent accidental bypass

This combination provides both convenience and security.


Request Attributes

After middleware runs, the request may contain:

request.org

The resolved internal organization, or None

request.organization

Alias for request.org

This alias exists for compatibility and readability.


Failure Behavior

If middleware cannot resolve an org:

  • request.org remains None
  • request continues
  • permissions later reject access if org is required

Middleware itself does not block the request.


Security Notes

Middleware is part of the multi-tenant infrastructure.

However, security does not rely on middleware alone.

Always use:

  • HasCurrentOrg
  • HasCurrentCustomerOrg

for protected endpoints.


Benefits

This middleware design provides:

  • early request setup
  • minimal coupling
  • clean layering
  • safer multi-tenant behavior

Future Extensions

Potential future middleware additions could include:

  • request correlation IDs
  • audit tracing context
  • locale/timezone resolution
  • feature flag bootstrap context

These should follow the same principle:

  • lightweight setup
  • delegate complex logic elsewhere

Summary

The middleware layer prepares request-scoped context without owning business logic.

CurrentOrgMiddleware is intentionally small and works together with:

  • request context services
  • permissions
  • policies

to support safe and predictable multi-tenant request handling.