Multi-Tenant (Organisations)
Activez les espaces de travail en équipe avec les organisations, invitations, rôles et facturation partagée.
Multi-Tenant (Organisations)
ScaleRocket inclut un support multi-tenant optionnel. Une fois activé, les utilisateurs peuvent créer des organisations, inviter des membres, attribuer des rôles et partager la facturation sous un seul plan.
Activer le Multi-Tenant
Activez le flag dans votre configuration :
// packages/config/src/site.ts
export const siteConfig = {
multiTenant: true, // ← mettre à true
// ...
};Puis activez le trigger de création automatique dans l'éditeur SQL de Supabase :
CREATE TRIGGER on_auth_user_created_org
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user_org();Cela crée automatiquement une organisation personnelle quand un nouvel utilisateur s'inscrit.
Ce qui change
| Fonctionnalité | multiTenant: false | multiTenant: true |
|---|---|---|
| Sidebar | Dashboard, Settings, Billing | Dashboard, Team, Settings, Billing |
| Crédits | Par utilisateur | Par organisation |
| Facturation | Par utilisateur | Par organisation (le propriétaire paie) |
| Accès aux données | L'user voit ses données | L'user voit les données de l'orga |
| Sélecteur d'orga | Caché | Visible dans la sidebar |
Schéma de base de données
Deux tables sont ajoutées par la migration 00002_multi_tenant.sql :
organizations
| Colonne | Type | Description |
|---|---|---|
id | UUID | Clé primaire |
name | TEXT | Nom d'affichage |
slug | TEXT | Identifiant unique pour l'URL |
owner_id | UUID | FK vers auth.users — le propriétaire/payeur |
plan_id | TEXT | Plan d'abonnement actuel |
stripe_customer_id | TEXT | Client Stripe pour la facturation |
stripe_subscription_id | TEXT | ID d'abonnement Stripe |
avatar_url | TEXT | Logo de l'organisation |
memberships
| Colonne | Type | Description |
|---|---|---|
id | UUID | Clé primaire |
organization_id | UUID | FK vers organizations |
user_id | UUID | FK vers auth.users (null si invitation en attente) |
invited_email | TEXT | Email pour les invitations en attente |
role | TEXT | owner, admin ou member |
status | TEXT | pending ou active |
Politiques RLS
La migration inclut des politiques RLS complètes :
- Organizations : les membres peuvent voir leurs orgas, seuls les propriétaires peuvent modifier/supprimer
- Memberships : les membres voient les membres de l'orga, les admins/propriétaires peuvent inviter/retirer, les utilisateurs peuvent accepter leurs invitations et quitter
Rôles
| Rôle | Peut inviter | Peut retirer des membres | Peut changer les rôles | Peut modifier l'orga | Peut supprimer l'orga | Peut gérer la facturation |
|---|---|---|---|---|---|---|
| Owner | Oui | Oui | Oui | Oui | Oui | Oui |
| Admin | Oui | Oui | Non | Oui | Non | Non |
| Member | Non | Non | Non | Non | Non | Non |
Edge Function : manage-organization
Toutes les opérations d'équipe passent par une seule Edge Function avec un paramètre action :
// Actions disponibles :
await callFunction("manage-organization", {
method: "POST",
body: { action: "create", name: "Mon Entreprise", slug: "mon-entreprise" },
});
await callFunction("manage-organization", {
method: "POST",
body: { action: "invite", organizationId: "...", email: "jean@exemple.com", role: "member" },
});
await callFunction("manage-organization", {
method: "POST",
body: { action: "accept-invite", membershipId: "..." },
});
await callFunction("manage-organization", {
method: "POST",
body: { action: "remove-member", membershipId: "..." },
});
await callFunction("manage-organization", {
method: "POST",
body: { action: "update-role", membershipId: "...", role: "admin" },
});
await callFunction("manage-organization", {
method: "POST",
body: { action: "delete-org", organizationId: "..." },
});Composants frontend
Sélecteur d'organisation (Sidebar)
Quand multiTenant est activé, la sidebar affiche un sélecteur d'organisation au-dessus des liens de navigation. Les utilisateurs peuvent :
- Voir leur organisation actuelle
- Basculer entre les organisations
- Créer une nouvelle organisation
L'ID de l'orga active est stocké dans localStorage et persiste entre les sessions.
Page Team (/team)
La page de gestion d'équipe comprend :
- Liste des membres avec badges de rôle et indicateurs de statut
- Formulaire d'invitation pour ajouter des membres par email
- Gestion des rôles pour que les propriétaires changent les rôles des membres
- Retirer un membre pour les propriétaires/admins
- Quitter l'organisation pour que les membres puissent partir volontairement
Adapter les crédits pour les organisations
Quand le multi-tenant est activé, vous voudrez que les crédits soient partagés au niveau de l'organisation plutôt que par utilisateur. Modifiez vos requêtes de crédits :
// Single-tenant : crédits par utilisateur
const { data: credits } = await supabase
.from("credits")
.select("*")
.eq("user_id", user.id)
.single();
// Multi-tenant : crédits par organisation
const { data: credits } = await supabase
.from("credits")
.select("*")
.eq("organization_id", currentOrgId)
.single();Note : Vous devrez ajouter une colonne
organization_idà la tablecreditset mettre à jour les politiques RLS en conséquence pour la facturation par organisation.
Étapes suivantes
- Authentification — comment l'auth fonctionne avec les organisations
- Paiements — facturation Stripe par organisation
- Crédits — adapter le système de crédits pour les équipes
- Déploiement — déployer avec le multi-tenant activé
Fini ? Marquez cette page comme terminée.