feat(auth): enhance JWT claims and app switcher configuration
Build and Push Auth Portal Docker Image / build-and-push (push) Successful in 1m44s
Build and Push Auth Portal Docker Image / create-release (push) Skipped

- Added support for optional tenant IDs in JWT claims for user permissions.
- Updated auth routes to include tenant information in the JWT payload.
- Enhanced app switcher configuration to handle tenant IDs without exposing them publicly.
- Improved documentation for EvoBGP tenant ID integration and its usage in JWT.
This commit is contained in:
Denozordec
2026-07-19 01:00:37 +07:00
parent 21d6603b57
commit bb17ad6f4d
5 changed files with 73 additions and 7 deletions
@@ -18,6 +18,8 @@ export const appSwitcherEntrySchema = z.object({
shortcut: z.string().optional(),
enabled: z.boolean(),
sort: z.number().int().optional(),
/** App-scoped tenant (e.g. EvoBGP UUID) — goes into JWT, not public switcher. */
tenantId: z.string().optional(),
})
export const appSwitcherConfigSchema = z.object({
@@ -73,6 +75,7 @@ export function normalizeAppSwitcherConfig(
sort: existing?.sort ?? index,
enabled: existing?.enabled ?? true,
icon: existing?.icon ?? fallback.icon,
tenantId: existing?.tenantId?.trim() || undefined,
}
}).sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0))
@@ -82,6 +85,32 @@ export function normalizeAppSwitcherConfig(
}
}
/** Public GET must not expose tenant IDs. */
export function publicAppSwitcherConfig(
config: AppSwitcherConfig,
): AppSwitcherConfig {
const normalized = normalizeAppSwitcherConfig(config)
return {
menuLabel: normalized.menuLabel,
apps: normalized.apps.map(({ tenantId: _tid, ...rest }) => rest),
}
}
/** Map appId → tenantId for JWT (only apps the user may access). */
export function tenantsClaimForUser(
config: AppSwitcherConfig,
userApps: readonly string[],
): Record<string, string> {
const allowed = new Set(userApps)
const out: Record<string, string> = {}
for (const app of normalizeAppSwitcherConfig(config).apps) {
if (!allowed.has(app.id)) continue
const tid = app.tenantId?.trim()
if (tid) out[app.id] = tid
}
return out
}
/** AppMeta list with URLs from switcher store (for /apps + catalog). */
export function appsMetaFromSwitcher(config: AppSwitcherConfig): AppMeta[] {
const normalized = normalizeAppSwitcherConfig(config)