Files

6.2 KiB

title
title
Авторизация по UID и pcode (Backend)

Сценарий 1.2: Авторизация по UID и pcode

Бизнес-цель

Часть пользователей приходит из медицинской системы (Инфоклиника / MIS): у пациента уже есть числовой идентификатор в сторонней системе. Сайт должен позволить:

  • связать этот UID с учётной записью в API (App\Entity\User::uid);
  • войти по email+паролю, если пользователь уже создан с тем же uid;
  • войти по pcode + дате рождения, если личный кабинет строится на «медицинском» коде без ввода email на первом шаге.

Что такое uid и pcode в коде

Термин в API Где в коде Смысл
uid поле User::$uid, уникальное int Идентификатор пациента/пользователя из внешней системы (в т.ч. MIS).
pcode в POST /user/auth-by-pcode мапится в UserUidAuthDto::$uid Тот же числовой идентификатор, что и uid; название «pcode» — контракт фронта/legacy.

Откуда берутся значения на практике: из МИС/личного кабинета после идентификации пациента (конкретный HTTP-запрос к Инфоклинике в этом приложении для «получить pcode» в сценарии логина не вызывается — клиент передаёт уже известные uid/pcode и дату рождения).

Точки входа

Тип Метод + URL Класс
HTTP POST /user/auth UserController::auth
HTTP POST /user/auth-by-pcode UserController::authByPcode

Пошаговый алгоритм — POST /user/auth

  1. Тело: uid, regionId, email, password, опционально bdateUserAuthDto, валидация.
  2. AuthenticationService::jwtAuth(dto):
    • UserRepository::findOneBy(['uid' => $dto->uid]);
    • если пользователь есть — проверка пароля введённого password через passwordHasher;
    • если пользователя нет — возвращается user: null (флаг пароля не применяется).
  3. Если пароль не совпал при существующем пользователе — 400, как при обычном логине.
  4. Если пользователя не было — RegistrationService::create(dto):
    • setEmail(md5($dto->email)) (в БД снова не хранится открытый email);
    • setUid, setRegionId, роли ROLE_USER, birthDate из bdate (формат Ymd), хэш пароля.
  5. updateLoggedIn, flush, выдача JWT через JWTTokenManagerInterface::create.

Пошаговый алгоритм — POST /user/auth-by-pcode

  1. Тело: pcode (кладётся в UserUidAuthDto::$uid), birthDate или bdate.
  2. Валидация DTO, разбор даты (Ymd или Y-m-d).
  3. UserRepository::findOneByUidAndBirthDate($uid, $birthDate) — сравнение даты по диапазону суток.
  4. Если не найден — RegistrationService::createByUidAndBirthDate:
    • email = md5((string) uid) — синтетический идентификатор для колонки email / JWT username;
    • регион по умолчанию 1 (аргумент сервиса);
    • пароль по умолчанию: hash( md5(uid . birthDateRaw) ) где первая часть — конкатенация строк из DTO перед нормализацией даты в сущности.
  5. updateLoggedIn, flush, JWT в ответе.

Mermaid

flowchart TD
    A[POST /user/auth или /user/auth-by-pcode] --> V{Валидация DTO}
    V -->|ошибка| E400[400 errors]
    V -->|ок| B{Какой маршрут?}
    B -->|auth| C[jwtAuth по uid]
    C --> D{User найден?}
    D -->|да| P[проверка password]
    P -->|fail| E400b[400 неверный пароль]
    P -->|ok| T[JWT + loggedIn]
    D -->|нет| R[RegistrationService.create]
    R --> T

    B -->|auth-by-pcode| F[findOneByUidAndBirthDate]
    F -->|есть| T
    F -->|нет| G[createByUidAndBirthDate]
    G -->|исключение| E500[500]
    G -->|ok| T

Внешние зависимости

Система Участие
PostgreSQL users
Инфоклиника не вызывается напрямую в этих методах; идентификатор приходит от клиента
JWT (Lexik) выдача токена

Обработка ошибок и edge cases

  • Неверный формат даты в auth-by-pcode400 с подсказкой по форматам.
  • Ошибка при создании пользователя500 с текстом исключения (может раскрывать внутренние детали — вопрос hardening).
  • Коллизии uid: на уровне сущности User есть ограничение уникальности uid; при конфликте БД вернёт ошибку при flush (в этом контроллере не разобрана отдельно).

Ссылки на классы

  • apps/backend/src/Controller/UserController.php (auth, authByPcode)
  • apps/backend/src/Service/User/AuthenticationService.php (jwtAuth)
  • apps/backend/src/Service/User/RegistrationService.php (create, createByUidAndBirthDate)
  • apps/backend/src/Dto/UserAuthDto.php, UserUidAuthDto.php
  • apps/backend/src/Repository/UserRepository.php (findOneByUidAndBirthDate)

См. backend-ddd.md (контекст Identity).