> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bedolagam.ru/llms.txt
> Use this file to discover all available pages before exploring further.

# Email-авторизация

> Регистрация, верификация, вход и сброс пароля через email в Cabinet

## Обзор

Cabinet поддерживает три способа авторизации:

| Способ                    | Описание                                               |
| ------------------------- | ------------------------------------------------------ |
| **Telegram WebApp**       | Автоматический вход через Telegram Mini App (initData) |
| **Telegram Login Widget** | Кнопка "Войти через Telegram" на веб-странице          |
| **Email + пароль**        | Классическая регистрация с верификацией email          |

Email-авторизация позволяет пользователям входить в Cabinet без Telegram — через браузер.

## Регистрация

### Флоу регистрации

1. Пользователь открывает Cabinet в браузере
2. Переходит на вкладку **Регистрация**
3. Заполняет: имя (опционально), email, пароль, подтверждение пароля
4. Нажимает **Зарегистрироваться**
5. Получает email со ссылкой верификации
6. Переходит по ссылке — аккаунт подтвержден, пользователь авторизован

### Валидация

* **Email**: проверка формата, блокировка одноразовых email-адресов (автоматически обновляемый список доменов)
* **Пароль**: минимум 8 символов, максимум 128
* **Уникальность**: email не должен быть занят другим аккаунтом

### Реферальный код

При регистрации можно указать реферальный код (сохраняется из URL кампании или вводится вручную). Самореферал заблокирован.

### Привязка email к Telegram-аккаунту

Если пользователь уже авторизован через Telegram, он может привязать email+пароль для входа через браузер:

```
POST /cabinet/auth/email/register
```

Требует JWT-токен от Telegram-авторизации.

## Верификация email

После регистрации на email отправляется письмо со ссылкой:

```
{CABINET_URL}/verify-email?token={64-символьный_токен}
```

* Токен: 64 символа hex (`secrets.token_hex(32)`)
* Срок действия: `CABINET_EMAIL_VERIFICATION_EXPIRE_HOURS` (по умолчанию 24 часа)
* После перехода по ссылке: email подтвержден, пользователь получает JWT-токены

### Повторная отправка

Если письмо не пришло, пользователь может запросить повторную отправку. Генерируется новый токен, старый становится недействительным.

### Тестовый email

Для разработки: переменная `TEST_EMAIL` позволяет создавать аккаунт с автоматической верификацией (без реального email).

## Вход

1. Пользователь вводит email и пароль
2. Сервер проверяет пароль (bcrypt, 12 раундов)
3. Проверяет что email верифицирован
4. Проверяет что аккаунт активен
5. Возвращает JWT access + refresh токены

### JWT-токены

| Токен   | Срок                   | Хранение                                           |
| ------- | ---------------------- | -------------------------------------------------- |
| Access  | 15 мин (настраивается) | sessionStorage (сбрасывается при закрытии вкладки) |
| Refresh | 7 дней (настраивается) | localStorage (переживает перезапуск Mini App)      |

Refresh-токен хранится в БД как SHA-256 хеш и может быть отозван.

### Автообновление токенов

* Перед каждым запросом проверяется срок access-токена (с буфером 30 секунд)
* Если истек — автоматический refresh через `POST /cabinet/auth/refresh`
* Если refresh не удался — редирект на страницу входа
* Параллельные запросы ожидают один refresh (без дублирования)

## Сброс пароля

### Запрос сброса

1. Пользователь нажимает **Забыли пароль?**
2. Вводит email
3. Получает письмо со ссылкой (или не получает, если email не найден — **ответ одинаковый** для защиты от перебора)

Ссылка в письме:

```
{CABINET_URL}/reset-password?token={64-символьный_токен}
```

Срок действия настраивается через `CABINET_PASSWORD_RESET_EXPIRE_HOURS`.

### Установка нового пароля

1. Пользователь переходит по ссылке
2. Вводит новый пароль (минимум 8 символов) и подтверждение
3. Пароль обновляется, токен сброса удаляется
4. Редирект на страницу входа

## Смена email

### Для неверифицированного email

Прямая замена: новый email устанавливается сразу, отправляется письмо верификации на новый адрес.

### Для верифицированного email

1. Пользователь запрашивает смену email
2. На **новый** адрес отправляется 6-значный код
3. Срок действия кода: `CABINET_EMAIL_CHANGE_CODE_EXPIRE_MINUTES` (по умолчанию 15 минут)
4. Пользователь вводит код — email обновляется

Доступные действия:

* `POST /cabinet/auth/email/change` — запрос смены
* `POST /cabinet/auth/email/change/verify` — ввод кода
* `POST /cabinet/auth/email/change/cancel` — отмена
* `GET /cabinet/auth/email/change/status` — статус ожидания

## Отправляемые письма

| Тип               | Когда                                           | Содержимое                            |
| ----------------- | ----------------------------------------------- | ------------------------------------- |
| Верификация email | Регистрация, привязка email, повторная отправка | Ссылка на `/verify-email?token=...`   |
| Сброс пароля      | Запрос "Забыли пароль"                          | Ссылка на `/reset-password?token=...` |
| Код смены email   | Запрос смены верифицированного email            | 6-значный код                         |

Все письма поддерживают **5 языков**: русский, английский, китайский, украинский, фарси.

Шаблоны можно переопределить через админ-панель Cabinet (таблица `email_templates` в БД).

## Безопасность

| Мера                         | Описание                                                     |
| ---------------------------- | ------------------------------------------------------------ |
| bcrypt (12 раундов)          | Хеширование паролей                                          |
| Защита от перебора email     | Сброс пароля всегда возвращает одинаковый ответ              |
| Блокировка одноразовых email | Автоматический список (обновляется раз в 24 часа)            |
| CSRF-защита                  | Токен в cookie + заголовок `X-CSRF-Token` для мутаций        |
| Кросс-аккаунт защита         | Сравнение JWT user ID с Telegram initData при каждом запросе |
| Разделение хранения токенов  | Access в sessionStorage, refresh в localStorage              |

## Настройка

### Переменные окружения

| Переменная                                 | По умолчанию | Описание                                     |
| ------------------------------------------ | ------------ | -------------------------------------------- |
| `CABINET_EMAIL_AUTH_ENABLED`               | `true`       | Включить email-регистрацию и вход            |
| `CABINET_EMAIL_VERIFICATION_ENABLED`       | `true`       | Требовать верификацию email                  |
| `CABINET_EMAIL_VERIFICATION_EXPIRE_HOURS`  | `24`         | Срок действия токена верификации             |
| `CABINET_EMAIL_CHANGE_CODE_EXPIRE_MINUTES` | `15`         | Срок действия кода смены email               |
| `CABINET_JWT_SECRET`                       | `BOT_TOKEN`  | Секрет для подписи JWT                       |
| `CABINET_ACCESS_TOKEN_EXPIRE_MINUTES`      | `15`         | Срок access-токена                           |
| `CABINET_REFRESH_TOKEN_EXPIRE_DAYS`        | `7`          | Срок refresh-токена                          |
| `TEST_EMAIL`                               | —            | Тестовый email (авто-верификация)            |
| `TEST_EMAIL_PASSWORD`                      | —            | Пароль тестового аккаунта                    |
| `ADMIN_EMAILS`                             | —            | Email-адреса администраторов (через запятую) |

### Требования

* `CABINET_ENABLED=true`
* Настроенный SMTP для отправки писем (см. [Настройка SMTP](/getting-started/smtp-setup))
* `CABINET_URL` — базовый URL для формирования ссылок в письмах

<Warning>
  Без настроенного SMTP письма верификации и сброса пароля не будут отправляться. Email-регистрация будет работать только с `TEST_EMAIL`.
</Warning>

## Устранение проблем

### Письмо верификации не приходит

1. Проверьте настройку SMTP (см. [Настройка SMTP](/getting-started/smtp-setup))
2. Проверьте спам-папку
3. Убедитесь что `CABINET_EMAIL_VERIFICATION_ENABLED=true`
4. Проверьте логи бота на ошибки отправки email

### "Email already registered"

Email уже используется другим аккаунтом. Если пользователь ранее входил через Telegram и привязывал email — используйте вход по email+паролю или Telegram.

### Токен верификации истек

Срок по умолчанию — 24 часа. Запросите повторную отправку письма верификации.

### Не работает вход после верификации

* Проверьте `CABINET_JWT_SECRET` — должен совпадать между перезапусками
* Убедитесь что `CABINET_URL` совпадает с реальным URL Cabinet
