import { db } from '@sim/db' import { environment } from '@sim/db/schema' import { createLogger } from '@sim/logger' import { eq } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log' import { getSession } from '@/lib/auth' import { decryptSecret, encryptSecret } from '@/lib/core/security/encryption' import { generateRequestId } from '@/lib/core/utils/request' import type { EnvironmentVariable } from '@/stores/settings/environment' const logger = createLogger('EnvironmentAPI') const EnvVarSchema = z.object({ variables: z.record(z.string()), }) export async function POST(req: NextRequest) { const requestId = generateRequestId() try { const session = await getSession() if (!session?.user?.id) { logger.warn(`[${requestId}] Unauthorized environment variables update attempt`) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const body = await req.json() try { const { variables } = EnvVarSchema.parse(body) const encryptedVariables = await Promise.all( Object.entries(variables).map(async ([key, value]) => { const { encrypted } = await encryptSecret(value) return [key, encrypted] as const }) ).then((entries) => Object.fromEntries(entries)) await db .insert(environment) .values({ id: crypto.randomUUID(), userId: session.user.id, variables: encryptedVariables, updatedAt: new Date(), }) .onConflictDoUpdate({ target: [environment.userId], set: { variables: encryptedVariables, updatedAt: new Date(), }, }) recordAudit({ actorId: session.user.id, actorName: session.user.name, actorEmail: session.user.email, action: AuditAction.ENVIRONMENT_UPDATED, resourceType: AuditResourceType.ENVIRONMENT, description: 'Updated global environment variables', metadata: { variableCount: Object.keys(variables).length }, request: req, }) return NextResponse.json({ success: true }) } catch (validationError) { if (validationError instanceof z.ZodError) { logger.warn(`[${requestId}] Invalid environment variables data`, { errors: validationError.errors, }) return NextResponse.json( { error: 'Invalid request data', details: validationError.errors }, { status: 400 } ) } throw validationError } } catch (error) { logger.error(`[${requestId}] Error updating environment variables`, error) return NextResponse.json({ error: 'Failed to update environment variables' }, { status: 500 }) } } export async function GET(request: Request) { const requestId = generateRequestId() try { const session = await getSession() if (!session?.user?.id) { logger.warn(`[${requestId}] Unauthorized environment variables access attempt`) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const userId = session.user.id const result = await db .select() .from(environment) .where(eq(environment.userId, userId)) .limit(1) if (!result.length || !result[0].variables) { return NextResponse.json({ data: {} }, { status: 200 }) } const encryptedVariables = result[0].variables as Record const decryptedVariables: Record = {} for (const [key, encryptedValue] of Object.entries(encryptedVariables)) { try { const { decrypted } = await decryptSecret(encryptedValue) decryptedVariables[key] = { key, value: decrypted } } catch (error) { logger.error(`[${requestId}] Error decrypting variable ${key}`, error) decryptedVariables[key] = { key, value: '' } } } return NextResponse.json({ data: decryptedVariables }, { status: 200 }) } catch (error: any) { logger.error(`[${requestId}] Environment fetch error`, error) return NextResponse.json({ error: error.message }, { status: 500 }) } }