mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-26 23:06:37 +00:00
fix for zod
This commit is contained in:
5
Makefile
5
Makefile
@@ -101,4 +101,7 @@ test-local:
|
|||||||
- npx tsc --noEmit
|
- npx tsc --noEmit
|
||||||
- docker build --build-arg DATABASE=pg -t fosrl/pangolin:postgresql-latest .
|
- docker build --build-arg DATABASE=pg -t fosrl/pangolin:postgresql-latest .
|
||||||
- docker build --build-arg DATABASE=sqlite -t fosrl/pangolin:latest .
|
- docker build --build-arg DATABASE=sqlite -t fosrl/pangolin:latest .
|
||||||
|
npm run set:saas
|
||||||
|
- npx tsc --noEmit
|
||||||
|
- docker build --build-arg DATABASE=pg -t fosrl/pangolin:postgresql-saas-latest .
|
||||||
|
- docker build --build-arg DATABASE=sqlite -t fosrl/pangolin:saas-latest .
|
||||||
@@ -116,6 +116,20 @@ export const ResourceSchema = z
|
|||||||
(target) => target == null || target.method !== undefined
|
(target) => target == null || target.method !== undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ["targets"],
|
||||||
|
error: "When protocol is 'http', all targets must have a 'method' field"
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(resource) => {
|
||||||
|
if (isTargetsOnlyResource(resource)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// If protocol is tcp or udp, no target should have method field
|
// If protocol is tcp or udp, no target should have method field
|
||||||
if (resource.protocol === "tcp" || resource.protocol === "udp") {
|
if (resource.protocol === "tcp" || resource.protocol === "udp") {
|
||||||
return resource.targets.every(
|
return resource.targets.every(
|
||||||
@@ -124,19 +138,9 @@ export const ResourceSchema = z
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
(resource) => {
|
{
|
||||||
if (resource.protocol === "http") {
|
path: ["targets"],
|
||||||
return {
|
error: "When protocol is 'tcp' or 'udp', targets must not have a 'method' field"
|
||||||
message:
|
|
||||||
"When protocol is 'http', all targets must have a 'method' field",
|
|
||||||
path: ["targets"]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
message:
|
|
||||||
"When protocol is 'tcp' or 'udp', targets must not have a 'method' field",
|
|
||||||
path: ["targets"]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.refine(
|
.refine(
|
||||||
@@ -218,30 +222,6 @@ export const ConfigSchema = z
|
|||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
// Enforce the full-domain uniqueness across resources in the same stack
|
// 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<string, string[]>();
|
|
||||||
|
|
||||||
Object.entries(config["proxy-resources"]).forEach(
|
|
||||||
([resourceKey, resource]) => {
|
|
||||||
const fullDomain = resource["full-domain"];
|
|
||||||
if (fullDomain) {
|
|
||||||
// Only process if full-domain is defined
|
|
||||||
if (!fullDomainMap.has(fullDomain)) {
|
|
||||||
fullDomainMap.set(fullDomain, []);
|
|
||||||
}
|
|
||||||
fullDomainMap.get(fullDomain)!.push(resourceKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Find duplicates
|
|
||||||
const duplicates = Array.from(fullDomainMap.entries()).filter(
|
|
||||||
([_, resourceKeys]) => resourceKeys.length > 1
|
|
||||||
);
|
|
||||||
|
|
||||||
return duplicates.length === 0;
|
|
||||||
},
|
|
||||||
(config) => {
|
(config) => {
|
||||||
// Extract duplicates for error message
|
// Extract duplicates for error message
|
||||||
const fullDomainMap = new Map<string, string[]>();
|
const fullDomainMap = new Map<string, string[]>();
|
||||||
@@ -267,38 +247,16 @@ export const ConfigSchema = z
|
|||||||
)
|
)
|
||||||
.join("; ");
|
.join("; ");
|
||||||
|
|
||||||
return {
|
if (duplicates.length !== 0) {
|
||||||
message: `Duplicate 'full-domain' values found: ${duplicates}`,
|
return {
|
||||||
path: ["resources"]
|
path: ["resources"],
|
||||||
};
|
error: `Duplicate 'full-domain' values found: ${duplicates}`
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.refine(
|
.refine(
|
||||||
// Enforce proxy-port uniqueness within proxy-resources per protocol
|
// Enforce proxy-port uniqueness within proxy-resources per protocol
|
||||||
(config) => {
|
|
||||||
const protocolPortMap = new Map<string, string[]>();
|
|
||||||
|
|
||||||
Object.entries(config["proxy-resources"]).forEach(
|
|
||||||
([resourceKey, resource]) => {
|
|
||||||
const proxyPort = resource["proxy-port"];
|
|
||||||
const protocol = resource.protocol;
|
|
||||||
if (proxyPort !== undefined && protocol !== undefined) {
|
|
||||||
const key = `${protocol}:${proxyPort}`;
|
|
||||||
if (!protocolPortMap.has(key)) {
|
|
||||||
protocolPortMap.set(key, []);
|
|
||||||
}
|
|
||||||
protocolPortMap.get(key)!.push(resourceKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Find duplicates
|
|
||||||
const duplicates = Array.from(protocolPortMap.entries()).filter(
|
|
||||||
([_, resourceKeys]) => resourceKeys.length > 1
|
|
||||||
);
|
|
||||||
|
|
||||||
return duplicates.length === 0;
|
|
||||||
},
|
|
||||||
(config) => {
|
(config) => {
|
||||||
// Extract duplicates for error message
|
// Extract duplicates for error message
|
||||||
const protocolPortMap = new Map<string, string[]>();
|
const protocolPortMap = new Map<string, string[]>();
|
||||||
@@ -327,36 +285,16 @@ export const ConfigSchema = z
|
|||||||
)
|
)
|
||||||
.join("; ");
|
.join("; ");
|
||||||
|
|
||||||
return {
|
if (duplicates.length !== 0) {
|
||||||
message: `Duplicate 'proxy-port' values found in proxy-resources: ${duplicates}`,
|
return {
|
||||||
path: ["proxy-resources"]
|
path: ["proxy-resources"],
|
||||||
};
|
error: `Duplicate 'proxy-port' values found in proxy-resources: ${duplicates}`
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.refine(
|
.refine(
|
||||||
// Enforce proxy-port uniqueness within client-resources
|
// Enforce proxy-port uniqueness within client-resources
|
||||||
(config) => {
|
|
||||||
const proxyPortMap = new Map<number, string[]>();
|
|
||||||
|
|
||||||
Object.entries(config["client-resources"]).forEach(
|
|
||||||
([resourceKey, resource]) => {
|
|
||||||
const proxyPort = resource["proxy-port"];
|
|
||||||
if (proxyPort !== undefined) {
|
|
||||||
if (!proxyPortMap.has(proxyPort)) {
|
|
||||||
proxyPortMap.set(proxyPort, []);
|
|
||||||
}
|
|
||||||
proxyPortMap.get(proxyPort)!.push(resourceKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Find duplicates
|
|
||||||
const duplicates = Array.from(proxyPortMap.entries()).filter(
|
|
||||||
([_, resourceKeys]) => resourceKeys.length > 1
|
|
||||||
);
|
|
||||||
|
|
||||||
return duplicates.length === 0;
|
|
||||||
},
|
|
||||||
(config) => {
|
(config) => {
|
||||||
// Extract duplicates for error message
|
// Extract duplicates for error message
|
||||||
const proxyPortMap = new Map<number, string[]>();
|
const proxyPortMap = new Map<number, string[]>();
|
||||||
@@ -381,10 +319,12 @@ export const ConfigSchema = z
|
|||||||
)
|
)
|
||||||
.join("; ");
|
.join("; ");
|
||||||
|
|
||||||
return {
|
if (duplicates.length !== 0) {
|
||||||
message: `Duplicate 'proxy-port' values found in client-resources: ${duplicates}`,
|
return {
|
||||||
path: ["client-resources"]
|
path: ["client-resources"],
|
||||||
};
|
error: `Duplicate 'proxy-port' values found in client-resources: ${duplicates}`
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const queryAccessAuditLogsQuery = z.object({
|
|||||||
})
|
})
|
||||||
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
|
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
|
||||||
.optional()
|
.optional()
|
||||||
.default(new Date().toISOString()),
|
.prefault(new Date().toISOString()),
|
||||||
action: z
|
action: z
|
||||||
.union([z.boolean(), z.string()])
|
.union([z.boolean(), z.string()])
|
||||||
.transform((val) => (typeof val === "string" ? val === "true" : val))
|
.transform((val) => (typeof val === "string" ? val === "true" : val))
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const queryActionAuditLogsQuery = z.object({
|
|||||||
})
|
})
|
||||||
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
|
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
|
||||||
.optional()
|
.optional()
|
||||||
.default(new Date().toISOString()),
|
.prefault(new Date().toISOString()),
|
||||||
action: z.string().optional(),
|
action: z.string().optional(),
|
||||||
actorType: z.string().optional(),
|
actorType: z.string().optional(),
|
||||||
actorId: z.string().optional(),
|
actorId: z.string().optional(),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const queryAccessAuditLogsQuery = z.object({
|
|||||||
})
|
})
|
||||||
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
|
.transform((val) => Math.floor(new Date(val).getTime() / 1000))
|
||||||
.optional()
|
.optional()
|
||||||
.default(new Date().toISOString()),
|
.prefault(new Date().toISOString()),
|
||||||
action: z
|
action: z
|
||||||
.union([z.boolean(), z.string()])
|
.union([z.boolean(), z.string()])
|
||||||
.transform((val) => (typeof val === "string" ? val === "true" : val))
|
.transform((val) => (typeof val === "string" ? val === "true" : val))
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ export default function Page() {
|
|||||||
.refine((val) => val.length > 0, {
|
.refine((val) => val.length > 0, {
|
||||||
message: t("siteRequired")
|
message: t("siteRequired")
|
||||||
}),
|
}),
|
||||||
subnet: z.union([z.ipv4(), z.ipv6()]).min(1, {
|
subnet: z.union([z.ipv4(), z.ipv6()])
|
||||||
|
.refine((val) => val.length > 0, {
|
||||||
message: t("subnetRequired")
|
message: t("subnetRequired")
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user