Auth Service — BR 1.4.3

Репо: erp-auth-service (C:\Users\A211\Desktop\erp-auth-service) Контракт: API + Data Model

Зависимости

Требуется готовый User Service (минимум Фаза 6 — internal endpoint /internal/users/{id}/permissions).


Фаза 1 — JWT payload

  • В JwtTokenProvider.generate(user) — добавить claim role_ids (List). Source: поле role_ids из User Service response
  • Parser — десериализовать role_ids из JWT
  • Обновить JwtUser / UserPrincipal — добавить List<UUID> roleIds

Фаза 2 — Redis-кэш user_permissions:{user_id}

  • Клиент Redis — использовать существующий (RedisTemplate или Lettuce)
  • UserPermissionsCache service:
    • getFromCache(userId): Optional<CachedPermissions>
    • loadAndCache(userId): CachedPermissions — вызывает User Service GET /internal/users/{id}/permissions, сохраняет в Redis с TTL 60 сек
    • getOrLoad(userId): CachedPermissions — единая точка входа с cache-aside
  • DTO CachedPermissions { roleIds: List<UUID>, permissions: List<String> } — Jackson-сериализуемый

Фаза 3 — POST /internal/auth/validate — расширение

  • В ValidateController / AuthInternalService.validate(token):
    • После валидации JWT — получить permissions и role_ids через UserPermissionsCache.getOrLoad(userId)
    • Response body дополнить полями role_ids[] и permissions[]
  • Не ломать обратную совместимость — существующие поля (role, franchise_id, store_ids, legal_entity_id) остаются

Фаза 4 — POST /auth/login — расширение

  • В AuthController.login после успешной валидации credentials:
    • Получить role_ids[] + permissions[] из User Service response (полe уже расширено в User Service Фаза 6)
    • Положить в JWT (role_ids) и в Redis-кэш user_permissions
    • Response user дополнить role_ids[] и permissions[]

Фаза 5 — Новый GET /auth/me

  • AuthController.me() — authenticated endpoint (Bearer JWT)
  • Извлечь userId из UserPrincipal
  • Получить user profile через User Service (новый или существующий endpoint GET /internal/users/{id}) — с полями (id, email, first_name, last_name, role, franchise_id, store_ids, legal_entity_id)
  • Получить roles[] (с name, is_system, store_ids) и permissions[] через agregator
  • Response:
    {
      "data": {
        "user": { ... },
        "roles": [ { id, name, is_system, store_ids } ],
        "permissions": [ ... ]
      }
    }

Фаза 6 — User Service Client

  • Расширить UserServiceClient методом getPermissions(userId): CachedPermissions
  • Покрыть retries / timeouts / circuit breaker как у остальных internal-вызовов

Фаза 7 — Тесты

  • Unit: UserPermissionsCache — cache hit/miss/expiry, загрузка из User Service (mock)
  • Integration: /internal/auth/validate с реальным JWT и Redis Testcontainer — проверка кэш-хита на втором вызове
  • Integration: /auth/me — возврат полного профиля для разных ролей

Выходные критерии

  • Все изменения обратно совместимы (существующие JWT без role_ids не ломаются — role_ids = [] или null parsing)
  • Redis TTL 60 сек подтверждён (можно задать через application.yml: auth.permissions-cache.ttl-seconds: 60)
  • Тесты проходят
  • Docker-сборка OK