import type { FastifyReply, FastifyRequest } from 'fastify' import type { UserRow } from '@authportal/db' import type { AppId, MeResponse } from '@authportal/shared' import { APP_IDS } from '@authportal/shared' import { getUserProfile, type UserProfile } from '../lib/user-profile.js' export type AuthUser = { id: string email: string name: string isAdmin: boolean apps: AppId[] permissions: string[] } declare module '@fastify/jwt' { interface FastifyJWT { payload: { sub: string email: string name: string apps: string[] permissions: string[] tenants?: Record bgp_tenant_id?: string is_admin?: boolean iss: string } user: { sub: string email: string name: string apps: string[] permissions: string[] tenants?: Record bgp_tenant_id?: string is_admin?: boolean iss: string } } } declare module 'fastify' { interface FastifyRequest { authUser?: AuthUser } } function asAppIds(apps: string[]): AppId[] { return apps.filter((a): a is AppId => (APP_IDS as readonly string[]).includes(a), ) } export function toMe(user: UserRow, apps: string[], permissions: string[]): MeResponse { return { id: user.id, email: user.email, name: user.name, is_admin: user.isAdmin, apps: asAppIds(apps), permissions, } } export function authUserFromProfile(profile: UserProfile): AuthUser { const { row } = profile return { id: row.id, email: row.email, name: row.name, isAdmin: row.isAdmin, apps: asAppIds(profile.apps), permissions: profile.permissions, } } export async function requireAuth( request: FastifyRequest, reply: FastifyReply, ): Promise { try { await request.jwtVerify() } catch { return reply.status(401).send({ error: { code: 'UNAUTHORIZED', message: 'Требуется авторизация' }, }) } const sub = request.user.sub const profile = getUserProfile(request.server.db, sub) if (!profile || profile.row.disabled) { return reply.status(401).send({ error: { code: 'UNAUTHORIZED', message: 'Пользователь недоступен' }, }) } request.authUser = authUserFromProfile(profile) } export async function requireAdmin( request: FastifyRequest, reply: FastifyReply, ): Promise { await requireAuth(request, reply) if (reply.sent) return if (!request.authUser?.isAdmin) { return reply.status(403).send({ error: { code: 'FORBIDDEN', message: 'Только для администраторов' }, }) } }