From aa4806fb7f99da364b070ee4ae5e2e48e63138ec Mon Sep 17 00:00:00 2001 From: Milo Schwartz Date: Sat, 26 Oct 2024 19:57:47 -0400 Subject: [PATCH] use fullDomain from resources in get traefik config --- server/index.ts | 4 +- server/routers/org/listOrgs.ts | 16 +- server/routers/traefik/getTraefikConfig.ts | 169 ++++++++++----------- src/app/layout.tsx | 34 ++--- src/app/page.tsx | 56 ++++--- 5 files changed, 143 insertions(+), 136 deletions(-) diff --git a/server/index.ts b/server/index.ts index a327740d..863b9a03 100644 --- a/server/index.ts +++ b/server/index.ts @@ -47,9 +47,7 @@ app.prepare().then(() => { } const prefix = `/api/v1`; - if (dev) { - externalServer.use(logIncomingMiddleware); - } + externalServer.use(logIncomingMiddleware); externalServer.use(prefix, unauthenticated); externalServer.use(prefix, authenticated); diff --git a/server/routers/org/listOrgs.ts b/server/routers/org/listOrgs.ts index 66937683..e0cc231c 100644 --- a/server/routers/org/listOrgs.ts +++ b/server/routers/org/listOrgs.ts @@ -6,7 +6,6 @@ import response from "@server/utils/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import { sql, inArray } from "drizzle-orm"; -import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions"; import logger from "@server/logger"; const listOrgsSchema = z.object({ @@ -32,7 +31,7 @@ export type ListOrgsResponse = { export async function listOrgs( req: Request, res: Response, - next: NextFunction, + next: NextFunction ): Promise { try { const parsedQuery = listOrgsSchema.safeParse(req.query); @@ -40,13 +39,15 @@ export async function listOrgs( return next( createHttpError( HttpCode.BAD_REQUEST, - parsedQuery.error.errors.map((e) => e.message).join(", "), - ), + parsedQuery.error.errors.map((e) => e.message).join(", ") + ) ); } const { limit, offset } = parsedQuery.data; + logger.debug("here0") + // Use the userOrgs passed from the middleware const userOrgIds = req.userOrgIds; @@ -65,6 +66,7 @@ export async function listOrgs( message: "No organizations found for the user", status: HttpCode.OK, }); + logger.debug("here1") } const organizations = await db @@ -80,6 +82,8 @@ export async function listOrgs( .where(inArray(orgs.orgId, userOrgIds)); const totalCount = totalCountResult[0].count; + logger.debug("here2") + return response(res, { data: { orgs: organizations, @@ -99,8 +103,8 @@ export async function listOrgs( return next( createHttpError( HttpCode.INTERNAL_SERVER_ERROR, - "An error occurred...", - ), + "An error occurred..." + ) ); } } diff --git a/server/routers/traefik/getTraefikConfig.ts b/server/routers/traefik/getTraefikConfig.ts index 3940c5f1..aea71cd9 100644 --- a/server/routers/traefik/getTraefikConfig.ts +++ b/server/routers/traefik/getTraefikConfig.ts @@ -2,100 +2,97 @@ import { Request, Response } from "express"; import db from "@server/db"; import * as schema from "@server/db/schema"; import { DynamicTraefikConfig } from "./configSchema"; -import { and, like, eq, isNotNull } from "drizzle-orm"; +import { and, eq, isNotNull } from "drizzle-orm"; import logger from "@server/logger"; import HttpCode from "@server/types/HttpCode"; import config from "@server/config"; -export async function traefikConfigProvider(_: Request, res: Response) { +export async function traefikConfigProvider( + _: Request, + res: Response +): Promise { try { - const targets = await getAllTargets(); - const traefikConfig = buildTraefikConfig(targets); - res.status(HttpCode.OK).json(traefikConfig); + const all = await db + .select() + .from(schema.targets) + .innerJoin( + schema.resources, + eq(schema.targets.resourceId, schema.resources.resourceId) + ) + .where( + and( + eq(schema.targets.enabled, true), + isNotNull(schema.resources.fullDomain) + ) + ); + + if (!all.length) { + return { http: {} } as DynamicTraefikConfig; + } + + const middlewareName = "badger"; + + const baseDomain = new URL(config.app.base_url).hostname; + + const tls = { + certResolver: config.traefik.cert_resolver, + ...(config.traefik.prefer_wildcard_cert + ? { domains: [baseDomain, `*.${baseDomain}`] } + : {}), + }; + + const http: any = { + routers: {}, + services: {}, + middlewares: { + [middlewareName]: { + plugin: { + [middlewareName]: { + apiBaseUrl: new URL( + "/api/v1", + `http://${config.server.internal_hostname}:${config.server.internal_port}` + ).href, + appBaseUrl: config.app.base_url, + }, + }, + }, + }, + }; + for (const item of all) { + const target = item.targets; + const resource = item.resources; + + const routerName = `${target.targetId}-router`; + const serviceName = `${target.targetId}-service`; + + http.routers![routerName] = { + entryPoints: [ + target.ssl + ? config.traefik.https_entrypoint + : config.traefik.http_entrypoint, + ], + middlewares: [middlewareName], + service: serviceName, + rule: `Host(\`${resource.fullDomain}\`)`, + ...(target.ssl ? { tls } : {}), + }; + + http.services![serviceName] = { + loadBalancer: { + servers: [ + { + url: `${target.method}://${target.ip}:${target.port}`, + }, + ], + }, + }; + } + + return res.status(HttpCode.OK).json({ http }); } catch (e) { logger.error(`Failed to build traefik config: ${e}`); - res.status(HttpCode.INTERNAL_SERVER_ERROR).json({ + return res.status(HttpCode.INTERNAL_SERVER_ERROR).json({ error: "Failed to build traefik config", }); } } - -export function buildTraefikConfig( - targets: schema.Target[] -): DynamicTraefikConfig { - if (!targets.length) { - return { http: {} } as DynamicTraefikConfig; - } - - const middlewareName = "badger"; - - const baseDomain = new URL(config.app.base_url).hostname; - - const tls = { - certResolver: config.traefik.cert_resolver, - ...(config.traefik.prefer_wildcard_cert - ? { domains: [baseDomain, `*.${baseDomain}`] } - : {}), - }; - - const http: any = { - routers: {}, - services: {}, - middlewares: { - [middlewareName]: { - plugin: { - [middlewareName]: { - apiBaseUrl: new URL( - "/api/v1", - `http://${config.server.internal_hostname}:${config.server.internal_port}` - ).href, - appBaseUrl: config.app.base_url, - }, - }, - }, - }, - }; - for (const target of targets) { - const routerName = `${target.targetId}-router`; - const serviceName = `${target.targetId}-service`; - - http.routers![routerName] = { - entryPoints: [ - target.ssl - ? config.traefik.https_entrypoint - : config.traefik.http_entrypoint, - ], - middlewares: [middlewareName], - service: serviceName, - rule: `Host(\`${target.resourceId}\`)`, // assuming resourceId is a valid full hostname - ...(target.ssl ? { tls } : {}), - }; - - http.services![serviceName] = { - loadBalancer: { - servers: [ - { url: `${target.method}://${target.ip}:${target.port}` }, - ], - }, - }; - } - - return { http } as DynamicTraefikConfig; -} - -export async function getAllTargets(): Promise { - const all = await db - .select() - .from(schema.targets) - .innerJoin( - schema.resources, - eq(schema.targets.resourceId, schema.resources.resourceId) - ) - .where( - and( - eq(schema.targets.enabled, true), - isNotNull(schema.resources.fullDomain) - ) - ); - return all.map((row) => row.targets); -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5db51f3b..66f969e6 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -24,24 +24,24 @@ export default async function RootLayout({ }>) { const user = await verifySession(); + console.log("layout.tsx user", user); + let orgs: ListOrgsResponse["orgs"] = []; - if (user) { - try { - const res = await internal.get>( - `/orgs`, - await authCookieHeader(), - ); - if (res && res.data.data.orgs) { - orgs = res.data.data.orgs; - } - - if (!orgs.length) { - redirect(`/setup`); - } - } catch (e) { - console.error("Error fetching orgs", e); - } - } + // if (user) { + // try { + // const res = await internal.get>( + // `/orgs`, + // await authCookieHeader() + // ); + // if (res && res.data.data.orgs) { + // orgs = res.data.data.orgs; + // } + // } catch {} + + // if (!orgs.length) { + // redirect(`/setup`); + // } + // } return ( diff --git a/src/app/page.tsx b/src/app/page.tsx index 297f5de3..faa0e1a4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -8,26 +8,30 @@ import { ArrowUpLeft, ArrowUpRight } from "lucide-react"; import Link from "next/link"; import { redirect } from "next/navigation"; -export default async function Page() { +export default async function Page(props: { + searchParams: Promise<{ [key: string]: string | string[] | undefined }>; +}) { + + const params = await props.searchParams; const user = await verifySession(); + console.log("page.tsx user", user); + if (!user) { - redirect("/auth/login"); + // redirect("/auth/login"); return; } - let orgs: ListOrgsResponse["orgs"] = []; - try { - const res = await internal.get>( - `/orgs`, - await authCookieHeader(), - ); - if (res && res.data.data.orgs) { - orgs = res.data.data.orgs; - } - } catch (e) { - console.error("Error fetching orgs", e); - } + // let orgs: ListOrgsResponse["orgs"] = []; + // try { + // const res = await internal.get>( + // `/orgs`, + // await authCookieHeader() + // ); + // if (res && res.data.data.orgs) { + // orgs = res.data.data.orgs; + // } + // } catch (e) {} return ( <> @@ -35,16 +39,20 @@ export default async function Page() {

Logged in as {user.email}

-
- {orgs.map((org) => ( - -
- {org.name} - -
- - ))} -
+ {/*
+ {orgs.map((org) => ( + +
+ {org.name} + +
+ + ))} +
*/} ); }