Авторизация — Логин

Роут: /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
EmailText 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}typecorporate | individual (управляет видимостью раздела «Юр. лица»)
    • scope: {type, legal_entity_ids?, store_ids?}typeall_franchise | legal_entity_ids | store_ids
    • permissions: [...] — список ключей 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
Любая страницаЛогинКнопка “Выйти”

Ссылки