Skip to content

User pooly — oddělení uživatelů per aplikace ​

Jabcore Platform slouží jako základ pro SaaS produkty i zakázkové aplikace pro klienty. Uživatel, který se zaregistruje do jedné aplikace, proto nesmí být automaticky uživatelem jiné — u zakázek je správcem osobních údajů klient a my zpracovatel, u SaaS se účel zpracování liší produkt od produktu.

User pool je oddělená množina uživatelských účtů:

  • každá aplikace patří do právě jednoho poolu,
  • nová aplikace dostane vlastní pool — její uživatelé jsou jen její,
  • aplikace, které mají uživatele sjednocené (jedno přihlášení, jeden profil), se dají do stejného poolu — jen tam, kde to výslovně nastavíme,
  • platform pool jabcore drží tým Jabcore a všechny, kdo se přihlašují do administračního panelu.

Účet = pool + e-mail ​

Stejná e-mailová adresa ve dvou poolech jsou dva nezávislé účty: vlastní heslo a MFA, vlastní ověření e-mailu, vlastní profil, role, notifikace i souhlasy. Deaktivace nebo smazání v jednom poolu se druhého netýká.

pool „onlybrain“ (OnlyBrain, OnlyBrain Desktop)   pool „klient-x“ (Navigace areálu)
┌───────────────────────────────┐                 ┌───────────────────────────────┐
│ jan@firma.cz  heslo A, profil │                 │ jan@firma.cz  heslo B, profil │
│ eva@firma.cz                  │                 │ petr@klient.cz                │
└───────────────────────────────┘                 └───────────────────────────────┘
        ↑ jedno SSO pro obě aplikace poolu                ↑ úplně jiný účet

Jak je oddělení vynucené ​

VrstvaCo dělá
ZitadelKaždý pool = jedna organizace. Účty poolu vznikají jen v ní.
Login (jabcore-platform-auth)Z client_id OIDC requestu zjistí pool aplikace (GET /api/zitadel/login-brand). Účty hledá a registruje jen v organizaci poolu, znovu použije jen session z téhož poolu a odmítne dokončit přihlášení účtem z jiné organizace (createCallback). Když API neodpoví, přihlášení neproběhne (fail-closed).
APIPool tokenu = organizace, která vlastní uživatele (sub) — z claimu urn:zitadel:iam:user:resourceowner:id, jinak dotazem do Zitadelu. Token účtu mimo jakýkoli pool nebo vydaný klientovi aplikace z jiného poolu je odmítnut (401).
API — aplikační endpointy/profile/me/check*, preference, notifikace, feedback aj. pro aplikaci X vyžadují, aby účet volajícího patřil do poolu aplikace X (jinak 403). Inbox a /profile/me/apps vrací jen aplikace poolu volajícího.
API — administraceSuperadmin, app admin a práva aplikace auth platí jen pro účty platform poolu. Uživatel aplikace se stejným e-mailem jako administrátor žádná admin práva nemá.
Kontrola oprávněníPOST /api/check (backend → API) kontroluje účet (pool aplikace, email). Superadmin a app admin mají „bypass“ jen v aplikacích platform poolu.

Co to znamená pro aplikaci ​

  • Nic nového v kódu aplikace. Aplikace se dál přihlašuje přes OIDC a volá API s JWT nebo x-internal-api-key s email + app. Pool se odvozuje sám.
  • Role se přiřazují v rámci aplikace (/users/:email/apps/:appCode/roles) — přiřazení platí pro účet s tímto e-mailem v poolu aplikace.
  • Profil sdílí jen aplikace stejného poolu. Jméno nebo jazyk změněný v jedné aplikaci se projeví v ostatních aplikacích poolu, jinde ne.
  • Registrace probíhá v loginu vždy do organizace poolu aplikace.

Správa v administraci ​

Menu User pooly:

  • přehled poolů, jejich aplikací, počtu účtů a propojené Zitadel organizace,
  • Nový pool — založí pool i Zitadel organizaci (potřebuje zitadel.serviceAccountToken); bez něj pool zůstane „nepropojeno“ a do jeho aplikací se nikdo nepřihlásí, dokud organizaci nepropojíte,
  • brand e-mailů — vzhled ověřovacích e-mailů a resetu hesla účtů poolu.

U aplikace (Aplikace → Nová / Upravit):

  • Vlastní pool (výchozí) — oddělení uživatelé,
  • Sdílet s poolem … — sjednocení s jinými aplikacemi.

Přesun existující aplikace do jiného poolu vyžaduje globální právo applications.manage (edit): do aplikace se pak přihlásí jen účty nového poolu a přiřazené role budou platit pro účty se stejným e-mailem v novém poolu.

U uživatelů je v seznamu sloupec User pool a detail účtu se otevírá s ?pool=<code>.

API ​

EndpointPopis
GET /api/admin/user-poolsSeznam poolů s aplikacemi a počtem účtů
POST /api/admin/user-poolsNový pool (code, name, description, brandId) + Zitadel organizace
PUT /api/admin/user-pools/:codeNázev, popis, brand
POST /api/admin/user-pools/:code/zitadel/syncVytvořit organizaci, nebo propojit existující (zitadelOrgId)
DELETE /api/admin/user-pools/:codeSmazat prázdný pool (bez aplikací a účtů)
POST /api/applicationsuserPoolCode — sdílet existující pool; bez něj vlastní pool
PUT /api/applications/:appCodeuserPoolCode — přesun do jiného poolu
GET /api/users?pool=<code>Účty jednoho poolu (bez parametru všechny, s userPoolCode)
GET /api/users/:email?pool=<code>Souhrn účtu; bez pool = platform pool
GET /api/admin/users/:email/detail?pool=<code>Detail účtu

Datový model ​

sql
user_pools (id, code, name, is_platform, brand_id, zitadel_org_id, …)
applications.user_pool_id → user_pools.id
users          PRIMARY KEY (user_pool_id, email)
user_profiles  UNIQUE (user_pool_id, email)
user_application_activity, user_activity_events → users (user_pool_id, email)

Tabulky vázané na aplikaci (user_app_roles, app_admins, user_resource_permissions, notifications, user_app_preferences …) zůstávají klíčované e-mailem + aplikací — aplikace patří do jednoho poolu, takže pool je jednoznačný.

Platform pool ​

Pool jabcore (is_platform = true) vzniká v sql/init.sql. Jeho organizací je platformní organizace (zitadel.projectOrgId / ZITADEL_PROJECT_ORG_ID), kterou API propojí při startu. Patří do něj aplikace auth (administrační panel) a interní aplikace Jabcore, které sdílejí účty týmu.

Jabcore Platform — interní dokumentace