import { checkModuleAccess, getModuleAccessLevel } from '@/lib/module-access-actions';
import { getTranslations } from 'next-intl/server';
import type { ReactNode } from 'react';
import { ModuleAccessDenied } from './module-access-denied';
/**
* Module, die als Ganzes Verwalten-Stufe verlangen (261002-icv): die API
* traegt dort `@ModuleManage` auf der ganzen Klasse (DkvController). Benutzer
* mit nur "Benutzen" bekaemen von der API ohnehin 403 — die Seite zeigt ihnen
* stattdessen eine erklaerende Zugriffsseite.
*/
const MANAGE_ONLY_MODULE_SLUGS = new Set(['dkv-fleet']);
interface ModuleAccessGateProps {
moduleSlug: string;
children: ReactNode;
}
/**
* Reusable server-side access gate for module routes (D-07, PERM-04).
*
* Calls checkModuleAccess(moduleSlug) — the same ModuleAccessService
* resolution the sidebar and ModuleGuard use (D-01), no separate role
* logic in the frontend. Renders the children only when access resolves
* to explicitly `true`; every other outcome (denied, or the access check
* throwing) renders the shared 403 markup instead.
*
* checkModuleAccess already fails closed itself and does not throw
* (T-15-29) — the try/catch here is a second line of defense so a future
* change to that function cannot silently flip this gate open. The
* condition is deliberately "only pass through on explicit grant", never
* "only block on explicit denial".
*
* No redirect and no not-found: the 403 rendering here is the server
* response itself (D-07) — the user learns the module exists and they
* lack a grant, they aren't bounced elsewhere or left thinking it's
* missing.
*/
export async function ModuleAccessGate({ moduleSlug, children }: ModuleAccessGateProps) {
if (MANAGE_ONLY_MODULE_SLUGS.has(moduleSlug)) {
let level: 'none' | 'use' | 'manage' = 'none';
try {
level = await getModuleAccessLevel(moduleSlug);
} catch {
level = 'none';
}
if (level === 'manage') {
return children;
}
const tm = await getTranslations('modules');
return (
);
}
let hasAccess = false;
try {
hasAccess = await checkModuleAccess(moduleSlug);
} catch {
hasAccess = false;
}
if (hasAccess === true) {
return children;
}
const t = await getTranslations('modules');
return (
);
}