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

Registration

Регистрация пользователей: OTP, жизненный цикл временного аккаунта, cleanup jobs.

OTP

Параметр Default Env-переменная
Длина кода 6 цифр (Random.secure().nextInt(999999).padLeft(6, '0'))
TTL кода 10 минут REGISTRATION_OTP_TTL_MINUTES
Максимум попыток ввода 5 REGISTRATION_OTP_MAX_ATTEMPTS
Rate limit 3 запроса за 10 минут REGISTRATION_OTP_RATE_LIMIT_PER_10MIN

OTP и счётчики попыток хранятся в Redis: - otp:{email} — код (TTL = otpTtlMinutes) - otp:attempts:{email} — счётчик неверных попыток (TTL 10 мин) - otp:ratelimit:{email} — счётчик запросов кодов (TTL 10 мин)

При превышении otpMaxAttempts неверных попыток — ключ otp:{email} удаляется, следующий код нужно запросить заново.

Создание пользователя

sequenceDiagram
  App->>AC: register(email)
  AC->>AC: createOrFindPendingUser(email)
  Note over AC: status=registration_in_progress\nregistrationExpiresAt = now + 7 дней\naccount_type=consumer
  AC->>SMTP: OTP код (HTML email)
  App->>AC: verifyOtp(email, code)
  AC->>AC: validateOTP() — Redis проверка
  App->>AC: finishRegistration(registrationToken, password)
  AC->>AC: linkAuthUser(email, authUserId)
  Note over AC: status → kyc_pending\nauthUserId установлен\nlastActivityAt обновлён
  App->>App: перейти к KYC

createOrFindPendingUser идемпотентен: если пользователь уже существует в статусе registration_in_progress, обновляет registrationExpiresAt.

Admin-created аккаунты (merchant, agent) создаются с status=active и пропускают kyc_pending: linkAuthUser сохраняет текущий статус, не переводит в kyc_pending.

Cleanup FutureCalls

Все jobs самоперепланируются после каждого выполнения.

Job Первый запуск Расписание Действие
DeleteIncompleteRegistrationsFutureCall через 1 минуту после старта каждые 6 часов DELETE пользователей без user_profile, старше REGISTRATION_INCOMPLETE_TTL_HOURS (default 24 ч), в статусах registration_in_progress / registration_expired
ArchiveExpiredRegistrationsFutureCall следующий день 02:00 UTC ежедневно 02:00 UTC UPDATE users SET isArchived=true, status=registration_expired где registrationExpiresAt < now
SendRegistrationRemindersFutureCall следующий день 09:00 UTC ежедневно 09:00 UTC Выборка пользователей, у которых registrationExpiresAt <= now + reminderDays; отправка email [PLAN] (TODO Phase 3)
HardDeleteArchivedUsersFutureCall через 7 дней после старта каждые 7 дней HARD DELETE через UserDeletionService.deleteWithDependencies() для isArchived=true и archivedAt < now - hardDeleteDays

Удаление (DeleteIncomplete, HardDelete) выполняется через UserDeletionService.deleteWithDependencies() — каскадное удаление всех связанных данных.

Env-переменные

Переменная Default Описание
REGISTRATION_OTP_TTL_MINUTES 10 Время жизни OTP в Redis (минуты)
REGISTRATION_OTP_MAX_ATTEMPTS 5 Максимум неверных вводов до инвалидации кода
REGISTRATION_OTP_RATE_LIMIT_PER_10MIN 3 Максимум запросов нового кода за 10 минут
REGISTRATION_TEMP_USER_TTL_DAYS 7 TTL временного аккаунта registration_in_progress
REGISTRATION_HARD_DELETE_ARCHIVED_AFTER_DAYS 30 Через сколько дней после архивации выполнять hard delete
REGISTRATION_REMINDER_DAYS_BEFORE_EXPIRY 2 За сколько дней до истечения регистрации слать напоминание
REGISTRATION_INCOMPLETE_TTL_HOURS 24 TTL для DeleteIncompleteRegistrations: удалять пользователей без профиля старше N часов