Handle getting resources

This commit is contained in:
Owen
2026-04-23 17:12:56 -07:00
parent 1ba7fca798
commit 5e293e8364
2 changed files with 65 additions and 8 deletions

View File

@@ -25,7 +25,7 @@ import {
ResourceHeaderAuthExtendedCompatibility, ResourceHeaderAuthExtendedCompatibility,
resourceHeaderAuthExtendedCompatibility resourceHeaderAuthExtendedCompatibility
} from "@server/db"; } from "@server/db";
import { and, eq, inArray } from "drizzle-orm"; import { and, eq, inArray, or, sql } from "drizzle-orm";
export type ResourceWithAuth = { export type ResourceWithAuth = {
resource: Resource | null; resource: Resource | null;
@@ -47,7 +47,17 @@ export type UserSessionWithUser = {
export async function getResourceByDomain( export async function getResourceByDomain(
domain: string domain: string
): Promise<ResourceWithAuth | null> { ): Promise<ResourceWithAuth | null> {
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() .select()
.from(resources) .from(resources)
.leftJoin( .leftJoin(
@@ -70,8 +80,29 @@ export async function getResourceByDomain(
) )
) )
.innerJoin(orgs, eq(orgs.orgId, resources.orgId)) .innerJoin(orgs, eq(orgs.orgId, resources.orgId))
.where(eq(resources.fullDomain, domain)) .where(
.limit(1); 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) { if (!result) {
return null; return null;

View File

@@ -50,7 +50,7 @@ import {
userOrgRoles, userOrgRoles,
roles roles
} from "@server/db"; } 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 { response } from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import { NextFunction, Request, Response } from "express"; 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() .select()
.from(resources) .from(resources)
.leftJoin( .leftJoin(
@@ -515,10 +523,28 @@ hybridRouter.get(
) )
) )
.innerJoin(orgs, eq(orgs.orgId, resources.orgId)) .innerJoin(orgs, eq(orgs.orgId, resources.orgId))
.where(eq(resources.fullDomain, domain)) .where(
.limit(1); 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 ( if (
result &&
await checkExitNodeOrg( await checkExitNodeOrg(
remoteExitNode.exitNodeId, remoteExitNode.exitNodeId,
result.resources.orgId result.resources.orgId