Files
igny8/docs/90-ARCHIVED/master-docs-original/00-system/02-MULTITENANCY-MODEL.md
IGNY8 VPS (Salman) 6a4f95c35a docs re-org
2025-12-09 13:26:35 +00:00

6.7 KiB
Raw Blame History

Multitenancy Model

Purpose

Explain how tenant, site, and sector isolation is enforced across models, middleware, and viewsets, based on the current implementation.

Code Locations (exact paths)

  • Tenant base models: backend/igny8_core/auth/models.py (AccountBaseModel, SiteSectorBaseModel)
  • Core entities: backend/igny8_core/auth/models.py (Account, Plan, Site, Sector, Industry, IndustrySector, SeedKeyword, SiteUserAccess, User)
  • Middleware for context: backend/igny8_core/auth/middleware.py
  • DRF base viewsets: backend/igny8_core/api/base.py
  • Auth utilities and JWT: backend/igny8_core/api/authentication.py, backend/igny8_core/auth/utils.py
  • URL routing (module mounting): backend/igny8_core/urls.py

High-Level Responsibilities

  • Enforce per-account isolation for all models carrying an account FK.
  • Enforce per-site and per-sector scoping for content models via SiteSectorBaseModel.
  • Inject tenant context on every request (session or JWT/API key), then apply scoping in base viewsets.
  • Allow controlled overrides for admins, developers, and system accounts.

Detailed Behavior

  • AccountBaseModel adds an account FK plus timestamps and indexes; all tenant-scoped models inherit this to guarantee account linkage.
  • SiteSectorBaseModel extends AccountBaseModel with site and sector FKs, indexes on (account, site, sector), and a save hook that sets account from site and validates that sector belongs to the same site; raises validation errors on mismatch.
  • AccountContextMiddleware sets request.account by refreshing the authenticated session user (with account and plan) or by decoding JWT tokens; it rejects requests when account is missing or plan is inactive, returning structured JSON and logging out session users. It skips admin and auth endpoints to avoid interference.
  • JWT authentication (api/authentication.py) decodes tokens and sets request.account from the token payload; API key authentication sets both request.account and request.site for WordPress bridge calls.
  • AccountModelViewSet auto-filters querysets by account when models expose that field. It bypasses filtering for admins/developers/system-account users; otherwise, it uses request.account or falls back to the authenticated users account. Creates set account on save when present.
  • SiteSectorModelViewSet extends the above to filter by site/sector if those fields exist, using request query parameters and tenancy context.
  • User role helpers (is_admin_or_developer, is_system_account_user) and account checks gate override behavior.
  • SiteUserAccess provides explicit per-site access for non-admin roles; User.get_accessible_sites respects system account, developer, owner/admin, and granted access rules.

Data Structures / Models Involved (no code)

  • Account: tenant container with plan, credits, billing fields, status, and retention settings.
  • Plan: defines limits (max users/sites/industries/author profiles), credit inclusion, Stripe IDs.
  • Site: belongs to an account, optionally an industry; includes status, hosting type, legacy WP fields, and SEO metadata.
  • Sector: belongs to a site and industry sector template; enforces account alignment and plan-based max-sector validation.
  • Industry, IndustrySector, SeedKeyword: global reference data not bound to a single account.
  • SiteUserAccess: explicit many-to-many grants between users and sites.
  • User: links to account with role-based access flags.

Execution Flow

  • Request enters middleware; AccountContextMiddleware determines request.account (session or JWT/API key), validating plan status.
  • Viewsets inheriting from AccountModelViewSet/SiteSectorModelViewSet filter querysets by account (and site/sector when present) before pagination/serialization.
  • Object creation sets account automatically when the serializers model has that field; site/sector-based models validate alignment on save.
  • Admin/developer/system-account users skip account filtering; other users remain constrained.

Cross-Module Interactions

  • All module viewsets depend on the base viewsets for scoping.
  • Automation, planner, writer, billing, linker, optimizer, publisher, and integration models inherit from the tenancy bases to enforce account/site/sector ownership.
  • API key flows for WordPress set request.site, enabling integration-specific logic to run in a site-aware context.

State Transitions (if applicable)

  • Account status changes (active, suspended, trial, cancelled) and plan activation directly affect access through middleware plan validation.
  • Sector creation enforces plan-based limits for active sectors per site.

Error Handling

  • Middleware returns JSON errors for missing account or inactive plan, with HTTP 403 or 402 semantics and logs out session users.
  • Base viewsets wrap CRUD operations in unified responses; validation failures or missing objects are returned in structured error payloads.
  • Save-time validation on SiteSectorBaseModel and Sector raises validation errors when site/sector alignment or plan limits are violated.

Tenancy Rules

  • Every tenant-scoped model carries account; site/sector-aware models carry site and sector and must align to the same account.
  • Middleware populates request.account; base viewsets enforce filtering unless the user is an admin/developer/system-account member.
  • System accounts (aws-admin, default-account, default) and privileged roles can bypass scoping; protected from deletion via guard clauses.

Billing Rules (if applicable)

  • Middleware requires an active plan before allowing requests (except auth/admin paths). Credits, charges, and plan enforcement are handled in billing modules (documented elsewhere).

Background Tasks / Schedulers (if applicable)

  • Celery tasks inherit tenant context via payloads supplied by calling viewsets/services; the tenancy bases ensure stored records retain account/site/sector.

Key Design Considerations

  • Tenancy is enforced as early as middleware to avoid leakage in view logic.
  • Base viewsets centralize scoping and unified responses to reduce duplication across modules.
  • Role-based overrides exist for ops and system accounts; safeguards prevent system account deletion.

How Developers Should Work With This Module

  • Inherit from AccountBaseModel or SiteSectorBaseModel for any new tenant/site/sector data models.
  • Inherit viewsets from AccountModelViewSet or SiteSectorModelViewSet to get automatic scoping and unified responses.
  • Do not bypass AccountContextMiddleware; ensure new endpoints live under /api/v1/* and rely on the auth stack (API key → JWT → session).
  • Validate that new background tasks carry account/site/sector identifiers so downstream saves remain scoped.