Ссылки README и CLAUDE.md переведены на архив. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
7.4 KiB
users-admin Specification
Purpose
Администрирование доступа: пользователи, назначение ролей и матрица «роль × право» как данные (role_permission), с
аудитом; минимальный экран администратора во фронте.
Requirements
Requirement: Пользователи — список, создание, изменение, деактивация
Маршруты /api/v1/admin/users (право USERS_ADMIN): GET — список с ролями и филиалом (поиск по email/ФИО, фильтр
is_active, пагинация); POST — создание с обязательными email (уникален без учёта регистра → 409 EMAIL_EXISTS),
full_name, regional_office_id, необязательными employee_no, business_segment, roles (коды); PATCH …/{id} —
full_name, employee_no, regional_office_id, business_segment, is_active. Удаление MUST NOT предоставляться.
external_id через API не задаётся. Каждая мутация пишет audit_event(USER_CHANGE, section = USERS).
Scenario: Создание с ролью
- WHEN администратор создаёт пользователя с
roles = ["KA_RF"] - THEN появляются
app_userиuser_role,GET /meот его имени (dev-токен) возвращает праваKA_RF
Scenario: Email в другом регистре
- WHEN создаётся пользователь с email, отличающимся от существующего только регистром
- THEN ответ 409
EMAIL_EXISTS
Requirement: Назначение ролей
PUT /api/v1/admin/users/{id}/roles (тело: список кодов) SHALL заменять набор ролей пользователя: отсутствующие в наборе
назначения удаляются, новые добавляются; неизвестный или неактивный код роли → 422; пишется audit_event(USER_ROLE_CHANGE, before_value = прежний набор, after_value = новый). Замена набора ролей MUST NOT оставить систему без активного пользователя с
USERS_ADMIN (409 LAST_ADMIN): администратор не может снять с себя последнюю роль, дающую USERS_ADMIN, если он —
единственный активный обладатель этого права; при наличии другого активного администратора снятие у себя разрешено
(решение №34).
Scenario: Замена набора ролей
- WHEN у пользователя роли
[KA_RF], администратор ставит[KA_GO, EXPERT] - THEN
user_roleсодержит ровно две новые строки, в аудитеbefore_value = ["KA_RF"],after_value = ["KA_GO","EXPERT"]
Scenario: Последний администратор
- WHEN единственный активный пользователь с
USERS_ADMINснимает с себя рольADMIN - THEN ответ 409
LAST_ADMIN, роли не изменены
Requirement: Матрица прав
GET /api/v1/admin/roles SHALL отдавать роли с их правами; GET /api/v1/admin/permissions — справочник прав (16 кодов, только
чтение; создание прав MUST NOT предоставляться); PUT /api/v1/admin/roles/{code}/permissions (тело: список кодов прав) SHALL
заменять набор прав роли и писать audit_event(ROLE_PERMISSION_CHANGE) с before/after. Системные роли (is_system)
нельзя деактивировать или переименовать; нельзя снять USERS_ADMIN с роли, если после этого ни у одного активного
пользователя не останется этого права (409 LAST_ADMIN).
Scenario: Изменение матрицы
- WHEN у роли
EXPERTдобавляется правоEXPORT - THEN
role_permissionсодержит новую строку, пользователь с рольюEXPERTпри следующем запросе/meвидитEXPORT, в аудитеROLE_PERMISSION_CHANGE
Scenario: Снятие USERS_ADMIN с единственной роли
- WHEN у роли
ADMIN(единственной сUSERS_ADMINу активных пользователей) убираютUSERS_ADMIN - THEN ответ 409
LAST_ADMIN
Requirement: Минимальный экран администратора
SPA SHALL содержать маршрут /admin (пункт «Система → Пользователи и роли» в боковом меню), доступный при наличии
USERS_ADMIN в ответе /api/v1/me: таблица пользователей с выбором ролей и формой создания, таблица «роль × право» с
чекбоксами и кнопкой сохранения; запросы идут через общий API-клиент с заголовком Authorization: Bearer. В режиме
разработки SHALL быть доступен ввод email для получения dev-токена (POST /api/v1/dev/token); в сборке для прода этот
ввод отсутствует.
Scenario: Назначение роли через экран
- WHEN администратор на
/adminвыбирает пользователю рольKA_GOи сохраняет - THEN вызывается
PUT /admin/users/{id}/roles, таблица показывает новую роль, ошибка API показывается уведомлением
Scenario: Нет права
- WHEN пользователь без
USERS_ADMINоткрывает/admin - THEN страница показывает сообщение об отсутствии доступа и не делает запросов к
/admin/*
Requirement: Краткий справочник пользователей
GET /api/v1/users/brief?ids=<uuid>,… SHALL быть доступен любому аутентифицированному пользователю без отдельного
права и отдавать [{id, full_name, is_active}] для найденных id, включая неактивных; неизвестные id MUST NOT
возвращаться и MUST NOT давать ошибку; больше 200 id — 422 TOO_MANY_IDS; некорректный UUID — 422. Админский список
пользователей не меняется.
Scenario: Имя загрузившего
- WHEN аналитик без права
USERS_ADMINзапрашиваетidsизuploaded_byдвух файлов и неизвестный UUID - THEN 200, два элемента с ФИО, неизвестный UUID отсутствует
Scenario: Слишком много id
- WHEN передан 201 id
- THEN 422
TOO_MANY_IDS