From 60982bf19fb74905062e441d369d5c4849df9367 Mon Sep 17 00:00:00 2001 From: Fred KISSIE Date: Mon, 23 Mar 2026 22:55:59 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=9A=A7=20edit=20niceid=20in=20private?= =?UTF-8?q?=20resources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../siteResource/updateSiteResource.ts | 78 +++++++++++-------- src/components/EditInternalResourceDialog.tsx | 12 +-- src/components/InternalResourceForm.tsx | 24 +++++- 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/server/routers/siteResource/updateSiteResource.ts b/server/routers/siteResource/updateSiteResource.ts index 596ed9a3f..fcb42a08e 100644 --- a/server/routers/siteResource/updateSiteResource.ts +++ b/server/routers/siteResource/updateSiteResource.ts @@ -1,5 +1,4 @@ -import { Request, Response, NextFunction } from "express"; -import { z } from "zod"; +import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { clientSiteResources, clientSiteResourcesAssociationsCache, @@ -8,19 +7,13 @@ import { orgs, roles, roleSiteResources, + SiteResource, + siteResources, sites, Transaction, userSiteResources } from "@server/db"; -import { siteResources, SiteResource } from "@server/db"; -import response from "@server/lib/response"; -import HttpCode from "@server/types/HttpCode"; -import createHttpError from "http-errors"; -import { eq, and, ne } from "drizzle-orm"; -import { fromError } from "zod-validation-error"; -import logger from "@server/logger"; -import { OpenAPITags, registry } from "@server/openApi"; -import { updatePeerData, updateTargets } from "@server/routers/client/targets"; +import { tierMatrix } from "@server/lib/billing/tierMatrix"; import { generateAliasConfig, generateRemoteSubnets, @@ -28,12 +21,17 @@ import { isIpInCidr, portRangeStringSchema } from "@server/lib/ip"; -import { - getClientSiteResourceAccess, - rebuildClientAssociationsFromSiteResource -} from "@server/lib/rebuildClientAssociations"; -import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; -import { tierMatrix } from "@server/lib/billing/tierMatrix"; +import { rebuildClientAssociationsFromSiteResource } from "@server/lib/rebuildClientAssociations"; +import response from "@server/lib/response"; +import logger from "@server/logger"; +import { OpenAPITags, registry } from "@server/openApi"; +import { updatePeerData, updateTargets } from "@server/routers/client/targets"; +import HttpCode from "@server/types/HttpCode"; +import { and, eq, ne } from "drizzle-orm"; +import { NextFunction, Request, Response } from "express"; +import createHttpError from "http-errors"; +import { z } from "zod"; +import { fromError } from "zod-validation-error"; const updateSiteResourceParamsSchema = z.strictObject({ siteResourceId: z.string().transform(Number).pipe(z.int().positive()) @@ -43,7 +41,15 @@ const updateSiteResourceSchema = z .strictObject({ name: z.string().min(1).max(255).optional(), siteId: z.int(), - // niceId: z.string().min(1).max(255).regex(/^[a-zA-Z0-9-]+$/, "niceId can only contain letters, numbers, and dashes").optional(), + niceId: z + .string() + .min(1) + .max(255) + .regex( + /^[a-zA-Z0-9-]+$/, + "niceId can only contain letters, numbers, and dashes" + ) + .optional(), // mode: z.enum(["host", "cidr", "port"]).optional(), mode: z.enum(["host", "cidr"]).optional(), // protocol: z.enum(["tcp", "udp"]).nullish(), @@ -167,6 +173,7 @@ export async function updateSiteResource( const { name, siteId, // because it can change + niceId, mode, destination, alias, @@ -321,7 +328,8 @@ export async function updateSiteResource( const sshPamSet = isLicensedSshPam && - (authDaemonPort !== undefined || authDaemonMode !== undefined) + (authDaemonPort !== undefined || + authDaemonMode !== undefined) ? { ...(authDaemonPort !== undefined && { authDaemonPort @@ -334,15 +342,16 @@ export async function updateSiteResource( [updatedSiteResource] = await trx .update(siteResources) .set({ - name: name, - siteId: siteId, - mode: mode, - destination: destination, - enabled: enabled, + name, + siteId, + niceId, + mode, + destination, + enabled, alias: alias && alias.trim() ? alias : null, - tcpPortRangeString: tcpPortRangeString, - udpPortRangeString: udpPortRangeString, - disableIcmp: disableIcmp, + tcpPortRangeString, + udpPortRangeString, + disableIcmp, ...sshPamSet }) .where( @@ -423,7 +432,8 @@ export async function updateSiteResource( // Update the site resource const sshPamSet = isLicensedSshPam && - (authDaemonPort !== undefined || authDaemonMode !== undefined) + (authDaemonPort !== undefined || + authDaemonMode !== undefined) ? { ...(authDaemonPort !== undefined && { authDaemonPort @@ -617,10 +627,14 @@ export async function handleMessagingForUpdatedSiteResource( mergedAllClients ); - await updateTargets(newt.newtId, { - oldTargets: oldTargets, - newTargets: newTargets - }, newt.version); + await updateTargets( + newt.newtId, + { + oldTargets: oldTargets, + newTargets: newTargets + }, + newt.version + ); } const olmJobs: Promise[] = []; diff --git a/src/components/EditInternalResourceDialog.tsx b/src/components/EditInternalResourceDialog.tsx index 866aebe3a..690ad405d 100644 --- a/src/components/EditInternalResourceDialog.tsx +++ b/src/components/EditInternalResourceDialog.tsx @@ -18,7 +18,7 @@ import { resourceQueries } from "@app/lib/queries"; import { ListSitesResponse } from "@server/routers/site"; import { useQueryClient } from "@tanstack/react-query"; import { useTranslations } from "next-intl"; -import { useState } from "react"; +import { useState, useTransition } from "react"; import { cleanForFQDN, InternalResourceForm, @@ -49,10 +49,9 @@ export default function EditInternalResourceDialog({ const t = useTranslations(); const api = createApiClient(useEnvContext()); const queryClient = useQueryClient(); - const [isSubmitting, setIsSubmitting] = useState(false); + const [isSubmitting, startTransition] = useTransition(); async function handleSubmit(values: InternalResourceFormValues) { - setIsSubmitting(true); try { let data = { ...values }; if (data.mode === "host" && isHostname(data.destination)) { @@ -70,6 +69,7 @@ export default function EditInternalResourceDialog({ name: data.name, siteId: data.siteId, mode: data.mode, + niceId: data.niceId, destination: data.destination, alias: data.alias && @@ -127,8 +127,6 @@ export default function EditInternalResourceDialog({ ), variant: "destructive" }); - } finally { - setIsSubmitting(false); } } @@ -162,7 +160,9 @@ export default function EditInternalResourceDialog({ orgId={orgId} siteResourceId={resource.id} formId="edit-internal-resource-form" - onSubmit={handleSubmit} + onSubmit={(values) => + startTransition(() => handleSubmit(values)) + } /> diff --git a/src/components/InternalResourceForm.tsx b/src/components/InternalResourceForm.tsx index 6df1aceb7..0cf86a8eb 100644 --- a/src/components/InternalResourceForm.tsx +++ b/src/components/InternalResourceForm.tsx @@ -132,6 +132,7 @@ export type InternalResourceData = { siteName: string; mode: "host" | "cidr"; siteId: number; + niceId: string; destination: string; alias?: string | null; tcpPortRangeString?: string | null; @@ -149,6 +150,7 @@ export type InternalResourceFormValues = { mode: "host" | "cidr"; destination: string; alias?: string | null; + niceId?: string; tcpPortRangeString?: string | null; udpPortRangeString?: string | null; disableIcmp?: boolean; @@ -243,6 +245,12 @@ export function InternalResourceForm({ : undefined ), alias: z.string().nullish(), + niceId: z + .string() + .min(1) + .max(255) + .regex(/^[a-zA-Z0-9-]+$/) + .optional(), tcpPortRangeString: createPortRangeStringSchema(t), udpPortRangeString: createPortRangeStringSchema(t), disableIcmp: z.boolean().optional(), @@ -387,6 +395,7 @@ export function InternalResourceForm({ disableIcmp: resource.disableIcmp ?? false, authDaemonMode: resource.authDaemonMode ?? "site", authDaemonPort: resource.authDaemonPort ?? null, + niceId: resource.niceId, roles: [], users: [], clients: [] @@ -534,7 +543,7 @@ export function InternalResourceForm({ className="space-y-6" id={formId} > -
+
)} /> + ( + + {t("identifier")} + + + + + + )} + /> Date: Tue, 24 Mar 2026 23:43:01 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=92=84=20update=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/InternalResourceForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/InternalResourceForm.tsx b/src/components/InternalResourceForm.tsx index 0cf86a8eb..4486b05fe 100644 --- a/src/components/InternalResourceForm.tsx +++ b/src/components/InternalResourceForm.tsx @@ -543,7 +543,7 @@ export function InternalResourceForm({ className="space-y-6" id={formId} > -
+