feat: Infrastructure multi-tenant avec isolation par sous-domaine
Une application SaaS éducative nécessite une séparation stricte des données entre établissements scolaires. L'architecture multi-tenant par sous-domaine (ecole-alpha.classeo.local) permet cette isolation tout en utilisant une base de code unique. Le choix d'une résolution basée sur les sous-domaines plutôt que sur des headers ou tokens facilite le routage au niveau infrastructure (reverse proxy) et offre une UX plus naturelle où chaque école accède à "son" URL dédiée.
This commit is contained in:
5
backend/config/packages/debug.yaml
Normal file
5
backend/config/packages/debug.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
when@dev:
|
||||
debug:
|
||||
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||
# See the "server:dump" command to start a new server.
|
||||
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
||||
18
backend/config/packages/dev/tenant.yaml
Normal file
18
backend/config/packages/dev/tenant.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
# Tenants de développement
|
||||
# Ces tenants sont automatiquement chargés en environnement dev
|
||||
|
||||
parameters:
|
||||
tenant.dev_configs:
|
||||
- tenantId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
||||
subdomain: 'ecole-alpha'
|
||||
databaseUrl: '%env(DATABASE_URL)%'
|
||||
- tenantId: 'b2c3d4e5-f6a7-8901-bcde-f12345678901'
|
||||
subdomain: 'ecole-beta'
|
||||
databaseUrl: '%env(DATABASE_URL)%'
|
||||
|
||||
services:
|
||||
App\Shared\Infrastructure\Tenant\TenantRegistry:
|
||||
class: App\Shared\Infrastructure\Tenant\InMemoryTenantRegistry
|
||||
factory: ['@App\Shared\Infrastructure\Tenant\TenantRegistryFactory', 'createFromConfig']
|
||||
arguments:
|
||||
$configs: '%tenant.dev_configs%'
|
||||
19
backend/config/packages/prod/tenant.yaml
Normal file
19
backend/config/packages/prod/tenant.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
# Configuration des tenants en production
|
||||
#
|
||||
# En production, les tenants peuvent être configurés de deux façons :
|
||||
# 1. Via la variable d'environnement TENANT_CONFIGS (JSON)
|
||||
# 2. Via une implémentation DatabaseTenantRegistry (à implémenter)
|
||||
#
|
||||
# Pour l'instant, on utilise InMemoryTenantRegistry avec configuration env.
|
||||
# Si aucun tenant n'est configuré, toutes les requêtes retourneront 404.
|
||||
|
||||
parameters:
|
||||
# Format JSON attendu: [{"tenantId":"uuid","subdomain":"ecole","databaseUrl":"postgres://..."}]
|
||||
tenant.prod_configs_json: '%env(default::TENANT_CONFIGS)%'
|
||||
|
||||
services:
|
||||
App\Shared\Infrastructure\Tenant\TenantRegistry:
|
||||
class: App\Shared\Infrastructure\Tenant\InMemoryTenantRegistry
|
||||
factory: ['@App\Shared\Infrastructure\Tenant\TenantRegistryFactory', 'createFromEnv']
|
||||
arguments:
|
||||
$configsJson: '%tenant.prod_configs_json%'
|
||||
3
backend/config/packages/property_info.yaml
Normal file
3
backend/config/packages/property_info.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
framework:
|
||||
property_info:
|
||||
with_constructor_extractor: true
|
||||
10
backend/config/packages/routing.yaml
Normal file
10
backend/config/packages/routing.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
framework:
|
||||
router:
|
||||
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||
default_uri: '%env(DEFAULT_URI)%'
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: null
|
||||
9
backend/config/packages/tenant.yaml
Normal file
9
backend/config/packages/tenant.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
services:
|
||||
# Tenant infrastructure event subscribers
|
||||
App\Shared\Infrastructure\Tenant\TenantMiddleware:
|
||||
tags:
|
||||
- { name: kernel.event_subscriber }
|
||||
|
||||
App\Shared\Infrastructure\Security\TenantAccessDeniedHandler:
|
||||
tags:
|
||||
- { name: kernel.event_subscriber }
|
||||
18
backend/config/packages/test/tenant.yaml
Normal file
18
backend/config/packages/test/tenant.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
# Tenants pour les tests
|
||||
# Utilise les mêmes tenants que dev pour les tests d'intégration
|
||||
|
||||
parameters:
|
||||
tenant.test_configs:
|
||||
- tenantId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
||||
subdomain: 'ecole-alpha'
|
||||
databaseUrl: '%env(DATABASE_URL)%'
|
||||
- tenantId: 'b2c3d4e5-f6a7-8901-bcde-f12345678901'
|
||||
subdomain: 'ecole-beta'
|
||||
databaseUrl: '%env(DATABASE_URL)%'
|
||||
|
||||
services:
|
||||
App\Shared\Infrastructure\Tenant\TenantRegistry:
|
||||
class: App\Shared\Infrastructure\Tenant\InMemoryTenantRegistry
|
||||
factory: ['@App\Shared\Infrastructure\Tenant\TenantRegistryFactory', 'createFromConfig']
|
||||
arguments:
|
||||
$configs: '%tenant.test_configs%'
|
||||
13
backend/config/packages/web_profiler.yaml
Normal file
13
backend/config/packages/web_profiler.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
|
||||
framework:
|
||||
profiler:
|
||||
collect_serializer_data: true
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
profiler:
|
||||
collect: false
|
||||
collect_serializer_data: true
|
||||
Reference in New Issue
Block a user