import type { FastifyInstance } from 'fastify' import { allPermissionKeys, normalizePermissionKeys, tenantsClaimForUser, type LoginResponse, } from '@authportal/shared' import { getAppSwitcherConfig, getUserApps, getUserPermissions, type UserRow, } from '@authportal/db' import { toMe } from '../plugins/auth-guards.js' import { getUserProfile } from './user-profile.js' /** Mint access JWT + Me from current DB state (login / reissue). */ export function issueAccessToken( app: FastifyInstance, user: UserRow, ): LoginResponse { // Профиль из кэша (инвалидируется записями в users/доступ); user — свежая строка вызывающего. const profile = getUserProfile(app.db, user.id) const apps = profile?.apps ?? getUserApps(app.db, user.id) const permissions = user.isAdmin ? allPermissionKeys() : (profile?.permissions ?? normalizePermissionKeys(getUserPermissions(app.db, user.id))) const switcher = getAppSwitcherConfig(app.db) const tenants = tenantsClaimForUser(switcher, apps) const me = toMe(user, apps, permissions) const expiresAt = new Date( Date.now() + app.config.jwtTtlHours * 60 * 60 * 1000, ) const accessToken = app.jwt.sign( { sub: user.id, email: user.email, name: user.name, apps, permissions, tenants, bgp_tenant_id: tenants.bgp, is_admin: user.isAdmin, iss: app.config.issuer, }, { expiresIn: `${app.config.jwtTtlHours}h` }, ) return { access_token: accessToken, expires_at: expiresAt.toISOString(), token_type: 'Bearer', user: me, } }