Администраторы
Модуль "Администраторы"
Версия: 1.0
Дата: 2025-11-24
Статус: Реализован
Содержание
- Общее описание
- Текущая реализация
- Права доступа
- Описание полей
- UI/UX
- Бизнес-логика
- Выявленные проблемы
- Рекомендации
1. Общее описание
1.1 Предназначение модуля
Модуль "Администраторы" предназначен для управления пользователями с административными правами (group_id = 1). Администраторы имеют полный или частичный доступ ко всем функциям системы.
Основные функции:
- Создание и редактирование учётных записей администраторов
- Назначение индивидуальных прав (политик) доступа
- Авторизация под учётной записью администратора (impersonate)
- Управление статусом активности
- Флаг "Суперадминистратор"
1.2 Связь с другими модулями
| Модуль | Связь |
|---|---|
| Политики доступа | Индивидуальные права через user_policies |
| Заказы | Администратор может управлять всеми заказами |
| Все модули | Доступ определяется политиками |
1.3 Статистика
| Метрика | Значение |
|---|---|
| Всего администраторов | 6 |
| Активных | 6 |
| Суперадминов | 6 |
| С Telegram | 2 |
2. Текущая реализация
2.1 Архитектура
┌─────────────────────────────────────────────────────────────────────────────┐
│ МОДУЛЬ "АДМИНИСТРАТОРЫ" │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ РОУТЫ (routes/web.php) │
│ ├── GET /admins → AdminController@index → Список │
│ ├── GET /admins/add → AdminController@create → Создание │
│ └── GET /admins/edit/{id} → AdminController@show → Редактирование │
│ │
│ КОНТРОЛЛЕР (AdminController.php) │
│ └── Проверка прав: admin_can_view, admin_can_add │
│ │
│ LIVEWIRE КОМПОНЕНТЫ │
│ ├── Admins/Listing.php — Таблица администраторов │
│ ├── Admins/Add.php — Форма создания │
│ ├── Admins/Edit.php — Форма редактирования с вкладками │
│ └── Admins/Policies.php — Таблица политик на вкладке "Права" │
│ │
│ МОДЕЛЬ │
│ └── User (group_id = 1) — администраторы в общей таблице users │
│ │
└─────────────────────────────────────────────────────────────────────────────┘2.2 Структура данных
Администраторы хранятся в таблице users с group_id = 1.
Поля администратора в таблице users
| Поле | Тип | Описание |
|---|---|---|
id | bigint | PK |
group_id | int | 1 для администраторов |
email | string | Email (уникальный) |
password | string | Хэш пароля |
name | string | Имя |
lastname | string | Фамилия |
middlename | string | Отчество |
position | string | Должность |
phone | string | Телефон |
tg_id | string | ID Telegram |
image | string | Аватар |
active | boolean | Активен |
superadmin | boolean | Суперадминистратор |
last_auth | datetime | Последняя авторизация |
created_at | timestamp | — |
updated_at | timestamp | — |
Таблица user_policies (индивидуальные права)
| Поле | Тип | Описание |
|---|---|---|
user_id | FK | Пользователь |
policy_id | FK | Политика |
value | boolean | Включена / выключена |
2.3 Файлы модуля
app/
├── Http/Controllers/
│ └── AdminController.php
├── Livewire/Admins/
│ ├── Add.php — Форма создания
│ ├── Edit.php — Форма редактирования (с вкладками)
│ ├── Listing.php — Таблица списка
│ └── Policies.php — Таблица политик
└── Models/
├── User.php (group_id = 1)
├── Policy.php
└── UserPolicy.php
resources/views/templates/admins/
├── table.blade.php
├── add.blade.php
├── edit.blade.php
└── policies.blade.php3. Права доступа
3.1 Политики модуля
| Политика | Описание |
|---|---|
admin_can_view | Просмотр списка администраторов |
admin_can_add | Создание администратора |
admin_can_edit | Редактирование данных администратора |
admin_can_delete | Удаление администратора |
admin_can_auth | Авторизация под администратором (impersonate) |
admin_can_edit_policy | Редактирование прав администратора |
3.2 Проверка в контроллере
// AdminController.php
public function index(Request $request)
{
if (!$user->check_access('admin_can_view'))
abort(403);
}
public function create(Request $request)
{
if (!$user->check_access('admin_can_add'))
abort(403);
}3.3 Матрица доступа по ролям
| Роль | Просмотр | Создание | Редактир. | Удаление | Impersonate | Права |
|---|---|---|---|---|---|---|
| Администратор | ✅* | ✅* | ✅* | ✅* | ✅* | ✅* |
| Менеджер | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Производство | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Дилер | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
*Зависит от индивидуальных политик пользователя
4. Описание полей
4.1 Форма создания (Add.php)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
email | TextInput | ✅ | Email (unique) |
password | Password | ✅ | Пароль |
lastname | TextInput | ✅ | Фамилия |
name | TextInput | ✅ | Имя |
middlename | TextInput | ❌ | Отчество |
position | TextInput | ❌ | Должность |
phone | TextInput | ❌ | Телефон (маска +7) |
active | Toggle | ✅ | Активен (по умолчанию true) |
image | FileUpload | ❌ | Аватар (1:1, crop) |
При создании автоматически: group_id = 1
4.2 Форма редактирования (Edit.php)
Вкладка "Данные"
| Поле | Тип | Особенности |
|---|---|---|
email | TextInput | Disabled если нет прав |
password | Password | Hidden если нет прав, хэшируется |
lastname | TextInput | — |
name | TextInput | — |
middlename | TextInput | — |
position | TextInput | — |
phone | TextInput | Маска +7(999) 999 99 99 |
tg_id | TextInput | ID Telegram |
last_auth | TextInput | Только чтение |
active | Toggle | — |
superadmin | Toggle | Флаг суперадмина |
image | FileUpload | Аватар |
Вкладка "Права"
Доступна только при наличии admin_can_edit_policy.
Содержит таблицу политик (Policies.php):
- Группировка по категориям
- ToggleColumn для включения/выключения
- Фильтр по категориям
- Поиск по ключу, названию, описанию
4.3 Колонки таблицы списка
| Колонка | Описание | Особенности |
|---|---|---|
image | Аватар | ImageColumn |
email | Поиск | |
name | Имя | Поиск |
lastname | Фамилия | Поиск |
phone | Телефон | Поиск |
tg_id | ID Telegram | Поиск |
active | Активен | ToggleColumn |
5. UI/UX
5.1 Список администраторов
┌─────────────────────────────────────────────────────────────────────────────┐
│ Администраторы [+ Создать] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Поиск...] [Столбцы ▾] │
├──────┬──────┬────────────────────┬─────────┬──────────┬──────────┬──────────┤
│ ☐ │ Фото │ Email │ Имя │ Фамилия │ Телефон │ Активен │
├──────┼──────┼────────────────────┼─────────┼──────────┼──────────┼──────────┤
│ ☐ │ [📷] │ admin@company.ru │ Админ │ Главный │ +7(999)..│ [●] │
│ ☐ │ [📷] │ manager@company.ru │ Иван │ Петров │ +7(916)..│ [●] │
└──────┴──────┴────────────────────┴─────────┴──────────┴──────────┴──────────┘
Действия:
✅ [Авторизоваться] — войти под учёткой (impersonate)
✅ [Удалить] — с подтверждением
Особенности:
- Кнопка "Создать" ведёт на отдельную страницу
- Клик по строке → карточка редактирования
- Массовое удаление5.2 Карточка редактирования
┌─────────────────────────────────────────────────────────────────────────────┐
│ [← Назад] Редактирование администратора [Удалить] [Сохранить] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Данные] [Права] │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────┐ ┌────────────────────────┐ │
│ │ Email [admin@company.ru ] │ │ Изображение │ │
│ │ │ │ ┌────────────────────┐ │ │
│ │ Пароль [•••••••• ] [👁] │ │ │ │ │ │
│ │ │ │ │ [📷 Аватар] │ │ │
│ │ Фамилия [Главный ] │ │ │ │ │ │
│ │ │ │ └────────────────────┘ │ │
│ │ Имя [Админ ] │ │ │ │
│ │ │ └────────────────────────┘ │
│ │ Отчество [ ] │ │
│ │ │ │
│ │ Должность [Руководитель ] │ │
│ │ │ │
│ │ Телефон [+7(999) 123-45-67 ] │ │
│ │ │ │
│ │ ID телеграмма [123456789 ] │ │
│ │ │ │
│ │ Посл. авторизация [2025-11-24 10:30:00] │ │
│ │ │ │
│ │ Активен [●] Суперадмин [●] │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘5.3 Вкладка "Права"
┌─────────────────────────────────────────────────────────────────────────────┐
│ [Данные] [Права] │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Поиск...] [Фильтр ▾] │
│ │
│ ▼ Категория: Администраторы │
│ ┌──────────────────────┬───────────────────────────┬──────────────┬───────┐│
│ │ Ключ │ Название │ Категория │ ││
│ ├──────────────────────┼───────────────────────────┼──────────────┼───────┤│
│ │ admin_can_view │ Может просматривать │Администраторы│ [ ] ││
│ │ admin_can_add │ Может добавлять │Администраторы│ [ ] ││
│ │ admin_can_edit │ Может редактировать │Администраторы│ [●] ││
│ │ admin_can_delete │ Может удалять │Администраторы│ [ ] ││
│ │ admin_can_auth │ Может авторизовываться │Администраторы│ [●] ││
│ │ admin_can_edit_policy│ Может редактировать права │Администраторы│ [ ] ││
│ └──────────────────────┴───────────────────────────┴──────────────┴───────┘│
│ │
│ ▼ Категория: Дилеры (Компании) │
│ ┌──────────────────────┬───────────────────────────┬──────────────┬───────┐│
│ │ company_can_view │ Может видеть все компании │Дилеры (Комп.)│ [●] ││
│ │ company_can_add │ Может добавлять компании │Дилеры (Комп.)│ [●] ││
│ │ ... │ ... │ ... │ ... ││
│ └──────────────────────┴───────────────────────────┴──────────────┴───────┘│
│ │
│ Показано с 1 по 10 из 57 [10][50][100][Все] │
└─────────────────────────────────────────────────────────────────────────────┘6. Бизнес-логика
6.1 Автоматическое создание UserPolicy при редактировании
При открытии карточки редактирования для администратора автоматически создаются записи в user_policies для всех существующих политик:
// Edit.php — mount()
$policies = Policy::all();
foreach ($policies as $policy) {
UserPolicy::firstOrCreate(
[
'user_id' => $this->record->id,
'policy_id' => $policy->id,
],
['value' => false] // По умолчанию выключено
);
}6.2 Проверка прав (check_access)
Метод check_access() в модели User проверяет права:
- Если пользователь — суперадмин → все права разрешены
- Иначе проверяет
user_policies.valueдля данной политики
6.3 Impersonate (авторизация под администратором)
Позволяет войти в систему под другим администратором:
// Listing.php
Action::make('auth')
->label('Авторизоваться')
->icon('heroicon-o-user')
->url(fn (User $record): string => route('impersonate', $record->id))Требует право: admin_can_auth
6.4 Хэширование пароля
// Edit.php
TextInput::make('password')
->dehydrateStateUsing(fn ($state) => $state ? Hash::make($state) : null)
->dehydrated(fn ($state) => filled($state)) // Только если заполнен6.5 Флаг Superadmin
Поле superadmin даёт полные права без проверки индивидуальных политик.
7. Выявленные проблемы
7.1 Критические
| # | Проблема | Файл | Влияние |
|---|---|---|---|
| — | Критических проблем не обнаружено | — | — |
7.2 Средние
| # | Проблема | Описание | Решение |
|---|---|---|---|
| 1 | Ошибка в проверке save() | Проверяется manager_can_edit вместо admin_can_edit | Исправить на admin_can_edit |
| 2 | Инверсия логики $can_edit | $can_edit = !check_access() — инвертированная логика | Переименовать в $disableEdit |
| 3 | Нет валидации email на уникальность при редактировании | Можно сохранить дублирующийся email | Добавить unique(ignoreRecord: true) |
| 4 | Разные маски телефона | В Add: +7 (999)..., в Edit: +7(999)... | Унифицировать |
7.3 Низкие
| # | Проблема | Описание |
|---|---|---|
| 5 | Нет истории изменений прав | Не видно кто и когда менял политики |
| 6 | Нет экспорта | Нельзя выгрузить список администраторов |
| 7 | Policies рендерит неправильный view | 'livewire.news.listing' вместо своего |
8. Рекомендации
8.1 Приоритет: Высокий
Исправить проверку прав при сохранении
// Edit.php:70 — было:
if ($this->authUser->check_access('manager_can_edit')) {
// Стало:
if ($this->authUser->check_access('admin_can_edit')) {8.2 Приоритет: Средний
Исправить инверсию логики
// Listing.php:28-29 — было:
$can_edit = !$this->auth_user->check_access('admin_can_edit');
$can_delete = !$this->auth_user->check_access('admin_can_delete');
// Стало (переименовать для ясности):
$disableEdit = !$this->auth_user->check_access('admin_can_edit');
$disableDelete = !$this->auth_user->check_access('admin_can_delete');Добавить уникальность email
// Edit.php — editData()
TextInput::make('email')
->unique(table: User::class, ignoreRecord: true)8.3 Приоритет: Низкий
Исправить view в Policies
// Policies.php:61 — было:
return view('livewire.news.listing');
// Стало:
return view('livewire.base.listing');Приложение: SQL для аналитики
Администраторы с их правами
SELECT
u.id,
u.email,
u.name,
u.lastname,
u.superadmin,
COUNT(CASE WHEN up.value = 1 THEN 1 END) as enabled_policies
FROM users u
LEFT JOIN user_policies up ON u.id = up.user_id
WHERE u.group_id = 1
GROUP BY u.id, u.email, u.name, u.lastname, u.superadmin;Неактивные администраторы
SELECT id, email, name, lastname, last_auth
FROM users
WHERE group_id = 1 AND active = 0;Все политики конкретного администратора
SELECT
p.key,
p.name,
p.category,
up.value
FROM user_policies up
JOIN policies p ON up.policy_id = p.id
WHERE up.user_id = :admin_id
ORDER BY p.category, p.name;Документ подготовлен на основе анализа исходного кода проекта