Refactor API permissions and throttling: Updated default permission classes to enforce authentication and tenant access. Introduced new permission for system accounts and developers. Enhanced throttling rates for various operations to reduce false 429 errors. Improved API key loading logic to prioritize account-specific settings, with fallbacks to system accounts and Django settings. Updated integration views and sidebar to reflect new permission structure.

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-07 17:23:42 +00:00
parent 3cbed65601
commit 65fea95d33
15 changed files with 374 additions and 71 deletions

View File

@@ -0,0 +1,104 @@
# Multi-Tenancy & Access Reference (Current State)
## Purpose
Authoritative map of tenant isolation, role access, and payment/API-key handling across the stack. Built from code as of Dec 2025.
## Core Enforcement Points (backend)
- Middleware:
- `backend/igny8_core/auth/middleware.py` (`AccountContextMiddleware`, ~L1-L220): resolves `request.account` from JWT/API key; blocks inactive/suspended accounts.
- `backend/igny8_core/middleware/request_id.py` (~L1-L70): request ID (not tenancy).
- `backend/igny8_core/middleware/resource_tracker.py` (~L1-L170): metrics (not tenancy).
- Base viewsets:
- `backend/igny8_core/api/base.py` (`AccountModelViewSet`, ~L1-L240): filters by `request.account`; admin/developer/system overrides; sets account on create.
- `backend/igny8_core/api/base.py` (`SiteSectorModelViewSet`, ~L238-L430): additionally filters by site/sector and users accessible sites (SiteUserAccess) unless admin/developer/system.
- Permissions:
- `backend/igny8_core/api/permissions.py`:
- `IsAuthenticatedAndActive`, `HasTenantAccess` (default in settings).
- `IsViewerOrAbove`, `IsEditorOrAbove`, `IsAdminOrOwner`.
- `IsSystemAccountOrDeveloper` (system/admin for integrations).
- Module-specific permissions also appear in `backend/igny8_core/auth/permissions.py` (legacy IsOwnerOrAdmin, IsEditorOrAbove, IsViewerOrAbove, AccountPermission).
- Settings defaults:
- `backend/igny8_core/settings.py` REST_FRAMEWORK `DEFAULT_PERMISSION_CLASSES` = `IsAuthenticatedAndActive` + `HasTenantAccess`.
- Auth order: APIKeyAuthentication → JWTAuthentication → CSRFExemptSessionAuthentication → BasicAuth.
- Throttling: `DebugScopedRateThrottle` bypasses throttles for authenticated users/system/debug.
- Models with enforced account/site/sector:
- Base models `AccountBaseModel`, `SiteSectorBaseModel` in `backend/igny8_core/auth/models.py` (top of file).
## Flow (text flowchart)
```
Request
-> Middleware: AccountContextMiddleware sets request.account (JWT/API key), validates account status/plan
-> DRF Auth: APIKey/JWT/Session
-> Permissions: IsAuthenticatedAndActive + HasTenantAccess (+ role-specific)
-> ViewSet:
AccountModelViewSet filters by account
SiteSectorModelViewSet filters by account + site/sector + SiteUserAccess
-> Action-specific role checks (IsEditorOrAbove, IsAdminOrOwner, IsSystemAccountOrDeveloper)
-> Business logic (services) + credit checks (billing)
-> Response
```
## Module Access (backend ViewSets & guards)
- Accounts/Users/Plans/Subscriptions:
- `auth/views.py`: `UsersViewSet`, `AccountsViewSet`, `SubscriptionsViewSet`, `SiteUserAccessViewSet` (account-scoped via AccountModelViewSet + role guards).
- Roles: owner/admin (or developer/system) can manage; others limited to self (UsersViewSet get_queryset).
- Sites/Sectors:
- `auth/views.py` (`SiteViewSet`, `Sector` actions): SiteSectorModelViewSet enforces account + site/sector + SiteUserAccess; public slug read is AllowAny for active site slug only.
- Planner:
- `modules/planner/views.py` (KeywordViewSet, ClusterViewSet, ContentIdeasViewSet) inherit SiteSectorModelViewSet; require site_id/sector_id; role: typically editor+ for writes.
- Writer:
- `modules/writer/views.py` (TasksViewSet, ContentViewSet, ImagesViewSet, ContentTaxonomyViewSet) inherit SiteSectorModelViewSet; site/sector scoping; editor+ for writes.
- Automation:
- `business/automation/views.py` (AutomationViewSet) inherits AccountModelViewSet/SiteSectorModelViewSet patterns; requires site_id for run/config; role: editor+ for mutate.
- System settings (non-integrations):
- `modules/system/views.py` / `settings_views.py`: AccountModelViewSet; role usually admin/owner; authenticated + tenant required.
- Integrations (OpenAI/Runware API keys):
- `modules/system/integration_views.py`: guarded by `IsSystemAccountOrDeveloper` (system account or developer only); tenant-scoped but effectively system-only for keys.
- Billing:
- `modules/billing/views.py`: AccountModelViewSet; `IsAdminOrOwner` for credit transactions/payment methods; balance/usage requires auth + tenant.
- Payments/Payment Methods:
- Payment methods: `AccountPaymentMethodViewSet` account-scoped; IsAuthenticated; default selection per account; admin/owner should manage.
- Payments: `PaymentViewSet` account-scoped; IsAuthenticated; list/available_methods/manual payment for current account only.
## Frontend Guards
- Route protection: `ProtectedRoute` (auth required, checks account/plan/payment methods), `ModuleGuard` (module enabled), `AdminGuard` (integration/admin pages only for system account or developer).
- Sidebar hides Integration for non-system/developer; admin section shown only for system/developer.
## AI Key Resolution
- `ai/ai_core.py` `_load_account_settings`: tries tenant IntegrationSettings → system account IntegrationSettings (`aws-admin`/`default-account`/`default`) → Django settings (`OPENAI_API_KEY`, `RUNWARE_API_KEY`). All users run AI with shared keys if tenant keys absent.
## Throttling
- `api/throttles.py` `DebugScopedRateThrottle`: bypass for authenticated users/system/debug; per-scope rates in `settings.py`. Prevents 429s for normal users.
## Payment / Billing Workflow (happy path)
1) User authenticates (JWT) → request.account set.
2) Payment methods (account-scoped) fetched via `/v1/billing/payment-methods/available/`; admin/owner can CRUD `/v1/billing/payment-methods/`.
3) Invoices/Payments via billing endpoints (account-scoped; admin/owner).
4) Credits used via CreditService on AI/automation calls (backend).
## Access Summary by Role (runtime enforcement)
- Viewer: read-only where viewsets allow `IsViewerOrAbove`; no writes.
- Editor: can write planner/writer/automation; cannot manage billing/integration.
- Admin/Owner: manage account/team/billing/payment methods; full module writes.
- Developer/System account: cross-tenant overrides in some base filters; integration settings and admin menus.
## Key Files (with line bands)
- Middleware: `auth/middleware.py` (~L1-220)
- Base viewsets: `api/base.py` (~L1-430)
- Permissions: `api/permissions.py` (~L1-200), `auth/permissions.py` (~L1-120)
- Settings (REST/Throttle): `settings.py` (REST_FRAMEWORK block, ~L200-360)
- AI core key loading: `ai/ai_core.py` (~L1-120)
- Integration settings views: `modules/system/integration_views.py` (~L1-300 main guards; actions throughout)
- Planner views: `modules/planner/views.py` (all ViewSets inherit SiteSectorModelViewSet)
- Writer views: `modules/writer/views.py`
- Automation: `business/automation/views.py`, `services/automation_service.py`
- Billing: `modules/billing/views.py`, `business/billing/services/credit_service.py`
- Payment methods: `modules/billing/views.py` AccountPaymentMethodViewSet
- Frontend guards: `src/components/auth/ProtectedRoute.tsx`, `src/components/auth/AdminGuard.tsx`, `src/components/common/ModuleGuard.tsx`
- Sidebar gating: `src/layout/AppSidebar.tsx`
## Open Items / Risks
- Ensure public endpoints explicitly override default permissions (e.g., auth register/login, site slug read).
- Validate all viewsets still inherit AccountModelViewSet/SiteSectorModelViewSet after future changes.
- Add automated tests for cross-tenant denial, role gates, plan limits, and integration access.***

View File

@@ -53,3 +53,9 @@
## How Developers Should Work With This Module
- Before running any fix/verify script, read it and constrain to target account/site if possible.
- Add notes here when new manual interventions occur, including date/purpose and scripts used.
## Recent Hardening (Dec 2025)
- Throttling bypass for authenticated users to prevent user-facing 429s.
- AI keys fallback: OpenAI/Runware pulled from system account (`aws-admin`/`default-account`/`default`) or Django settings if tenant key absent.
- Integration settings restricted to system account or developer (`IsSystemAccountOrDeveloper` backend guard, `AdminGuard` frontend).
- DRF default permissions tightened to authenticated + tenant access (`IsAuthenticatedAndActive`, `HasTenantAccess`); public endpoints must override explicitly (e.g., AuthViewSet).