Prava a bezpecnost: spravce firmy uz nemuze nastavit priznak spravce platformy ani clenstvi v cizi firme; pozvanky, konektory a automatizace kontroluji sve pravo; cizi firma v query je 404; zivy stream posila udalosti jen firmam, kterych se tykaji; akce nad ticketem maji kontrolu prava za firmu ticketu a strop viditelnosti; tokeny se nelogujou; limit pokusu na prihlaseni, kontakt a pozvanky; bezpecnostni hlavicky; zachyceni chyb v async handlerech; timing-safe porovnani tokenu. Vykon: audit neskenuje celou kolekci pri kazdem zapisu a konecne maze firemni zaznamy; ticket se uklada jednou misto trikrat; zapisy do Postgresu jsou serializovane podle ID; prava se pocitaji jednou na request; widgety nacitaji tickety jednou; strankovani seznamu; worker je pool misto kol; na webu udalost ze streamu neodmontuje stranku, dotazy maji spolecny debounce a cache, ciselniky drzi typovany sklad. Runtime: opakuji se jen chyby oznacene retryable; smycka nenarazi na strop 50 kroku (novy strop 1000 akci); podminka nad datem funguje; vystup MCP nastroje neprepisuje spoustec; sandbox skriptu firmy nejde opustit; MCP session id se drzi mezi volanimi; incident z kroku patri firme; jedno rozhodnuti o rezimu uloziste; snapshot neprepise soubor po chybe cteni. Refaktory: sdilene typy API v src/shared (web nic nekopiruje, osm rozjetych tvaru sjednoceno); spolecny modul net/guard pro volani ven; formularova vrstva ui/form; rozdeleni Connectors a FlowCanvas; jeden helper pro firmu z query, validaci a CRUD udalosti; pomucky ctx.util pro skripty konektoru; i18n verejneho webu vcetne anglictiny. Nova funkce: zalozeni firmy z registru ARES v Nastaveni (IC nebo nazev, dotazeni IC, DIC, sidla a pravni formy, vyber soucasnych statutarnich zastupcu a prokury, ucty spravce firmy s nahradnim e-mailem IC-poradi@placeholder.cz). Dokumentace: zaznam v 99-zmeny.md a aktualizace 15 dalsich dokumentu. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
/**
|
|
* 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.
|
|
*/
|
|
|
|
import type { Membership, PublicUser } from './shared/users.js';
|
|
|
|
/** Clenstvi a verejny tvar uctu jsou sdilene s webem, viz src/shared/users.ts. */
|
|
export type { Membership, PublicUser };
|
|
|
|
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[];
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Prava spocitana jednou za request, viz `middleware/tenant.ts`.
|
|
*
|
|
* Doplnek k `req.user` z `middleware/auth.ts`. Jen typ, zadny kod - proto
|
|
* import typu, ne modulu.
|
|
*/
|
|
declare global {
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
namespace Express {
|
|
interface Request {
|
|
access?: import('./data/access.js').Access;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 ?? [];
|
|
}
|