Документация ЛК
Модули

Группы пользователей

Модуль "Группы пользователей"

Версия: 1.0
Дата: 2025-11-19
Статус: Реализован


Содержание

  1. Общее описание
  2. Текущая реализация
  3. Права доступа
  4. Описание полей
  5. UI/UX
  6. Бизнес-логика
  7. Выявленные проблемы
  8. Рекомендации

1. Общее описание

1.1 Предназначение модуля

Модуль "Группы пользователей" предназначен для справочного просмотра групп пользователей системы. Это базовый справочник ролей, к которым привязываются пользователи.

Основные функции:

  • Просмотр списка групп
  • Отображение количества пользователей в каждой группе
  • Базовые данные для системы прав доступа

1.2 Связь с другими модулями

МодульСвязь
Все пользователиuser.group_id → определяет роль пользователя
Политики доступаgroup_policies → групповые права по умолчанию
Администраторыgroup_id = 1
Дилерыgroup_id = 2
Менеджерыgroup_id = 3
Производствоgroup_id = 4

1.3 Статистика

IDГруппаПользователей
1Администратор6
2Дилер13
3Менеджер10
4Производство1

Всего групповых политик: 124


2. Текущая реализация

2.1 Архитектура

┌─────────────────────────────────────────────────────────────────────────────┐
│                      МОДУЛЬ "ГРУППЫ ПОЛЬЗОВАТЕЛЕЙ"                           │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  РОУТЫ (routes/web.php)                                                      │
│  └── GET /groups → GroupController@index → Список групп                      │
│                                                                              │
│  КОНТРОЛЛЕР (GroupController.php)                                            │
│  └── БЕЗ ПРОВЕРКИ ПРАВ! Доступен всем авторизованным                        │
│                                                                              │
│  LIVEWIRE КОМПОНЕНТЫ                                                         │
│  └── Groups/Listing.php — Таблица групп (только просмотр)                   │
│                                                                              │
│  МОДЕЛИ                                                                      │
│  ├── Group — группа пользователей                                           │
│  └── GroupPolicy — связь группы с политикой                                 │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

2.2 Структура БД

Таблица groups

ПолеТипОписание
idbigintPK
namestringНазвание группы
managerbooleanФлаг менеджера (не используется)

⚠️ Примечание: Таблица groups создаётся в 2013 году (2013_03_06_193349), что раньше миграции users. Это legacy-дизайн.

Таблица group_policies

ПолеТипОписание
idbigintPK
group_idFKГруппа
policy_idFKПолитика
valuebooleanВключена / выключена

2.3 Файлы модуля

app/
├── Http/Controllers/
│   └── GroupController.php
├── Livewire/Groups/
│   └── Listing.php  — Только просмотр списка
└── Models/
    ├── Group.php
    └── GroupPolicy.php

database/migrations/
├── 2013_03_06_193349_create_groups_table.php
└── 2024_03_06_194633_create_group_policies_table.php

3. Права доступа

3.1 Контроллер БЕЗ проверки прав

// GroupController.php — НЕТ ПРОВЕРКИ!
public function index()
{
    return view('templates.groups.table');
}

⚠️ Внимание! Модуль доступен всем авторизованным пользователям. Нет проверки прав доступа.

3.2 Видимость в Sidebar

// Sidebar.php — показывается только администраторам
if ($this->authUser->group_id == 1) {
    // ... другие пункты
    $this->items['groups'] = 'Группы пользователей';
}

Фактически: Модуль виден только администраторам (group_id = 1), но URL /groups технически доступен всем.

3.3 Матрица доступа

РольПросмотр URLВидит в менюРедактирование
Администратор
Менеджер
Производство
Дилер

4. Описание полей

4.1 Колонки таблицы

КолонкаОписаниеОсобенности
idID группыПоиск
nameНазваниеПоиск
users_countКол-во пользователейАгрегация counts('users')

4.2 Модель Group

class Group extends Model
{
    public $timestamps = false;  // Нет created_at/updated_at
    protected $guarded = false;
    
    public function users()
    {
        return $this->hasMany(User::class);
    }
}

4.3 Модель GroupPolicy

class GroupPolicy extends Model
{
    public $table = "group_policies";
    public $timestamps = false;
    protected $guarded = false;
}

5. UI/UX

5.1 Список групп

┌─────────────────────────────────────────────────────────────────────────────┐
│ Группы пользователей                                                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                              [Поиск...]      │
├──────────────────┬────────────────────────┬─────────────────────────────────┤
│ Id               │ Название               │ Кол-во пользователей            │
├──────────────────┼────────────────────────┼─────────────────────────────────┤
│ 1                │ Администратор          │ 6                               │
│ 2                │ Дилер                  │ 13                              │
│ 3                │ Менеджер               │ 10                              │
│ 4                │ Производство           │ 1                               │
└──────────────────┴────────────────────────┴─────────────────────────────────┘

Особенности:
❌ Нет кнопки "Создать"
❌ Нет действий со строками
❌ Нет редактирования
❌ Нет ссылок на пользователей
✅ Только просмотр и поиск

6. Бизнес-логика

6.1 Роль group_id в системе

Поле group_id в таблице users определяет роль пользователя:

group_idРольОписание
1АдминистраторПолный доступ
2ДилерПредставитель дилерской компании
3МенеджерКуратор дилеров
4ПроизводствоРаботник производства

6.2 Групповые политики (GroupPolicy)

Для дилеров (group_id = 2) права берутся напрямую из group_policies:

// User.php — check_access()
if ($this->group_id == 2) {
    $out = GroupPolicy::where('group_id', 2)
        ->where('policy_id', $policy->id)
        ->first();
} else {
    $out = $this->user_policies()
        ->where('policy_id', $policy->id)
        ->first();
}

Важно: Дилеры не имеют индивидуальных политик (user_policies). Все их права определяются групповыми политиками.

6.3 Копирование политик при создании менеджера

При создании менеджера (group_id = 3) групповые политики копируются в индивидуальные:

// User.php — boot()
static::created(function (User $user): void {
    if ((int) $user->group_id === 3) {
        $user->seedManagerPoliciesFromGroupDefaults();
    }
});

// Метод копирования
public function seedManagerPoliciesFromGroupDefaults(): void
{
    $groupPolicies = GroupPolicy::query()->where('group_id', 3)->get();
    foreach ($groupPolicies as $gp) {
        UserPolicy::firstOrCreate(
            ['user_id' => $this->id, 'policy_id' => $gp->policy_id],
            ['value' => $gp->value]
        );
    }
}

6.4 Редактирование групповых политик

Групповые политики редактируются в модуле "Политики доступа" (/policies):

// Policies/Listing.php
Tables\Columns\ToggleColumn::make('admin.value')     // group_id = 1
Tables\Columns\ToggleColumn::make('manager.value')   // group_id = 3
Tables\Columns\ToggleColumn::make('dealer.value')    // group_id = 2
Tables\Columns\ToggleColumn::make('production.value') // group_id = 4

6.5 Схема прав доступа

┌─────────────────────────────────────────────────────────────────────────────┐
│                          СИСТЕМА ПРАВ ДОСТУПА                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌─────────────────┐          ┌─────────────────┐                           │
│  │     groups      │          │    policies     │                           │
│  │ (4 группы)      │          │ (57+ политик)   │                           │
│  └────────┬────────┘          └────────┬────────┘                           │
│           │                            │                                     │
│           └──────────┬─────────────────┘                                     │
│                      │                                                       │
│                      ▼                                                       │
│           ┌─────────────────────┐                                           │
│           │   group_policies    │   ← Групповые права по умолчанию          │
│           │   (124 записи)      │                                           │
│           └─────────┬───────────┘                                           │
│                     │                                                        │
│       ┌─────────────┼─────────────┐                                         │
│       │             │             │                                          │
│       ▼             ▼             ▼                                          │
│   ┌───────┐     ┌───────┐    ┌───────┐                                      │
│   │Дилеры │     │Менедж.│    │Админы │                                      │
│   │(gr=2) │     │(gr=3) │    │(gr=1) │                                      │
│   └───┬───┘     └───┬───┘    └───┬───┘                                      │
│       │             │            │                                           │
│       │             ▼            ▼                                           │
│       │      ┌─────────────────────┐                                        │
│       │      │   user_policies     │   ← Индивидуальные права               │
│       │      │ (копия при создании)│                                        │
│       │      └─────────────────────┘                                        │
│       │                                                                      │
│       └──────► Права из group_policies напрямую (без user_policies)         │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

7. Выявленные проблемы

7.1 Критические

#ПроблемаФайлВлияние
Критических проблем не обнаружено

7.2 Средние

#ПроблемаОписаниеРешение
1Нет проверки прав в контроллереURL доступен всем авторизованнымДобавить проверку group_can_view
2Listing рендерит неправильный view'livewire.news.listing' вместо правильногоЗаменить на 'livewire.base.listing'
3Неиспользуемое поле managerВ таблице groups есть флаг managerУдалить или использовать

7.3 Низкие

#ПроблемаОписание
4Нет CRUDНельзя создать/редактировать группы
5Нет ссылки на пользователейНельзя перейти к списку пользователей группы
6Нет групповых политик в UIНужно идти в /policies

8. Рекомендации

8.1 Приоритет: Высокий

Добавить проверку прав в контроллер

// GroupController.php — было:
public function index()
{
    return view('templates.groups.table');
}

// Стало:
public function index(Request $request)
{
    $user = $request->user();
    if (!$user or $user->group_id != 1)  // Только админы
        abort(403);
    return view('templates.groups.table');
}

8.2 Приоритет: Средний

Исправить view в Listing

// Listing.php:43 — было:
return view('livewire.news.listing');

// Стало:
return view('livewire.base.listing');

Добавить ссылку на пользователей группы

->columns([
    Tables\Columns\TextColumn::make('id'),
    Tables\Columns\TextColumn::make('name'),
    Tables\Columns\TextColumn::make('users_count')
        ->counts('users')
        ->url(fn ($record) => route('users-by-group', $record->id)),  // Если роут есть
])

8.3 Приоритет: Низкий

Добавить колонку с групповыми политиками

Tables\Columns\TextColumn::make('policies_count')
    ->label('Политик')
    ->getStateUsing(fn ($record) => GroupPolicy::where('group_id', $record->id)->where('value', true)->count()),

Приложение: SQL для аналитики

Группы с количеством пользователей

SELECT 
    g.id,
    g.name,
    COUNT(u.id) as users_count
FROM groups g
LEFT JOIN users u ON g.id = u.group_id
GROUP BY g.id, g.name
ORDER BY g.id;

Включённые политики по группам

SELECT 
    g.name as group_name,
    p.key as policy_key,
    p.name as policy_name,
    gp.value
FROM group_policies gp
JOIN groups g ON gp.group_id = g.id
JOIN policies p ON gp.policy_id = p.id
WHERE gp.value = 1
ORDER BY g.id, p.category, p.name;

Количество политик по группам

SELECT 
    g.name,
    COUNT(CASE WHEN gp.value = 1 THEN 1 END) as enabled,
    COUNT(CASE WHEN gp.value = 0 THEN 1 END) as disabled,
    COUNT(*) as total
FROM groups g
LEFT JOIN group_policies gp ON g.id = gp.group_id
GROUP BY g.id, g.name;

Документ подготовлен на основе анализа исходного кода проекта

On this page

Модуль "Группы пользователей"Содержание1. Общее описание1.1 Предназначение модуля1.2 Связь с другими модулями1.3 Статистика2. Текущая реализация2.1 Архитектура2.2 Структура БДТаблица groupsТаблица group_policies2.3 Файлы модуля3. Права доступа3.1 Контроллер БЕЗ проверки прав3.2 Видимость в Sidebar3.3 Матрица доступа4. Описание полей4.1 Колонки таблицы4.2 Модель Group4.3 Модель GroupPolicy5. UI/UX5.1 Список групп6. Бизнес-логика6.1 Роль group_id в системе6.2 Групповые политики (GroupPolicy)6.3 Копирование политик при создании менеджера6.4 Редактирование групповых политик6.5 Схема прав доступа7. Выявленные проблемы7.1 Критические7.2 Средние7.3 Низкие8. Рекомендации8.1 Приоритет: ВысокийДобавить проверку прав в контроллер8.2 Приоритет: СреднийИсправить view в ListingДобавить ссылку на пользователей группы8.3 Приоритет: НизкийДобавить колонку с групповыми политикамиПриложение: SQL для аналитикиГруппы с количеством пользователейВключённые политики по группамКоличество политик по группам