mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
feat: add RBAC permission system to admin cabinet frontend
- Permission store (Zustand) with wildcard matching and role level checks - PermissionRoute guard for route-level access control - PermissionGate component for element-level visibility - Admin Roles page: CRUD, permission editor, role assignment - Admin Policies page: ABAC policy management (time/IP conditions) - Admin Audit Log page: filterable log viewer with CSV export - AdminPanel sidebar navigation gated by permissions - 4 locale files updated (en, ru, zh, fa) with RBAC translations - API client module for all RBAC endpoints
This commit is contained in:
@@ -884,7 +884,11 @@
|
||||
"pinnedMessages": "Закреплённые",
|
||||
"partners": "Партнёры",
|
||||
"withdrawals": "Выводы",
|
||||
"channelSubscriptions": "Обязательные каналы"
|
||||
"channelSubscriptions": "Обязательные каналы",
|
||||
"roles": "Роли",
|
||||
"roleAssign": "Назначение ролей",
|
||||
"policies": "Политики доступа",
|
||||
"auditLog": "Журнал аудита"
|
||||
},
|
||||
"panel": {
|
||||
"title": "Панель администратора",
|
||||
@@ -912,7 +916,11 @@
|
||||
"pinnedMessagesDesc": "Управление закреплёнными сообщениями",
|
||||
"partnersDesc": "Управление заявками партнёров и комиссиями",
|
||||
"withdrawalsDesc": "Проверка и обработка заявок на вывод",
|
||||
"channelSubscriptionsDesc": "Управление обязательными подписками на каналы"
|
||||
"channelSubscriptionsDesc": "Управление обязательными подписками на каналы",
|
||||
"rolesDesc": "Управление ролями и правами администраторов",
|
||||
"roleAssignDesc": "Назначение и отзыв ролей пользователей",
|
||||
"policiesDesc": "Настройка политик контроля доступа ABAC",
|
||||
"auditLogDesc": "Просмотр активности системы и истории доступа"
|
||||
},
|
||||
"trafficUsage": {
|
||||
"title": "Расход трафика",
|
||||
@@ -3063,7 +3071,8 @@
|
||||
"marketing": "Маркетинг",
|
||||
"system": "Система",
|
||||
"tariffs": "Тарифы и продажи",
|
||||
"users": "Пользователи"
|
||||
"users": "Пользователи",
|
||||
"security": "Безопасность"
|
||||
},
|
||||
"theme": {
|
||||
"accentColor": "Акцентный цвет",
|
||||
@@ -3472,6 +3481,283 @@
|
||||
"unhealthy": "Проблема",
|
||||
"components": "Компоненты",
|
||||
"uptime": "Аптайм"
|
||||
},
|
||||
"roles": {
|
||||
"title": "Роли и права",
|
||||
"subtitle": "Управление ролями администраторов и их правами",
|
||||
"createRole": "Создать роль",
|
||||
"noRoles": "Роли не найдены",
|
||||
"systemBadge": "Системная",
|
||||
"inactiveBadge": "Неактивна",
|
||||
"levelLabel": "Уровень",
|
||||
"usersCount_one": "{{count}} пользователь",
|
||||
"usersCount_few": "{{count}} пользователя",
|
||||
"usersCount_many": "{{count}} пользователей",
|
||||
"permissionsCount_one": "{{count}} разрешение",
|
||||
"permissionsCount_few": "{{count}} разрешения",
|
||||
"permissionsCount_many": "{{count}} разрешений",
|
||||
"stats": {
|
||||
"totalRoles": "Всего ролей",
|
||||
"active": "Активные",
|
||||
"system": "Системные"
|
||||
},
|
||||
"actions": {
|
||||
"edit": "Редактировать",
|
||||
"delete": "Удалить"
|
||||
},
|
||||
"modal": {
|
||||
"createTitle": "Создание роли",
|
||||
"editTitle": "Редактирование роли",
|
||||
"close": "Закрыть"
|
||||
},
|
||||
"form": {
|
||||
"name": "Название роли",
|
||||
"namePlaceholder": "например, Модератор",
|
||||
"description": "Описание",
|
||||
"descriptionPlaceholder": "Для чего нужна эта роль...",
|
||||
"level": "Уровень приоритета",
|
||||
"levelValue": "Значение уровня",
|
||||
"levelHint": "Чем выше уровень, тем больше полномочий. Пользователи могут управлять только ролями с уровнем ниже своего.",
|
||||
"color": "Цвет",
|
||||
"presets": "Шаблоны прав",
|
||||
"permissions": "Разрешения",
|
||||
"toggleSection": "Переключить все права {{section}}",
|
||||
"selectedPermissions_one": "{{count}} разрешение выбрано",
|
||||
"selectedPermissions_few": "{{count}} разрешения выбрано",
|
||||
"selectedPermissions_many": "{{count}} разрешений выбрано",
|
||||
"cancel": "Отмена",
|
||||
"saving": "Сохранение...",
|
||||
"save": "Сохранить"
|
||||
},
|
||||
"presets": {
|
||||
"moderator": "Модератор",
|
||||
"marketer": "Маркетолог",
|
||||
"support": "Поддержка"
|
||||
},
|
||||
"confirm": {
|
||||
"title": "Удалить роль?",
|
||||
"text": "Роль будет безвозвратно удалена. Пользователи с этой ролью потеряют её права.",
|
||||
"cancel": "Отмена",
|
||||
"delete": "Удалить",
|
||||
"deleting": "Удаление..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Не удалось загрузить роли",
|
||||
"createFailed": "Не удалось создать роль",
|
||||
"updateFailed": "Не удалось обновить роль",
|
||||
"nameRequired": "Укажите название роли"
|
||||
}
|
||||
},
|
||||
"roleAssign": {
|
||||
"title": "Назначение ролей",
|
||||
"subtitle": "Назначение и управление ролями пользователей",
|
||||
"assignSection": "Назначить роль",
|
||||
"userLabel": "Пользователь",
|
||||
"searchPlaceholder": "Поиск по имени, username, Telegram ID или email...",
|
||||
"clearUser": "Очистить выбранного пользователя",
|
||||
"noUsersFound": "Пользователи не найдены",
|
||||
"roleLabel": "Роль",
|
||||
"selectRole": "Выберите роль...",
|
||||
"expiresLabel": "Истекает (необязательно)",
|
||||
"expiresHint": "Оставьте пустым для бессрочного назначения",
|
||||
"assignButton": "Назначить",
|
||||
"assigning": "Назначение...",
|
||||
"assignSuccess": "Роль успешно назначена",
|
||||
"currentAssignments": "Текущие назначения",
|
||||
"totalAssignments_one": "{{count}} назначение",
|
||||
"totalAssignments_few": "{{count}} назначения",
|
||||
"totalAssignments_many": "{{count}} назначений",
|
||||
"noAssignments": "Назначения ролей не найдены",
|
||||
"unknownUser": "Неизвестный пользователь",
|
||||
"system": "Система",
|
||||
"permanent": "Бессрочно",
|
||||
"expired": "истекло",
|
||||
"revoke": "Отозвать",
|
||||
"revokeAriaLabel": "Отозвать роль {{role}} у {{user}}",
|
||||
"table": {
|
||||
"user": "Пользователь",
|
||||
"role": "Роль",
|
||||
"assignedBy": "Назначил",
|
||||
"assignedAt": "Дата назначения",
|
||||
"expires": "Истекает",
|
||||
"actions": "Действия"
|
||||
},
|
||||
"pagination": {
|
||||
"showing": "{{from}}-{{to}} из {{total}}",
|
||||
"prev": "Предыдущая страница",
|
||||
"next": "Следующая страница"
|
||||
},
|
||||
"confirm": {
|
||||
"title": "Отозвать роль?",
|
||||
"text": "Пользователь немедленно потеряет все права, связанные с этой ролью.",
|
||||
"cancel": "Отмена",
|
||||
"revoke": "Отозвать",
|
||||
"revoking": "Отзыв..."
|
||||
},
|
||||
"errors": {
|
||||
"userRequired": "Выберите пользователя",
|
||||
"roleRequired": "Выберите роль",
|
||||
"assignFailed": "Не удалось назначить роль"
|
||||
}
|
||||
},
|
||||
"policies": {
|
||||
"title": "Политики доступа",
|
||||
"subtitle": "Управление политиками контроля доступа ABAC",
|
||||
"createPolicy": "Создать политику",
|
||||
"noPolicies": "Политики не найдены",
|
||||
"inactiveBadge": "Неактивна",
|
||||
"effectAllow": "Разрешить",
|
||||
"effectDeny": "Запретить",
|
||||
"global": "Глобальная",
|
||||
"unknownRole": "Неизвестная роль",
|
||||
"roleLabel": "Роль",
|
||||
"priorityLabel": "Приоритет",
|
||||
"stats": {
|
||||
"total": "Всего политик",
|
||||
"allow": "Разрешающие",
|
||||
"deny": "Запрещающие",
|
||||
"active": "Активные"
|
||||
},
|
||||
"actions": {
|
||||
"edit": "Редактировать",
|
||||
"delete": "Удалить"
|
||||
},
|
||||
"modal": {
|
||||
"createTitle": "Создание политики",
|
||||
"editTitle": "Редактирование политики",
|
||||
"close": "Закрыть"
|
||||
},
|
||||
"form": {
|
||||
"name": "Название политики",
|
||||
"namePlaceholder": "например, Блокировка ночного доступа",
|
||||
"description": "Описание",
|
||||
"descriptionPlaceholder": "Что делает эта политика...",
|
||||
"effect": "Эффект",
|
||||
"resource": "Ресурс",
|
||||
"selectResource": "Выберите ресурс...",
|
||||
"actions": "Действия",
|
||||
"role": "Роль (необязательно)",
|
||||
"globalOption": "Глобальная (все роли)",
|
||||
"roleHint": "Оставьте Глобальная, чтобы политика применялась ко всем ролям.",
|
||||
"priority": "Приоритет",
|
||||
"priorityHint": "Политики с более высоким приоритетом проверяются первыми. Запрет перекрывает Разрешение при равном приоритете.",
|
||||
"conditions": "Условия",
|
||||
"cancel": "Отмена",
|
||||
"saving": "Сохранение...",
|
||||
"save": "Сохранить"
|
||||
},
|
||||
"conditions": {
|
||||
"timeRange": "Временной диапазон",
|
||||
"timeStart": "Время начала",
|
||||
"timeEnd": "Время окончания",
|
||||
"ipWhitelist": "Белый список IP",
|
||||
"ipPlaceholder": "Введите IP и нажмите Enter...",
|
||||
"removeIp": "Удалить {{ip}}",
|
||||
"ipCount_one": "{{count}} IP",
|
||||
"ipCount_few": "{{count}} IP",
|
||||
"ipCount_many": "{{count}} IP",
|
||||
"rateLimit": "Лимит запросов",
|
||||
"rateLimitValue": "Значение лимита запросов",
|
||||
"rateValue": "{{count}}/ч",
|
||||
"perHour": "действий в час"
|
||||
},
|
||||
"confirm": {
|
||||
"title": "Удалить политику?",
|
||||
"text": "Политика будет безвозвратно удалена. Правила контроля доступа будут пересчитаны.",
|
||||
"cancel": "Отмена",
|
||||
"delete": "Удалить",
|
||||
"deleting": "Удаление..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Не удалось загрузить политики",
|
||||
"createFailed": "Не удалось создать политику",
|
||||
"updateFailed": "Не удалось обновить политику",
|
||||
"nameRequired": "Укажите название политики",
|
||||
"resourceRequired": "Выберите ресурс",
|
||||
"actionsRequired": "Выберите хотя бы одно действие"
|
||||
}
|
||||
},
|
||||
"auditLog": {
|
||||
"title": "Журнал аудита",
|
||||
"subtitle": "Просмотр активности системы и истории доступа",
|
||||
"back": "Назад",
|
||||
"exportCsv": "Экспорт CSV",
|
||||
"exporting": "Экспорт...",
|
||||
"refresh": "Обновить",
|
||||
"unknownUser": "Неизвестный пользователь",
|
||||
"noEntries": "Записи журнала аудита не найдены",
|
||||
"totalEntries_one": "{{count}} запись",
|
||||
"totalEntries_few": "{{count}} записи",
|
||||
"totalEntries_many": "{{count}} записей",
|
||||
"autoRefresh": {
|
||||
"label": "Автообновление",
|
||||
"tooltip": "Автообновление каждые 30 секунд"
|
||||
},
|
||||
"filters": {
|
||||
"title": "Фильтры",
|
||||
"active": "Активны",
|
||||
"action": "Действие",
|
||||
"actionPlaceholder": "Поиск по действию...",
|
||||
"resource": "Тип ресурса",
|
||||
"allResources": "Все ресурсы",
|
||||
"status": "Статус",
|
||||
"allStatuses": "Все статусы",
|
||||
"dateFrom": "Дата от",
|
||||
"dateTo": "Дата до",
|
||||
"apply": "Применить",
|
||||
"clear": "Сбросить"
|
||||
},
|
||||
"status": {
|
||||
"success": "Успешно",
|
||||
"denied": "Отказано",
|
||||
"error": "Ошибка"
|
||||
},
|
||||
"resourceTypes": {
|
||||
"users": "Пользователи",
|
||||
"tickets": "Тикеты",
|
||||
"roles": "Роли",
|
||||
"policies": "Политики",
|
||||
"settings": "Настройки",
|
||||
"broadcasts": "Рассылки",
|
||||
"tariffs": "Тарифы",
|
||||
"servers": "Серверы",
|
||||
"payments": "Платежи",
|
||||
"campaigns": "Кампании",
|
||||
"promocodes": "Промокоды"
|
||||
},
|
||||
"details": {
|
||||
"userAgent": "User Agent",
|
||||
"requestPath": "Путь запроса",
|
||||
"ipAddress": "IP-адрес",
|
||||
"timestamp": "Время",
|
||||
"before": "До",
|
||||
"after": "После",
|
||||
"fullDetails": "Полные данные"
|
||||
},
|
||||
"time": {
|
||||
"justNow": "Только что",
|
||||
"minutesAgo_one": "{{count}} мин назад",
|
||||
"minutesAgo_few": "{{count}} мин назад",
|
||||
"minutesAgo_many": "{{count}} мин назад",
|
||||
"hoursAgo_one": "{{count}} ч назад",
|
||||
"hoursAgo_few": "{{count}} ч назад",
|
||||
"hoursAgo_many": "{{count}} ч назад",
|
||||
"daysAgo_one": "{{count}} день назад",
|
||||
"daysAgo_few": "{{count}} дня назад",
|
||||
"daysAgo_many": "{{count}} дней назад"
|
||||
},
|
||||
"pagination": {
|
||||
"pageSize": "На странице:",
|
||||
"pageOf": "{{current}} / {{total}}",
|
||||
"first": "Первая страница",
|
||||
"previous": "Предыдущая страница",
|
||||
"next": "Следующая страница",
|
||||
"last": "Последняя страница"
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Не удалось загрузить журнал аудита",
|
||||
"retry": "Попробовать снова"
|
||||
}
|
||||
}
|
||||
},
|
||||
"profile": {
|
||||
|
||||
Reference in New Issue
Block a user