diff --git a/apps/backoffice/src/app/layouts/nav-config.ts b/apps/backoffice/src/app/layouts/nav-config.ts
index ddc1fd7ec..62a358cd6 100644
--- a/apps/backoffice/src/app/layouts/nav-config.ts
+++ b/apps/backoffice/src/app/layouts/nav-config.ts
@@ -26,7 +26,13 @@ import {
IconUserShield,
} from '@tabler/icons-react';
import type { NavSection } from '@ema-platform/ui';
-import { LICENSE_PERMISSIONS as P } from '@ema-platform/auth';
+import {
+ IAM_ADMIN_PERMISSIONS,
+ LICENSE_PERMISSIONS as P,
+} from '@ema-platform/auth';
+
+/** Any user-administration duty opens the embedded User Management module. */
+export const UM_PERMISSIONS = Object.values(IAM_ADMIN_PERMISSIONS);
/**
* Every licence-type queue and its review workspace share one gate: the
@@ -143,7 +149,12 @@ export const NAV_SECTIONS: NavSection[] = [
{
label: 'nav.groupAdministration',
items: [
- { to: '/um/user-management/dashboard', label: 'nav.userManagement', icon: IconUserShield },
+ {
+ to: '/um/user-management/dashboard',
+ label: 'nav.userManagement',
+ icon: IconUserShield,
+ permissions: UM_PERMISSIONS,
+ },
{
// Professions, locations and certifications have no dedicated keys;
// the config-view keys are the closest published contract.
diff --git a/apps/backoffice/src/app/router/index.tsx b/apps/backoffice/src/app/router/index.tsx
index a5a2c5c5b..dafbda888 100644
--- a/apps/backoffice/src/app/router/index.tsx
+++ b/apps/backoffice/src/app/router/index.tsx
@@ -14,6 +14,7 @@ import {
} from '@ema-platform/auth';
import { AuthLayout } from '../layouts/AuthLayout';
import { BackofficeLayout } from '../layouts/BackofficeLayout';
+import { UM_PERMISSIONS } from '../layouts/nav-config';
import { ProtectedRoute } from './ProtectedRoute';
import { DashboardPage } from '../features/dashboard/pages/DashboardPage';
import UserManagementPage from '../features/user-management/UserManagementPage';
@@ -60,7 +61,10 @@ const router = createBrowserRouter([
{ path: '/otp-verify', element: },
],
},
- { path: '/um/*', element: },
+ {
+ path: '/um/*',
+ element: guard(UM_PERMISSIONS, ),
+ },
{ path: '/', element: },
{ path: '/profile-setup', element: },
{
diff --git a/libs/auth/src/index.ts b/libs/auth/src/index.ts
index 886e79d3b..1b63df2cc 100644
--- a/libs/auth/src/index.ts
+++ b/libs/auth/src/index.ts
@@ -28,6 +28,7 @@ export { usePermissions } from "./lib/hooks/usePermissions";
export type { PermissionSet } from "./lib/hooks/usePermissions";
export { RequirePermission } from "./lib/components/RequirePermission";
export {
+ IAM_ADMIN_PERMISSIONS,
LICENSE_PERMISSIONS,
PORTAL_PERMISSIONS,
} from "./lib/permissions.constants";
diff --git a/libs/auth/src/lib/permissions.constants.ts b/libs/auth/src/lib/permissions.constants.ts
index e3229ae90..987c57c0d 100644
--- a/libs/auth/src/lib/permissions.constants.ts
+++ b/libs/auth/src/lib/permissions.constants.ts
@@ -59,6 +59,19 @@ export const LICENSE_PERMISSIONS = {
DECIDE_EXAM_APPEAL: "can:decide:exam-appeal",
} as const;
+/**
+ * IAM baseline keys (iamapi-common seed, granted to the admin roles) used to
+ * decide who sees the embedded User Management module. Any one of these marks
+ * a user-administration duty: super_admin carries the role keys, organization
+ * and unit admins carry the employee keys.
+ */
+export const IAM_ADMIN_PERMISSIONS = {
+ VIEW_ALL_USERS: "can:viewAllUsers",
+ CREATE_EMPLOYEE: "can:createEmployee",
+ CREATE_USER_ROLE: "can:create:user_role",
+ CREATE_ROLE: "can:create:role",
+} as const;
+
export const PORTAL_PERMISSIONS = {
VIEW_OWN_PROFILE: "can:View:own-profile",
EDIT_OWN_PROFILE: "can:edit:own-profile",