Move proxy and client to public and private

This commit is contained in:
Owen 2026-05-31 17:30:31 -07:00
parent b99e9a6468
commit 08a2923cfc
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD
25 changed files with 53 additions and 81 deletions

View file

@ -22,7 +22,21 @@ const nextConfig: NextConfig = {
reactCompiler: true, reactCompiler: true,
transpilePackages: ["@novnc/novnc"], transpilePackages: ["@novnc/novnc"],
output: "standalone", output: "standalone",
allowedDevOrigins allowedDevOrigins,
async redirects() {
return [
{
source: "/:orgId/settings/resources/proxy/:path*",
destination: "/:orgId/settings/resources/public/:path*",
permanent: true
},
{
source: "/:orgId/settings/resources/client/:path*",
destination: "/:orgId/settings/resources/private/:path*",
permanent: true
}
];
}
}; };
export default withNextIntl(nextConfig); export default withNextIntl(nextConfig);

View file

@ -343,8 +343,8 @@ export default function GeneralPage() {
<Link <Link
href={ href={
row.original.type === "ssh" row.original.type === "ssh"
? `/${row.original.orgId}/settings/resources/client?query=${row.original.resourceNiceId}` ? `/${row.original.orgId}/settings/resources/private?query=${row.original.resourceNiceId}`
: `/${row.original.orgId}/settings/resources/proxy/${row.original.resourceNiceId}` : `/${row.original.orgId}/settings/resources/public/${row.original.resourceNiceId}`
} }
> >
<Button variant="outline" size="sm"> <Button variant="outline" size="sm">

View file

@ -325,7 +325,7 @@ export default function ConnectionLogsPage() {
if (row.original.resourceName && row.original.resourceNiceId) { if (row.original.resourceName && row.original.resourceNiceId) {
return ( return (
<Link <Link
href={`/${row.original.orgId}/settings/resources/client/?query=${row.original.resourceNiceId}`} href={`/${row.original.orgId}/settings/resources/private/?query=${row.original.resourceNiceId}`}
> >
<Button variant="outline" size="sm"> <Button variant="outline" size="sm">
{row.original.resourceName} {row.original.resourceName}

View file

@ -400,8 +400,8 @@ export default function GeneralPage() {
<Link <Link
href={ href={
row.original.reason == 108 // for now the client will only have reason 108 so we know where to go row.original.reason == 108 // for now the client will only have reason 108 so we know where to go
? `/${row.original.orgId}/settings/resources/client?query=${row.original.resourceNiceId}` ? `/${row.original.orgId}/settings/resources/private?query=${row.original.resourceNiceId}`
: `/${row.original.orgId}/settings/resources/proxy/${row.original.resourceNiceId}` : `/${row.original.orgId}/settings/resources/public/${row.original.resourceNiceId}`
} }
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >

View file

@ -11,5 +11,5 @@ export interface ResourcesPageProps {
export default async function ResourcesPage(props: ResourcesPageProps) { export default async function ResourcesPage(props: ResourcesPageProps) {
const params = await props.params; const params = await props.params;
redirect(`/${params.orgId}/settings/resources/proxy`); redirect(`/${params.orgId}/settings/resources/public`);
} }

View file

@ -1,5 +1,5 @@
import type { InternalResourceRow } from "@app/components/ClientResourcesTable"; import type { InternalResourceRow } from "@app/components/PrivateResourcesTable";
import PrivateResourcesTable from "@app/components/ClientResourcesTable"; import PrivateResourcesTable from "@app/components/PrivateResourcesTable";
import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
import PrivateResourcesBanner from "@app/components/PrivateResourcesBanner"; import PrivateResourcesBanner from "@app/components/PrivateResourcesBanner";
import { internal } from "@app/lib/api"; import { internal } from "@app/lib/api";

View file

@ -548,7 +548,7 @@ export default function GeneralForm() {
if (data.niceId && data.niceId !== resource?.niceId) { if (data.niceId && data.niceId !== resource?.niceId) {
router.replace( router.replace(
`/${updated.orgId}/settings/resources/proxy/${data.niceId}/general` `/${updated.orgId}/settings/resources/public/${data.niceId}/general`
); );
} }

View file

@ -39,69 +39,27 @@ import {
FormLabel, FormLabel,
FormMessage FormMessage
} from "@app/components/ui/form"; } from "@app/components/ui/form";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow
} from "@app/components/ui/table";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from "@app/components/ui/tooltip";
import type { ResourceContextType } from "@app/contexts/resourceContext"; import type { ResourceContextType } from "@app/contexts/resourceContext";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
import { useResourceContext } from "@app/hooks/useResourceContext"; import { useResourceContext } from "@app/hooks/useResourceContext";
import { toast } from "@app/hooks/useToast"; import { toast } from "@app/hooks/useToast";
import { createApiClient } from "@app/lib/api"; import { createApiClient } from "@app/lib/api";
import { formatAxiosError } from "@app/lib/api/formatAxiosError"; import { formatAxiosError } from "@app/lib/api/formatAxiosError";
import { DockerManager, DockerState } from "@app/lib/docker"; import { resourceQueries } from "@app/lib/queries";
import { orgQueries, resourceQueries } from "@app/lib/queries";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { build } from "@server/build";
import { tlsNameSchema } from "@server/lib/schemas"; import { tlsNameSchema } from "@server/lib/schemas";
import { type GetResourceResponse } from "@server/routers/resource";
import type { ListSitesResponse } from "@server/routers/site";
import { CreateTargetResponse } from "@server/routers/target";
import { ListTargetsResponse } from "@server/routers/target/listTargets";
import { ArrayElement } from "@server/types/ArrayElement";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { import {
LocalTarget,
ProxyResourceTargetsForm ProxyResourceTargetsForm
} from "@app/app/[orgId]/settings/resources/proxy/ProxyResourceTargetsForm"; } from "@app/app/[orgId]/settings/resources/public/ProxyResourceTargetsForm";
import {
ColumnDef,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from "@tanstack/react-table";
import { AxiosResponse } from "axios";
import { import {
AlertTriangle, AlertTriangle,
CircleCheck,
CircleX,
ExternalLink,
Info,
Plus,
Settings
} from "lucide-react"; } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { import {
use, use,
useActionState, useActionState,
useCallback,
useEffect,
useMemo,
useState
} from "react"; } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";

View file

@ -83,22 +83,22 @@ export default async function ResourceLayout(props: ResourceLayoutProps) {
const navItems = [ const navItems = [
{ {
title: t("general"), title: t("general"),
href: `/{orgId}/settings/resources/proxy/{niceId}/general` href: `/{orgId}/settings/resources/public/{niceId}/general`
}, },
{ {
title: t(`${resource.mode}Settings`), title: t(`${resource.mode}Settings`),
href: `/{orgId}/settings/resources/proxy/{niceId}/${resource.mode}` href: `/{orgId}/settings/resources/public/{niceId}/${resource.mode}`
} }
]; ];
if (["http", "ssh", "rdp", "vnc"].includes(resource.mode)) { if (["http", "ssh", "rdp", "vnc"].includes(resource.mode)) {
navItems.push({ navItems.push({
title: t("authentication"), title: t("authentication"),
href: `/{orgId}/settings/resources/proxy/{niceId}/authentication` href: `/{orgId}/settings/resources/public/{niceId}/authentication`
}); });
// navItems.push({ // navItems.push({
// title: t("rules"), // title: t("rules"),
// href: `/{orgId}/settings/resources/proxy/{niceId}/rules` // href: `/{orgId}/settings/resources/public/{niceId}/rules`
// }); // });
} }

View file

@ -10,6 +10,6 @@ export default async function ResourcePage(props: {
}) { }) {
const params = await props.params; const params = await props.params;
redirect( redirect(
`/${params.orgId}/settings/resources/proxy/${params.niceId}/general` `/${params.orgId}/settings/resources/public/${params.niceId}/general`
); );
} }

View file

@ -89,7 +89,7 @@ import { useQuery } from "@tanstack/react-query";
import { import {
LocalTarget, LocalTarget,
ProxyResourceTargetsForm ProxyResourceTargetsForm
} from "@app/app/[orgId]/settings/resources/proxy/ProxyResourceTargetsForm"; } from "@app/app/[orgId]/settings/resources/public/ProxyResourceTargetsForm";
import { import {
ColumnDef, ColumnDef,
flexRender, flexRender,
@ -514,7 +514,7 @@ export default function Page() {
} }
} }
router.push( router.push(
`/${orgId}/settings/resources/proxy/${newNiceId}` `/${orgId}/settings/resources/public/${newNiceId}`
); );
} else if (resourceType === "ssh") { } else if (resourceType === "ssh") {
if (isNative) { if (isNative) {
@ -550,7 +550,7 @@ export default function Page() {
} }
router.push( router.push(
`/${orgId}/settings/resources/proxy/${newNiceId}` `/${orgId}/settings/resources/public/${newNiceId}`
); );
} else if (resourceType === "rdp" || resourceType === "vnc") { } else if (resourceType === "rdp" || resourceType === "vnc") {
for (const site of bgSelectedSites) { for (const site of bgSelectedSites) {
@ -566,7 +566,7 @@ export default function Page() {
} }
router.push( router.push(
`/${orgId}/settings/resources/proxy/${newNiceId}` `/${orgId}/settings/resources/public/${newNiceId}`
); );
} else { } else {
// TCP / UDP — create targets then show snippets // TCP / UDP — create targets then show snippets
@ -1308,7 +1308,7 @@ export default function Page() {
type="button" type="button"
onClick={() => onClick={() =>
router.push( router.push(
`/${orgId}/settings/resources/proxy/${niceId}` `/${orgId}/settings/resources/public/${niceId}`
) )
} }
> >

View file

@ -71,12 +71,12 @@ export const orgNavSections = (
items: [ items: [
{ {
title: "sidebarProxyResources", title: "sidebarProxyResources",
href: "/{orgId}/settings/resources/proxy", href: "/{orgId}/settings/resources/public",
icon: <Globe className="size-4 flex-none" /> icon: <Globe className="size-4 flex-none" />
}, },
{ {
title: "sidebarClientResources", title: "sidebarClientResources",
href: "/{orgId}/settings/resources/client", href: "/{orgId}/settings/resources/private",
icon: <GlobeLock className="size-4 flex-none" /> icon: <GlobeLock className="size-4 flex-none" />
} }
] ]

View file

@ -406,7 +406,7 @@ export default function HealthChecksTable({
} }
return ( return (
<Link <Link
href={`/${orgId}/settings/resources/proxy/${r.resourceNiceId}`} href={`/${orgId}/settings/resources/public/${r.resourceNiceId}`}
> >
<Button variant="outline" size="sm"> <Button variant="outline" size="sm">
{r.resourceName} {r.resourceName}
@ -627,7 +627,7 @@ export default function HealthChecksTable({
</DropdownMenu> </DropdownMenu>
{r.resourceId && r.resourceName && r.resourceNiceId ? ( {r.resourceId && r.resourceName && r.resourceNiceId ? (
<Link <Link
href={`/${orgId}/settings/resources/proxy/${r.resourceNiceId}`} href={`/${orgId}/settings/resources/public/${r.resourceNiceId}`}
> >
<Button variant="outline" disabled={!isPaid}> <Button variant="outline" disabled={!isPaid}>
{t("edit")} {t("edit")}

View file

@ -609,7 +609,7 @@ export default function ProxyResourcesTable({
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<Link <Link
className="block w-full" className="block w-full"
href={`/${resourceRow.orgId}/settings/resources/proxy/${resourceRow.nice}`} href={`/${resourceRow.orgId}/settings/resources/public/${resourceRow.nice}`}
> >
<DropdownMenuItem> <DropdownMenuItem>
{t("viewSettings")} {t("viewSettings")}
@ -628,7 +628,7 @@ export default function ProxyResourcesTable({
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
<Link <Link
href={`/${resourceRow.orgId}/settings/resources/proxy/${resourceRow.nice}`} href={`/${resourceRow.orgId}/settings/resources/public/${resourceRow.nice}`}
> >
<Button variant={"outline"}> <Button variant={"outline"}>
{t("edit")} {t("edit")}
@ -744,7 +744,9 @@ export default function ProxyResourcesTable({
onPaginationChange={handlePaginationChange} onPaginationChange={handlePaginationChange}
onAdd={() => onAdd={() =>
startNavigation(() => startNavigation(() =>
router.push(`/${orgId}/settings/resources/proxy/create`) router.push(
`/${orgId}/settings/resources/public/create`
)
) )
} }
addButtonText={t("resourceAdd")} addButtonText={t("resourceAdd")}

View file

@ -145,7 +145,7 @@ export default function ShareLinksTable({
const r = row.original; const r = row.original;
return ( return (
<Link <Link
href={`/${orgId}/settings/resources/proxy/${r.resourceNiceId}`} href={`/${orgId}/settings/resources/public/${r.resourceNiceId}`}
> >
<Button variant="outline" size="sm"> <Button variant="outline" size="sm">
{r.resourceName} {r.resourceName}
@ -328,9 +328,7 @@ export default function ShareLinksTable({
onConfirm={async () => onConfirm={async () =>
deleteSharelink(selectedLink.accessTokenId) deleteSharelink(selectedLink.accessTokenId)
} }
string={ string={selectedLink.title || selectedLink.resourceName}
selectedLink.title || selectedLink.resourceName
}
title={t("shareDelete")} title={t("shareDelete")}
/> />
)} )}

View file

@ -421,15 +421,15 @@ export default function SiteResourcesOverview({
publicList.length === 0 && publicList.length === 0 &&
privateList.length === 0; privateList.length === 0;
const publicViewAllHref = `/${orgId}/settings/resources/proxy?siteId=${siteId}`; const publicViewAllHref = `/${orgId}/settings/resources/public?siteId=${siteId}`;
const privateViewAllHref = `/${orgId}/settings/resources/client?siteId=${siteId}`; const privateViewAllHref = `/${orgId}/settings/resources/private?siteId=${siteId}`;
const publicRows = publicList.map((r) => ({ const publicRows = publicList.map((r) => ({
key: r.resourceId, key: r.resourceId,
meta: <PublicResourceMeta resource={r} />, meta: <PublicResourceMeta resource={r} />,
name: r.name, name: r.name,
access: <PublicAccessMethod resource={r} />, access: <PublicAccessMethod resource={r} />,
editHref: `/${orgId}/settings/resources/proxy/${r.niceId}` editHref: `/${orgId}/settings/resources/public/${r.niceId}`
})); }));
const privateRows = privateList.map((row) => { const privateRows = privateList.map((row) => {
@ -442,7 +442,7 @@ export default function SiteResourcesOverview({
meta: <PrivateResourceMeta row={row} />, meta: <PrivateResourceMeta row={row} />,
name: row.name, name: row.name,
access: <PrivateAccessMethod row={row} />, access: <PrivateAccessMethod row={row} />,
editHref: `/${orgId}/settings/resources/client?${qs.toString()}` editHref: `/${orgId}/settings/resources/private?${qs.toString()}`
}; };
}); });

View file

@ -506,7 +506,7 @@ export default function SitesTable({
</Link> </Link>
<Link <Link
className="block w-full" className="block w-full"
href={`/${siteRow.orgId}/settings/resources/proxy?siteId=${siteRow.id}`} href={`/${siteRow.orgId}/settings/resources/public?siteId=${siteRow.id}`}
> >
<DropdownMenuItem> <DropdownMenuItem>
{t("sitesTableViewPublicResources")} {t("sitesTableViewPublicResources")}
@ -514,7 +514,7 @@ export default function SitesTable({
</Link> </Link>
<Link <Link
className="block w-full" className="block w-full"
href={`/${siteRow.orgId}/settings/resources/client?siteId=${siteRow.id}`} href={`/${siteRow.orgId}/settings/resources/private?siteId=${siteRow.id}`}
> >
<DropdownMenuItem> <DropdownMenuItem>
{t( {t(