Comment implémenter des autorisations collaborateurs fines, verrouiller la création de documents à l'expiration du compte principal et monétiser le module en option payante.
Dans les applications SaaS B2B (comme les ERP ou plateformes de facturation), le propriétaire d'un compte invite régulièrement des sous-utilisateurs (appelés Collaborateurs) pour gérer les opérations quotidiennes. La délégation d'accès pose deux défis techniques majeurs :
1. Découpage Granulaire des Autorisations : Les collaborateurs ne doivent pas posséder des droits administrateur globaux. Un responsable de stock doit pouvoir créer des articles sans avoir l'autorisation de supprimer des factures ou modifier la fiscalité.
2. Verrouillage en Cascade à l'Expiration de l'Abonnement : Lorsque l'abonnement du compte principal expire, la création de documents (ventes, dépenses, factures) doit être bloquée instantanément pour l'ensemble des collaborateurs liés, empêchant toute contournement.
Voici comment nous avons conçu un pipeline de contrôle d'accès basé sur les rôles (RBAC) et transformé la gestion des collaborateurs en une option d'abonnement payante.
Plutôt que d'assigner des rôles globaux rigides (admin, staff), créez un schéma d'autorisations explicites associant des actions clés (invoices.create, invoices.delete, expenses.view) à des rôles personnalisés par le propriétaire.
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// app/Services/PermissionService.php
namespace App\Services;
use App\Models\User;
class PermissionService
{
public static function canUserPerform(User $user, string $permission): bool
{
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// 1. Le propriétaire du compte dispose de tous les accès
if ($user->is_workspace_owner) {
return true;
}
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// 2. Récupère les autorisations du rôle collaborateur
$permissions = $user->role ? $user->role->permissions->pluck('name')->toArray() : [];
return in_array($permission, $permissions);
}
}Appliquez ensuite ces règles de manière transparente via un middleware Laravel :
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// app/Http/Middleware/CheckModulePermission.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Services\PermissionService;
class CheckModulePermission
{
public function handle(Request $request, Closure $next, string $permission)
{
$user = $request->user();
if (!PermissionService::canUserPerform($user, $permission)) {
return response()->json([
'error' => 'Vous ne disposez pas des autorisations requises pour exécuter cette action.'
], 403);
}
return $next($request);
}
}Une faille de sécurité classique survient lorsque les vérifications d'expiration ne ciblent que l'utilisateur directement connecté. Si un collaborateur se connecte, son statut individuel peut apparaître actif, lui permettant de créer des ventes ou dépenses alors que l'abonnement du compte propriétaire est expiré.
Pour corriger cette faille, vérifiez systématiquement le statut d'abonnement du compte propriétaire principal lors de chaque tentative de création :
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// app/Http/Middleware/EnsureActiveSubscription.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class EnsureActiveSubscription
{
public function handle(Request $request, Closure $next)
{
$user = $request->user();
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// Résolution du compte propriétaire principal (tenant principal)
$owner = $user->is_workspace_owner ? $user : $user->workspaceOwner;
if (!$owner || !$owner->hasActiveSubscription()) {
return response()->json([
'error' => 'Abonnement expiré. Veuillez contacter l'administrateur du compte pour renouveler l'offre.',
'code' => 'SUBSCRIPTION_EXPIRED'
], 402);
}
return $next($request);
}
}Après la sécurisation du système RBAC et du verrouillage des abonnements, l'équipe a identifié que la collaboration multi-utilisateurs représentait une valeur à fort impact pour les entreprises en croissance.
Plutôt que d'inclure la gestion des collaborateurs dans les forfaits de base, la fonctionnalité a été configurée comme un module d'extension payant (Add-On) :
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// app/Models/Workspace.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Workspace extends Model
{
public function canAddCollaborators(): bool
{
class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// Vérifie si le compte possède l'option Collaborateurs ou un forfait Entreprise
return $this->hasAddon('collaborators_module') || $this->plan_tier === 'enterprise';
}
public function maxCollaboratorLimit(): int
{
if (!$this->canAddCollaborators()) {
return 0; class=class="text-emerald-500 dark:text-emerald-400 font-medium">"text-slate-500 italic">// Plan gratuit / standard sans option
}
return $this->addon_seats ?? 5;
}
}En combinant contrôle d'accès granulaire, verrouillage global du tenant et monétisation par fonctionnalités, vous transformez la gestion des autorisations en un module sécurisé et générateur de valeur.