diff --git a/server/routers/resource/deleteResource.ts b/server/routers/resource/deleteResource.ts index 8759e61..d41440f 100644 --- a/server/routers/resource/deleteResource.ts +++ b/server/routers/resource/deleteResource.ts @@ -1,13 +1,15 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources } from "@server/db/schema"; +import { newts, resources, sites, targets } from "@server/db/schema"; import { eq } from "drizzle-orm"; import response from "@server/utils/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; +import { addPeer } from "../gerbil/peers"; +import { removeTargets } from "../newt/targets"; // Define Zod schema for request parameters validation const deleteResourceSchema = z.object({ @@ -32,12 +34,17 @@ export async function deleteResource( const { resourceId } = parsedParams.data; - const deletedResource = await db + const targetsToBeRemoved = await db + .select() + .from(targets) + .where(eq(targets.resourceId, resourceId)); + + const [deletedResource] = await db .delete(resources) .where(eq(resources.resourceId, resourceId)) .returning(); - if (deletedResource.length === 0) { + if (!deletedResource) { return next( createHttpError( HttpCode.NOT_FOUND, @@ -46,6 +53,55 @@ export async function deleteResource( ); } + const [site] = await db + .select() + .from(sites) + .where(eq(sites.siteId, deletedResource.siteId!)) + .limit(1); + + if (!site) { + return next( + createHttpError( + HttpCode.NOT_FOUND, + `Site with ID ${deletedResource.siteId} not found` + ) + ); + } + + if (site.pubKey) { + if (site.type == "wireguard") { + // TODO: is this all inefficient? + // Fetch resources for this site + const resourcesRes = await db.query.resources.findMany({ + where: eq(resources.siteId, site.siteId), + }); + + // Fetch targets for all resources of this site + const targetIps = await Promise.all( + resourcesRes.map(async (resource) => { + const targetsRes = await db.query.targets.findMany({ + where: eq(targets.resourceId, resource.resourceId), + }); + return targetsRes.map((target) => `${target.ip}/32`); + }) + ); + + await addPeer(site.exitNodeId!, { + publicKey: site.pubKey, + allowedIps: targetIps.flat(), + }); + } else if (site.type == "newt") { + // get the newt on the site by querying the newt table for siteId + const [newt] = await db + .select() + .from(newts) + .where(eq(newts.siteId, site.siteId)) + .limit(1); + + removeTargets(newt.newtId, targetsToBeRemoved); + } + } + return response(res, { data: null, success: true, diff --git a/server/routers/site/createSite.ts b/server/routers/site/createSite.ts index 45be6b2..fec4f78 100644 --- a/server/routers/site/createSite.ts +++ b/server/routers/site/createSite.ts @@ -166,7 +166,6 @@ export async function createSite( status: HttpCode.CREATED, }); } catch (error) { - throw error; return next( createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") ); diff --git a/server/routers/site/deleteSite.ts b/server/routers/site/deleteSite.ts index 2e0770b..4082d8e 100644 --- a/server/routers/site/deleteSite.ts +++ b/server/routers/site/deleteSite.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { sites } from "@server/db/schema"; +import { newts, newtSessions, sites } from "@server/db/schema"; import { eq } from "drizzle-orm"; import response from "@server/utils/response"; import HttpCode from "@server/types/HttpCode"; @@ -9,8 +9,7 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { deletePeer } from "../gerbil/peers"; import { fromError } from "zod-validation-error"; - -const API_BASE_URL = "http://localhost:3000"; +import { sendToClient } from "../ws"; const deleteSiteSchema = z.object({ siteId: z.string().transform(Number).pipe(z.number().int().positive()), @@ -34,12 +33,13 @@ export async function deleteSite( const { siteId } = parsedParams.data; - const [deletedSite] = await db - .delete(sites) + const [site] = await db + .select() + .from(sites) .where(eq(sites.siteId, siteId)) - .returning(); + .limit(1); - if (!deletedSite) { + if (!site) { return next( createHttpError( HttpCode.NOT_FOUND, @@ -48,10 +48,32 @@ export async function deleteSite( ); } - if (deletedSite.pubKey) { - await deletePeer(deletedSite.exitNodeId!, deletedSite.pubKey); + if (site.pubKey) { + if (site.type == "wireguard") { + await deletePeer(site.exitNodeId!, site.pubKey); + } else if (site.type == "newt") { + // get the newt on the site by querying the newt table for siteId + const [deletedNewt] = await db + .delete(newts) + .where(eq(newts.siteId, siteId)) + .returning(); + if (deletedNewt) { + const payload = { + type: `newt/terminate`, + data: {}, + }; + sendToClient(deletedNewt.newtId, payload); + + // delete all of the sessions for the newt + db.delete(newtSessions) + .where(eq(newtSessions.newtId, deletedNewt.newtId)) + .run(); + } + } } + db.delete(sites).where(eq(sites.siteId, siteId)).run(); + return response(res, { data: null, success: true, @@ -66,25 +88,3 @@ export async function deleteSite( ); } } - -async function removePeer(publicKey: string) { - try { - const response = await fetch( - `${API_BASE_URL}/peer?public_key=${encodeURIComponent(publicKey)}`, - { - method: "DELETE", - } - ); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const data = await response.json(); - logger.info("Peer removed successfully:", data.status); - return data; - } catch (error: any) { - console.error("Error removing peer:", error.message); - throw error; - } -}