refactor(api): add granular permission enforcement on admin routes

- add optional `permission` field to route definitions with type validation in `define.js`
- check `hasPermission()` in router after `requireAdmin()` and return 403 if denied
- document `permission` and `skipRateLimit` optional fields in api README
- load user permissions in `AdminPage.server.js` and pass them to client via `user` prop
- use `user.permissions` in `RolesPage` and `UsersPage` to conditionally render actions
- expose permission-gated API routes in `auth/api.js`
This commit is contained in:
2026-04-25 09:21:07 -04:00
parent 188e1d82f8
commit c959b16db5
7 changed files with 91 additions and 53 deletions
+7 -2
View File
@@ -3,18 +3,23 @@ import { protectAdmin } from './protect.js';
import { collectWidgetData } from './registry.js';
import { getAppConfig, getPublicBaseUrl } from '@zen/core';
import { isDevkitEnabled } from '../../shared/lib/appConfig.js';
import { getUserPermissions } from '@zen/core/users';
export default async function AdminPage({ params }) {
const resolvedParams = await params;
const session = await protectAdmin();
const widgetData = await collectWidgetData();
const [widgetData, permissions] = await Promise.all([
collectWidgetData(),
getUserPermissions(session.user.id),
]);
const appConfig = { ...getAppConfig(), siteUrl: getPublicBaseUrl() };
const devkitEnabled = isDevkitEnabled();
const user = { ...session.user, permissions };
return (
<AdminPageClient
params={resolvedParams}
user={session.user}
user={user}
widgetData={widgetData}
appConfig={appConfig}
devkitEnabled={devkitEnabled}