From fe6e3b013e2a41617674620ecc94f1feb99dca18 Mon Sep 17 00:00:00 2001 From: Owen Date: Mon, 8 Sep 2025 17:50:07 -0700 Subject: [PATCH] Resource identified with niceId now --- server/db/names.ts | 21 ++++++++++++++++++- server/routers/resource/createResource.ts | 7 +++++++ .../authentication/page.tsx | 0 .../general/page.tsx | 0 .../{[resourceId] => [niceId]}/layout.tsx | 12 +++++------ .../{[resourceId] => [niceId]}/page.tsx | 4 ++-- .../{[resourceId] => [niceId]}/proxy/page.tsx | 6 +++--- .../{[resourceId] => [niceId]}/rules/page.tsx | 10 ++++----- src/components/ResourcesTable.tsx | 2 +- 9 files changed, 44 insertions(+), 18 deletions(-) rename src/app/[orgId]/settings/resources/{[resourceId] => [niceId]}/authentication/page.tsx (100%) rename src/app/[orgId]/settings/resources/{[resourceId] => [niceId]}/general/page.tsx (100%) rename src/app/[orgId]/settings/resources/{[resourceId] => [niceId]}/layout.tsx (89%) rename src/app/[orgId]/settings/resources/{[resourceId] => [niceId]}/page.tsx (53%) rename src/app/[orgId]/settings/resources/{[resourceId] => [niceId]}/proxy/page.tsx (99%) rename src/app/[orgId]/settings/resources/{[resourceId] => [niceId]}/rules/page.tsx (98%) diff --git a/server/db/names.ts b/server/db/names.ts index 41f4c170..9c671a22 100644 --- a/server/db/names.ts +++ b/server/db/names.ts @@ -1,6 +1,6 @@ import { join } from "path"; import { readFileSync } from "fs"; -import { db } from "@server/db"; +import { db, resources } from "@server/db"; import { exitNodes, sites } from "@server/db"; import { eq, and } from "drizzle-orm"; import { __DIRNAME } from "@server/lib/consts"; @@ -34,6 +34,25 @@ export async function getUniqueSiteName(orgId: string): Promise { } } +export async function getUniqueResourceName(orgId: string): Promise { + let loops = 0; + while (true) { + if (loops > 100) { + throw new Error("Could not generate a unique name"); + } + + const name = generateName(); + const count = await db + .select({ niceId: resources.niceId, orgId: resources.orgId }) + .from(resources) + .where(and(eq(resources.niceId, name), eq(resources.orgId, orgId))); + if (count.length === 0) { + return name; + } + loops++; + } +} + export async function getUniqueExitNodeEndpointName(): Promise { let loops = 0; const count = await db diff --git a/server/routers/resource/createResource.ts b/server/routers/resource/createResource.ts index e3e431ec..152b8f8c 100644 --- a/server/routers/resource/createResource.ts +++ b/server/routers/resource/createResource.ts @@ -21,6 +21,7 @@ import { subdomainSchema } from "@server/lib/schemas"; import config from "@server/lib/config"; import { OpenAPITags, registry } from "@server/openApi"; import { build } from "@server/build"; +import { getUniqueResourceName } from "@server/db/names"; const createResourceParamsSchema = z .object({ @@ -283,10 +284,13 @@ async function createHttpResource( let resource: Resource | undefined; + const niceId = await getUniqueResourceName(orgId); + await db.transaction(async (trx) => { const newResource = await trx .insert(resources) .values({ + niceId, fullDomain, domainId, orgId, @@ -391,10 +395,13 @@ async function createRawResource( let resource: Resource | undefined; + const niceId = await getUniqueResourceName(orgId); + await db.transaction(async (trx) => { const newResource = await trx .insert(resources) .values({ + niceId, orgId, name, http, diff --git a/src/app/[orgId]/settings/resources/[resourceId]/authentication/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/authentication/page.tsx similarity index 100% rename from src/app/[orgId]/settings/resources/[resourceId]/authentication/page.tsx rename to src/app/[orgId]/settings/resources/[niceId]/authentication/page.tsx diff --git a/src/app/[orgId]/settings/resources/[resourceId]/general/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/general/page.tsx similarity index 100% rename from src/app/[orgId]/settings/resources/[resourceId]/general/page.tsx rename to src/app/[orgId]/settings/resources/[niceId]/general/page.tsx diff --git a/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx b/src/app/[orgId]/settings/resources/[niceId]/layout.tsx similarity index 89% rename from src/app/[orgId]/settings/resources/[resourceId]/layout.tsx rename to src/app/[orgId]/settings/resources/[niceId]/layout.tsx index 8a5d0997..3f8425ce 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/layout.tsx +++ b/src/app/[orgId]/settings/resources/[niceId]/layout.tsx @@ -18,7 +18,7 @@ import { getTranslations } from 'next-intl/server'; interface ResourceLayoutProps { children: React.ReactNode; - params: Promise<{ resourceId: number | string; orgId: string }>; + params: Promise<{ niceId: string; orgId: string }>; } export default async function ResourceLayout(props: ResourceLayoutProps) { @@ -31,7 +31,7 @@ export default async function ResourceLayout(props: ResourceLayoutProps) { let resource = null; try { const res = await internal.get>( - `/resource/${params.resourceId}`, + `/org/${params.orgId}/resource/${params.niceId}`, await authCookieHeader() ); resource = res.data.data; @@ -77,22 +77,22 @@ export default async function ResourceLayout(props: ResourceLayoutProps) { const navItems = [ { title: t('general'), - href: `/{orgId}/settings/resources/{resourceId}/general` + href: `/{orgId}/settings/resources/{niceId}/general` }, { title: t('proxy'), - href: `/{orgId}/settings/resources/{resourceId}/proxy` + href: `/{orgId}/settings/resources/{niceId}/proxy` } ]; if (resource.http) { navItems.push({ title: t('authentication'), - href: `/{orgId}/settings/resources/{resourceId}/authentication` + href: `/{orgId}/settings/resources/{niceId}/authentication` }); navItems.push({ title: t('rules'), - href: `/{orgId}/settings/resources/{resourceId}/rules` + href: `/{orgId}/settings/resources/{niceId}/rules` }); } diff --git a/src/app/[orgId]/settings/resources/[resourceId]/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/page.tsx similarity index 53% rename from src/app/[orgId]/settings/resources/[resourceId]/page.tsx rename to src/app/[orgId]/settings/resources/[niceId]/page.tsx index a0d45a94..41995661 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/page.tsx +++ b/src/app/[orgId]/settings/resources/[niceId]/page.tsx @@ -1,10 +1,10 @@ import { redirect } from "next/navigation"; export default async function ResourcePage(props: { - params: Promise<{ resourceId: number | string; orgId: string }>; + params: Promise<{ niceId: string; orgId: string }>; }) { const params = await props.params; redirect( - `/${params.orgId}/settings/resources/${params.resourceId}/proxy` + `/${params.orgId}/settings/resources/${params.niceId}/proxy` ); } diff --git a/src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx similarity index 99% rename from src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx rename to src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx index 87c3dd13..27c795ef 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/proxy/page.tsx +++ b/src/app/[orgId]/settings/resources/[niceId]/proxy/page.tsx @@ -256,7 +256,7 @@ export default function ReverseProxyTargets(props: { const fetchTargets = async () => { try { const res = await api.get>( - `/resource/${params.resourceId}/targets` + `/resource/${resource.resourceId}/targets` ); if (res.status === 200) { @@ -447,7 +447,7 @@ export default function ReverseProxyTargets(props: { if (target.new) { const res = await api.put< AxiosResponse - >(`/resource/${params.resourceId}/target`, data); + >(`/resource/${resource.resourceId}/target`, data); target.targetId = res.data.data.targetId; target.new = false; } else if (target.updated) { @@ -475,7 +475,7 @@ export default function ReverseProxyTargets(props: { }; // Single API call to update all settings - await api.post(`/resource/${params.resourceId}`, payload); + await api.post(`/resource/${resource.resourceId}`, payload); // Update local resource context updateResource({ diff --git a/src/app/[orgId]/settings/resources/[resourceId]/rules/page.tsx b/src/app/[orgId]/settings/resources/[niceId]/rules/page.tsx similarity index 98% rename from src/app/[orgId]/settings/resources/[resourceId]/rules/page.tsx rename to src/app/[orgId]/settings/resources/[niceId]/rules/page.tsx index 424d7973..8b5e4709 100644 --- a/src/app/[orgId]/settings/resources/[resourceId]/rules/page.tsx +++ b/src/app/[orgId]/settings/resources/[niceId]/rules/page.tsx @@ -128,7 +128,7 @@ export default function ResourceRules(props: { try { const res = await api.get< AxiosResponse - >(`/resource/${params.resourceId}/rules`); + >(`/resource/${resource.resourceId}/rules`); if (res.status === 200) { setRules(res.data.data.rules); } @@ -251,7 +251,7 @@ export default function ResourceRules(props: { // Save rules enabled state const res = await api - .post(`/resource/${params.resourceId}`, { + .post(`/resource/${resource.resourceId}`, { applyRules: rulesEnabled }) .catch((err) => { @@ -336,13 +336,13 @@ export default function ResourceRules(props: { if (rule.new) { const res = await api.put( - `/resource/${params.resourceId}/rule`, + `/resource/${resource.resourceId}/rule`, data ); rule.ruleId = res.data.data.ruleId; } else if (rule.updated) { await api.post( - `/resource/${params.resourceId}/rule/${rule.ruleId}`, + `/resource/${resource.resourceId}/rule/${rule.ruleId}`, data ); } @@ -361,7 +361,7 @@ export default function ResourceRules(props: { for (const ruleId of rulesToRemove) { await api.delete( - `/resource/${params.resourceId}/rule/${ruleId}` + `/resource/${resource.resourceId}/rule/${ruleId}` ); setRules(rules.filter((r) => r.ruleId !== ruleId)); } diff --git a/src/components/ResourcesTable.tsx b/src/components/ResourcesTable.tsx index 8a62c14b..3352c4fa 100644 --- a/src/components/ResourcesTable.tsx +++ b/src/components/ResourcesTable.tsx @@ -481,7 +481,7 @@ export default function ResourcesTable({