Авторизация и мультиарендность¶
Guard'ы¶
В config/auth.php настроены четыре guard'а:
| Guard | Provider / модель | Способ входа |
|---|---|---|
agent |
agent_staff → AgentStaff |
Телефон + пароль / код из мессенджера (email-вход — фолбэк) |
client |
users → User |
Телефон + OTP (Telegram/MAX) или пароль |
srm_admin |
srm_admins → SrmAdmin |
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)¶
- Ввод телефона →
PhoneAuthController::checkопределяет: зарегистрирован ли номер и подключён ли мессенджер. - Зарегистрирован → форма пароля (+ опция отправить код в Telegram/MAX).
- Не зарегистрирован → самостоятельная регистрация (
RegisterController): создаётсяAgent(статусmoderation) + owner-AgentStaff+ пробный тариф + базовый тариф клиента + клонирование групп прав (AgentProvisioner). - Подтверждение телефона (
ConfirmController): Telegram — deeplink/start <token>, MAX — код. - После входа — редирект на поддомен
{sub}.test142.ru/agent.
Старый email-вход сохранён на /agent/login-email (фолбэк).
Клиент (/client/login)¶
- Ввод телефона →
OtpController::checkсмотритmessenger_contacts: подключён ли канал. Код не шлётся, если канал не привязан. - Подключён → «Отправить код» (Telegram/MAX) → ввод 6-значного кода (
OtpService, Redis, TTL 10 мин, 3 попытки, антиспам 60 с). - Зарегистрированный клиент может войти и по паролю.
- Регистрация — только по реф-ссылке:
?agent=<id>(новый клиент-владелец) или?hash=<invite>(сотрудник существующего клиента). Без членства вход отклоняется.
Подтверждение телефона и боты¶
Привязка телефон ↔ chat_id хранится в messenger_contacts. Заполняется вебхуками:
- Telegram (
/webhooks/telegram) —/start <token>или «поделиться контактом». - MAX (
/webhooks/max) — код/контакт.
OtpService хранит код в Redis (хэш), OtpDispatcher шлёт его по подключённым каналам (можно выбрать конкретный).
Восстановление пароля¶
Маршруты recovery/* (и у клиента, и у посредника):
start— проверка, есть ли подключённые каналы.send— код только в уже подключённый канал.verify→reset.
Привязать новый мессенджер во время восстановления нельзя (анти-угон). Нет подключённых каналов → восстановление через мессенджер недоступно.
После регистрации: онбординг и кабинеты¶
- Онбординг-визард посредника: пошаговая первичная настройка (страны работы → валюты → поддомен → сотрудники → логотип). Состояние — в
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).