diff --git a/server/routers/target/createTarget.ts b/server/routers/target/createTarget.ts index cbbd5a23..41df7fd6 100644 --- a/server/routers/target/createTarget.ts +++ b/server/routers/target/createTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, sites, Target, targets } from "@server/db/schema"; +import { newts, resources, sites, Target, targets } from "@server/db/schema"; import response from "@server/utils/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; @@ -75,9 +75,6 @@ export async function createTarget( ); } - // TODO: is this all inefficient? - - // get the site const [site] = await db .select() .from(sites) @@ -103,40 +100,74 @@ export async function createTarget( ); } + // Fetch resources for this site + const resourcesRes = await db.query.resources.findMany({ + where: eq(resources.siteId, site.siteId), + }); + + // TODO: is this all inefficient? + // Fetch targets for all resources of this site + let targetIps: string[] = []; + let targetInternalPorts: number[] = []; + await Promise.all( + resourcesRes.map(async (resource) => { + const targetsRes = await db.query.targets.findMany({ + where: eq(targets.resourceId, resource.resourceId), + }); + targetsRes.forEach((target) => { + targetIps.push(`${target.ip}/32`); + if (target.internalPort) { + targetInternalPorts.push(target.internalPort); + } + }); + }) + ); + + let internalPort!: number; + // pick a port + for (let i = 40000; i < 65535; i++) { + if (!targetInternalPorts.includes(i)) { + internalPort = i; + break; + } + } + + if (!internalPort) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + `No available internal port` + ) + ); + } + const newTarget = await db .insert(targets) .values({ resourceId, protocol: "tcp", // hard code for now + internalPort, ...targetData, }) .returning(); if (site.pubKey) { - if ( site.type == "wireguard") { - // Fetch resources for this site - const resourcesRes = await db.query.resources.findMany({ - where: eq(resources.siteId, site.siteId), - }); + if (site.type == "wireguard") { + 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); - // 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") { - addTargets("",newTarget); // TODO: we need to generate and save the internal port somewhere and also come up with the newtId + addTargets(newt.newtId, newTarget); + } } - } return response(res, { data: newTarget[0], diff --git a/server/routers/target/deleteTarget.ts b/server/routers/target/deleteTarget.ts index efe69181..eb89bfa6 100644 --- a/server/routers/target/deleteTarget.ts +++ b/server/routers/target/deleteTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, sites, targets } 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"; @@ -63,9 +63,6 @@ export async function deleteTarget( ); } - // TODO: is this all inefficient? - - // get the site const [site] = await db .select() .from(sites) @@ -83,6 +80,7 @@ export async function deleteTarget( 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), @@ -103,7 +101,14 @@ export async function deleteTarget( allowedIps: targetIps.flat(), }); } else if (site.type == "newt") { - removeTargets("", [deletedTarget]); // TODO: we need to generate and save the internal port somewhere and also come up with the newtId + // 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, [deletedTarget]); } } diff --git a/server/routers/target/updateTarget.ts b/server/routers/target/updateTarget.ts index 7adf4c7a..b1b453cf 100644 --- a/server/routers/target/updateTarget.ts +++ b/server/routers/target/updateTarget.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; import { db } from "@server/db"; -import { resources, sites, targets } 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"; @@ -9,6 +9,7 @@ import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { addPeer } from "../gerbil/peers"; +import { addTargets } from "../newt/targets"; const updateTargetParamsSchema = z.object({ targetId: z.string().transform(Number).pipe(z.number().int().positive()), @@ -54,7 +55,7 @@ export async function updateTarget( const { targetId } = parsedParams.data; const updateData = parsedBody.data; - + const [updatedTarget] = await db .update(targets) .set(updateData) @@ -70,63 +71,70 @@ export async function updateTarget( ); } - // get the resource - const [resource] = await db - .select({ - siteId: resources.siteId, - }) - .from(resources) - .where(eq(resources.resourceId, updatedTarget.resourceId!)); - - if (!resource) { - return next( - createHttpError( - HttpCode.NOT_FOUND, - `Resource with ID ${updatedTarget.resourceId} not found` - ) - ); - } - - // TODO: is this all inefficient? - - // get the site - const [site] = await db - .select() - .from(sites) - .where(eq(sites.siteId, resource.siteId!)) - .limit(1); - - if (!site) { - return next( - createHttpError( - HttpCode.NOT_FOUND, - `Site with ID ${resource.siteId} not found` - ) - ); - } + // get the resource + const [resource] = await db + .select({ + siteId: resources.siteId, + }) + .from(resources) + .where(eq(resources.resourceId, updatedTarget.resourceId!)); - if (site.pubKey && site.type == "wireguard") { - // 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`); - }) + if (!resource) { + return next( + createHttpError( + HttpCode.NOT_FOUND, + `Resource with ID ${updatedTarget.resourceId} not found` + ) ); - - await addPeer(site.exitNodeId!, { - publicKey: site.pubKey, - allowedIps: targetIps.flat(), - }); } + const [site] = await db + .select() + .from(sites) + .where(eq(sites.siteId, resource.siteId!)) + .limit(1); + + if (!site) { + return next( + createHttpError( + HttpCode.NOT_FOUND, + `Site with ID ${resource.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); + + addTargets(newt.newtId, [updatedTarget]); + } + } return response(res, { data: updatedTarget, success: true,