import { NextResponse } from "next/server"; import { z } from "zod"; import { assertAgencyAdmin, getRouteAgencyContextOrThrow } from "@/lib/agency"; import { assertRateLimit } from "@/lib/api/rate-limit"; import { assertSameOrigin } from "@/lib/api/security"; import { encryptPleskSecret } from "@/lib/crypto"; import { testPleskConnection } from "@/lib/plesk/client"; import { createSupabaseRouteClient } from "@/lib/supabase/route"; const createSchema = z.object({ name: z.string().min(2), base_url: z.string().url(), auth_type: z.enum(["api_key", "basic"]), api_key: z.string().min(8).optional(), username: z.string().min(1).optional(), password: z.string().min(1).optional(), }); export async function POST(req: Request) { try { assertSameOrigin(req); const context = await getRouteAgencyContextOrThrow(); assertAgencyAdmin(context); assertRateLimit(`plesk-connect:${context.userId}`, 10, 60_000); const input = createSchema.parse(await req.json()); const payload = input.auth_type === "api_key" ? { ...input, secret: input.api_key, } : { ...input, secret: input.username && input.password ? `${input.username}:${input.password}` : undefined, }; if (!payload.secret) { throw new Error("Missing credentials for selected auth type"); } const supabase = createSupabaseRouteClient() as any; const { encryptedSecret, secretKid } = encryptPleskSecret(payload.secret); try { await testPleskConnection({ baseUrl: payload.base_url, authType: payload.auth_type, encryptedSecret: encryptedSecret, }); } catch (connectError) { const errorMessage = connectError instanceof Error ? connectError.message.slice(0, 1000) : "Connection test failed"; await supabase.from("actions_log").insert({ agency_id: context.agencyId, actor_user_id: context.userId, target_type: "plesk_instance", target_id: null, action: "connect", status: "failed", error_message: errorMessage, metadata: { base_url: payload.base_url, auth_type: payload.auth_type }, }); throw new Error(errorMessage); } const { data: instance, error } = await supabase .from("plesk_instances") .insert({ agency_id: context.agencyId, name: payload.name, base_url: payload.base_url, auth_type: payload.auth_type, encrypted_secret: encryptedSecret, secret_kid: secretKid, status: "connected", error_message: null, last_connected_at: new Date().toISOString(), }) .select( "id, name, base_url, auth_type, status, error_message, last_connected_at", ) .single(); if (error || !instance) { throw new Error(error?.message ?? "Failed to create Plesk instance"); } await supabase.from("actions_log").insert({ agency_id: context.agencyId, actor_user_id: context.userId, target_type: "plesk_instance", target_id: instance.id, action: "connect", status: "success", error_message: null, metadata: { base_url: payload.base_url, auth_type: payload.auth_type }, }); return NextResponse.json({ instance }); } catch (error) { return NextResponse.json( { error: error instanceof Error ? error.message : "Failed to create Plesk instance", }, { status: 400 }, ); } }