mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-05 15:26:35 +00:00
Moving to mode replacing http and protocol fields
This commit is contained in:
@@ -35,16 +35,54 @@ const createResourceParamsSchema = z.strictObject({
|
||||
orgId: z.string()
|
||||
});
|
||||
|
||||
function resolveModeFromLegacyFields(data: {
|
||||
mode?: "http" | "ssh" | "rdp" | "vnc" | "tcp" | "udp";
|
||||
http?: boolean;
|
||||
protocol?: "tcp" | "udp";
|
||||
}): {
|
||||
mode?: "http" | "ssh" | "rdp" | "vnc" | "tcp" | "udp";
|
||||
error?: string;
|
||||
} {
|
||||
if (data.mode) {
|
||||
return { mode: data.mode };
|
||||
}
|
||||
|
||||
if (typeof data.http === "boolean" && data.protocol) {
|
||||
if (data.http && data.protocol === "tcp") {
|
||||
return { mode: "http" };
|
||||
}
|
||||
if (!data.http && data.protocol === "tcp") {
|
||||
return { mode: "tcp" };
|
||||
}
|
||||
if (!data.http && data.protocol === "udp") {
|
||||
return { mode: "udp" };
|
||||
}
|
||||
return {
|
||||
error: "Invalid deprecated http/protocol combination"
|
||||
};
|
||||
}
|
||||
|
||||
return { mode: undefined };
|
||||
}
|
||||
|
||||
const createHttpResourceSchema = z
|
||||
.strictObject({
|
||||
name: z.string().min(1).max(255),
|
||||
subdomain: z.string().nullable().optional(),
|
||||
http: z.boolean(),
|
||||
protocol: z.enum(["tcp", "udp"]),
|
||||
http: z.boolean().optional().openapi({
|
||||
deprecated: true,
|
||||
description:
|
||||
"Deprecated. Use `mode` instead. Legacy compatibility only."
|
||||
}),
|
||||
protocol: z.enum(["tcp", "udp"]).optional().openapi({
|
||||
deprecated: true,
|
||||
description:
|
||||
"Deprecated. Use `mode` instead. Legacy compatibility only."
|
||||
}),
|
||||
domainId: z.string(),
|
||||
stickySession: z.boolean().optional(),
|
||||
postAuthPath: z.string().nullable().optional(),
|
||||
browserAccessType: z.enum(["http", "ssh", "rdp", "vnc"]).optional(),
|
||||
mode: z.enum(["http", "ssh", "rdp", "vnc", "tcp", "udp"]).optional(),
|
||||
// SSH Settings
|
||||
pamMode: z.enum(["passthrough", "push"]).optional(),
|
||||
authDaemonPort: z.int().positive().optional(),
|
||||
@@ -68,13 +106,27 @@ const createHttpResourceSchema = z
|
||||
const createRawResourceSchema = z
|
||||
.strictObject({
|
||||
name: z.string().min(1).max(255),
|
||||
http: z.boolean(),
|
||||
protocol: z.enum(["tcp", "udp"]),
|
||||
http: z.boolean().optional().openapi({
|
||||
deprecated: true,
|
||||
description:
|
||||
"Deprecated. Use `mode` instead. Legacy compatibility only."
|
||||
}),
|
||||
protocol: z.enum(["tcp", "udp"]).optional().openapi({
|
||||
deprecated: true,
|
||||
description:
|
||||
"Deprecated. Use `mode` instead. Legacy compatibility only."
|
||||
}),
|
||||
mode: z.enum(["tcp", "udp"]).optional(),
|
||||
proxyPort: z.int().min(1).max(65535)
|
||||
// enableProxy: z.boolean().default(true) // always true now
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
const resolved = resolveModeFromLegacyFields(data);
|
||||
if (resolved.error || !resolved.mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config.getRawConfig().flags?.allow_raw_resources) {
|
||||
if (data.proxyPort !== undefined) {
|
||||
return false;
|
||||
@@ -151,17 +203,18 @@ export async function createResource(
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof req.body.http !== "boolean") {
|
||||
const resolvedMode = resolveModeFromLegacyFields(req.body);
|
||||
if (resolvedMode.error) {
|
||||
return next(
|
||||
createHttpError(HttpCode.BAD_REQUEST, "http field is required")
|
||||
createHttpError(HttpCode.BAD_REQUEST, resolvedMode.error)
|
||||
);
|
||||
}
|
||||
|
||||
const { http } = req.body;
|
||||
if (resolvedMode.mode) {
|
||||
req.body.mode = resolvedMode.mode;
|
||||
}
|
||||
|
||||
if (http) {
|
||||
return await createHttpResource({ req, res, next }, { orgId });
|
||||
} else {
|
||||
if (typeof req.body.proxyPort === "number") {
|
||||
if (
|
||||
!config.getRawConfig().flags?.allow_raw_resources &&
|
||||
build == "oss"
|
||||
@@ -175,6 +228,17 @@ export async function createResource(
|
||||
}
|
||||
return await createRawResource({ req, res, next }, { orgId });
|
||||
}
|
||||
|
||||
if (req.body.mode) {
|
||||
return await createHttpResource({ req, res, next }, { orgId });
|
||||
} else {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.BAD_REQUEST,
|
||||
"mode is required when deprecated fields are not provided"
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return next(
|
||||
@@ -210,7 +274,7 @@ async function createHttpResource(
|
||||
name,
|
||||
domainId,
|
||||
postAuthPath,
|
||||
browserAccessType,
|
||||
mode,
|
||||
authDaemonPort,
|
||||
authDaemonMode,
|
||||
pamMode
|
||||
@@ -338,12 +402,10 @@ async function createHttpResource(
|
||||
orgId,
|
||||
name,
|
||||
subdomain: finalSubdomain,
|
||||
http: true,
|
||||
browserAccessType: browserAccessType,
|
||||
mode: mode,
|
||||
pamMode: pamMode,
|
||||
authDaemonMode: authDaemonMode,
|
||||
authDaemonPort: authDaemonPort,
|
||||
protocol: "tcp",
|
||||
ssl: true,
|
||||
stickySession: stickySession,
|
||||
postAuthPath: postAuthPath,
|
||||
@@ -425,7 +487,17 @@ async function createRawResource(
|
||||
);
|
||||
}
|
||||
|
||||
const { name, http, protocol, proxyPort } = parsedBody.data;
|
||||
const { name, proxyPort } = parsedBody.data;
|
||||
const resolvedMode = resolveModeFromLegacyFields(parsedBody.data);
|
||||
if (resolvedMode.error || !resolvedMode.mode) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.BAD_REQUEST,
|
||||
resolvedMode.error ||
|
||||
"mode is required when deprecated fields are not provided"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let resource: Resource | undefined;
|
||||
|
||||
@@ -438,9 +510,8 @@ async function createRawResource(
|
||||
niceId,
|
||||
orgId,
|
||||
name,
|
||||
http,
|
||||
protocol,
|
||||
proxyPort
|
||||
proxyPort,
|
||||
mode: resolvedMode.mode
|
||||
// enableProxy
|
||||
})
|
||||
.returning();
|
||||
|
||||
@@ -137,8 +137,6 @@ export type ResourceWithTargets = {
|
||||
sso: boolean;
|
||||
pincodeId: number | null;
|
||||
whitelist: boolean;
|
||||
http: boolean;
|
||||
protocol: string;
|
||||
proxyPort: number | null;
|
||||
enabled: boolean;
|
||||
domainId: string | null;
|
||||
@@ -146,7 +144,7 @@ export type ResourceWithTargets = {
|
||||
headerAuthId: number | null;
|
||||
wildcard: boolean;
|
||||
health: string | null;
|
||||
browserAccessType: string | null;
|
||||
mode: string | null;
|
||||
targets: Array<{
|
||||
targetId: number;
|
||||
ip: string;
|
||||
@@ -175,8 +173,6 @@ function queryResourcesBase() {
|
||||
sso: resources.sso,
|
||||
pincodeId: resourcePincode.pincodeId,
|
||||
whitelist: resources.emailWhitelistEnabled,
|
||||
http: resources.http,
|
||||
protocol: resources.protocol,
|
||||
proxyPort: resources.proxyPort,
|
||||
enabled: resources.enabled,
|
||||
domainId: resources.domainId,
|
||||
@@ -186,7 +182,7 @@ function queryResourcesBase() {
|
||||
headerAuthExtendedCompatibilityId:
|
||||
resourceHeaderAuthExtendedCompatibility.headerAuthExtendedCompatibilityId,
|
||||
health: resources.health,
|
||||
browserAccessType: resources.browserAccessType
|
||||
mode: resources.mode
|
||||
})
|
||||
.from(resources)
|
||||
.leftJoin(
|
||||
@@ -346,7 +342,9 @@ export async function listResources(
|
||||
if (typeof authState !== "undefined") {
|
||||
switch (authState) {
|
||||
case "none":
|
||||
conditions.push(eq(resources.http, false));
|
||||
conditions.push(
|
||||
or(eq(resources.mode, "tcp"), eq(resources.mode, "udp"))
|
||||
);
|
||||
break;
|
||||
case "protected":
|
||||
conditions.push(
|
||||
@@ -525,11 +523,9 @@ export async function listResources(
|
||||
sso: row.sso,
|
||||
pincodeId: row.pincodeId,
|
||||
whitelist: row.whitelist,
|
||||
http: row.http,
|
||||
protocol: row.protocol,
|
||||
proxyPort: row.proxyPort,
|
||||
wildcard: row.wildcard,
|
||||
browserAccessType: row.browserAccessType,
|
||||
mode: row.mode,
|
||||
enabled: row.enabled,
|
||||
domainId: row.domainId,
|
||||
headerAuthId: row.headerAuthId,
|
||||
|
||||
@@ -72,7 +72,6 @@ const updateHttpResourceBodySchema = z
|
||||
maintenanceMessage: z.string().max(2000).nullable().optional(),
|
||||
maintenanceEstimatedTime: z.string().max(100).nullable().optional(),
|
||||
postAuthPath: z.string().nullable().optional(),
|
||||
browserAccessType: z.enum(["http", "ssh", "rdp", "vnc"]).optional(),
|
||||
// SSH settings
|
||||
pamMode: z.enum(["passthrough", "push"]).optional(),
|
||||
authDaemonMode: z.enum(["site", "remote", "native"]).optional(),
|
||||
|
||||
@@ -144,6 +144,21 @@ const createSiteResourceSchema = z
|
||||
"HTTP mode requires scheme (http or https) and a valid destination port"
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// destination is only optional for ssh mode with native authDaemonMode
|
||||
if (data.mode === "ssh" && data.authDaemonMode === "native") {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
data.destination !== undefined && data.destination.trim() !== ""
|
||||
);
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Destination is required unless mode is ssh with authDaemonMode native"
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
return (
|
||||
|
||||
@@ -153,6 +153,21 @@ const updateSiteResourceSchema = z
|
||||
"HTTP mode requires scheme (http or https) and a valid destination port"
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// destination is only optional for ssh mode with native authDaemonMode
|
||||
if (data.mode === "ssh" && data.authDaemonMode === "native") {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
data.destination !== undefined && data.destination.trim() !== ""
|
||||
);
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Destination is required unless mode is ssh with authDaemonMode native"
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user