🚧 edit niceid in private resources

This commit is contained in:
Fred KISSIE
2026-03-23 22:55:59 +01:00
parent 7c8b865379
commit 60982bf19f
3 changed files with 75 additions and 39 deletions

View File

@@ -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<void>[] = [];

View File

@@ -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))
}
/>
</CredenzaBody>
<CredenzaFooter>

View File

@@ -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}
>
<div className="grid grid-cols-2 gap-4">
<div className="grid gap-4">
<FormField
control={form.control}
name="name"
@@ -548,6 +557,19 @@ export function InternalResourceForm({
</FormItem>
)}
/>
<FormField
control={form.control}
name="niceId"
render={({ field }) => (
<FormItem>
<FormLabel>{t("identifier")}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="siteId"