/** * Uzivatel muze patrit do vic firem najednou (napr. externista, ktery dela * servicedesk dvema klientum). Proto `memberships`, ne jedno `tenantId`. * * Role je vzdy az uvnitr firmy. Pristup napric firmami je zvlast, jako * `platformAdmin` - to je nase pravo, ne zakaznicke. */ /** * Clenstvi ve firme. * * `roleIds` je seznam, ne jedna role. Duvod: `'admin' | 'agent'` na ucetni, * skladnika a vedouciho nestacilo a pridavat dalsi hodnoty do unionu je slepa * ulicka, kazdy klient chce jine. Role jsou proto zaznamy, viz `data/permissions.ts`. * * Odkaz smi byt ID role, nebo klic systemove role (`admin`, `agent`), aby slo * zapsat oboji a stara data dal fungovala. */ export interface Membership { tenantId: string; roleIds: string[]; /** * Vidi vsechny tickety firmy, ne jen svoje a svych sekci. * * Je to **postaveni uctu ve firme**, ne vlastnost resitele, proto to visi * tady a ne na `Person`: clovek muze byt ve dvou firmach jednou reditel * a jednou brigadnik. * * `undefined` u zaznamu ulozenych driv. Co pak plati, resi `visibilityFor` * v data/access.ts - nemuze to byt tise `false`, jinak by pri nasazeni * kazdemu spravci zmizela vetsina ticketu. */ seesAllTenant?: boolean; } export interface User { id: string; email: string; /** bcrypt hash - nikdy neposilat na klienta */ passwordHash: string; name: string; /** Vidi napric vsemi firmami a muze mezi nimi prepinat. */ platformAdmin: boolean; memberships: Membership[]; } /** Verze uzivatele bezpecna pro odeslani na klienta. */ export interface PublicUser { id: string; email: string; name: string; platformAdmin: boolean; memberships: Membership[]; } export interface JwtPayload { sub: string; email: string; /** * Jen u tokenu impersonace: kdo se za uzivatele vydava. * Bez toho by v auditu zustalo jen "uzivatel to udelal sam". */ act?: string; actEmail?: string; /** Jen u impersonace: smi i zapisovat. */ writes?: boolean; } export function toPublicUser(user: User): PublicUser { const { passwordHash: _passwordHash, ...rest } = user; return rest; } /** Role uzivatele v dane firme. Prazdne pole = do firmy nepatri. */ export function rolesIn(user: User, tenantId: string): string[] { return user.memberships.find((m) => m.tenantId === tenantId)?.roleIds ?? []; }