Can create gateway resource

This commit is contained in:
Owen
2026-09-24 09:49:09 -04:00
parent a17b870ed2
commit 3378125f8e
5 changed files with 38 additions and 17 deletions
+6
View File
@@ -307,6 +307,8 @@
"privateResourceTypeCidrDescription": "Expose a CIDR range on the site network to connected clients",
"privateResourceTypeHttpDescription": "Access an HTTP or HTTPS service through a domain",
"privateResourceTypeSshDescription": "Access an SSH server from connected clients",
"privateResourceTypeGatewayDescription": "Send all internet traffic to exit through the site network.",
"resourceTypeGatewayDescription": "Send all internet traffic to exit through the site network.",
"resourceDomainDescription": "The resource will be served at this fully qualified domain name.",
"resourceHTTPSSettings": "HTTPS Settings",
"resourceHTTPSSettingsDescription": "Configure how the resource will be accessed over HTTPS",
@@ -2927,6 +2929,7 @@
"editInternalResourceDialogModePort": "Port",
"editInternalResourceDialogModeHost": "Host",
"editInternalResourceDialogModeCidr": "CIDR",
"editInternalResourceDialogModeGateway": "Exit Node",
"editInternalResourceDialogModeHttp": "HTTP",
"editInternalResourceDialogModeHttps": "HTTPS",
"editInternalResourceDialogModeInference": "AI Gateway",
@@ -2938,6 +2941,7 @@
"editInternalResourceDialogDestinationHostDescription": "The IP address or hostname of the resource on the site's network.",
"editInternalResourceDialogDestinationIPDescription": "The IP or hostname address of the resource on the site's network.",
"editInternalResourceDialogDestinationCidrDescription": "The CIDR range of the resource on the site's network.",
"editInternalResourceDialogDestinationGatewayDescription": "The sites to uses as exit nodes for this resource",
"editInternalResourceDialogAlias": "Alias",
"editInternalResourceDialogAliasDescription": "An optional internal DNS alias for this resource.",
"createInternalResourceDialogNoSitesAvailable": "No Sites Available",
@@ -2952,6 +2956,7 @@
"privateResourceNetworkAccessDescription": "Control TCP/UDP port access and whether ICMP ping is allowed for this resource.",
"hostSettings": "Host",
"cidrSettings": "CIDR",
"gatewaySettings": "Exit Node",
"createInternalResourceDialogResourceProperties": "Resource Properties",
"createInternalResourceDialogName": "Name",
"createInternalResourceDialogSite": "Site",
@@ -2990,6 +2995,7 @@
"createInternalResourceDialogModeHttps": "HTTPS",
"createInternalResourceDialogModeSsh": "SSH",
"createInternalResourceDialogModeInference": "AI Gateway",
"createInternalResourceDialogModeGateway": "Exit Node",
"scheme": "Scheme",
"createInternalResourceDialogScheme": "Scheme",
"createInternalResourceDialogEnableSsl": "Enable TLS",
+1 -1
View File
@@ -493,7 +493,7 @@ export const siteResources = pgTable(
ssl: boolean("ssl").notNull().default(false),
mode: varchar("mode")
.$type<"host" | "cidr" | "http" | "ssh" | "inference" | "gateway">()
.notNull(), // "host" | "cidr" | "http"
.notNull(),
scheme: varchar("scheme").$type<"http" | "https">(), // only for when we are doing https or http mode
proxyPort: integer("proxyPort"), // only for port mode
destinationPort: integer("destinationPort"), // only for port mode
+1 -1
View File
@@ -514,7 +514,7 @@ export const siteResources = sqliteTable("siteResources", {
ssl: integer("ssl", { mode: "boolean" }).notNull().default(false),
mode: text("mode")
.$type<"host" | "cidr" | "http" | "ssh" | "inference" | "gateway">()
.notNull(), // "host" | "cidr" | "http"
.notNull(),
scheme: text("scheme").$type<"http" | "https">(), // only for when we are doing https or http mode
proxyPort: integer("proxyPort"), // only for port mode
destinationPort: integer("destinationPort"), // only for port mode
+21 -14
View File
@@ -108,15 +108,19 @@ export function PrivateResourceInfoSections({
tcpPortRangeString: siteResource.tcpPortRangeString ?? "*",
udpPortRangeString: siteResource.udpPortRangeString ?? "*"
});
const showAccess = siteResource.mode !== "gateway";
const showAlias =
siteResource.mode !== "cidr" &&
siteResource.mode !== "http" &&
siteResource.mode !== "inference";
siteResource.mode !== "inference" &&
siteResource.mode !== "gateway";
const showDestination =
!(
siteResource.mode === "ssh" &&
siteResource.authDaemonMode === "native"
) && siteResource.mode !== "inference";
) &&
siteResource.mode !== "inference" &&
siteResource.mode !== "gateway";
const showCertificate = !!(
(siteResource.mode === "http" || siteResource.mode === "inference") &&
siteResource.ssl &&
@@ -129,7 +133,8 @@ export function PrivateResourceInfoSections({
siteResource.mode !== "inference";
const numSections =
2 +
1 +
(showAccess ? 1 : 0) +
(showDestination ? 1 : 0) +
(showAlias ? 1 : 0) +
(showCertificate ? 1 : 0) +
@@ -144,17 +149,19 @@ export function PrivateResourceInfoSections({
</InfoSectionContent>
</InfoSection>
<InfoSection>
<InfoSectionTitle>{t("access")}</InfoSectionTitle>
<InfoSectionContent>
<AccessMethodContent
accessDisplay={access.accessDisplay}
accessCopyValue={access.accessCopyValue}
accessUrl={access.accessUrl}
className={accessClassName}
/>
</InfoSectionContent>
</InfoSection>
{showAccess ? (
<InfoSection>
<InfoSectionTitle>{t("access")}</InfoSectionTitle>
<InfoSectionContent>
<AccessMethodContent
accessDisplay={access.accessDisplay}
accessCopyValue={access.accessCopyValue}
accessUrl={access.accessUrl}
className={accessClassName}
/>
</InfoSectionContent>
</InfoSection>
) : null}
{showDestination ? (
<InfoSection>
+9 -1
View File
@@ -421,7 +421,14 @@ export function createCreateFormSchema(t: TranslateFn) {
.min(1, t("createInternalResourceDialogNameRequired"))
.max(255, t("createInternalResourceDialogNameMaxLength")),
siteIds: z.array(z.number().int().positive()).optional(),
mode: z.enum(["host", "cidr", "http", "ssh", "inference"]),
mode: z.enum([
"host",
"cidr",
"http",
"ssh",
"inference",
"gateway"
]),
destination: z.string().nullish(),
alias: z.string().nullish(),
destinationPort: z
@@ -468,6 +475,7 @@ export function createCreateFormSchema(t: TranslateFn) {
if (
data.mode !== "ssh" &&
data.mode !== "inference" &&
data.mode !== "gateway" &&
(!trimmedDestination || trimmedDestination.length < 1)
) {
ctx.addIssue({