mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-12 00:42:21 +02:00
move cert to info box and add network access to create wizard
This commit is contained in:
@@ -3585,6 +3585,7 @@
|
|||||||
"memberPortalResourceDisabled": "Resource Disabled",
|
"memberPortalResourceDisabled": "Resource Disabled",
|
||||||
"memberPortalShowingResources": "Showing {start}-{end} of {total} resources",
|
"memberPortalShowingResources": "Showing {start}-{end} of {total} resources",
|
||||||
"resourceLauncherTitle": "Resource Launcher",
|
"resourceLauncherTitle": "Resource Launcher",
|
||||||
|
"resourceSidebarLauncherTitle": "Launcher",
|
||||||
"resourceLauncherDescription": "View all available resources and launch them from one central hub",
|
"resourceLauncherDescription": "View all available resources and launch them from one central hub",
|
||||||
"resourceLauncherSearchPlaceholder": "Search your resources...",
|
"resourceLauncherSearchPlaceholder": "Search your resources...",
|
||||||
"resourceLauncherDefaultView": "Default",
|
"resourceLauncherDefaultView": "Default",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import CertificateStatus from "@app/components/CertificateStatus";
|
|
||||||
import DomainPicker from "@app/components/DomainPicker";
|
import DomainPicker from "@app/components/DomainPicker";
|
||||||
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
||||||
import {
|
import {
|
||||||
@@ -27,7 +26,6 @@ import {
|
|||||||
SelectValue
|
SelectValue
|
||||||
} from "@app/components/ui/select";
|
} from "@app/components/ui/select";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
import { build } from "@server/build";
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import type { Control, UseFormSetValue, UseFormWatch } from "react-hook-form";
|
import type { Control, UseFormSetValue, UseFormWatch } from "react-hook-form";
|
||||||
|
|
||||||
@@ -38,8 +36,6 @@ type PrivateResourceHttpFieldsProps = {
|
|||||||
watch: UseFormWatch<any>;
|
watch: UseFormWatch<any>;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
siteResourceId?: number;
|
siteResourceId?: number;
|
||||||
resourceDomainId?: string | null;
|
|
||||||
resourceFullDomain?: string | null;
|
|
||||||
labelPrefix?: "create" | "edit";
|
labelPrefix?: "create" | "edit";
|
||||||
hideDomainPicker?: boolean;
|
hideDomainPicker?: boolean;
|
||||||
hidePaidFeaturesAlert?: boolean;
|
hidePaidFeaturesAlert?: boolean;
|
||||||
@@ -52,8 +48,6 @@ export function PrivateResourceHttpFields({
|
|||||||
watch,
|
watch,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
siteResourceId,
|
siteResourceId,
|
||||||
resourceDomainId,
|
|
||||||
resourceFullDomain,
|
|
||||||
labelPrefix = "edit",
|
labelPrefix = "edit",
|
||||||
hideDomainPicker = false,
|
hideDomainPicker = false,
|
||||||
hidePaidFeaturesAlert = false
|
hidePaidFeaturesAlert = false
|
||||||
@@ -91,7 +85,6 @@ export function PrivateResourceHttpFields({
|
|||||||
const httpConfigSubdomain = watch("httpConfigSubdomain");
|
const httpConfigSubdomain = watch("httpConfigSubdomain");
|
||||||
const httpConfigDomainId = watch("httpConfigDomainId");
|
const httpConfigDomainId = watch("httpConfigDomainId");
|
||||||
const httpConfigFullDomain = watch("httpConfigFullDomain");
|
const httpConfigFullDomain = watch("httpConfigFullDomain");
|
||||||
const ssl = watch("ssl");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsFormGrid>
|
<SettingsFormGrid>
|
||||||
@@ -274,29 +267,6 @@ export function PrivateResourceHttpFields({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SettingsFormCell>
|
</SettingsFormCell>
|
||||||
{siteResourceId &&
|
|
||||||
resourceDomainId &&
|
|
||||||
httpConfigFullDomain &&
|
|
||||||
httpConfigDomainId === resourceDomainId &&
|
|
||||||
httpConfigFullDomain === resourceFullDomain &&
|
|
||||||
build != "oss" &&
|
|
||||||
ssl && (
|
|
||||||
<SettingsFormCell span="half">
|
|
||||||
<div className="flex items-center gap-2 pt-1">
|
|
||||||
<span className="text-sm font-medium">
|
|
||||||
{t("certificateStatus")}:
|
|
||||||
</span>
|
|
||||||
<CertificateStatus
|
|
||||||
orgId={orgId}
|
|
||||||
domainId={resourceDomainId}
|
|
||||||
fullDomain={httpConfigFullDomain}
|
|
||||||
autoFetch={true}
|
|
||||||
showLabel={false}
|
|
||||||
polling={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</SettingsFormCell>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -122,12 +122,6 @@ export default function PrivateResourceHttpPage() {
|
|||||||
watch={asAnyWatch(form.watch)}
|
watch={asAnyWatch(form.watch)}
|
||||||
disabled={httpSectionDisabled}
|
disabled={httpSectionDisabled}
|
||||||
siteResourceId={siteResource.id}
|
siteResourceId={siteResource.id}
|
||||||
resourceDomainId={
|
|
||||||
siteResource.domainId
|
|
||||||
}
|
|
||||||
resourceFullDomain={
|
|
||||||
siteResource.fullDomain
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</SettingsFormCell>
|
</SettingsFormCell>
|
||||||
</SettingsFormGrid>
|
</SettingsFormGrid>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import { z } from "zod";
|
|||||||
import { PrivateResourceSitesField } from "../PrivateResourceSitesField";
|
import { PrivateResourceSitesField } from "../PrivateResourceSitesField";
|
||||||
import { PrivateResourceHttpFields } from "../PrivateResourceHttpFields";
|
import { PrivateResourceHttpFields } from "../PrivateResourceHttpFields";
|
||||||
import { PrivateResourceSshFields } from "../PrivateResourceSshFields";
|
import { PrivateResourceSshFields } from "../PrivateResourceSshFields";
|
||||||
|
import { PrivateResourcePortRanges } from "../PrivateResourcePortRanges";
|
||||||
import {
|
import {
|
||||||
PrivateResourceAliasField,
|
PrivateResourceAliasField,
|
||||||
PrivateResourceCidrDestinationField,
|
PrivateResourceCidrDestinationField,
|
||||||
@@ -105,6 +106,8 @@ export default function CreatePrivateResourcePage() {
|
|||||||
standardDaemonLocation: "site",
|
standardDaemonLocation: "site",
|
||||||
authDaemonPort: null,
|
authDaemonPort: null,
|
||||||
pamMode: "passthrough",
|
pamMode: "passthrough",
|
||||||
|
tcpPortRangeString: "*",
|
||||||
|
udpPortRangeString: "*",
|
||||||
disableIcmp: false
|
disableIcmp: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -426,6 +429,16 @@ export default function CreatePrivateResourcePage() {
|
|||||||
hideAlias
|
hideAlias
|
||||||
/>
|
/>
|
||||||
</SettingsFormCell>
|
</SettingsFormCell>
|
||||||
|
<SettingsFormCell span="full">
|
||||||
|
<PrivateResourcePortRanges
|
||||||
|
control={asAnyControl(
|
||||||
|
form.control
|
||||||
|
)}
|
||||||
|
setValue={asAnySetValue(
|
||||||
|
form.setValue
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SettingsFormCell>
|
||||||
</SettingsFormGrid>
|
</SettingsFormGrid>
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
@@ -466,6 +479,16 @@ export default function CreatePrivateResourcePage() {
|
|||||||
labelPrefix="create"
|
labelPrefix="create"
|
||||||
/>
|
/>
|
||||||
</SettingsFormCell>
|
</SettingsFormCell>
|
||||||
|
<SettingsFormCell span="full">
|
||||||
|
<PrivateResourcePortRanges
|
||||||
|
control={asAnyControl(
|
||||||
|
form.control
|
||||||
|
)}
|
||||||
|
setValue={asAnySetValue(
|
||||||
|
form.setValue
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SettingsFormCell>
|
||||||
</SettingsFormGrid>
|
</SettingsFormGrid>
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ export function LayoutMobileMenu({
|
|||||||
</span>
|
</span>
|
||||||
<span className="flex-1">
|
<span className="flex-1">
|
||||||
{t(
|
{t(
|
||||||
"resourceLauncherTitle"
|
"resourceSidebarLauncherTitle"
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ export function LayoutSidebar({
|
|||||||
sideOffset={8}
|
sideOffset={8}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
{t("resourceLauncherTitle")}
|
{t("resourceSidebarLauncherTitle")}
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -211,7 +211,7 @@ export function LayoutSidebar({
|
|||||||
<SquareMousePointer className="h-4 w-4" />
|
<SquareMousePointer className="h-4 w-4" />
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-1">
|
<span className="flex-1">
|
||||||
{t("resourceLauncherTitle")}
|
{t("resourceSidebarLauncherTitle")}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import CertificateStatus from "@app/components/CertificateStatus";
|
||||||
import CopyToClipboard from "@app/components/CopyToClipboard";
|
import CopyToClipboard from "@app/components/CopyToClipboard";
|
||||||
import {
|
import {
|
||||||
InfoSection,
|
InfoSection,
|
||||||
@@ -17,14 +18,17 @@ import {
|
|||||||
type LauncherAccessFields
|
type LauncherAccessFields
|
||||||
} from "@app/lib/launcherResourceAccess";
|
} from "@app/lib/launcherResourceAccess";
|
||||||
import type { PrivateResourceMode } from "@app/lib/privateResourceForm";
|
import type { PrivateResourceMode } from "@app/lib/privateResourceForm";
|
||||||
|
import { build } from "@server/build";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
type SiteResourceInfoInput = {
|
type SiteResourceInfoInput = {
|
||||||
|
orgId: string;
|
||||||
mode: PrivateResourceMode;
|
mode: PrivateResourceMode;
|
||||||
destination: string | null;
|
destination: string | null;
|
||||||
destinationPort: number | null;
|
destinationPort: number | null;
|
||||||
scheme: "http" | "https" | null;
|
scheme: "http" | "https" | null;
|
||||||
ssl: boolean;
|
ssl: boolean;
|
||||||
|
domainId?: string | null;
|
||||||
fullDomain?: string | null;
|
fullDomain?: string | null;
|
||||||
alias?: string | null;
|
alias?: string | null;
|
||||||
aliasAddress?: string | null;
|
aliasAddress?: string | null;
|
||||||
@@ -108,9 +112,20 @@ export function SiteResourceInfoSections({
|
|||||||
const showDestination = !(
|
const showDestination = !(
|
||||||
siteResource.mode === "ssh" && siteResource.authDaemonMode === "native"
|
siteResource.mode === "ssh" && siteResource.authDaemonMode === "native"
|
||||||
);
|
);
|
||||||
|
const showCertificate = !!(
|
||||||
|
siteResource.mode === "http" &&
|
||||||
|
siteResource.ssl &&
|
||||||
|
siteResource.domainId &&
|
||||||
|
siteResource.fullDomain &&
|
||||||
|
build != "oss"
|
||||||
|
);
|
||||||
|
|
||||||
const numSections =
|
const numSections =
|
||||||
2 + (showDestination ? 1 : 0) + (showAlias ? 1 : 0) + (isPanel ? 1 : 0);
|
2 +
|
||||||
|
(showDestination ? 1 : 0) +
|
||||||
|
(showAlias ? 1 : 0) +
|
||||||
|
(showCertificate ? 1 : 0) +
|
||||||
|
(isPanel ? 1 : 0);
|
||||||
|
|
||||||
const sections = (
|
const sections = (
|
||||||
<InfoSections cols={numSections} layout={isPanel ? "panel" : "default"}>
|
<InfoSections cols={numSections} layout={isPanel ? "panel" : "default"}>
|
||||||
@@ -155,6 +170,26 @@ export function SiteResourceInfoSections({
|
|||||||
</InfoSection>
|
</InfoSection>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{showCertificate ? (
|
||||||
|
<InfoSection>
|
||||||
|
<InfoSectionTitle>
|
||||||
|
{t("certificateStatus", {
|
||||||
|
defaultValue: "Certificate"
|
||||||
|
})}
|
||||||
|
</InfoSectionTitle>
|
||||||
|
<InfoSectionContent>
|
||||||
|
<CertificateStatus
|
||||||
|
orgId={siteResource.orgId}
|
||||||
|
domainId={siteResource.domainId!}
|
||||||
|
fullDomain={siteResource.fullDomain!}
|
||||||
|
autoFetch={true}
|
||||||
|
showLabel={false}
|
||||||
|
polling={true}
|
||||||
|
/>
|
||||||
|
</InfoSectionContent>
|
||||||
|
</InfoSection>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{isPanel ? (
|
{isPanel ? (
|
||||||
<InfoSection>
|
<InfoSection>
|
||||||
<InfoSectionTitle>{t("portRestrictions")}</InfoSectionTitle>
|
<InfoSectionTitle>{t("portRestrictions")}</InfoSectionTitle>
|
||||||
|
|||||||
@@ -400,6 +400,8 @@ export function createCreateFormSchema(t: TranslateFn) {
|
|||||||
.nullable(),
|
.nullable(),
|
||||||
authDaemonPort: z.number().int().positive().optional().nullable(),
|
authDaemonPort: z.number().int().positive().optional().nullable(),
|
||||||
pamMode: z.enum(["passthrough", "push"]).optional().nullable(),
|
pamMode: z.enum(["passthrough", "push"]).optional().nullable(),
|
||||||
|
tcpPortRangeString: createPortRangeStringSchema(t),
|
||||||
|
udpPortRangeString: createPortRangeStringSchema(t),
|
||||||
disableIcmp: z.boolean().optional()
|
disableIcmp: z.boolean().optional()
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user