routeGuard

Documentation de cbk-toolkit

RouteGuard Provider + auto-protection

Protection de routes côté client basée sur les rôles. Le Provider détecte automatiquement le chemin de chaque page et vérifie le roleName courant. Vous fournissez un hook qui retourne une simple chaine, le toolkit compare avec pagePermissions. Complète la protection côté serveur : Option A authGuard (JWT) ou Option B proxy better-auth (voir page SessionExpired).

Avantage :vous configurez une seule fois, toutes les pages sont protégées automatiquement. Pas besoin de modifier chaque page.
1Créer le fichier de configuration

Dans le dossier src/config/de votre projet, créez un fichier permissions.ts. C’est ici que vous définissez qui peut accéder à quoi. Les deux options sont valides, choisissez selon votre auth.

📁 src/config/permissions.ts

Option A — JWT / session classique

Mappez votre réponse /api/me vers une simple chaine. Votre hook, nom libre, doit retourner roleName + isLoading.

import { createRouteGuardConfig } from "@ramses1er/cbk-toolkit/client";

// Votre hook, nom libre. Doit retourner roleName + isLoading.
// Mappez votre reponse /api/me vers une simple chaine.
export function useRoleName() {
  const { data, isLoading } = fetchCurrentUser();
  return { roleName: data?.roleName ?? null, isLoading };
}

export const routeGuardConfig = createRouteGuardConfig({
  useRoleName,
  pagePermissions: {
    "/administrations": ["admin"],
    "/dashboard":       ["admin", "manager"],
    "/profile":         ["admin", "manager", "user"],
  },
  deniedPath: "/access-denied",
});

Option B — better-auth (authClient.useSession)

Si vous utilisez better-auth, utilisez authClient.useSession() dans src/config/permissions.ts. Seul le contenu de useRoleNamechange :pagePermissions et deniedPathrestent identiques. Adaptez ensuite les rôles à vos routes.

"use client";

import { createRouteGuardConfig } from "@ramses1er/cbk-toolkit/client";
import { authClient } from "@/lib/auth-client";

export function useRoleName() {
  const { data, isPending } = authClient.useSession();
  return { roleName: data?.user ? "admin" : null, isLoading: isPending };
}

export const routeGuardConfig = createRouteGuardConfig({
  useRoleName,
  pagePermissions: {
    "/administrations": ["admin"],
    "/dashboard":       ["admin", "manager"],
    "/profile":         ["admin", "manager", "user"],
  },
  deniedPath: "/access-denied",
});
Exemple réel : avec better-auth, pagePermissions peut devenir { "/dashboard": ["admin"], "/enrollment": ["admin", "student"] } selon vos routes. Seule la logique interne de useRoleNamedépend de better-auth.

Paramètres :

  • useRoleName — votre hook React qui retourne { roleName, isLoading } avec roleName string ou null
  • pagePermissions— objet qui associe chaque chemin aux rôles autorisés
  • deniedPath — (optionnel) page de redirection si accès refusé. Défaut : /access-denied
2Ajouter le Provider dans le layout racine

Dans src/app/layout.tsx, importez la config et enveloppez l’application avec RouteGuardProvider.

📁 src/app/layout.tsx
import { RouteGuardProvider } from "@ramses1er/cbk-toolkit/client";
import { routeGuardConfig } from "@/config/permissions";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <RouteGuardProvider config={routeGuardConfig}>
      {children}
    </RouteGuardProvider>
  );
}
Important :une seule fois dans le layout racine. Toutes les pages sont automatiquement protégées.
Héritage automatique des permissions

Les permissions sont héritées par les sous-chemins. Une seule règle suffit pour protéger tout un module.

RouteRôles autorisésDéfini dans la config
/administrationsadminoui
/administrations/usersadminhérité de /administrations
/administrations/users/ajouteradminhérité de /administrations
/dashboardadmin, manageroui
/profileadmin, manager, useroui
/publicaucune restrictionnon défini
Comportement
  • Pas de permissions configuréespour le chemin → la page est accessible sans vérification
  • Chargement→ écran de chargement pendant la récupération de l’utilisateur
  • Utilisateur non connecté ou rôle non autorisé → redirection vers deniedPath
  • Rôle autorisé→ la page s’affiche normalement
  • Héritage→ une permission sur/adminprotège aussi /admin/users,/admin/settings, etc.
Récapitulatif — 2 fichiers, 0 manipulation par page
1Créersrc/config/permissions.ts
avec createRouteGuardConfig→ vous définissez les droits par route
2Modifiersrc/app/layout.tsx
ajouter <RouteGuardProvider config={routeGuardConfig}>
Terminé.Plus rien à faire. Toutes les pages sont protégées automatiquement.