mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 22:48:17 +00:00
- Introduced encoding and decoding of OAuth state to include tenant metadata, allowing the gateway to route callbacks without hard-coded tenant slugs. - Updated the AuthController to handle social account linking and sign-in with compatibility for legacy paths. - Refactored redirect URI construction to simplify tenant slug handling. - Enhanced documentation to reflect changes in the OAuth flow and state management. Signed-off-by: Innei <tukon479@gmail.com>
56 lines
2.5 KiB
Plaintext
56 lines
2.5 KiB
Plaintext
---
|
|
title: SaaS Architecture
|
|
description: Tenant model, domain routing, OAuth flow, and data injection paths.
|
|
createdAt: 2025-11-23T20:20:00+08:00
|
|
lastModified: 2025-11-30T14:03:05+08:00
|
|
order: 36
|
|
---
|
|
|
|
# SaaS Architecture
|
|
|
|
## Tenant model
|
|
|
|
- Tenants identified by **slug**; reserved: `root` (superadmin) and the placeholder slug.
|
|
- Status checks: active, suspended, banned (requests are rejected with dedicated error codes).
|
|
- Per-tenant plans and quotas enforced by `BillingPlanService` + `BillingUsageService`.
|
|
|
|
## Domains
|
|
|
|
- **Base domain** (default `afilmory.art`, editable in System Settings): tenants available at `<slug>.<baseDomain>`.
|
|
- **Custom domains**: tenant can request a domain; verification passes if CNAME points to `<baseDomain>` or TXT contains the issued token (handled by `TenantDomainService`).
|
|
- **Placeholder tenant**: used when slug is missing to render onboarding instead of erroring.
|
|
|
|
## Tenant resolution (core)
|
|
|
|
1. Existing context? reuse.
|
|
2. Match custom domain → `TenantDomainService`.
|
|
3. Else derive slug from host via `extractTenantSlugFromHost` and `baseDomain`.
|
|
4. Root/admin paths fallback to `root` tenant.
|
|
5. If still none, apply placeholder (unless configured to throw).
|
|
|
|
## OAuth gateway flow
|
|
|
|
- Providers redirect to the fixed `https://auth.<baseDomain>/api/auth/callback/{provider}`.
|
|
- Tenant slug is wrapped into the OAuth `state` so the gateway can restore the inner Better Auth state and forward to `https://<slug>.<baseDomain>/api/auth/callback/{provider}`.
|
|
- Keeps provider config simple (single callback URL) while maintaining per-tenant sessions.
|
|
|
|
## Data path
|
|
|
|
- Core serves the SPA and dashboard static bundles.
|
|
- Before sending `index.html`, it injects `window.__CONFIG__` and `window.__MANIFEST__` built from live DB/storage, so the frontend stays source-agnostic.
|
|
|
|
## Static assets roots
|
|
|
|
- Web: `apps/web` build copied into `be/apps/core/dist/static/web`.
|
|
- Dashboard: `be/apps/dashboard` build copied into `be/apps/core/dist/static/dashboard`.
|
|
- During tenant resolution, static roots are chosen per route segment; fallback logs are emitted if missing.
|
|
|
|
## Billing & plans
|
|
|
|
- System Settings define plan catalogs/pricing/overrides (billing + storage).
|
|
- Usage is aggregated per tenant; superadmin can change plan or ban via `/api/super-admin/tenants`.
|
|
|
|
## Root account provisioning
|
|
|
|
- On first boot, `RootAccountProvisioner` creates/updates the superadmin (`DEFAULT_SUPERADMIN_EMAIL/USERNAME`) and prints credentials and `/platform/root-login` URLs to stdout.
|