mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-31 06:56:39 +00:00
Merge pull request #2697 from Fredkiss3/feat/modify-private-resource-niceid
feat: edit niceid in private resources
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
import { z } from "zod";
|
|
||||||
import {
|
import {
|
||||||
clientSiteResources,
|
clientSiteResources,
|
||||||
clientSiteResourcesAssociationsCache,
|
clientSiteResourcesAssociationsCache,
|
||||||
@@ -8,19 +7,13 @@ import {
|
|||||||
orgs,
|
orgs,
|
||||||
roles,
|
roles,
|
||||||
roleSiteResources,
|
roleSiteResources,
|
||||||
|
SiteResource,
|
||||||
|
siteResources,
|
||||||
sites,
|
sites,
|
||||||
Transaction,
|
Transaction,
|
||||||
userSiteResources
|
userSiteResources
|
||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import { siteResources, SiteResource } from "@server/db";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
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 {
|
import {
|
||||||
generateAliasConfig,
|
generateAliasConfig,
|
||||||
generateRemoteSubnets,
|
generateRemoteSubnets,
|
||||||
@@ -28,12 +21,17 @@ import {
|
|||||||
isIpInCidr,
|
isIpInCidr,
|
||||||
portRangeStringSchema
|
portRangeStringSchema
|
||||||
} from "@server/lib/ip";
|
} from "@server/lib/ip";
|
||||||
import {
|
import { rebuildClientAssociationsFromSiteResource } from "@server/lib/rebuildClientAssociations";
|
||||||
getClientSiteResourceAccess,
|
import response from "@server/lib/response";
|
||||||
rebuildClientAssociationsFromSiteResource
|
import logger from "@server/logger";
|
||||||
} from "@server/lib/rebuildClientAssociations";
|
import { OpenAPITags, registry } from "@server/openApi";
|
||||||
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
import { updatePeerData, updateTargets } from "@server/routers/client/targets";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
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({
|
const updateSiteResourceParamsSchema = z.strictObject({
|
||||||
siteResourceId: z.string().transform(Number).pipe(z.int().positive())
|
siteResourceId: z.string().transform(Number).pipe(z.int().positive())
|
||||||
@@ -43,7 +41,15 @@ const updateSiteResourceSchema = z
|
|||||||
.strictObject({
|
.strictObject({
|
||||||
name: z.string().min(1).max(255).optional(),
|
name: z.string().min(1).max(255).optional(),
|
||||||
siteId: z.int(),
|
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", "port"]).optional(),
|
||||||
mode: z.enum(["host", "cidr"]).optional(),
|
mode: z.enum(["host", "cidr"]).optional(),
|
||||||
// protocol: z.enum(["tcp", "udp"]).nullish(),
|
// protocol: z.enum(["tcp", "udp"]).nullish(),
|
||||||
@@ -167,6 +173,7 @@ export async function updateSiteResource(
|
|||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
siteId, // because it can change
|
siteId, // because it can change
|
||||||
|
niceId,
|
||||||
mode,
|
mode,
|
||||||
destination,
|
destination,
|
||||||
alias,
|
alias,
|
||||||
@@ -321,7 +328,8 @@ export async function updateSiteResource(
|
|||||||
|
|
||||||
const sshPamSet =
|
const sshPamSet =
|
||||||
isLicensedSshPam &&
|
isLicensedSshPam &&
|
||||||
(authDaemonPort !== undefined || authDaemonMode !== undefined)
|
(authDaemonPort !== undefined ||
|
||||||
|
authDaemonMode !== undefined)
|
||||||
? {
|
? {
|
||||||
...(authDaemonPort !== undefined && {
|
...(authDaemonPort !== undefined && {
|
||||||
authDaemonPort
|
authDaemonPort
|
||||||
@@ -334,15 +342,16 @@ export async function updateSiteResource(
|
|||||||
[updatedSiteResource] = await trx
|
[updatedSiteResource] = await trx
|
||||||
.update(siteResources)
|
.update(siteResources)
|
||||||
.set({
|
.set({
|
||||||
name: name,
|
name,
|
||||||
siteId: siteId,
|
siteId,
|
||||||
mode: mode,
|
niceId,
|
||||||
destination: destination,
|
mode,
|
||||||
enabled: enabled,
|
destination,
|
||||||
|
enabled,
|
||||||
alias: alias && alias.trim() ? alias : null,
|
alias: alias && alias.trim() ? alias : null,
|
||||||
tcpPortRangeString: tcpPortRangeString,
|
tcpPortRangeString,
|
||||||
udpPortRangeString: udpPortRangeString,
|
udpPortRangeString,
|
||||||
disableIcmp: disableIcmp,
|
disableIcmp,
|
||||||
...sshPamSet
|
...sshPamSet
|
||||||
})
|
})
|
||||||
.where(
|
.where(
|
||||||
@@ -423,7 +432,8 @@ export async function updateSiteResource(
|
|||||||
// Update the site resource
|
// Update the site resource
|
||||||
const sshPamSet =
|
const sshPamSet =
|
||||||
isLicensedSshPam &&
|
isLicensedSshPam &&
|
||||||
(authDaemonPort !== undefined || authDaemonMode !== undefined)
|
(authDaemonPort !== undefined ||
|
||||||
|
authDaemonMode !== undefined)
|
||||||
? {
|
? {
|
||||||
...(authDaemonPort !== undefined && {
|
...(authDaemonPort !== undefined && {
|
||||||
authDaemonPort
|
authDaemonPort
|
||||||
@@ -617,10 +627,14 @@ export async function handleMessagingForUpdatedSiteResource(
|
|||||||
mergedAllClients
|
mergedAllClients
|
||||||
);
|
);
|
||||||
|
|
||||||
await updateTargets(newt.newtId, {
|
await updateTargets(
|
||||||
|
newt.newtId,
|
||||||
|
{
|
||||||
oldTargets: oldTarget ? [oldTarget] : [],
|
oldTargets: oldTarget ? [oldTarget] : [],
|
||||||
newTargets: newTarget ? [newTarget] : []
|
newTargets: newTarget ? [newTarget] : []
|
||||||
}, newt.version);
|
},
|
||||||
|
newt.version
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const olmJobs: Promise<void>[] = [];
|
const olmJobs: Promise<void>[] = [];
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { resourceQueries } from "@app/lib/queries";
|
|||||||
import { ListSitesResponse } from "@server/routers/site";
|
import { ListSitesResponse } from "@server/routers/site";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { useState } from "react";
|
import { useState, useTransition } from "react";
|
||||||
import {
|
import {
|
||||||
cleanForFQDN,
|
cleanForFQDN,
|
||||||
InternalResourceForm,
|
InternalResourceForm,
|
||||||
@@ -49,10 +49,9 @@ export default function EditInternalResourceDialog({
|
|||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const api = createApiClient(useEnvContext());
|
const api = createApiClient(useEnvContext());
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, startTransition] = useTransition();
|
||||||
|
|
||||||
async function handleSubmit(values: InternalResourceFormValues) {
|
async function handleSubmit(values: InternalResourceFormValues) {
|
||||||
setIsSubmitting(true);
|
|
||||||
try {
|
try {
|
||||||
let data = { ...values };
|
let data = { ...values };
|
||||||
if (data.mode === "host" && isHostname(data.destination)) {
|
if (data.mode === "host" && isHostname(data.destination)) {
|
||||||
@@ -70,6 +69,7 @@ export default function EditInternalResourceDialog({
|
|||||||
name: data.name,
|
name: data.name,
|
||||||
siteId: data.siteId,
|
siteId: data.siteId,
|
||||||
mode: data.mode,
|
mode: data.mode,
|
||||||
|
niceId: data.niceId,
|
||||||
destination: data.destination,
|
destination: data.destination,
|
||||||
alias:
|
alias:
|
||||||
data.alias &&
|
data.alias &&
|
||||||
@@ -127,8 +127,6 @@ export default function EditInternalResourceDialog({
|
|||||||
),
|
),
|
||||||
variant: "destructive"
|
variant: "destructive"
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
setIsSubmitting(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +160,9 @@ export default function EditInternalResourceDialog({
|
|||||||
orgId={orgId}
|
orgId={orgId}
|
||||||
siteResourceId={resource.id}
|
siteResourceId={resource.id}
|
||||||
formId="edit-internal-resource-form"
|
formId="edit-internal-resource-form"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={(values) =>
|
||||||
|
startTransition(() => handleSubmit(values))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</CredenzaBody>
|
</CredenzaBody>
|
||||||
<CredenzaFooter>
|
<CredenzaFooter>
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ export type InternalResourceData = {
|
|||||||
siteName: string;
|
siteName: string;
|
||||||
mode: "host" | "cidr";
|
mode: "host" | "cidr";
|
||||||
siteId: number;
|
siteId: number;
|
||||||
|
niceId: string;
|
||||||
destination: string;
|
destination: string;
|
||||||
alias?: string | null;
|
alias?: string | null;
|
||||||
tcpPortRangeString?: string | null;
|
tcpPortRangeString?: string | null;
|
||||||
@@ -149,6 +150,7 @@ export type InternalResourceFormValues = {
|
|||||||
mode: "host" | "cidr";
|
mode: "host" | "cidr";
|
||||||
destination: string;
|
destination: string;
|
||||||
alias?: string | null;
|
alias?: string | null;
|
||||||
|
niceId?: string;
|
||||||
tcpPortRangeString?: string | null;
|
tcpPortRangeString?: string | null;
|
||||||
udpPortRangeString?: string | null;
|
udpPortRangeString?: string | null;
|
||||||
disableIcmp?: boolean;
|
disableIcmp?: boolean;
|
||||||
@@ -243,6 +245,12 @@ export function InternalResourceForm({
|
|||||||
: undefined
|
: undefined
|
||||||
),
|
),
|
||||||
alias: z.string().nullish(),
|
alias: z.string().nullish(),
|
||||||
|
niceId: z
|
||||||
|
.string()
|
||||||
|
.min(1)
|
||||||
|
.max(255)
|
||||||
|
.regex(/^[a-zA-Z0-9-]+$/)
|
||||||
|
.optional(),
|
||||||
tcpPortRangeString: createPortRangeStringSchema(t),
|
tcpPortRangeString: createPortRangeStringSchema(t),
|
||||||
udpPortRangeString: createPortRangeStringSchema(t),
|
udpPortRangeString: createPortRangeStringSchema(t),
|
||||||
disableIcmp: z.boolean().optional(),
|
disableIcmp: z.boolean().optional(),
|
||||||
@@ -387,6 +395,7 @@ export function InternalResourceForm({
|
|||||||
disableIcmp: resource.disableIcmp ?? false,
|
disableIcmp: resource.disableIcmp ?? false,
|
||||||
authDaemonMode: resource.authDaemonMode ?? "site",
|
authDaemonMode: resource.authDaemonMode ?? "site",
|
||||||
authDaemonPort: resource.authDaemonPort ?? null,
|
authDaemonPort: resource.authDaemonPort ?? null,
|
||||||
|
niceId: resource.niceId,
|
||||||
roles: [],
|
roles: [],
|
||||||
users: [],
|
users: [],
|
||||||
clients: []
|
clients: []
|
||||||
@@ -548,6 +557,19 @@ export function InternalResourceForm({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="niceId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("identifier")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="siteId"
|
name="siteId"
|
||||||
|
|||||||
Reference in New Issue
Block a user