Add auto-login-idp support to blueprints

Co-authored-by: oschwartz10612 <4999704+oschwartz10612@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-11-19 16:50:06 +00:00
parent 8f9b665bef
commit 01b5158b73
3 changed files with 46 additions and 1 deletions

View File

@@ -31,6 +31,7 @@ proxy-resources:
# - owen@pangolin.net # - owen@pangolin.net
# whitelist-users: # whitelist-users:
# - owen@pangolin.net # - owen@pangolin.net
# auto-login-idp: My IDP Name
headers: headers:
- name: X-Example-Header - name: X-Example-Header
value: example-value value: example-value

View File

@@ -14,7 +14,9 @@ import {
Transaction, Transaction,
userOrgs, userOrgs,
userResources, userResources,
users users,
idp,
idpOrg
} from "@server/db"; } from "@server/db";
import { resources, targets, sites } from "@server/db"; import { resources, targets, sites } from "@server/db";
import { eq, and, asc, or, ne, count, isNotNull } from "drizzle-orm"; import { eq, and, asc, or, ne, count, isNotNull } from "drizzle-orm";
@@ -208,6 +210,16 @@ export async function updateProxyResources(
); );
resource = existingResource; resource = existingResource;
} else { } else {
// Lookup IDP ID if auto-login-idp is specified
let skipToIdpId: number | null = null;
if (resourceData.auth?.["auto-login-idp"]) {
skipToIdpId = await getIdpIdByName(
orgId,
resourceData.auth["auto-login-idp"],
trx
);
}
// Update existing resource // Update existing resource
[resource] = await trx [resource] = await trx
.update(resources) .update(resources)
@@ -221,6 +233,7 @@ export async function updateProxyResources(
domainId: domain ? domain.domainId : null, domainId: domain ? domain.domainId : null,
enabled: resourceEnabled, enabled: resourceEnabled,
sso: resourceData.auth?.["sso-enabled"] || false, sso: resourceData.auth?.["sso-enabled"] || false,
skipToIdpId: skipToIdpId,
ssl: resourceSsl, ssl: resourceSsl,
setHostHeader: resourceData["host-header"] || null, setHostHeader: resourceData["host-header"] || null,
tlsServerName: resourceData["tls-server-name"] || null, tlsServerName: resourceData["tls-server-name"] || null,
@@ -595,6 +608,16 @@ export async function updateProxyResources(
); );
} }
// Lookup IDP ID if auto-login-idp is specified
let skipToIdpId: number | null = null;
if (resourceData.auth?.["auto-login-idp"]) {
skipToIdpId = await getIdpIdByName(
orgId,
resourceData.auth["auto-login-idp"],
trx
);
}
// Create new resource // Create new resource
const [newResource] = await trx const [newResource] = await trx
.insert(resources) .insert(resources)
@@ -610,6 +633,7 @@ export async function updateProxyResources(
domainId: domain ? domain.domainId : null, domainId: domain ? domain.domainId : null,
enabled: resourceEnabled, enabled: resourceEnabled,
sso: resourceData.auth?.["sso-enabled"] || false, sso: resourceData.auth?.["sso-enabled"] || false,
skipToIdpId: skipToIdpId,
setHostHeader: resourceData["host-header"] || null, setHostHeader: resourceData["host-header"] || null,
tlsServerName: resourceData["tls-server-name"] || null, tlsServerName: resourceData["tls-server-name"] || null,
ssl: resourceSsl, ssl: resourceSsl,
@@ -1084,3 +1108,22 @@ async function getDomainId(
domainId: domainSelection.domainId domainId: domainSelection.domainId
}; };
} }
async function getIdpIdByName(
orgId: string,
idpName: string,
trx: Transaction
): Promise<number | null> {
const [idpResult] = await trx
.select({ idpId: idp.idpId })
.from(idp)
.innerJoin(idpOrg, eq(idp.idpId, idpOrg.idpId))
.where(and(eq(idp.name, idpName), eq(idpOrg.orgId, orgId)))
.limit(1);
if (!idpResult) {
throw new Error(`IDP not found: ${idpName} in org ${orgId}`);
}
return idpResult.idpId;
}

View File

@@ -59,6 +59,7 @@ export const AuthSchema = z.object({
}), }),
"sso-users": z.array(z.string().email()).optional().default([]), "sso-users": z.array(z.string().email()).optional().default([]),
"whitelist-users": z.array(z.string().email()).optional().default([]), "whitelist-users": z.array(z.string().email()).optional().default([]),
"auto-login-idp": z.string().min(1).optional(),
}); });
export const RuleSchema = z.object({ export const RuleSchema = z.object({