- Next 16.4 и Payload 3.91 в одном приложении, PostgreSQL с UUID, TypeScript 6, ESLint 9, Prettier, Vitest - Payload: администраторы с ролями, multi-tenant по сайтам, локализация en/ru/de/fr/es, интерфейс админки ru/en, языки сайта (sites.locales) - Коллекции sites, domains, currencies, countries, locations, tags, tariffs, payment-systems (manual), media и начальные данные (pnpm seed) - Proxy: хост → домен, язык и валюта, внутренние маршруты по хосту; /admin и /api закрыты на доменах брендов - Токены и темы брендов, оболочки сайта и кабинета, переключатели языка, валюты и темы, заглушки страниц - /svc/health, юнит systemd veilix-dev.service - Документация: решения D-022…D-024, команды в CLAUDE.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 KiB
11 KiB
05. Вход, сессии, аккаунты
1. Аккаунты
- Аккаунты раздельные по сайтам (D-011). Уникальность: (
site,email) и (site,telegramId). - Один человек на двух сайтах — два разных пользователя с разными балансами и ключами.
- Администраторы — отдельная коллекция
adminsс паролем, к пользователям отношения не имеют.
2. Вход по коду из письма
Одно поле email: если аккаунта нет — он создаётся, если есть — выполняется вход. Ответ всегда одинаковый, по нему нельзя узнать, есть ли аккаунт.
2.1 Запрос кода
- Пользователь вводит email и проходит ALTCHA.
- Сервер нормализует email (обрезает пробелы, переводит в нижний регистр) и проверяет лимиты: a. по email — не чаще раза в 60 секунд и не больше 5 кодов в час; b. по IP — не больше 20 запросов в час.
- Прошлые неиспользованные коды для этого email и сайта аннулируются.
- Создаётся код: 6 цифр, действует 10 минут. В базе хранится только HMAC-SHA256 (секрет из
.env, сайт, email, код). - Письмо
login_codeна языке текущей страницы. Если в настройках почты включено «Записывать коды входа в журнал», код пишется в журнал писем (раздел 4). - Ответ: «Код отправлен на {email}. Он действует 10 минут». Кнопка «Отправить ещё раз» — через 60 секунд, «Другая почта» — назад.
2.2 Проверка кода
- Берётся последний действующий код для email и сайта. Счётчик попыток +1; после 5 неудачных код аннулируется.
- Сравнение — за постоянное время.
- Код верный:
a. найти пользователя (сайт, email) или создать:
registeredVia = email, язык — текущий, валюта — выбранная (Q-04), реферальная привязка из cookievx_ref, хэш IP регистрации; b. пользовательblocked— отказ: «Аккаунт заблокирован, напишите в поддержку»; c. проставитьemailVerifiedAtиlastLoginAt, создать сессию, вернуть на страницу, с которой пришёл (кабинет или оформление заказа).
3. Сессии
- Cookie
vx_session: случайные 32 байта, только для хоста кабинета (my.veilix.appи т.д., без атрибута Domain),HttpOnly,Secure,SameSite=Lax. - В базе (
customer-sessions) — только SHA-256 токена. Срок — 30 дней, продлевается при активности (не чаще раза в сутки). - «Выйти» отзывает текущую сессию, «Выйти на всех устройствах» — все.
- Payload: коллекция
customers— коллекция авторизации сdisableLocalStrategy: trueи своей стратегией. Стратегия читает cookie, находит сессию и возвращает пользователя. Поэтому правила доступа Payload работают и для пользователей. - Защита от CSRF:
SameSite=Lax; server actions Next.js сверяют Origin и Host; свои POST-эндпоинты проверяют Origin. - Cookie хостовые, поэтому dev и prod не пересекаются:
dev.my.veilix.appиmy.veilix.appне видят cookie друг друга.
4. Коды в журнале для отладки
- Глобальная настройка «Почта» → «Записывать коды входа в журнал».
- Включено: в записи журнала писем видно поле
debugCodeс кодом открытым текстом. В dev-логе процесса код тоже печатается. - Видят только роли owner и admin. Пока настройка включена, в админке висит предупреждение. Записи с кодом удаляются через сутки.
- Вместе с транспортом «только журнал» (письма не отправляются, только пишутся в журнал) это позволяет тестировать вход без настроенной почты.
- В prod по умолчанию выключено: с кодами из журнала можно войти в любой аккаунт.
5. Оформление заказа
Шаг «Почта» на странице заказа — тот же вход по коду. После подтверждения пользователь остаётся на шаге «Оплата».
6. Telegram (этап 3)
6.1 Вход из MiniApp
- MiniApp передаёт серверу
initDataот Telegram. - Сервер проверяет подпись: HMAC-SHA256 с ключом
HMAC_SHA256("WebAppData", токен основного бота),auth_dateне старше суток. - Ищем пользователя (сайт, telegramId). Нет — создаём:
registeredVia = telegram, язык — изlanguage_codeTelegram (если он среди включённых), валюта — по умолчанию домена. - Сессия
kind = miniapp. Как её хранить (cookie внутри WebView Telegram или токен в памяти) — решаем на этапе 3.
6.2 Привязка почты из Telegram
- Пользователь вводит email в боте или MiniApp и получает код с назначением
link_email. - Код верный — три случая: a. на этом сайте нет пользователя с такой почтой — почта привязывается, теперь работает вход на сайте по коду; b. есть пользователь с этой почтой без Telegram — аккаунты объединяются (раздел 6.4); c. у пользователя с этой почтой привязан другой Telegram — автоматически не объединяем: «Эта почта привязана к другому Telegram-аккаунту, напишите в поддержку».
6.3 Привязка Telegram с сайта и вход через Telegram
- «Подключить Telegram» в кабинете создаёт одноразовый токен (10 минут) и открывает
t.me/<основной бот>?start=link_<токен>. Бот проверяет токен и привязывает Telegram к аккаунту. Если этот Telegram уже у другого пользователя сайта — правила раздела 6.4. - «Войти через Telegram» на сайте — официальный виджет Telegram Login. Для основного бота в BotFather указывается домен кабинета. Нет пользователя с этим Telegram — создаётся новый.
6.4 Объединение аккаунтов (в пределах сайта)
- Основным остаётся аккаунт с почтой, к нему переходит Telegram второго.
- Ключи, заказы, платежи, сохранённые карты, заявки переназначаются на основной аккаунт.
- Баланс переносится парой движений
adjustmentс комментарием «Объединение аккаунтов»: минус на втором, плюс на основном. Сами движения не меняются. - Реферальная привязка: если у обоих есть пригласивший — остаётся более ранний. Реферальный код — основного аккаунта.
- Второй аккаунт блокируется со ссылкой «объединён с …». Всё пишется в журнал действий.
- Конфликты переводят объединение в ручной режим, его делает администратор кнопкой «Объединить аккаунты»: разные валюты при ненулевых балансах, у обоих привязан Telegram.
7. Администраторы
- Стандартная авторизация Payload: email и пароль, cookie только на хосте админки.
- Админка открывается только на
plc.veilix.ccиdev.plc.veilix.cc; nginx пускает туда только с разрешённых IP. - 5 неудачных попыток — блокировка на 15 минут.
- Первый администратор каждого окружения создаётся на экране первого входа Payload и автоматически получает роль owner.
8. Cookies
| Cookie | Где | Срок | Зачем |
|---|---|---|---|
vx_session |
хост кабинета | 30 дней | сессия пользователя |
vx_ref |
хост кабинета | 60 дней | реферальный код |
NEXT_LOCALE |
каждый хост | 1 год | выбранный язык |
vx_currency |
хост сайта и кабинета | 1 год | выбранная валюта (у вошедшего — валюта аккаунта) |
vx_consent |
хост сайта и кабинета | 1 год | согласие на cookies (этап 1h) |
payload-token |
хост админки | сессия админки | вход администратора |
Тема (светлая, тёмная, как в системе) хранится в localStorage, как в макете, и применяется скриптом до отрисовки, без мигания.