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 { parseSubscriptionStatusDetailsFromInfo, pleskCliCall, suspendPleskSubscription, unsuspendPleskSubscription, } from "@/lib/plesk/client"; import { createSupabaseRouteClient } from "@/lib/supabase/route"; const actionSchema = z.object({ action: z.enum(["suspend", "unsuspend"]), }); export async function POST( req: Request, { params }: { params: { id: string } }, ) { let requestedAction: "suspend" | "unsuspend" | null = null; const supabase = createSupabaseRouteClient() as any; let context: Awaited> | null = null; let subscription: { id: string; plesk_subscription_id: string; plesk_instance_id: string; } | null = null; try { assertSameOrigin(req); context = await getRouteAgencyContextOrThrow(); assertAgencyAdmin(context); assertRateLimit(`plesk-subscription-action:${context.userId}`, 20, 60_000); const payload = actionSchema.parse(await req.json()); requestedAction = payload.action; const { data, error } = await supabase .from("plesk_subscriptions") .select("id, plesk_subscription_id, plesk_instance_id") .eq("id", params.id) .eq("agency_id", context.agencyId) .single(); subscription = data; if (error || !subscription) { throw new Error("Subscription not found"); } const { data: instance, error: instanceError } = await supabase .from("plesk_instances") .select("id, base_url, auth_type, encrypted_secret") .eq("id", subscription.plesk_instance_id) .eq("agency_id", context.agencyId) .single(); if (instanceError || !instance) { throw new Error("Plesk instance not found"); } const connection = { baseUrl: instance.base_url, authType: instance.auth_type, encryptedSecret: instance.encrypted_secret, } as const; if (payload.action === "suspend") { await suspendPleskSubscription( connection, subscription.plesk_subscription_id, ); } else { await unsuspendPleskSubscription( connection, subscription.plesk_subscription_id, ); } const fallbackStatus = payload.action === "suspend" ? "suspended" : "active"; let refreshedStatus = fallbackStatus; let refreshedStatusRaw: string | null = null; let refreshErrorMessage: string | null = null; try { const infoResult = await pleskCliCall(connection, "subscription", [ "--info", subscription.plesk_subscription_id, ]); const parsed = parseSubscriptionStatusDetailsFromInfo( infoResult.stdout ?? "", ); refreshedStatus = parsed.status; refreshedStatusRaw = parsed.statusRaw; } catch (refreshError) { refreshErrorMessage = refreshError instanceof Error ? refreshError.message.slice(0, 1000) : "subscription_status_refresh_failed"; await supabase.from("actions_log").insert({ agency_id: context.agencyId, actor_user_id: context.userId, target_type: "plesk_subscription", target_id: subscription.id, action: "subscription_status_refresh_failed", status: "failed", error_message: refreshErrorMessage, metadata: { subscription_id: subscription.id, plesk_subscription_id: subscription.plesk_subscription_id, plesk_instance_id: subscription.plesk_instance_id, }, }); } const { error: updateError } = await supabase .from("plesk_subscriptions") .update({ status: refreshedStatus, status_raw: refreshedStatusRaw, last_status_sync_at: new Date().toISOString(), }) .eq("id", subscription.id); await supabase .from("plesk_domains") .update({ status: refreshedStatus }) .eq("agency_id", context.agencyId) .eq("subscription_id", subscription.id); await supabase.from("actions_log").insert({ agency_id: context.agencyId, actor_user_id: context.userId, target_type: "plesk_subscription", target_id: subscription.id, action: payload.action, status: "success", metadata: { plesk_subscription_id: subscription.plesk_subscription_id, refreshed_status: refreshedStatus, refresh_error: refreshErrorMessage, db_status_update_error: updateError?.message ?? null, }, }); return NextResponse.json({ ok: true, status: refreshedStatus, dbStatusUpdated: !updateError, refreshError: refreshErrorMessage, }); } catch (error) { if (supabase && context && subscription) { const message = error instanceof Error ? error.message : "Subscription action failed"; await supabase.from("actions_log").insert({ agency_id: context.agencyId, actor_user_id: context.userId, target_type: "plesk_subscription", target_id: subscription.id, action: requestedAction ?? "subscription_action", status: "failed", error_message: message, metadata: { plesk_subscription_id: subscription.plesk_subscription_id, }, }); } return NextResponse.json( { error: error instanceof Error ? error.message : "Subscription action failed", }, { status: 400 }, ); } }