CognxSafeTrack
feat: agentic platform β text-to-sql, pedagogy advisor, security hardening & performance
5b8761d | import { FastifyRequest, FastifyReply } from 'fastify'; | |
| import { prisma } from '../services/prisma'; | |
| import { decryptSecrets } from '../services/organization'; | |
| export async function injectTenantConfig(request: FastifyRequest, reply: FastifyReply) { | |
| const organizationId = request.organizationId; | |
| if (!organizationId) { | |
| return; // Some routes might not require it, guarded routes will check this later if needed | |
| } | |
| try { | |
| const organization = await prisma.organization.findUnique({ | |
| where: { id: organizationId }, | |
| include: { phoneNumbers: true } | |
| }); | |
| if (!organization) { | |
| return reply.code(404).send({ error: 'Organization not found' }); | |
| } | |
| // Reject requests from hard-stopped (suspended) organizations | |
| if (organization.isHardStopped) { | |
| // Super-admin API key calls always pass (needed for management) | |
| const isInternalCall = request.headers['x-api-key'] === process.env.ADMIN_API_KEY; | |
| if (!isInternalCall) { | |
| return reply.code(402).send({ error: 'Service suspended β payment required', code: 'ORG_SUSPENDED' }); | |
| } | |
| } | |
| // Attach decrypted config to request | |
| request.tenantConfig = decryptSecrets(organization); | |
| } catch (err) { | |
| request.log.error({ err, organizationId }, '[TENANT_MIDDLEWARE] Failed to resolve tenant config'); | |
| return reply.code(500).send({ error: 'Internal server error resolving organization' }); | |
| } | |
| } | |