Merge branch 'dev' into clients-user

This commit is contained in:
Owen
2025-11-17 11:28:47 -05:00
251 changed files with 3872 additions and 1666 deletions

View File

@@ -13,20 +13,17 @@ import { addTargets } from "../client/targets";
import { getUniqueSiteResourceName } from "@server/db/names";
import { rebuildSiteClientAssociations } from "@server/lib/rebuildSiteClientAssociations";
const createSiteResourceParamsSchema = z
.object({
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
const createSiteResourceParamsSchema = z.strictObject({
siteId: z.string().transform(Number).pipe(z.int().positive()),
orgId: z.string()
})
.strict();
});
const createSiteResourceSchema = z
.object({
const createSiteResourceSchema = z.strictObject({
name: z.string().min(1).max(255),
mode: z.enum(["host", "cidr", "port"]),
protocol: z.enum(["tcp", "udp"]).optional(),
proxyPort: z.number().int().positive().optional(),
destinationPort: z.number().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()
@@ -51,8 +48,8 @@ const createSiteResourceSchema = z
.refine(
(data) => {
if (data.mode === "host") {
// Check if it's a valid IP address using zod
const isValidIP = z.string().ip().safeParse(data.destination).success;
// Check if it's a valid IP address using zod (v4 or v6)
const isValidIP = z.union([z.ipv4(), z.ipv6()]).safeParse(data.destination).success;
// Check if it's a valid domain (hostname pattern, TLD not required)
const domainRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
@@ -70,8 +67,8 @@ const createSiteResourceSchema = z
.refine(
(data) => {
if (data.mode === "cidr") {
// Check if it's a valid CIDR
const isValidCIDR = z.string().cidr().safeParse(data.destination).success;
// Check if it's a valid CIDR (v4 or v6)
const isValidCIDR = z.union([z.cidrv4(), z.cidrv6()]).safeParse(data.destination).success;
return isValidCIDR;
}
return true;

View File

@@ -12,16 +12,11 @@ import { OpenAPITags, registry } from "@server/openApi";
import { removeTargets } from "../client/targets";
import { rebuildSiteClientAssociations } from "@server/lib/rebuildSiteClientAssociations";
const deleteSiteResourceParamsSchema = z
.object({
siteResourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive()),
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
const deleteSiteResourceParamsSchema = z.strictObject({
siteResourceId: z.string().transform(Number).pipe(z.int().positive()),
siteId: z.string().transform(Number).pipe(z.int().positive()),
orgId: z.string()
})
.strict();
});
export type DeleteSiteResourceResponse = {
message: string;

View File

@@ -10,19 +10,17 @@ import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
const getSiteResourceParamsSchema = z
.object({
const getSiteResourceParamsSchema = z.strictObject({
siteResourceId: z
.string()
.optional()
.transform((val) => val ? Number(val) : undefined)
.pipe(z.number().int().positive().optional())
.pipe(z.int().positive().optional())
.optional(),
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
siteId: z.string().transform(Number).pipe(z.int().positive()),
niceId: z.string().optional(),
orgId: z.string()
})
.strict();
});
async function query(siteResourceId?: number, siteId?: number, niceId?: string, orgId?: string) {
if (siteResourceId && siteId && orgId) {

View File

@@ -10,11 +10,9 @@ import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
const listAllSiteResourcesByOrgParamsSchema = z
.object({
const listAllSiteResourcesByOrgParamsSchema = z.strictObject({
orgId: z.string()
})
.strict();
});
const listAllSiteResourcesByOrgQuerySchema = z.object({
limit: z
@@ -22,13 +20,13 @@ const listAllSiteResourcesByOrgQuerySchema = z.object({
.optional()
.default("1000")
.transform(Number)
.pipe(z.number().int().positive()),
.pipe(z.int().positive()),
offset: z
.string()
.optional()
.default("0")
.transform(Number)
.pipe(z.number().int().nonnegative())
.pipe(z.int().nonnegative())
});
export type ListAllSiteResourcesByOrgResponse = {

View File

@@ -10,12 +10,10 @@ import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
const listSiteResourcesParamsSchema = z
.object({
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
const listSiteResourcesParamsSchema = z.strictObject({
siteId: z.string().transform(Number).pipe(z.int().positive()),
orgId: z.string()
})
.strict();
});
const listSiteResourcesQuerySchema = z.object({
limit: z
@@ -23,13 +21,13 @@ const listSiteResourcesQuerySchema = z.object({
.optional()
.default("100")
.transform(Number)
.pipe(z.number().int().positive()),
.pipe(z.int().positive()),
offset: z
.string()
.optional()
.default("0")
.transform(Number)
.pipe(z.number().int().nonnegative())
.pipe(z.int().nonnegative())
});
export type ListSiteResourcesResponse = {

View File

@@ -11,24 +11,21 @@ import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import { addTargets } from "../client/targets";
const updateSiteResourceParamsSchema = z
.object({
const updateSiteResourceParamsSchema = z.strictObject({
siteResourceId: z
.string()
.transform(Number)
.pipe(z.number().int().positive()),
siteId: z.string().transform(Number).pipe(z.number().int().positive()),
.pipe(z.int().positive()),
siteId: z.string().transform(Number).pipe(z.int().positive()),
orgId: z.string()
})
.strict();
});
const updateSiteResourceSchema = z
.object({
const updateSiteResourceSchema = z.strictObject({
name: z.string().min(1).max(255).optional(),
mode: z.enum(["host", "cidr", "port"]).optional(),
protocol: z.enum(["tcp", "udp"]).nullish(),
proxyPort: z.number().int().positive().nullish(),
destinationPort: z.number().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()