Route guards, WS lifecycle, ticket stats. Refs EventHub/EventHubFrontAdmin#3

This commit is contained in:
2026-07-07 21:03:46 +03:00
parent 896e3bcd35
commit ecfa1a66bb
18 changed files with 1331 additions and 955 deletions
+54
View File
@@ -0,0 +1,54 @@
/** Роли доступа к разделам админки (согласовано с меню и маршрутами). */
export type AdminRole = 'superadmin' | 'admin' | 'moderator' | 'support';
export const ROUTE_ACCESS: Record<string, AdminRole[] | undefined> = {
'/dashboard': undefined,
'/profile': undefined,
'/monitoring': undefined,
'/users': ['superadmin', 'admin'],
'/calendars': ['superadmin', 'admin'],
'/events': ['superadmin', 'admin'],
'/reports': ['superadmin', 'admin', 'moderator'],
'/reviews': ['superadmin', 'admin', 'moderator'],
'/banned-words': ['superadmin', 'admin'],
'/tickets': ['superadmin', 'admin', 'support'],
'/subscriptions': ['superadmin', 'admin'],
'/admins': ['superadmin'],
'/audit': ['superadmin'],
};
export const MENU_ITEMS: Array<{
key: string;
label: string;
roles?: AdminRole[];
}> = [
{ key: '/dashboard', label: 'Дашборд' },
{ key: '/users', label: 'Пользователи', roles: ['superadmin', 'admin'] },
{ key: '/calendars', label: 'Календари', roles: ['superadmin', 'admin'] },
{ key: '/events', label: 'События', roles: ['superadmin', 'admin'] },
{ key: '/reports', label: 'Жалобы', roles: ['superadmin', 'admin', 'moderator'] },
{ key: '/reviews', label: 'Отзывы', roles: ['superadmin', 'admin', 'moderator'] },
{ key: '/banned-words', label: 'Бан-слова', roles: ['superadmin', 'admin'] },
{ key: '/tickets', label: 'Тикеты', roles: ['superadmin', 'admin', 'support'] },
{ key: '/subscriptions', label: 'Подписки', roles: ['superadmin', 'admin'] },
{ key: '/admins', label: 'Администраторы', roles: ['superadmin'] },
{ key: '/audit', label: 'Аудит', roles: ['superadmin'] },
{ key: '/monitoring', label: 'Мониторинг' },
];
export function canAccessRoute(pathname: string, role: string | undefined): boolean {
if (!role) return false;
const base = pathname.split('/').slice(0, 2).join('/') || '/';
const allowed = ROUTE_ACCESS[base];
if (allowed === undefined) {
return ROUTE_ACCESS[pathname] === undefined || ROUTE_ACCESS[pathname]!.includes(role as AdminRole);
}
return allowed.includes(role as AdminRole);
}
export function filterMenuByRole<T extends { roles?: AdminRole[] }>(
items: T[],
role: string | undefined
): T[] {
return items.filter((item) => !item.roles || (role && item.roles.includes(role as AdminRole)));
}