Авторизация — Логин
Роут: /login
Доступ: Public (неавторизованные пользователи)
(Обновлено в BR 1.4.4)
JWT упрощён — поля
role(enum),store_ids,legal_entity_idудалены. Payload:{sub, franchise_id, role_ids}. Scope сотрудника считается на бэке по правилам Ролевой модели и отдаётся фронту черезGET /api/v1/admin/auth/meвместе сfranchise.type.
Что видит пользователь
Страница логина по центру экрана. Логотип бренда сверху. Форма ниже.
Форма
| Поле | Тип ввода | Placeholder |
|---|---|---|
| Text input (type=email) | “Email” | |
| Пароль | Password input | ”Пароль” |
- Кнопка “Войти” (primary, полная ширина)
- Ссылка “Забыли пароль?” под кнопкой →
/forgot-password
Действия
Нажатие “Войти”
API: POST /api/v1/admin/auth/login (через BFF)
Успех:
- Сохранить
access_tokenиrefresh_tokenв localStorage - Запросить
GET /api/v1/admin/auth/me— получить данные пользователя:user: {id, first_name, last_name, email}franchise: {id, name, type}—type∈corporate|individual(управляет видимостью раздела «Юр. лица»)scope: {type, legal_entity_ids?, store_ids?}—type∈all_franchise|legal_entity_ids|store_idspermissions: [...]— список ключей permissions сотрудника (агрегат всех его ролей)
- Сохранить ответ в PermissionContext (фронт-сторе)
- Redirect на
/(Dashboard)
PermissionContext
(Введено в BR 1.4.4) — Фронт хранит в контексте
franchise.type(для скрытия раздела «Юр. лица» приindividual),scope(для фильтрации UI-операций) иpermissions(для гейтов на кнопках/пунктах меню).
Ошибки:
| Код ошибки | Что показываем |
|---|---|
INVALID_CREDENTIALS (401) | “Неверный email или пароль” — под формой, красным |
ACCOUNT_DISABLED (403) | “Учётная запись деактивирована. Обратитесь к администратору.” |
ACCOUNT_LOCKED (429) | “Слишком много попыток. Попробуйте через 15 минут.” |
| Сетевая ошибка | ”Не удалось подключиться к серверу. Попробуйте позже.” |
Сессия и автовход
- При открытии
/loginпроверить: есть лиaccess_tokenв localStorage? - Если есть и валиден → redirect на
/(Dashboard) - Если expired → попробовать refresh (
POST /api/v1/admin/auth/refresh) - Если refresh успешен → redirect на
/ - Если refresh неуспешен → остаться на
/login, очистить токены
После логина: Layout
После успешного входа пользователь видит:
- Sidebar (боковое меню) — разделы в зависимости от роли
- Header (шапка) — имя пользователя + кнопка “Выйти”
- Content area — Dashboard
Кнопка “Выйти”
API: POST /api/v1/admin/auth/logout (через BFF)
- Очистить
access_tokenиrefresh_tokenиз localStorage - Redirect на
/login
Состояния
| Состояние | Что показываем |
|---|---|
| Начальное | Пустая форма |
| Загрузка | Кнопка “Войти” disabled, спиннер |
| Ошибка | Сообщение под формой красным |
| Блокировка | Сообщение + форма disabled |
Переходы
| Откуда | Куда | Триггер |
|---|---|---|
| Логин | Dashboard | Успешный вход |
| Логин | Забыли пароль | Ссылка “Забыли пароль?” |
| Любая страница | Логин | JWT expired + refresh failed |
| Любая страница | Логин | Кнопка “Выйти” |