mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-02 00:36:38 +00:00
Handle auto provisioning
This commit is contained in:
@@ -13,17 +13,13 @@ export enum TierFeature {
|
|||||||
DevicePosture = "devicePosture",
|
DevicePosture = "devicePosture",
|
||||||
TwoFactorEnforcement = "twoFactorEnforcement",
|
TwoFactorEnforcement = "twoFactorEnforcement",
|
||||||
SessionDurationPolicies = "sessionDurationPolicies",
|
SessionDurationPolicies = "sessionDurationPolicies",
|
||||||
PasswordExpirationPolicies = "passwordExpirationPolicies"
|
PasswordExpirationPolicies = "passwordExpirationPolicies",
|
||||||
|
AutoProvisioning = "autoProvisioning"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tierMatrix: Record<TierFeature, Tier[]> = {
|
export const tierMatrix: Record<TierFeature, Tier[]> = {
|
||||||
[TierFeature.OrgOidc]: ["tier1", "tier2", "tier3", "enterprise"],
|
[TierFeature.OrgOidc]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
[TierFeature.LoginPageDomain]: [
|
[TierFeature.LoginPageDomain]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
"tier1",
|
|
||||||
"tier2",
|
|
||||||
"tier3",
|
|
||||||
"enterprise"
|
|
||||||
],
|
|
||||||
[TierFeature.DeviceApprovals]: ["tier1", "tier3", "enterprise"],
|
[TierFeature.DeviceApprovals]: ["tier1", "tier3", "enterprise"],
|
||||||
[TierFeature.LoginPageBranding]: ["tier1", "tier3", "enterprise"],
|
[TierFeature.LoginPageBranding]: ["tier1", "tier3", "enterprise"],
|
||||||
[TierFeature.LogExport]: ["tier3", "enterprise"],
|
[TierFeature.LogExport]: ["tier3", "enterprise"],
|
||||||
@@ -32,7 +28,23 @@ export const tierMatrix: Record<TierFeature, Tier[]> = {
|
|||||||
[TierFeature.RotateCredentials]: ["tier1", "tier2", "tier3", "enterprise"],
|
[TierFeature.RotateCredentials]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
[TierFeature.MaintencePage]: ["tier1", "tier2", "tier3", "enterprise"],
|
[TierFeature.MaintencePage]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
[TierFeature.DevicePosture]: ["tier2", "tier3", "enterprise"],
|
[TierFeature.DevicePosture]: ["tier2", "tier3", "enterprise"],
|
||||||
[TierFeature.TwoFactorEnforcement]: ["tier1", "tier2", "tier3", "enterprise"],
|
[TierFeature.TwoFactorEnforcement]: [
|
||||||
[TierFeature.SessionDurationPolicies]: ["tier1", "tier2", "tier3", "enterprise"],
|
"tier1",
|
||||||
[TierFeature.PasswordExpirationPolicies]: ["tier1", "tier2", "tier3", "enterprise"]
|
"tier2",
|
||||||
|
"tier3",
|
||||||
|
"enterprise"
|
||||||
|
],
|
||||||
|
[TierFeature.SessionDurationPolicies]: [
|
||||||
|
"tier1",
|
||||||
|
"tier2",
|
||||||
|
"tier3",
|
||||||
|
"enterprise"
|
||||||
|
],
|
||||||
|
[TierFeature.PasswordExpirationPolicies]: [
|
||||||
|
"tier1",
|
||||||
|
"tier2",
|
||||||
|
"tier3",
|
||||||
|
"enterprise"
|
||||||
|
],
|
||||||
|
[TierFeature.AutoProvisioning]: ["tier1", "tier3", "enterprise"]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import { generateOidcRedirectUrl } from "@server/lib/idp/generateRedirectUrl";
|
|||||||
import { encrypt } from "@server/lib/crypto";
|
import { encrypt } from "@server/lib/crypto";
|
||||||
import config from "@server/lib/config";
|
import config from "@server/lib/config";
|
||||||
import { CreateOrgIdpResponse } from "@server/routers/orgIdp/types";
|
import { CreateOrgIdpResponse } from "@server/routers/orgIdp/types";
|
||||||
|
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||||
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
|
||||||
const paramsSchema = z.strictObject({ orgId: z.string().nonempty() });
|
const paramsSchema = z.strictObject({ orgId: z.string().nonempty() });
|
||||||
|
|
||||||
@@ -100,12 +102,21 @@ export async function createOrgOidcIdp(
|
|||||||
emailPath,
|
emailPath,
|
||||||
namePath,
|
namePath,
|
||||||
name,
|
name,
|
||||||
autoProvision,
|
|
||||||
variant,
|
variant,
|
||||||
roleMapping,
|
roleMapping,
|
||||||
tags
|
tags
|
||||||
} = parsedBody.data;
|
} = parsedBody.data;
|
||||||
|
|
||||||
|
let { autoProvision } = parsedBody.data;
|
||||||
|
|
||||||
|
const subscribed = await isSubscribed(
|
||||||
|
orgId,
|
||||||
|
tierMatrix.deviceApprovals
|
||||||
|
);
|
||||||
|
if (!subscribed) {
|
||||||
|
autoProvision = false;
|
||||||
|
}
|
||||||
|
|
||||||
const key = config.getRawConfig().server.secret!;
|
const key = config.getRawConfig().server.secret!;
|
||||||
|
|
||||||
const encryptedSecret = encrypt(clientSecret, key);
|
const encryptedSecret = encrypt(clientSecret, key);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import { idp, idpOidcConfig } from "@server/db";
|
|||||||
import { eq, and } from "drizzle-orm";
|
import { eq, and } from "drizzle-orm";
|
||||||
import { encrypt } from "@server/lib/crypto";
|
import { encrypt } from "@server/lib/crypto";
|
||||||
import config from "@server/lib/config";
|
import config from "@server/lib/config";
|
||||||
|
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||||
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
|
||||||
const paramsSchema = z
|
const paramsSchema = z
|
||||||
.object({
|
.object({
|
||||||
@@ -106,11 +108,20 @@ export async function updateOrgOidcIdp(
|
|||||||
emailPath,
|
emailPath,
|
||||||
namePath,
|
namePath,
|
||||||
name,
|
name,
|
||||||
autoProvision,
|
|
||||||
roleMapping,
|
roleMapping,
|
||||||
tags
|
tags
|
||||||
} = parsedBody.data;
|
} = parsedBody.data;
|
||||||
|
|
||||||
|
let { autoProvision } = parsedBody.data;
|
||||||
|
|
||||||
|
const subscribed = await isSubscribed(
|
||||||
|
orgId,
|
||||||
|
tierMatrix.deviceApprovals
|
||||||
|
);
|
||||||
|
if (!subscribed) {
|
||||||
|
autoProvision = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if IDP exists and is of type OIDC
|
// Check if IDP exists and is of type OIDC
|
||||||
const [existingIdp] = await db
|
const [existingIdp] = await db
|
||||||
.select()
|
.select()
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import { FeatureId } from "@server/lib/billing";
|
|||||||
import { usageService } from "@server/lib/billing/usageService";
|
import { usageService } from "@server/lib/billing/usageService";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
||||||
|
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||||
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
|
||||||
const ensureTrailingSlash = (url: string): string => {
|
const ensureTrailingSlash = (url: string): string => {
|
||||||
return url;
|
return url;
|
||||||
@@ -326,6 +328,33 @@ export async function validateOidcCallback(
|
|||||||
.where(eq(idpOrg.idpId, existingIdp.idp.idpId))
|
.where(eq(idpOrg.idpId, existingIdp.idp.idpId))
|
||||||
.innerJoin(orgs, eq(orgs.orgId, idpOrg.orgId));
|
.innerJoin(orgs, eq(orgs.orgId, idpOrg.orgId));
|
||||||
allOrgs = idpOrgs.map((o) => o.orgs);
|
allOrgs = idpOrgs.map((o) => o.orgs);
|
||||||
|
|
||||||
|
// TODO: when there are multiple orgs we need to do this better!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
|
||||||
|
if (allOrgs.length > 1) {
|
||||||
|
// for some reason there is more than one org
|
||||||
|
logger.error(
|
||||||
|
"More than one organization linked to this IdP. This should not happen with auto-provisioning enabled."
|
||||||
|
);
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.INTERNAL_SERVER_ERROR,
|
||||||
|
"Multiple organizations linked to this IdP. Please contact support."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscribed = await isSubscribed(
|
||||||
|
allOrgs[0].orgId,
|
||||||
|
tierMatrix.autoProvisioning
|
||||||
|
);
|
||||||
|
if (subscribed) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.FORBIDDEN,
|
||||||
|
"This organization's current plan does not support this feature."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
allOrgs = await db.select().from(orgs);
|
allOrgs = await db.select().from(orgs);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user