Skip to content

Architektura

Přehled systému

Atrea User API je centralizovaný backend pro správu uživatelů. Žádná z aplikací v ekosystému si nespravuje oprávnění sama — vše jde přes tento servis.

┌──────────────────────────────────────────────────────────────────┐
│                        Klientské aplikace                        │
│         (web frontendy, mobilní apps, admin panely)              │
└──────────┬───────────────────────────────────────────────────────┘
           │  JWT Bearer token (Zitadel / Microsoft / Google)

┌──────────────────────────────────────────────────────────────────┐
│                       Atrea User API :3001                       │
│                                                                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │ /api/check  │  │ /api/users  │  │    /api/profile/me      │  │
│  │ /api/check  │  │ /api/roles  │  │    /api/profile/me/...  │  │
│  │    /bulk    │  │ /api/perms  │  │                         │  │
│  └──────┬──────┘  └──────┬──────┘  └────────────┬────────────┘  │
│         │                │                       │               │
│  ┌──────▼────────────────▼───────────────────────▼────────────┐  │
│  │                    Services vrstva                          │  │
│  │  CheckService · UserService · ProfileService · ...         │  │
│  └──────────────────────────┬──────────────────────────────────┘ │
│                             │                                    │
│  ┌──────────────────────────▼──────────────────────────────────┐ │
│  │                TypeORM (PostgreSQL 16)                       │ │
│  └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘

           │  Service-to-service (x-internal-api-key)

┌──────────────────────────────────────────────────────────────────┐
│                    Backend aplikace Atrea                        │
│   (volají /check, /internal/notifications bez JWT tokenu)        │
└──────────────────────────────────────────────────────────────────┘

Tech Stack

Backend

VrstvaTechnologieVerze
RuntimeNode.js Alpine20
JazykTypeScript5.7
HTTP FrameworkExpress4.21
ORMTypeORM0.3
DatabázePostgreSQL16
Konfiguraceconfig (YAML)3.3
LogováníWinston3.17

Autentizace & Bezpečnost

KomponentaTechnologie
JWT verifikacejsonwebtoken + jwk-to-pem
OIDC providerZitadel (self-hosted)
Multi-providerMicrosoft OAuth, Google OAuth, Amotion
Service-to-servicex-internal-api-key header

Výkon

KomponentaTechnologieDetail
Permission cachelru-cacheTTL 30 s, max 5 000 záznamů
HTTP loggingmorganJSON structured
Validationexpress-validatorRequest validace

Notifikace

KomponentaTechnologie
Emailnodemailer + DKIM
Web Pushweb-push (VAPID)
Template engineMustache-style (custom)

Request Flow

Chráněný endpoint (JWT)

Klient → POST /api/users/:email

           ├─ authorizationMiddleware()
           │    ├─ Načtení JWKS klíčů (cache)
           │    ├─ Verifikace JWT podpisu
           │    ├─ Extrakce emailu z claims
           │    └─ req.token = { email, orgId, ... }

           ├─ loadSuperAdminFlag()
           │    └─ SELECT FROM super_admins WHERE email = ?
           │       req.isSuperAdmin = true/false

           ├─ requireAppAdmin() nebo requireSuperAdmin()
           │    └─ 403 pokud podmínka nesplněna

           └─ Route handler → Service → TypeORM → PostgreSQL

                                          ← Response JSON

Permission check (bez JWT)

Backend app → POST /api/check

               ├─ (volitelně: x-internal-api-key validation)

               └─ CheckService.check(email, app, permission)

                    ├─ Zkontroluj LRU cache (TTL 30 s)
                    │    └─ HIT → vrátit { allowed }

                    ├─ MISS → databázový dotaz:
                    │    ├─ Je uživatel aktivní?          (user.active)
                    │    ├─ Je superadmin?                (super_admins)
                    │    ├─ Resource-level override?      (user_resource_permissions)
                    │    └─ Role permissions?             (user_app_roles → role_permissions)

                    └─ Cache výsledek → vrátit { allowed }

Databázová vrstva

TypeORM je nakonfigurován na synchronize: false v produkci. Schema je definováno v sql/init.sql a entity v src/entities/. Viz Databázové schema pro kompletní přehled.

Adresářová struktura

src/
├── index.ts                # Bootstrap: DB, JWT, Express, Swagger
├── middleware/
│   ├── authorization.ts    # JWT middleware stack
│   ├── JWTService.ts       # Multi-provider JWKS manager
│   └── internalAuth.ts     # x-internal-api-key validace
├── routes/
│   ├── router.ts           # Hlavní agregátor routerů
│   ├── checkRouter.ts      # /check — bez JWT
│   ├── userRouter.ts       # /users — CRUD + role assignment
│   ├── profileRouter.ts    # /profile — profil, preference, push
│   ├── applicationRouter.ts # /applications — superadmin only
│   ├── permissionRouter.ts  # /applications/:code/permissions
│   ├── roleRouter.ts        # /applications/:code/roles
│   ├── notificationRouter.ts # /internal/notifications
│   ├── adminNotificationRouter.ts # /admin/notifications
│   ├── adminBrandRouter.ts  # /admin/brands
│   ├── adminDashboardRouter.ts # /admin/dashboard
│   └── zitadelRouter.ts     # /zitadel — webhooks, OIDC, org mgmt
├── services/               # Business logika (18 servisů)
├── entities/               # TypeORM entity (17 tabulek)
└── utils/
    ├── ApiResponse.ts      # Standardizovaný response wrapper
    ├── ApiException.ts     # Custom exception s HTTP kódem
    ├── ApiExceptionCode.ts # Enum error kódů
    ├── data-source.ts      # TypeORM DataSource
    ├── serverConfig.ts     # Typovaná konfigurace
    └── logger.ts           # Winston logger

Klíčové architektonické vzory

1. Email jako primární identifikátor

Email je PK tabulky users a cizí klíč ve všech relacích. Eliminuje nutnost UUID mapping mezi JWT claims a DB.

2. Lazy vytváření entit

UserProfile, UserAppPreference a User záznamy se vytvářejí až při prvním přístupu (upsert pattern). Admin nemusí předem zakládat uživatele.

3. Tříúrovňová admin hierarchie

SuperAdmin (global)
    └── AppAdmin (per-app)
            └── User (jen co role + overrides povolí)

4. Resource-level overrides

Pro granulární kontrolu (sdílení konkrétního projektu) bez nutnosti vytvářet novou roli:

user_resource_permissions (email, app, resourceType, resourceId, permission, granted)

5. Stateless API s cacheovanými oprávněními

API je stateless — žádný session state. LRU cache v paměti zkracuje latenci permission checků na minimum. Cache se automaticky expiruje po 30 s.

6. Multi-provider JWKS

JWKS klíče se načítají ze všech providerů při startu a refreshují každých 60 minut. Verifikace probíhá vyzkoušením všech providerů, dokud jeden neuspěje.

Atrea User API — interní dokumentace