From 5e293e8364ff4a5b701815755c879aa4a3312cd6 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 23 Apr 2026 17:12:56 -0700 Subject: [PATCH] Handle getting resources --- server/db/queries/verifySessionQueries.ts | 39 ++++++++++++++++++++--- server/private/routers/hybrid.ts | 34 +++++++++++++++++--- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/server/db/queries/verifySessionQueries.ts b/server/db/queries/verifySessionQueries.ts index 989e111a7..46b45b1a0 100644 --- a/server/db/queries/verifySessionQueries.ts +++ b/server/db/queries/verifySessionQueries.ts @@ -25,7 +25,7 @@ import { ResourceHeaderAuthExtendedCompatibility, resourceHeaderAuthExtendedCompatibility } from "@server/db"; -import { and, eq, inArray } from "drizzle-orm"; +import { and, eq, inArray, or, sql } from "drizzle-orm"; export type ResourceWithAuth = { resource: Resource | null; @@ -47,7 +47,17 @@ export type UserSessionWithUser = { export async function getResourceByDomain( domain: string ): Promise { - const [result] = await db + // Build wildcard domain variants to match against. + // For a domain like "me.example.test.com", we want to match: + // - "*.example.test.com" (subdomain wildcard) + // - "*.test.com" (parent wildcard, i.e. just "*" subdomain on parent) + const parts = domain.split("."); + const wildcardCandidates: string[] = []; + for (let i = 1; i < parts.length; i++) { + wildcardCandidates.push(`*.${parts.slice(i).join(".")}`); + } + + const potentialResults = await db .select() .from(resources) .leftJoin( @@ -70,8 +80,29 @@ export async function getResourceByDomain( ) ) .innerJoin(orgs, eq(orgs.orgId, resources.orgId)) - .where(eq(resources.fullDomain, domain)) - .limit(1); + .where( + or( + // Exact match + eq(resources.fullDomain, domain), + // Wildcard match: resource fullDomain is one of the wildcard candidates + wildcardCandidates.length > 0 + ? and( + eq(resources.wildcard, true), + inArray(resources.fullDomain, wildcardCandidates) + ) + : sql`false` + ) + ); + + if (!potentialResults.length) { + return null; + } + + // Prefer exact match over wildcard match + const exactMatch = potentialResults.find( + (r) => r.resources?.fullDomain === domain + ); + const result = exactMatch ?? potentialResults[0]; if (!result) { return null; diff --git a/server/private/routers/hybrid.ts b/server/private/routers/hybrid.ts index b3ef792d9..98e7ff671 100644 --- a/server/private/routers/hybrid.ts +++ b/server/private/routers/hybrid.ts @@ -50,7 +50,7 @@ import { userOrgRoles, roles } from "@server/db"; -import { eq, and, inArray, isNotNull, ne } from "drizzle-orm"; +import { eq, and, inArray, isNotNull, ne, or, sql } from "drizzle-orm"; import { response } from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import { NextFunction, Request, Response } from "express"; @@ -492,7 +492,15 @@ hybridRouter.get( ); } - const [result] = await db + // Build wildcard domain candidates for the requested domain. + // e.g. "me.example.test.com" -> ["*.example.test.com", "*.test.com"] + const domainParts = domain.split("."); + const wildcardCandidates: string[] = []; + for (let i = 1; i < domainParts.length; i++) { + wildcardCandidates.push(`*.${domainParts.slice(i).join(".")}`); + } + + const potentialResults = await db .select() .from(resources) .leftJoin( @@ -515,10 +523,28 @@ hybridRouter.get( ) ) .innerJoin(orgs, eq(orgs.orgId, resources.orgId)) - .where(eq(resources.fullDomain, domain)) - .limit(1); + .where( + or( + // Exact match + eq(resources.fullDomain, domain), + // Wildcard match + wildcardCandidates.length > 0 + ? and( + eq(resources.wildcard, true), + inArray(resources.fullDomain, wildcardCandidates) + ) + : sql`false` + ) + ); + + // Prefer exact match over wildcard match + const exactMatch = potentialResults.find( + (r) => r.resources?.fullDomain === domain + ); + const result = exactMatch ?? potentialResults[0]; if ( + result && await checkExitNodeOrg( remoteExitNode.exitNodeId, result.resources.orgId