feat(admin): add permission-based filtering to admin navigation

- add optional `permission` field to nav items in registry
- filter nav items by user permissions in `buildNavigationSections`
- auto-hide sections when all their items are filtered out
- fetch user permissions in `AdminLayout.server.js` and pass to navigation builder
- update docs and README to document `permission` param and new signature
This commit is contained in:
2026-04-25 09:27:07 -04:00
parent cb8266d9a9
commit 97f8baf502
5 changed files with 26 additions and 13 deletions
+12 -4
View File
@@ -5,14 +5,15 @@ import {
getNavItems,
} from './registry.js';
import { isDevkitEnabled } from '../../shared/lib/appConfig.js';
import { PERMISSIONS } from '@zen/core/users';
// Sections et items core — enregistrés à l'import de ce module.
registerNavSection({ id: 'dashboard', title: 'Tableau de bord', icon: 'DashboardSquare03Icon', order: 10 });
registerNavSection({ id: 'system', title: 'Utilisateurs', icon: 'UserMultiple02Icon', order: 20 });
registerNavItem({ id: 'dashboard', label: 'Tableau de bord', icon: 'DashboardSquare03Icon', href: '/admin/dashboard', sectionId: 'dashboard', order: 10 });
registerNavItem({ id: 'users', label: 'Utilisateurs', icon: 'UserMultiple02Icon', href: '/admin/users', sectionId: 'system', order: 10 });
registerNavItem({ id: 'roles', label: 'Rôles', icon: 'Crown03Icon', href: '/admin/roles', sectionId: 'system', order: 20 });
registerNavItem({ id: 'users', label: 'Utilisateurs', icon: 'UserMultiple02Icon', href: '/admin/users', sectionId: 'system', order: 10, permission: PERMISSIONS.USERS_VIEW });
registerNavItem({ id: 'roles', label: 'Rôles', icon: 'Crown03Icon', href: '/admin/roles', sectionId: 'system', order: 20, permission: PERMISSIONS.ROLES_VIEW });
registerNavItem({ id: 'settings', label: 'Paramètres', icon: 'Settings02Icon', href: '/admin/settings', position: 'bottom', order: 10 });
if (isDevkitEnabled()) {
@@ -24,10 +25,17 @@ if (isDevkitEnabled()) {
/**
* Build sections for AdminSidebar. Items are sérialisables (pas de composants),
* icônes en chaînes résolues côté client.
* @param {string} pathname
* @param {string[]} [userPermissions] - Permissions de l'utilisateur connecté ; les items
* avec un champ `permission` sont masqués si la permission n'est pas présente.
*/
export function buildNavigationSections(pathname) {
export function buildNavigationSections(pathname, userPermissions = []) {
const sections = getNavSections();
const items = getNavItems().filter(item => item.position !== 'bottom');
const items = getNavItems().filter(item => {
if (item.position === 'bottom') return false;
if (item.permission && !userPermissions.includes(item.permission)) return false;
return true;
});
const bySection = new Map();
for (const item of items) {