Bedrud реализует 5-уровневую систему ролей для управления доступом. Каждая роль сопоставляется с набором строк доступа, хранящихся в записи пользователя, и применяется как на уровне API (промежуточное ПО бэкенда), так и на уровне UI (гварды фронтенда и условный рендеринг).
Иерархия ролей
| Роль | Массив доступа | Вес бэкенда | Описание |
|---|---|---|---|
| Суперадмин | ['superadmin', 'user'] | 4 | Полный доступ к системе, все возможности администрирования |
| Админ | ['admin', 'user'] | 3 | Полный административный доступ, как суперадмин |
| Модератор | ['moderator', 'user'] | 2 | Просмотр админки только для чтения, без изменений |
| Пользователь | ['user'] | 1 | Стандартный зарегистрированный пользователь |
| Гость | ['guest'] | 0 | Незарегистрированный участник, только присоединение |
Применение на бэкенде
Уровни доступа применяются через промежуточное ПО RequireAccess на каждом административном маршруте. Промежуточное ПО проверяет массив доступа пользователя на соответствие минимально необходимому уровню:
- Маршруты, требующие доступа
superadmin, отклоняют админа, модератора, пользователя и гостя - Маршруты, требующие доступа
admin, разрешают суперадмина и админа - Маршруты, требующие доступа
moderator, разрешают суперадмина, админа и модератора
Бэкенд хранит доступы в виде строки, разделенной запятыми, в базе данных (столбец accesses в таблице users). Тип GORM StringArray обрабатывает сериализацию и десериализацию.
Интеграция с фронтендом
Тип пользователя
Интерфейс User в user.store.ts включает два булевых поля, производных от массива доступа:
interface User {
// ...
isSuperAdmin: boolean // accesses.includes('superadmin')
isAdmin: boolean // accesses.includes('admin') || accesses.includes('superadmin')
accesses: string[] // raw access list from backend
}Гвард администратора
Макет администратора (/dashboard/admin) пропускает суперадмина, админа и модератора. Модераторы получают контекстную переменную isReadOnly=true:
// routes/dashboard/admin.tsx
const canAccess = user?.isSuperAdmin || accesses.includes('admin') || accesses.includes('moderator')Хук useAdminContext() предоставляет флаг isReadOnly всем дочерним маршрутам:
const { isReadOnly } = useAdminContext()Что модераторы могут видеть vs делать
| Страница | Просмотр | Изменение |
|---|---|---|
| Статистика обзора | ✅ Полная статистика | Н/Д |
| Список пользователей | ✅ Полный список | ❌ Нет массовых действий |
| Детали пользователя | ✅ Полный профиль | ❌ Нет статуса/роли/удаления/выхода |
| Список комнат | ✅ Полный список | ❌ Нет приостановки/удаления/редактирования лимита |
| Детали комнаты | ✅ Полная информация | ❌ Нет приостановки/удаления/кика/мута |
| Настройки | ❌ Перенаправление | ❌ |
Селектор ролей
Административный интерфейс предоставляет выпадающий список <Select> как в таблице списка пользователей, так и на странице деталей пользователя, заменяя предыдущий бинарный переключатель суперадмина. Доступные опции:
| Опция | Сохраняет как |
|---|---|
| Суперадмин | ['superadmin', 'user'] |
| Админ | ['admin', 'user'] |
| Модератор | ['moderator', 'user'] |
| Пользователь | ['user'] |
| Гость | ['guest'] |
Выпадающий список отправляет запрос PUT /api/admin/users/:id/accesses с полным массивом доступа.
Управление через CLI
Команды bedrud user promote и bedrud user demote принимают флаг --role:
# Promote to superadmin (default)
bedrud user promote --email user@example.com
# Promote to admin
bedrud user promote --email user@example.com --role admin
# Promote to moderator
bedrud user promote --email user@example.com --role moderator
# Demote specific role
bedrud user demote --email user@example.com --role adminДопустимые значения --role: superadmin, admin, moderator, user, guest.
Расположение кода
| Файл | Назначение |
|---|---|
server/internal/models/user.go | Константы уровней доступа бэкенда |
server/internal/middleware/ | Промежуточное ПО RequireAccess |
server/internal/usercli/usercli.go | Функции управления ролями CLI |
apps/web/src/lib/user.store.ts | Тип пользователя фронтенда |
apps/web/src/routes/dashboard/admin.tsx | Гвард администратора + контекст isReadOnly |
apps/web/src/components/admin/UserTable.tsx | Выпадающий список селектора ролей + значки |
apps/web/src/components/admin/RoomTable.tsx | Маскировка таблицы комнат только для чтения |