diff --git a/diff b/diff deleted file mode 100644 index 9e71f905..00000000 --- a/diff +++ /dev/null @@ -1,194 +0,0 @@ -@@ -216,36 +216,12 @@ export const ClientResourceSchema = z.object({ - // Schema for the entire configuration object - export const ConfigSchema = z - .object({ -- "proxy-resources": z.record(z.string(), ResourceSchema).optional().default({}), -- "client-resources": z.record(z.string(), ClientResourceSchema).optional().default({}), -- sites: z.record(z.string(), SiteSchema).optional().default({}) -+ "proxy-resources": z.record(z.string(), ResourceSchema).optional().prefault({}), -+ "client-resources": z.record(z.string(), ClientResourceSchema).optional().prefault({}), -+ sites: z.record(z.string(), SiteSchema).optional().prefault({}) - }) - .refine( - // Enforce the full-domain uniqueness across resources in the same stack -- (config) => { -- // Extract all full-domain values with their resource keys -- const fullDomainMap = new Map(); -- --- - .optional(), - log_level: z -@@ -31,14 +29,14 @@ export const configSchema = z - anonymous_usage: z.boolean().optional().default(true) - }) - .optional() -- .default({}), -+ .prefault({}), - notifications: z - .object({ - product_updates: z.boolean().optional().default(true), - new_releases: z.boolean().optional().default(true) - }) - .optional() -- .default({}) -+ .prefault({}) - }) - .optional() - .default({ -@@ -107,7 +105,7 @@ export const configSchema = z - token: z.string().optional().default("P-Access-Token") - }) - .optional() -- .default({}), -+ .prefault({}), - resource_session_request_param: z - .string() - .optional() -@@ -132,7 +130,7 @@ export const configSchema = z - credentials: z.boolean().optional() - }) - .optional(), --- - maxmind_db_path: z.string().optional() - }) -@@ -189,7 +187,7 @@ export const configSchema = z - .default(5000) - }) - .optional() -- .default({}) -+ .prefault({}) - }) - .optional(), - traefik: z -@@ -222,7 +220,7 @@ export const configSchema = z - .default("pp-transport-v") - }) - .optional() -- .default({}), -+ .prefault({}), - gerbil: z - .object({ - exit_node_name: z.string().optional(), -@@ -247,7 +245,7 @@ export const configSchema = z - .default(30) - }) - .optional() -- .default({}), -+ .prefault({}), - orgs: z - .object({ - block_size: z.number().positive().gt(0).optional().default(24), -@@ -276,7 +274,7 @@ export const configSchema = z - .default(500) - }) - .optional() -- .default({}), -+ .prefault({}), - auth: z - .object({ - window_minutes: z -@@ -293,10 +291,10 @@ export const configSchema = z - .default(500) - }) - .optional() -- .default({}) -+ .prefault({}) - }) - .optional() -- .default({}), -+ .prefault({}), - email: z - .object({ - smtp_host: z.string().optional(), -@@ -308,7 +306,7 @@ export const configSchema = z - .transform(getEnvOrYaml("EMAIL_SMTP_PASS")), - smtp_secure: z.boolean().optional(), - smtp_tls_reject_unauthorized: z.boolean().optional(), --- - .optional(), - flags: z -@@ -340,7 +338,7 @@ export const configSchema = z - .default("cname.pangolin.net") - }) - .optional() -- .default({}) -+ .prefault({}) - }) - .refine( - (data) => { -@@ -355,7 +353,7 @@ export const configSchema = z - return true; - }, - { --- - ) - .optional() -@@ -79,14 +79,14 @@ export const privateConfigSchema = z.object({ - .default("http://gerbil:3004") - }) - .optional() -- .default({}), -+ .prefault({}), - flags: z - .object({ - enable_redis: z.boolean().optional().default(false), - use_pangolin_dns: z.boolean().optional().default(false) - }) - .optional() -- .default({}), -+ .prefault({}), - branding: z - .object({ - app_name: z.string().optional(), -diff --git a/server/private/routers/auditLogs/queryAccessAuditLog.ts b/server/private/routers/auditLogs/queryAccessAuditLog.ts -index 33383c25..3e0b4601 100644 ---- a/server/private/routers/auditLogs/queryAccessAuditLog.ts -+++ b/server/private/routers/auditLogs/queryAccessAuditLog.ts --- - .refine((val) => !isNaN(Date.parse(val)), { -- message: "timeEnd must be a valid ISO date string" -+ error: "timeEnd must be a valid ISO date string" - }) - .transform((val) => Math.floor(new Date(val).getTime() / 1000)) - .optional() -- .default(new Date().toISOString()), -+ .prefault(new Date().toISOString()), - action: z - .union([z.boolean(), z.string()]) - .transform((val) => (typeof val === "string" ? val === "true" : val)) -@@ -51,7 +51,7 @@ export const queryAccessAuditLogsQuery = z.object({ - .string() - .optional() - .transform(Number) --- - .refine((val) => !isNaN(Date.parse(val)), { -- message: "timeEnd must be a valid ISO date string" -+ error: "timeEnd must be a valid ISO date string" - }) - .transform((val) => Math.floor(new Date(val).getTime() / 1000)) - .optional() -- .default(new Date().toISOString()), -+ .prefault(new Date().toISOString()), - action: z.string().optional(), - actorType: z.string().optional(), - actorId: z.string().optional(), -@@ -50,13 +50,13 @@ export const queryActionAuditLogsQuery = z.object({ - .optional() - .default("1000") - .transform(Number) --- - .refine((val) => !isNaN(Date.parse(val)), { -- message: "timeEnd must be a valid ISO date string" -+ error: "timeEnd must be a valid ISO date string" - }) - .transform((val) => Math.floor(new Date(val).getTime() / 1000)) - .optional() -- .default(new Date().toISOString()), -+ .prefault(new Date().toISOString()), - action: z - .union([z.boolean(), z.string()]) - .transform((val) => (typeof val === "string" ? val === "true" : val)) -@@ -37,13 +37,13 @@ export const queryAccessAuditLogsQuery = z.object({ - .string() - .optional() - .transform(Number) diff --git a/server/lib/blueprints/applyBlueprint.ts b/server/lib/blueprints/applyBlueprint.ts index 8e74186b..7b4f3b22 100644 --- a/server/lib/blueprints/applyBlueprint.ts +++ b/server/lib/blueprints/applyBlueprint.ts @@ -6,7 +6,7 @@ import logger from "@server/logger"; import { sites } from "@server/db"; import { eq, and, isNotNull } from "drizzle-orm"; import { addTargets as addProxyTargets } from "@server/routers/newt/targets"; -import { addTarget as addClientTargets } from "@server/routers/client/targets"; +import { addTargets as addClientTargets } from "@server/routers/client/targets"; import { ClientResourcesResults, updateClientResources @@ -122,19 +122,17 @@ export async function applyBlueprint({ ) .limit(1); - if (site && result.resource.mode === "port" && result.resource.protocol && result.resource.proxyPort && result.resource.destinationPort) { - logger.debug( - `Updating client resource ${result.resource.siteResourceId} on site ${site.sites.siteId}` - ); + logger.debug( + `Updating client resource ${result.resource.siteResourceId} on site ${site.sites.siteId}` + ); - await addClientTargets( - site.newt.newtId, - result.resource.destination, - result.resource.destinationPort, - result.resource.protocol, - result.resource.proxyPort - ); - } + // await addClientTargets( + // site.newt.newtId, + // result.resource.destination, + // result.resource.destinationPort, + // result.resource.protocol, + // result.resource.proxyPort + // ); } blueprintSucceeded = true; diff --git a/server/lib/ip.ts b/server/lib/ip.ts index e8bb1a8a..db8c6667 100644 --- a/server/lib/ip.ts +++ b/server/lib/ip.ts @@ -1,8 +1,10 @@ -import { db, SiteResource } from "@server/db"; +import { clientSites, db, SiteResource, Transaction } from "@server/db"; import { clients, orgs, sites } from "@server/db"; import { and, eq, isNotNull } from "drizzle-orm"; import config from "@server/lib/config"; import z from "zod"; +import { getClientSiteResourceAccess } from "./rebuildSiteClientAssociations"; +import logger from "@server/logger"; interface IPRange { start: bigint; @@ -328,31 +330,47 @@ export function generateRemoteSubnetsStr(allSiteResources: SiteResource[]) { } export type SubnetProxyTarget = { - cidr: string; + sourcePrefix: string; + destPrefix: string; portRange?: { min: number; max: number; }[]; }; -export function generateSubnetProxyTargets( - allSiteResources: SiteResource[] -): SubnetProxyTarget[] { +export async function generateSubnetProxyTargets( + allSiteResources: SiteResource[], + trx: Transaction | typeof db = db +): Promise { let targets: SubnetProxyTarget[] = []; for (const siteResource of allSiteResources) { - if (siteResource.mode == "host") { - // check if this is a valid ip - const ipSchema = z.union([z.ipv4(), z.ipv6()]); - if (ipSchema.safeParse(siteResource.destination).success) { + const { mergedAllClients } = + await getClientSiteResourceAccess(siteResource, trx); + + if (mergedAllClients.length === 0) { + logger.debug(`No clients have access to site resource ${siteResource.siteResourceId}, skipping target generation.`); + continue; + } + + for (const clientSite of mergedAllClients) { + const clientPrefix = `${clientSite.subnet.split("/")[0]}/32`; + + if (siteResource.mode == "host") { + // check if this is a valid ip + const ipSchema = z.union([z.ipv4(), z.ipv6()]); + if (ipSchema.safeParse(siteResource.destination).success) { + targets.push({ + sourcePrefix: clientPrefix, + destPrefix: `${siteResource.destination}/32` + }); + } + } else if (siteResource.mode == "cidr") { targets.push({ - cidr: `${siteResource.destination}/32` + sourcePrefix: clientPrefix, + destPrefix: siteResource.destination }); } - } else if (siteResource.mode == "cidr") { - targets.push({ - cidr: siteResource.destination - }); } } diff --git a/server/lib/rebuildSiteClientAssociations.ts b/server/lib/rebuildSiteClientAssociations.ts index aa1d2dec..6e5c0629 100644 --- a/server/lib/rebuildSiteClientAssociations.ts +++ b/server/lib/rebuildSiteClientAssociations.ts @@ -29,24 +29,21 @@ import { } from "@server/routers/olm/peers"; import { sendToExitNode } from "#dynamic/lib/exitNodes"; import logger from "@server/logger"; -import z from "zod"; import { generateRemoteSubnetsStr } from "@server/lib/ip"; -export async function rebuildSiteClientAssociations( +export async function getClientSiteResourceAccess( siteResource: SiteResource, trx: Transaction | typeof db = db -): Promise { - const siteId = siteResource.siteId; - +) { // get the site const [site] = await trx .select() .from(sites) - .where(eq(sites.siteId, siteId)) + .where(eq(sites.siteId, siteResource.siteId)) .limit(1); if (!site) { - throw new Error(`Site with ID ${siteId} not found`); + throw new Error(`Site with ID ${siteResource.siteId} not found`); } const roleIds = await trx @@ -87,27 +84,6 @@ export async function rebuildSiteClientAssociations( .from(clients) .where(inArray(clients.userId, newAllUserIds)); - const existingClientSites = await trx - .select({ - clientId: clientSites.clientId - }) - .from(clientSites) - .where(eq(clientSites.siteId, siteId)); - - const existingClientSiteIds = existingClientSites.map( - (row) => row.clientId - ); - - // Get full client details for existing clients (needed for sending delete messages) - const existingClients = await trx - .select({ - clientId: clients.clientId, - pubKey: clients.pubKey, - subnet: clients.subnet - }) - .from(clients) - .where(inArray(clients.clientId, existingClientSiteIds)); - const allClientSiteResources = await trx // this is for if a client is directly associated with a resource instead of implicitly via a user .select() .from(clientSiteResources) @@ -134,6 +110,43 @@ export async function rebuildSiteClientAssociations( const mergedAllClients = Array.from(allClientsMap.values()); const mergedAllClientIds = mergedAllClients.map((c) => c.clientId); + return { + site, + mergedAllClients, + mergedAllClientIds + }; +} + +export async function rebuildSiteClientAssociations( + siteResource: SiteResource, + trx: Transaction | typeof db = db +): Promise { + const siteId = siteResource.siteId; + + const { site, mergedAllClients, mergedAllClientIds } = + await getClientSiteResourceAccess(siteResource, trx); + + const existingClientSites = await trx + .select({ + clientId: clientSites.clientId + }) + .from(clientSites) + .where(eq(clientSites.siteId, siteResource.siteId)); + + const existingClientSiteIds = existingClientSites.map( + (row) => row.clientId + ); + + // Get full client details for existing clients (needed for sending delete messages) + const existingClients = await trx + .select({ + clientId: clients.clientId, + pubKey: clients.pubKey, + subnet: clients.subnet + }) + .from(clients) + .where(inArray(clients.clientId, existingClientSiteIds)); + // ------------- calculations begin below ------------- const clientSitesToAdd = mergedAllClientIds.filter( @@ -345,7 +358,8 @@ async function handleMessagesForSiteClients( publicKey: site.publicKey, serverIP: site.address, serverPort: site.listenPort, - remoteSubnets: generateRemoteSubnetsStr(allSiteResources) + remoteSubnets: + generateRemoteSubnetsStr(allSiteResources) }, olm.olmId ) diff --git a/server/routers/client/targets.ts b/server/routers/client/targets.ts index b9ef1f97..f0f70fd3 100644 --- a/server/routers/client/targets.ts +++ b/server/routers/client/targets.ts @@ -1,30 +1,32 @@ import { sendToClient } from "#dynamic/routers/ws"; import { SubnetProxyTarget } from "@server/lib/ip"; -export async function addTarget(newtId: string, target: SubnetProxyTarget) { +export async function addTargets(newtId: string, targets: SubnetProxyTarget[]) { await sendToClient(newtId, { type: `newt/wg/target/add`, - data: target + data: targets }); } -export async function removeTarget(newtId: string, target: SubnetProxyTarget) { +export async function removeTargets( + newtId: string, + targets: SubnetProxyTarget[] +) { await sendToClient(newtId, { type: `newt/wg/target/remove`, - data: target + data: targets }); } -export async function updateTarget( +export async function updateTargets( newtId: string, - oldTarget: SubnetProxyTarget, - newTarget: SubnetProxyTarget + targets: { + oldTargets: SubnetProxyTarget[], + newTargets: SubnetProxyTarget[] + } ) { await sendToClient(newtId, { type: `newt/wg/target/update`, - data: { - oldTarget, - newTarget - } + data: targets }); -} \ No newline at end of file +} diff --git a/server/routers/newt/handleGetConfigMessage.ts b/server/routers/newt/handleGetConfigMessage.ts index 8d8b853d..83a208c5 100644 --- a/server/routers/newt/handleGetConfigMessage.ts +++ b/server/routers/newt/handleGetConfigMessage.ts @@ -15,7 +15,10 @@ import { clients, clientSites, Newt, sites } from "@server/db"; import { eq, and, inArray } from "drizzle-orm"; import { updatePeer } from "../olm/peers"; import { sendToExitNode } from "#dynamic/lib/exitNodes"; -import { generateRemoteSubnetsStr, generateSubnetProxyTargets } from "@server/lib/ip"; +import { + generateRemoteSubnetsStr, + generateSubnetProxyTargets +} from "@server/lib/ip"; const inputSchema = z.object({ publicKey: z.string(), @@ -195,7 +198,8 @@ export const handleGetConfigMessage: MessageHandler = async (context) => { publicKey: site.publicKey, serverIP: site.address, serverPort: site.listenPort, - remoteSubnets: generateRemoteSubnetsStr(allSiteResources) + remoteSubnets: + generateRemoteSubnetsStr(allSiteResources) }); } catch (error) { logger.error( @@ -222,11 +226,13 @@ export const handleGetConfigMessage: MessageHandler = async (context) => { .from(siteResources) .where(eq(siteResources.siteId, siteId)); + const targetsToSend = await generateSubnetProxyTargets(allSiteResources); + // Build the configuration response const configResponse = { ipAddress: site.address, peers: validPeers, - targets: generateSubnetProxyTargets(allSiteResources) + targets: targetsToSend }; logger.debug("Sending config: ", configResponse); diff --git a/server/routers/siteResource/createSiteResource.ts b/server/routers/siteResource/createSiteResource.ts index 463441fb..478615ac 100644 --- a/server/routers/siteResource/createSiteResource.ts +++ b/server/routers/siteResource/createSiteResource.ts @@ -9,7 +9,7 @@ import { eq, and } from "drizzle-orm"; import { fromError } from "zod-validation-error"; import logger from "@server/logger"; import { OpenAPITags, registry } from "@server/openApi"; -import { addTarget } from "../client/targets"; +import { addTargets } from "../client/targets"; import { getUniqueSiteResourceName } from "@server/db/names"; import { rebuildSiteClientAssociations } from "@server/lib/rebuildSiteClientAssociations"; import { generateSubnetProxyTargets } from "@server/lib/ip"; @@ -24,29 +24,29 @@ const createSiteResourceSchema = z name: z.string().min(1).max(255), mode: z.enum(["host", "cidr", "port"]), protocol: z.enum(["tcp", "udp"]).optional(), - proxyPort: z.int().positive().optional(), - destinationPort: z.int().positive().optional(), + // proxyPort: z.int().positive().optional(), + // destinationPort: z.int().positive().optional(), destination: z.string().min(1), enabled: z.boolean().default(true), alias: z.string().optional() }) .strict() - .refine( - (data) => { - if (data.mode === "port") { - return ( - data.protocol !== undefined && - data.proxyPort !== undefined && - data.destinationPort !== undefined - ); - } - return true; - }, - { - message: - "Protocol, proxy port, and destination port are required for port mode" - } - ) + // .refine( + // (data) => { + // if (data.mode === "port") { + // return ( + // data.protocol !== undefined && + // data.proxyPort !== undefined && + // data.destinationPort !== undefined + // ); + // } + // return true; + // }, + // { + // message: + // "Protocol, proxy port, and destination port are required for port mode" + // } + // ) .refine( (data) => { if (data.mode === "host") { @@ -139,8 +139,8 @@ export async function createSiteResource( name, mode, protocol, - proxyPort, - destinationPort, + // proxyPort, + // destinationPort, destination, enabled, alias @@ -157,29 +157,29 @@ export async function createSiteResource( return next(createHttpError(HttpCode.NOT_FOUND, "Site not found")); } - // check if resource with same protocol and proxy port already exists (only for port mode) - if (mode === "port" && protocol && proxyPort) { - const [existingResource] = await db - .select() - .from(siteResources) - .where( - and( - eq(siteResources.siteId, siteId), - eq(siteResources.orgId, orgId), - eq(siteResources.protocol, protocol), - eq(siteResources.proxyPort, proxyPort) - ) - ) - .limit(1); - if (existingResource && existingResource.siteResourceId) { - return next( - createHttpError( - HttpCode.CONFLICT, - "A resource with the same protocol and proxy port already exists" - ) - ); - } - } + // // check if resource with same protocol and proxy port already exists (only for port mode) + // if (mode === "port" && protocol && proxyPort) { + // const [existingResource] = await db + // .select() + // .from(siteResources) + // .where( + // and( + // eq(siteResources.siteId, siteId), + // eq(siteResources.orgId, orgId), + // eq(siteResources.protocol, protocol), + // eq(siteResources.proxyPort, proxyPort) + // ) + // ) + // .limit(1); + // if (existingResource && existingResource.siteResourceId) { + // return next( + // createHttpError( + // HttpCode.CONFLICT, + // "A resource with the same protocol and proxy port already exists" + // ) + // ); + // } + // } const niceId = await getUniqueSiteResourceName(orgId); @@ -195,8 +195,8 @@ export async function createSiteResource( name, mode, protocol: mode === "port" ? protocol : null, - proxyPort: mode === "port" ? proxyPort : null, - destinationPort: mode === "port" ? destinationPort : null, + // proxyPort: mode === "port" ? proxyPort : null, + // destinationPort: mode === "port" ? destinationPort : null, destination, enabled, alias: alias || null @@ -232,9 +232,8 @@ export async function createSiteResource( ); } - const [target] = generateSubnetProxyTargets([newSiteResource]); - - await addTarget(newt.newtId, target); + const targets = await generateSubnetProxyTargets([newSiteResource], trx); + await addTargets(newt.newtId, targets); await rebuildSiteClientAssociations(newSiteResource, trx); // we need to call this because we added to the admin role }); diff --git a/server/routers/siteResource/deleteSiteResource.ts b/server/routers/siteResource/deleteSiteResource.ts index 0f6ec1b6..7d9f53ce 100644 --- a/server/routers/siteResource/deleteSiteResource.ts +++ b/server/routers/siteResource/deleteSiteResource.ts @@ -9,7 +9,7 @@ import { eq, and } from "drizzle-orm"; import { fromError } from "zod-validation-error"; import logger from "@server/logger"; import { OpenAPITags, registry } from "@server/openApi"; -import { removeTarget } from "../client/targets"; +import { removeTargets } from "../client/targets"; import { rebuildSiteClientAssociations } from "@server/lib/rebuildSiteClientAssociations"; import { generateSubnetProxyTargets } from "@server/lib/ip"; @@ -108,8 +108,8 @@ export async function deleteSiteResource( ); } - const [target] = generateSubnetProxyTargets([removedSiteResource]); - await removeTarget(newt.newtId, target); + const targets = await generateSubnetProxyTargets([removedSiteResource], trx); + await removeTargets(newt.newtId, targets); await rebuildSiteClientAssociations(existingSiteResource, trx); }); diff --git a/server/routers/siteResource/updateSiteResource.ts b/server/routers/siteResource/updateSiteResource.ts index b1dc4ddd..754909ef 100644 --- a/server/routers/siteResource/updateSiteResource.ts +++ b/server/routers/siteResource/updateSiteResource.ts @@ -9,7 +9,7 @@ import { eq, and } from "drizzle-orm"; import { fromError } from "zod-validation-error"; import logger from "@server/logger"; import { OpenAPITags, registry } from "@server/openApi"; -import { updateTarget } from "@server/routers/client/targets"; +import { updateTargets } from "@server/routers/client/targets"; import { generateSubnetProxyTargets } from "@server/lib/ip"; const updateSiteResourceParamsSchema = z.strictObject({ @@ -21,10 +21,11 @@ const updateSiteResourceParamsSchema = z.strictObject({ const updateSiteResourceSchema = z .strictObject({ name: z.string().min(1).max(255).optional(), - mode: z.enum(["host", "cidr", "port"]).optional(), + // mode: z.enum(["host", "cidr", "port"]).optional(), + mode: z.enum(["host", "cidr"]).optional(), protocol: z.enum(["tcp", "udp"]).nullish(), - proxyPort: z.int().positive().nullish(), - destinationPort: z.int().positive().nullish(), + // proxyPort: z.int().positive().nullish(), + // destinationPort: z.int().positive().nullish(), destination: z.string().min(1).optional(), enabled: z.boolean().optional(), alias: z.string().nullish() @@ -115,8 +116,8 @@ export async function updateSiteResource( // Determine the final mode and validate port mode requirements const finalMode = updateData.mode || existingSiteResource.mode; const finalProtocol = updateData.protocol !== undefined ? updateData.protocol : existingSiteResource.protocol; - const finalProxyPort = updateData.proxyPort !== undefined ? updateData.proxyPort : existingSiteResource.proxyPort; - const finalDestinationPort = updateData.destinationPort !== undefined ? updateData.destinationPort : existingSiteResource.destinationPort; + // const finalProxyPort = updateData.proxyPort !== undefined ? updateData.proxyPort : existingSiteResource.proxyPort; + // const finalDestinationPort = updateData.destinationPort !== undefined ? updateData.destinationPort : existingSiteResource.destinationPort; // Prepare update data const updateValues: any = {}; @@ -136,25 +137,25 @@ export async function updateSiteResource( } // Handle port mode fields - include in update if explicitly provided (null or value) or if mode changed - const isModeChangingFromPort = - existingSiteResource.mode === "port" && - updateData.mode && - updateData.mode !== "port"; + // const isModeChangingFromPort = + // existingSiteResource.mode === "port" && + // updateData.mode && + // updateData.mode !== "port"; - if (updateData.protocol !== undefined || isModeChangingFromPort) { - updateValues.protocol = finalMode === "port" ? finalProtocol : null; - } - if (updateData.proxyPort !== undefined || isModeChangingFromPort) { - updateValues.proxyPort = - finalMode === "port" ? finalProxyPort : null; - } - if ( - updateData.destinationPort !== undefined || - isModeChangingFromPort - ) { - updateValues.destinationPort = - finalMode === "port" ? finalDestinationPort : null; - } + // if (updateData.protocol !== undefined || isModeChangingFromPort) { + // updateValues.protocol = finalMode === "port" ? finalProtocol : null; + // } + // if (updateData.proxyPort !== undefined || isModeChangingFromPort) { + // updateValues.proxyPort = + // finalMode === "port" ? finalProxyPort : null; + // } + // if ( + // updateData.destinationPort !== undefined || + // isModeChangingFromPort + // ) { + // updateValues.destinationPort = + // finalMode === "port" ? finalDestinationPort : null; + // } // Update the site resource const [updatedSiteResource] = await db @@ -179,10 +180,13 @@ export async function updateSiteResource( return next(createHttpError(HttpCode.NOT_FOUND, "Newt not found")); } - const [oldTarget] = generateSubnetProxyTargets([existingSiteResource]); - const [newTarget] = generateSubnetProxyTargets([updatedSiteResource]); + const oldTargets = await generateSubnetProxyTargets([existingSiteResource]); + const newTargets = await generateSubnetProxyTargets([updatedSiteResource]); - await updateTarget(newt.newtId, oldTarget, newTarget); + await updateTargets(newt.newtId, { + oldTargets: oldTargets, + newTargets: newTargets + }); logger.info( `Updated site resource ${siteResourceId} for site ${siteId}` diff --git a/src/app/[orgId]/settings/clients/create/page.tsx b/src/app/[orgId]/settings/clients/create/page.tsx index dfe08031..67972eb6 100644 --- a/src/app/[orgId]/settings/clients/create/page.tsx +++ b/src/app/[orgId]/settings/clients/create/page.tsx @@ -42,17 +42,14 @@ import { FaFreebsd, FaWindows } from "react-icons/fa"; -import { - SiNixos, - SiKubernetes -} from "react-icons/si"; +import { SiNixos, SiKubernetes } from "react-icons/si"; import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { CreateClientBody, CreateClientResponse, - PickClientDefaultsResponse, + PickClientDefaultsResponse } from "@server/routers/client"; import { ListSitesResponse } from "@server/routers/site"; import { toast } from "@app/hooks/useToast"; @@ -93,18 +90,7 @@ export default function Page() { .min(2, { message: t("nameMin", { len: 2 }) }) .max(30, { message: t("nameMax", { len: 30 }) }), method: z.enum(["olm"]), - siteIds: z - .array( - z.object({ - id: z.string(), - text: z.string() - }) - ) - .refine((val) => val.length > 0, { - message: t("siteRequired") - }), - subnet: z.union([z.ipv4(), z.ipv6()]) - .refine((val) => val.length > 0, { + subnet: z.union([z.ipv4(), z.ipv6()]).refine((val) => val.length > 0, { message: t("subnetRequired") }) }); @@ -123,10 +109,6 @@ export default function Page() { ]); const [loadingPage, setLoadingPage] = useState(true); - const [sites, setSites] = useState([]); - const [activeSitesTagIndex, setActiveSitesTagIndex] = useState< - number | null - >(null); const [platform, setPlatform] = useState("unix"); const [architecture, setArchitecture] = useState("All"); @@ -236,12 +218,11 @@ export default function Page() { } }; - const form = useForm({ + const form = useForm({ resolver: zodResolver(createClientFormSchema), defaultValues: { name: "", method: "olm", - siteIds: [], subnet: "" } }); @@ -330,7 +311,7 @@ export default function Page() { const latestVersion = data.tag_name; olmVersion = latestVersion; } catch (error) { - if (error instanceof Error && error.name === 'AbortError') { + if (error instanceof Error && error.name === "AbortError") { console.error(t("olmErrorFetchTimeout")); } else { console.error( @@ -456,13 +437,17 @@ export default function Page() { - {t("addressDescription")} + {t( + "addressDescription" + )} )} @@ -536,7 +521,9 @@ export default function Page() { {t("clientOlmCredentials")} - {t("clientOlmCredentialsDescription")} + {t( + "clientOlmCredentialsDescription" + )} diff --git a/src/components/CreateInternalResourceDialog.tsx b/src/components/CreateInternalResourceDialog.tsx index 9fc35291..5a700d79 100644 --- a/src/components/CreateInternalResourceDialog.tsx +++ b/src/components/CreateInternalResourceDialog.tsx @@ -86,19 +86,20 @@ export default function CreateInternalResourceDialog({ .string() .min(1, t("createInternalResourceDialogNameRequired")) .max(255, t("createInternalResourceDialogNameMaxLength")), - mode: z.enum(["host", "cidr", "port"]), + // mode: z.enum(["host", "cidr", "port"]), + mode: z.enum(["host", "cidr"]), destination: z.string().min(1), siteId: z.int().positive(t("createInternalResourceDialogPleaseSelectSite")), protocol: z.enum(["tcp", "udp"]), - proxyPort: z.int() - .positive() - .min(1, t("createInternalResourceDialogProxyPortMin")) - .max(65535, t("createInternalResourceDialogProxyPortMax")), - destinationPort: z.int() - .positive() - .min(1, t("createInternalResourceDialogDestinationPortMin")) - .max(65535, t("createInternalResourceDialogDestinationPortMax")) - .nullish(), + // proxyPort: z.int() + // .positive() + // .min(1, t("createInternalResourceDialogProxyPortMin")) + // .max(65535, t("createInternalResourceDialogProxyPortMax")), + // destinationPort: z.int() + // .positive() + // .min(1, t("createInternalResourceDialogDestinationPortMin")) + // .max(65535, t("createInternalResourceDialogDestinationPortMax")) + // .nullish(), alias: z.string().nullish(), roles: z.array( z.object({ @@ -119,42 +120,42 @@ export default function CreateInternalResourceDialog({ }) ).optional() }) - .refine( - (data) => { - if (data.mode === "port") { - return data.protocol !== undefined && data.protocol !== null; - } - return true; - }, - { - message: t("createInternalResourceDialogProtocol") + " is required for port mode", - path: ["protocol"] - } - ) - .refine( - (data) => { - if (data.mode === "port") { - return data.proxyPort !== undefined && data.proxyPort !== null; - } - return true; - }, - { - message: t("createInternalResourceDialogSitePort") + " is required for port mode", - path: ["proxyPort"] - } - ) - .refine( - (data) => { - if (data.mode === "port") { - return data.destinationPort !== undefined && data.destinationPort !== null; - } - return true; - }, - { - message: t("targetPort") + " is required for port mode", - path: ["destinationPort"] - } - ); + // .refine( + // (data) => { + // if (data.mode === "port") { + // return data.protocol !== undefined && data.protocol !== null; + // } + // return true; + // }, + // { + // error: t("createInternalResourceDialogProtocol") + " is required for port mode", + // path: ["protocol"] + // } + // ) + // .refine( + // (data) => { + // if (data.mode === "port") { + // return data.proxyPort !== undefined && data.proxyPort !== null; + // } + // return true; + // }, + // { + // error: t("createInternalResourceDialogSitePort") + " is required for port mode", + // path: ["proxyPort"] + // } + // ) + // .refine( + // (data) => { + // if (data.mode === "port") { + // return data.destinationPort !== undefined && data.destinationPort !== null; + // } + // return true; + // }, + // { + // error: t("targetPort") + " is required for port mode", + // path: ["destinationPort"] + // } + // ); type FormData = z.infer; @@ -177,9 +178,9 @@ export default function CreateInternalResourceDialog({ siteId: availableSites[0]?.siteId || 0, mode: "host", protocol: "tcp", - proxyPort: undefined, + // proxyPort: undefined, destination: "", - destinationPort: undefined, + // destinationPort: undefined, alias: "", roles: [], users: [], @@ -196,9 +197,9 @@ export default function CreateInternalResourceDialog({ siteId: availableSites[0].siteId, mode: "host", protocol: "tcp", - proxyPort: undefined, + // proxyPort: undefined, destination: "", - destinationPort: undefined, + // destinationPort: undefined, alias: "", roles: [], users: [], @@ -260,8 +261,8 @@ export default function CreateInternalResourceDialog({ name: data.name, mode: data.mode, protocol: data.mode === "port" ? data.protocol : undefined, - proxyPort: data.mode === "port" ? data.proxyPort : undefined, - destinationPort: data.mode === "port" ? data.destinationPort : undefined, + // proxyPort: data.mode === "port" ? data.proxyPort : undefined, + // destinationPort: data.mode === "port" ? data.destinationPort : undefined, destination: data.destination, enabled: true, alias: data.alias && typeof data.alias === "string" && data.alias.trim() ? data.alias : undefined @@ -452,7 +453,7 @@ export default function CreateInternalResourceDialog({ )} /> - +{/* {mode === "port" && ( <>
@@ -510,7 +511,7 @@ export default function CreateInternalResourceDialog({ />
- )} + )} */} @@ -541,7 +542,7 @@ export default function CreateInternalResourceDialog({ )} /> - {mode === "port" && ( + {/* {mode === "port" && ( )} /> - )} + )} */}