Skip to content

Оргструктура, пользователи и доступы: инструкция для дизайна и фронтенда ​

Документ описывает административный интерфейс для создания пользователя, настройки отделов, руководителей, ролей и отображения оргструктуры.

Цель ​

Админ должен за один сценарий завести сотрудника в систему и связать его с организационной моделью:

  • создать или обновить пользователя;
  • назначить системную роль и RBAC-роли;
  • назначить один или несколько отделов;
  • выбрать primary department;
  • назначить прямого руководителя;
  • назначить должность;
  • при необходимости назначить руководителя отдела;
  • при необходимости настроить родительский отдел;
  • при необходимости добавить персональные allow/deny permissions как исключение;
  • проверить, какие права и видимость получит пользователь.

Обычный сотрудник должен видеть свой оргконтекст:

  • к каким отделам относится;
  • какой отдел primary;
  • кто руководитель отдела;
  • кто прямой руководитель;
  • кто находится выше по цепочке;
  • кто его подчинённые.

Аватары в списках ​

Ссылка на аватар (avatar_url) приходит в самих списках: GET /users, узлы GET /org/tree, user и руководители отделов в GET /org/me, GET /directory/users. Запрашивать профиль каждого сотрудника ради картинки не нужно; нет avatar_url — интерфейс рисует инициалы.

Роли Интерфейса ​

ПользовательЧто видитЧто может менять
adminвсе пользователи, роли, отделы, оргдерево, должности, permissionsвсё
directorвсе бизнес-данные в read-режиме, оргструктуру и отчётыничего административного без отдельной роли admin
пользователь с users.manageсписок и карточки пользователейпользователей, их primary role, отделы, активность
пользователь с departments.manageотделыотделы и руководителей отделов
пользователь с org.viewоргдерево, должности, чужие цепочки руководителейтолько просмотр
пользователь с org.manageоргдерево, должности, руководителипрямых руководителей и должности
любой авторизованный сотрудниктолько свой оргконтекст через /org/meничего в оргструктуре

Для первого релиза административной страницы можно открывать весь раздел только admin. Позже можно разделить доступ по permissions выше.

Рекомендуемая Навигация ​

Раздел верхнего уровня: Организация.

Внутри:

  1. Оргструктура

    • дерево пользователей;
    • поиск по сотруднику;
    • фильтр по отделу;
    • боковая панель выбранного сотрудника.
  2. Пользователи

    • таблица сотрудников;
    • создание пользователя;
    • редактирование пользователя;
    • роли, отделы, руководитель, должность.
  3. Отделы

    • список отделов;
    • создание/редактирование отдела;
    • родительский отдел;
    • назначение руководителя отдела.
  4. Роли и права

    • список ролей;
    • permissions роли;
    • роли пользователя.
  5. Должности

    • справочник должностей;
    • уровень должности;
    • default RBAC-роли должности;
    • описание.

Модель Доступов ​

Правило для интерфейса:

  • отдел определяет область данных;
  • роль определяет действия;
  • должность применяет default-роли;
  • персональные permissions используются только для исключений.

Пример: должность Руководитель отдела должна иметь role_codes: ["head_of_department"]. При назначении такой должности пользователю backend добавит роль head_of_department и поднимет primary role, если пользователь не admin. Чтобы руководитель видел дочерние отделы, у отделов нужно настроить parent_id, а у руководимого отдела manager_id.

Должность Директор должна иметь role_codes: ["director"]. Это даёт глобальный read-доступ через system.global_read, но не даёт техническое администрирование. Если директор должен управлять пользователями и правами, ему отдельно назначается роль admin.

Экран: Оргструктура ​

Основной экран должен быть рабочим инструментом, а не landing page.

Layout ​

  • Левая колонка: фильтры и список/дерево отделов.
  • Центральная область: оргдерево сотрудников.
  • Правая панель: карточка выбранного сотрудника.

Центральная область ​

Показывать дерево по users.manager_id.

Узел сотрудника:

  • ФИО;
  • должность;
  • отдел primary;
  • статус активности;
  • количество прямых подчинённых;
  • иконка/метка, если сотрудник руководит отделом.

Не перегружать узел permissions. Права показывать в карточке сотрудника или отдельной вкладке.

Правая Панель Сотрудника ​

Вкладки:

  • Профиль: ФИО, email, телефон, активность.
  • Оргструктура: отделы, primary department, прямой руководитель, цепочка руководителей, подчинённые.
  • Роли: primary role, RBAC-роли, effective permissions.
  • Проекты: проекты пользователя, проектные роли, активность в команде.

Для обычного сотрудника аналогичная информация берётся из GET /api/v1/org/me, но без доступа к чужим данным.

Экран: Пользователи ​

Таблица ​

Колонки:

  • ФИО;
  • email;
  • primary role;
  • RBAC-роли;
  • primary department;
  • все отделы;
  • прямой руководитель;
  • должность;
  • активен/неактивен;
  • дата создания/обновления.

Фильтры:

  • отдел;
  • роль;
  • активность;
  • руководитель;
  • должность;
  • поиск по ФИО/email.

Создание Пользователя ​

Форма должна быть разделена на шаги или секции.

1. Учётная запись

  • email;
  • пароль;
  • ФИО или части ФИО;
  • телефон;
  • активность.

API: POST /api/v1/users.

Минимальное тело:

json
{
  "email": "ivan.petrov@example.com",
  "password": "strong-password-123",
  "last_name": "Петров",
  "first_name": "Иван",
  "middle_name": "Сергеевич",
  "role": "manager",
  "department_ids": [1, 2],
  "phone": "+79991234567"
}

Важно:

  • role обязателен и должен существовать в /rbac/roles;
  • первый ID в department_ids становится primary department;
  • пользователь не может остаться без роли;
  • почта входа без учёта регистра: сохраняется строчными, вход, сброс пароля и проверка занятости ищут по lower(email) (индекс 0158); почта, отличающаяся от занятой только регистром, — 409 users_email_already_in_use;
  • новый пароль (создание, регистрация, сброс) — от 8 символов и не длиннее 72 байт (предел bcrypt, ≈36 букв кириллицы); пароль сохраняется как введён, без обрезки пробелов — вход сравнивает его так же. Вход старые пароли не перепроверяет.

Правка (PUT /api/v1/users/:id, PUT /api/v1/users/:id/roles, DELETE /api/v1/users/:id/roles/:role):

  • свою учётную запись отключить нельзя (409 users_cannot_deactivate_yourself), свою роль владельца снять нельзя (409 users_cannot_remove_own_owner_role) — это делает другой администратор; интерфейс выключает переключатель и роль с причиной;
  • phone: "" очищает телефон; должность снимается PUT /api/v1/org/users/:id/position {"position_id": null}.

Список «Пользователи» читает GET /api/v1/users?include_inactive=true (пресет «Неактивные», включение обратно); справочник сотрудников сессии для выбора исполнителей — только активные. Подсчёт носителей роли и должности (кнопка «Удалить» выключена с причиной) тоже включает отключённых — сервер считает и их.

2. Роли

После создания пользователя:

  • показать primary role из user.role;
  • показать все RBAC-роли из user.roles в ответах GET /api/v1/users и GET /api/v1/users/:id;
  • дать заменить список через PUT /api/v1/users/:id/roles.

API:

json
{
  "roles": ["manager", "engineer"]
}

Правило:

  • первая роль в массиве становится primary role (users.role);
  • primary role всегда должна присутствовать в user_roles;
  • нельзя отправлять пустой массив.

3. Отделы

Назначение отделов выполняется через PUT /api/v1/users/:id.

json
{
  "department_ids": [1, 2]
}

Правило:

  • первый отдел в массиве является primary department;
  • порядок отделов в UI должен быть управляемым;
  • если нужно сменить primary department, фронт переставляет отдел первым.
  • добавление отдела расширяет scope данных, но не выдаёт действия без соответствующей роли.

4. Руководитель и должность

Прямой руководитель:

http
PUT /api/v1/org/users/:id/manager
json
{
  "manager_id": 10
}

Снять руководителя:

json
{
  "manager_id": null
}

Должность:

http
PUT /api/v1/org/users/:id/position
json
{
  "position_id": 3
}

При назначении должности backend добавляет пользователю default-роли из org_position_roles. Снятие должности не удаляет роли автоматически, чтобы не отозвать доступы неожиданно; роли редактируются явно на вкладке Роли.

Backend запрещает циклы в иерархии: сотрудник не может стать руководителем самого себя или своего руководителя по нижней цепочке.

Экран: Отделы ​

Таблица ​

Колонки:

  • название;
  • родительский отдел;
  • руководитель отдела;
  • количество сотрудников;
  • количество проектов;
  • дата создания/обновления.

GET /api/v1/departments и GET /api/v1/departments/:id отдают users_count, projects_count и краткий объект manager.

users_count — число разных сотрудников отдела: и привязанных через user_departments, и тех, у кого отдел указан основным (users.department_id). Один человек в обоих источниках считается один раз.

Создание/Редактирование ​

API:

  • POST /api/v1/departments;
  • PUT /api/v1/departments/:id;
  • DELETE /api/v1/departments/:id.

Тело:

json
{
  "name": "Проектный офис",
  "parent_id": null,
  "manager_id": 10
}

Правила:

  • название обязательно и уникально;
  • parent_id должен быть существующим отделом или null;
  • backend запрещает циклы в дереве отделов;
  • manager_id должен быть существующим пользователем;
  • удаление отдела запрещено, если есть связанные пользователи или проекты, а также задачи, командировки или позиции заявок в команду этого отдела — 409 с перечнем и числом (departments_department_in_use), а не ошибка внешнего ключа; снимки KPI заполнения табеля отдела удаляются вместе с ним (расчётные данные);
  • несуществующий отдел в GET /api/v1/departments/:id — 404 departments_department_not_found;
  • руководитель отдела (departments.manager_id) не равен автоматически прямому руководителю (users.manager_id).

UI должен явно различать:

  • руководитель отдела — управляет отделом как структурной единицей;
  • прямой руководитель сотрудника — используется в оргдереве и цепочке подчинения.

Экран: Роли и Права ​

Роли ​

API:

  • GET /api/v1/rbac/roles;
  • POST /api/v1/rbac/roles;
  • GET /api/v1/rbac/roles/:role;
  • PUT /api/v1/rbac/roles/:role;
  • DELETE /api/v1/rbac/roles/:role.

Создание:

json
{
  "name": "project_manager",
  "description": "Менеджер проекта",
  "permission_codes": ["projects.manage", "tasks.manage"]
}

Permissions Роли ​

API:

  • GET /api/v1/rbac/roles/:role/permissions;
  • PUT /api/v1/rbac/roles/:role/permissions;
  • GET /api/v1/rbac/permissions.

Тело замены permissions:

json
{
  "permission_codes": ["users.manage", "org.view"]
}

Роли Пользователя ​

API:

  • GET /api/v1/users/:id/roles;
  • PUT /api/v1/users/:id/roles;
  • POST /api/v1/users/:id/roles/:role;
  • DELETE /api/v1/users/:id/roles/:role.

Для UX предпочтителен PUT /users/:id/roles, потому что он явно показывает итоговый набор ролей и порядок primary role.

Персональные Permissions ​

API:

  • GET /api/v1/users/:id/permissions;
  • PUT /api/v1/users/:id/permissions.

Тело полной замены override:

json
{
  "permissions": [
    {"permission_code": "finance.manage", "effect": "allow"},
    {"permission_code": "files.delete", "effect": "deny"}
  ]
}

Используйте этот механизм только для исключений. Если одинаковое исключение нужно многим сотрудникам, создавайте роль или настройте default-роли должности.

Экран: Должности ​

API:

  • GET /api/v1/org/positions;
  • POST /api/v1/org/positions;
  • GET /api/v1/org/positions/:id;
  • PUT /api/v1/org/positions/:id;
  • DELETE /api/v1/org/positions/:id.

Поля:

  • name;
  • description;
  • level.
  • role_codes.

level определяет уровень в иерархии: чем меньше число, тем выше должность.

Пример:

json
{
  "name": "Руководитель отдела",
  "description": "Руководитель структурного подразделения",
  "level": 3,
  "role_codes": ["head_of_department"]
}

API Для Сотрудника ​

GET /api/v1/org/me доступен любому авторизованному пользователю.

Использовать для виджета “Моя оргструктура” в профиле или на dashboard.

Ответ содержит:

  • user;
  • departments;
  • primary_department;
  • manager_chain;
  • subordinates.

UI-состояния:

  • нет отдела: показать пустое состояние “Отдел не назначен”;
  • нет руководителя: “Прямой руководитель не назначен”;
  • нет подчинённых: “Подчинённых нет”;
  • несколько отделов: primary department показывать первым и отмечать бейджем.

Порядок Вызовов Для Формы Создания ​

  1. Загрузить справочники:

    • GET /api/v1/rbac/roles;
    • GET /api/v1/departments;
    • GET /api/v1/users;
    • GET /api/v1/org/positions.
  2. Создать пользователя:

    • POST /api/v1/users.
  3. Если выбрано несколько RBAC-ролей:

    • PUT /api/v1/users/:id/roles.
  4. Если выбран прямой руководитель:

    • PUT /api/v1/org/users/:id/manager.
  5. Если выбрана должность:

    • PUT /api/v1/org/users/:id/position.
  6. Перезагрузить карточку:

    • GET /api/v1/users/:id;
    • GET /api/v1/org/users/:id/chain;
    • GET /api/v1/org/users/:id/subordinates.

Ошибки и Состояния ​

Обязательные состояния UI:

  • loading;
  • empty state;
  • validation errors;
  • forbidden;
  • conflict;
  • stale data после обновления.

Типовые ошибки:

СценарийКодПоведение UI
роль не существует400подсветить поле роли
пустой список ролей400запретить сохранение
последний admin удаляется409показать блокирующее сообщение
отдел уже существует409подсветить название
отдел используется409запретить удаление
циклический руководитель400показать ошибку в поле руководителя
нет permission403скрыть действие или показать read-only

Видимость Проектных Сущностей ​

Ограничения видимости не должны быть только на отделе или только на роли. Нужна комбинированная модель:

  1. Роль/permission отвечает за capability

    • что пользователь в принципе может делать;
    • примеры: projects.manage, tasks.manage, finance.manage, org.view.
  2. Отдел отвечает за организационный scope

    • к какой части компании пользователь относится;
    • подходит для dashboard, KPI, отчетности, дефолтных фильтров и управления ресурсами отдела.
  3. Участие в проекте отвечает за фактическую видимость конкретного проекта

    • менеджер проекта;
    • активный участник команды проекта;
    • автор/исполнитель/соисполнитель задач проекта.
  4. Проектная роль отвечает за разделы внутри проекта

    • финансы видят не все участники, а менеджер проекта и участники с финансовыми проектными ролями;
    • документы и логистика могут иметь отдельные section grants.

Итоговое правило для фронтенда:

  • не показывать пользователю проект только потому, что он в том же отделе;
  • не показывать финансовые разделы только потому, что у пользователя роль manager;
  • сначала проверять список/детали, которые вернул backend;
  • действия включать по permissions и по данным доступа в сущности;
  • для фильтров отдел использовать как scope, но не как единственный access-control механизм.

Рекомендуемая модель для продукта:

СущностьВидимость
проектadmin/global, руководитель отдела продаж или участник проекта/задач
задачаadmin/global, менеджер проекта или участник задачи; в списках также задачи подчинённых, прямой руководитель участника задачи имеет прямой доступ
финансы проектаadmin/global finance, менеджер проекта, финансовая проектная роль
документы проектаучастник проекта с доступом к documents или explicit grant
логистика проектаучастник проекта с доступом к logistics или explicit grant
KPI отделаadmin/global или руководитель/сотрудник своего отдела
оргструктура целикомorg.view
свой оргконтекстлюбой авторизованный пользователь

Для дизайна это означает: права и видимость нужно объяснять пользователю через бейджи и disabled states, но финальное решение о доступе всегда остаётся за backend.

Загружаем документацию…