Перейти к содержанию

Авторизация и мультиарендность

Guard'ы

В config/auth.php настроены четыре guard'а:

Guard Provider / модель Способ входа
agent agent_staffAgentStaff Телефон + пароль / код из мессенджера (email-вход — фолбэк)
client usersUser Телефон + OTP (Telegram/MAX) или пароль
srm_admin srm_adminsSrmAdmin Email + пароль (Filament)
web users Совместимость

Мультиарендность на guard agent

Guard agent скоупит данные по agent_staff.agent_id. У самого agents нет своего agent_id — это и есть арендатор. Сотрудник всегда привязан к одному посреднику.

Модели личностей

flowchart TD
    Agent[agents — посредник/арендатор] --> Staff[agent_staff — сотрудники]
    Agent --> Clients[clients — клиенты посредника]
    User[users — пользователь/телефон] -->|membership| Clients
    Staff --> Group[access_groups — группа прав]
    Clients --> Manager[assigned_manager_id → agent_staff]
  • Agent — посредник (арендатор). Имеет тариф СРМ, баланс в ¥, поддомен, статус модерации.
  • AgentStaff — сотрудник посредника. Входит по email/телефону, привязан к группе прав.
  • User — физлицо с телефоном. Один User может быть связан с несколькими клиентами (client_memberships).
  • Client — клиент конкретного посредника (личность «клиент»). У клиента могут быть сотрудники (другие User через membership).
  • SrmAdmin — администратор СРМ (Filament).

Сценарии входа

Посредник (/agent/login)

  1. Ввод телефона → PhoneAuthController::check определяет: зарегистрирован ли номер и подключён ли мессенджер.
  2. Зарегистрирован → форма пароля (+ опция отправить код в Telegram/MAX).
  3. Не зарегистрирован → самостоятельная регистрация (RegisterController): создаётся Agent (статус moderation) + owner-AgentStaff + пробный тариф + базовый тариф клиента + клонирование групп прав (AgentProvisioner).
  4. Подтверждение телефона (ConfirmController): Telegram — deeplink /start <token>, MAX — код.
  5. После входа — редирект на поддомен {sub}.test142.ru/agent.

Старый email-вход сохранён на /agent/login-email (фолбэк).

Клиент (/client/login)

  1. Ввод телефона → OtpController::check смотрит messenger_contacts: подключён ли канал. Код не шлётся, если канал не привязан.
  2. Подключён → «Отправить код» (Telegram/MAX) → ввод 6-значного кода (OtpService, Redis, TTL 10 мин, 3 попытки, антиспам 60 с).
  3. Зарегистрированный клиент может войти и по паролю.
  4. Регистрация — только по реф-ссылке: ?agent=<id> (новый клиент-владелец) или ?hash=<invite> (сотрудник существующего клиента). Без членства вход отклоняется.

Подтверждение телефона и боты

Привязка телефон ↔ chat_id хранится в messenger_contacts. Заполняется вебхуками:

  • Telegram (/webhooks/telegram) — /start <token> или «поделиться контактом».
  • MAX (/webhooks/max) — код/контакт.

OtpService хранит код в Redis (хэш), OtpDispatcher шлёт его по подключённым каналам (можно выбрать конкретный).

Восстановление пароля

Маршруты recovery/* (и у клиента, и у посредника):

  1. start — проверка, есть ли подключённые каналы.
  2. send — код только в уже подключённый канал.
  3. verifyreset.

Привязать новый мессенджер во время восстановления нельзя (анти-угон). Нет подключённых каналов → восстановление через мессенджер недоступно.

После регистрации: онбординг и кабинеты

  • Онбординг-визард посредника: пошаговая первичная настройка (страны работы → валюты → поддомен → сотрудники → логотип). Состояние — в agents.onboarding (json). Маршруты agent.onboarding.*. См. Доп. модули.
  • Переключение кабинетов: один User может состоять в нескольких клиентах/посредниках; активный кабинет переключается без повторного входа (POST /switch, CabinetService). Поэтому client_memberships.user_id — nullable (приглашённый сотрудник до привязки).

Система прав (ПДИУ)

Подробности — в разделе Ключевые решения, п.3. Кратко:

  • Объект × уровень × scope. Уровни: view / add / edit / delete. Scope: own (свои, по assigned_manager_id) / foreign (чужие) / all.
  • Группы клонируются посреднику при регистрации (AgentProvisioner::provisionGroups).
  • Редактор матрицы прав — на стороне посредника (/agent/access-groups), гейт hasPermission('staff','edit').
  • Права прокинуты в Inertia: auth.agent.permissions + group.

Каналы вещания (broadcasting)

Приватный канал order.{orderId} (routes/channels.php) авторизуется по обоим guard'ам:

  • сотрудник посредника-владельца заказа (agent_id совпадает), или
  • пользователь-член клиента заказа (memberships содержит client_id).