diff --git a/bruno/Sites/Get Site.bru b/bruno/Sites/Get Site.bru new file mode 100644 index 00000000..09ffa6c8 --- /dev/null +++ b/bruno/Sites/Get Site.bru @@ -0,0 +1,11 @@ +meta { + name: Get Site + type: http + seq: 2 +} + +get { + url: http://localhost:3000/api/v1/org/theorg/sites/mexican-mole-lizard-windy + body: none + auth: none +} diff --git a/server/db/names.ts b/server/db/names.ts index 2e76bdf2..06982432 100644 --- a/server/db/names.ts +++ b/server/db/names.ts @@ -12,7 +12,7 @@ export const names = JSON.parse(readFileSync(file, 'utf-8')); export function getUniqueName(): string { return ( - names.animals[Math.floor(Math.random() * names.animals.length)] + - names.descriptor[Math.floor(Math.random() * names.descriptor.length)] - ).toLowerCase(); + names.descriptors[Math.floor(Math.random() * names.descriptors.length)] + "-" + + names.animals[Math.floor(Math.random() * names.animals.length)] + ).toLowerCase().replace(/\s/g, '-'); } \ No newline at end of file diff --git a/server/routers/external.ts b/server/routers/external.ts index 33f5e9fd..7fd0c69e 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -44,10 +44,12 @@ authenticated.delete("/org/:orgId", verifyOrgAccess, org.deleteOrg); authenticated.put("/org/:orgId/site", verifyOrgAccess, site.createSite); authenticated.get("/org/:orgId/sites", verifyOrgAccess, site.listSites); -authenticated.get("/site/:siteId", verifySiteAccess, site.getSite); -authenticated.get("/site/:siteId/roles", verifySiteAccess, site.listSiteRoles); -authenticated.post("/site/:siteId", verifySiteAccess, site.updateSite); -authenticated.delete("/site/:siteId", verifySiteAccess, site.deleteSite); +authenticated.get("/org/:orgId/site/:niceId", verifyOrgAccess, site.getSite); + +authenticated.get("/site/siteId/:siteId", verifySiteAccess, site.getSite); +authenticated.get("/site/siteId/:siteId/roles", verifySiteAccess, site.listSiteRoles); +authenticated.post("/site/siteId/:siteId", verifySiteAccess, site.updateSite); +authenticated.delete("/site/siteId/:siteId", verifySiteAccess, site.deleteSite); authenticated.put( "/org/:orgId/site/:siteId/resource", diff --git a/server/routers/site/createSite.ts b/server/routers/site/createSite.ts index abef0b35..d8ae8986 100644 --- a/server/routers/site/createSite.ts +++ b/server/routers/site/createSite.ts @@ -82,7 +82,6 @@ export async function createSite(req: Request, res: Response, next: NextFunction orgId, name, niceId, - subdomain, pubKey, subnet, }).returning(); @@ -129,7 +128,7 @@ export async function createSite(req: Request, res: Response, next: NextFunction status: HttpCode.CREATED, }); } catch (error) { - logger.error(error); + throw error; return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred...")); } } diff --git a/server/routers/site/getSite.ts b/server/routers/site/getSite.ts index 85afe11f..79701750 100644 --- a/server/routers/site/getSite.ts +++ b/server/routers/site/getSite.ts @@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express'; import { z } from 'zod'; import { db } from '@server/db'; import { sites } from '@server/db/schema'; -import { eq } from 'drizzle-orm'; +import { eq, and } from 'drizzle-orm'; import response from "@server/utils/response"; import HttpCode from '@server/types/HttpCode'; import createHttpError from 'http-errors'; @@ -11,7 +11,9 @@ import logger from '@server/logger'; // Define Zod schema for request parameters validation const getSiteSchema = z.object({ - siteId: z.string().transform(Number).pipe(z.number().int().positive()) + siteId: z.string().transform(Number).pipe(z.number().int().positive()).optional(), + niceId: z.string().optional(), + orgId: z.string().optional(), }); export type GetSiteResponse = { @@ -34,7 +36,7 @@ export async function getSite(req: Request, res: Response, next: NextFunction): ); } - const { siteId } = parsedParams.data; + const { siteId, niceId, orgId } = parsedParams.data; // Check if the user has permission to list sites const hasPermission = await checkUserActionPermission(ActionsEnum.updateSite, req); @@ -42,11 +44,23 @@ export async function getSite(req: Request, res: Response, next: NextFunction): return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action')); } + let site; // Fetch the site from the database - const site = await db.select() - .from(sites) - .where(eq(sites.siteId, siteId)) - .limit(1); + if (siteId) { + site = await db.select() + .from(sites) + .where(eq(sites.siteId, siteId)) + .limit(1); + } else if (niceId && orgId) { + site = await db.select() + .from(sites) + .where(and(eq(sites.niceId, niceId), eq(sites.orgId, orgId))) + .limit(1); + } + + if (!site) { + return next(createHttpError(HttpCode.NOT_FOUND, 'Site not found')); + } if (site.length === 0) { return next( @@ -60,8 +74,8 @@ export async function getSite(req: Request, res: Response, next: NextFunction): return response(res, { data: { siteId: site[0].siteId, + niceId: site[0].niceId, name: site[0].name, - subdomain: site[0].subdomain, subnet: site[0].subnet, }, success: true, @@ -70,7 +84,7 @@ export async function getSite(req: Request, res: Response, next: NextFunction): status: HttpCode.OK, }); } catch (error) { - logger.error(error); + logger.error("Error from getSite: ", error); return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred...")); } } diff --git a/server/routers/site/listSites.ts b/server/routers/site/listSites.ts index 1a8c6fcd..7fc05cf3 100644 --- a/server/routers/site/listSites.ts +++ b/server/routers/site/listSites.ts @@ -32,6 +32,7 @@ function querySites(orgId: string, accessibleSiteIds: number[]) { return db .select({ siteId: sites.siteId, + niceId: sites.niceId, name: sites.name, pubKey: sites.pubKey, subnet: sites.subnet, diff --git a/src/app/[orgId]/sites/[siteId]/appearance/page.tsx b/src/app/[orgId]/sites/[niceId]/appearance/page.tsx similarity index 100% rename from src/app/[orgId]/sites/[siteId]/appearance/page.tsx rename to src/app/[orgId]/sites/[niceId]/appearance/page.tsx diff --git a/src/app/[orgId]/sites/[siteId]/components/create-site.tsx b/src/app/[orgId]/sites/[niceId]/components/create-site.tsx similarity index 92% rename from src/app/[orgId]/sites/[siteId]/components/create-site.tsx rename to src/app/[orgId]/sites/[niceId]/components/create-site.tsx index 85ab2d1d..8bc86165 100644 --- a/src/app/[orgId]/sites/[siteId]/components/create-site.tsx +++ b/src/app/[orgId]/sites/[niceId]/components/create-site.tsx @@ -8,14 +8,6 @@ import { z } from "zod" import { cn } from "@/lib/utils" import { toast } from "@/hooks/use-toast" import { Button, buttonVariants } from "@/components/ui/button" -import { - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, -} from "@/components/ui/command" import { Form, FormControl, @@ -26,15 +18,9 @@ import { FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover" import { generateKeypair } from "./wireguard-config"; import React, { useState, useEffect } from "react"; import { api } from "@/api"; -import { AxiosResponse } from "axios" import { useParams } from "next/navigation"; import { useRouter } from "next/navigation"; import { Checkbox } from "@app/components/ui/checkbox" @@ -89,12 +75,6 @@ export function CreateSiteForm() { } }, []); - // const name = form.watch("name"); - // useEffect(() => { - // const subdomain = name.toLowerCase().replace(/\s+/g, "-"); - // form.setValue("subdomain", subdomain, { shouldValidate: true }); - // }, [name, form]); - async function onSubmit(data: AccountFormValues) { const res = await api .put(`/org/${orgId}/site/`, { @@ -109,9 +89,9 @@ export function CreateSiteForm() { }); if (res && res.status === 201) { - const siteId = res.data.data.siteId; + const niceId = res.data.data.niceId; // navigate to the site page - router.push(`/${orgId}/sites/${siteId}`); + router.push(`/${orgId}/sites/${niceId}`); } } diff --git a/src/app/[orgId]/sites/[siteId]/components/newt-config.tsx b/src/app/[orgId]/sites/[niceId]/components/newt-config.tsx similarity index 100% rename from src/app/[orgId]/sites/[siteId]/components/newt-config.tsx rename to src/app/[orgId]/sites/[niceId]/components/newt-config.tsx diff --git a/src/app/[orgId]/sites/[siteId]/components/wireguard-config.ts b/src/app/[orgId]/sites/[niceId]/components/wireguard-config.ts similarity index 100% rename from src/app/[orgId]/sites/[siteId]/components/wireguard-config.ts rename to src/app/[orgId]/sites/[niceId]/components/wireguard-config.ts diff --git a/src/app/[orgId]/sites/[siteId]/display/page.tsx b/src/app/[orgId]/sites/[niceId]/display/page.tsx similarity index 100% rename from src/app/[orgId]/sites/[siteId]/display/page.tsx rename to src/app/[orgId]/sites/[niceId]/display/page.tsx diff --git a/src/app/[orgId]/sites/[siteId]/layout.tsx b/src/app/[orgId]/sites/[niceId]/layout.tsx similarity index 85% rename from src/app/[orgId]/sites/[siteId]/layout.tsx rename to src/app/[orgId]/sites/[niceId]/layout.tsx index 973323c3..84fdb88c 100644 --- a/src/app/[orgId]/sites/[siteId]/layout.tsx +++ b/src/app/[orgId]/sites/[niceId]/layout.tsx @@ -18,32 +18,32 @@ export const metadata: Metadata = { const sidebarNavItems = [ { title: "Profile", - href: "/{orgId}/sites/{siteId}", + href: "/{orgId}/sites/{niceId}", }, { title: "Appearance", - href: "/{orgId}/sites/{siteId}/appearance", + href: "/{orgId}/sites/{niceId}/appearance", }, { title: "Notifications", - href: "/{orgId}/sites/{siteId}/notifications", + href: "/{orgId}/sites/{niceId}/notifications", }, { title: "Display", - href: "/{orgId}/sites/{siteId}/display", + href: "/{orgId}/sites/{niceId}/display", }, ] interface SettingsLayoutProps { children: React.ReactNode, - params: { siteId: string, orgId: string } + params: { niceId: string, orgId: string } } export default async function SettingsLayout({ children, params }: SettingsLayoutProps) { let site = null; - if (params.siteId !== "create") { + if (params.niceId !== "create") { try { - const res = await internal.get>(`/site/${params.siteId}`, authCookieHeader()); + const res = await internal.get>(`/org/${params.orgId}/site/${params.niceId}`, authCookieHeader()); site = res.data.data; } catch { redirect(`/${params.orgId}/sites`) @@ -72,13 +72,13 @@ export default async function SettingsLayout({ children, params }: SettingsLayou

Settings

- {params.siteId == "create" ? "Create site..." : "Manage settings on " + site?.name || ""}. + {params.niceId == "create" ? "Create site..." : "Manage settings on " + site?.name || ""}.

diff --git a/src/app/[orgId]/sites/[siteId]/notifications/page.tsx b/src/app/[orgId]/sites/[niceId]/notifications/page.tsx similarity index 100% rename from src/app/[orgId]/sites/[siteId]/notifications/page.tsx rename to src/app/[orgId]/sites/[niceId]/notifications/page.tsx diff --git a/src/app/[orgId]/sites/[siteId]/page.tsx b/src/app/[orgId]/sites/[niceId]/page.tsx similarity index 91% rename from src/app/[orgId]/sites/[siteId]/page.tsx rename to src/app/[orgId]/sites/[niceId]/page.tsx index 81d672cc..7bb23a9c 100644 --- a/src/app/[orgId]/sites/[siteId]/page.tsx +++ b/src/app/[orgId]/sites/[niceId]/page.tsx @@ -6,9 +6,9 @@ import { CreateSiteForm } from "./components/create-site"; export default function SettingsProfilePage({ params, }: { - params: { siteId: string }; + params: { niceId: string }; }) { - const isCreateForm = params.siteId === "create"; + const isCreateForm = params.niceId === "create"; return (
diff --git a/src/components/sidebar-nav.tsx b/src/components/sidebar-nav.tsx index bd8d4661..3b6a82ee 100644 --- a/src/components/sidebar-nav.tsx +++ b/src/components/sidebar-nav.tsx @@ -17,7 +17,7 @@ export function SidebarNav({ className, items, disabled = false, ...props }: Sid const pathname = usePathname(); const params = useParams(); const orgId = params.orgId as string; - const siteId = params.siteId as string; + const niceId = params.niceId as string; const resourceId = params.resourceId as string; return ( @@ -31,11 +31,11 @@ export function SidebarNav({ className, items, disabled = false, ...props }: Sid > {items.map((item) => (