Add more tier matrix checks

This commit is contained in:
Owen
2026-02-09 19:52:28 -08:00
parent 5ca598139e
commit 0850a28d20
8 changed files with 35 additions and 13 deletions

View File

@@ -2,7 +2,7 @@ import { Tier } from "@server/types/Tiers";
export enum TierFeature { export enum TierFeature {
OrgOidc = "orgOidc", OrgOidc = "orgOidc",
CustomAuthenticationDomain = "customAuthenticationDomain", LoginPageDomain = "loginPageDomain",
DeviceApprovals = "deviceApprovals", DeviceApprovals = "deviceApprovals",
LoginPageBranding = "loginPageBranding", LoginPageBranding = "loginPageBranding",
LogExport = "logExport", LogExport = "logExport",
@@ -18,7 +18,7 @@ export enum TierFeature {
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.CustomAuthenticationDomain]: [ [TierFeature.LoginPageDomain]: [
"tier1", "tier1",
"tier2", "tier2",
"tier3", "tier3",

View File

@@ -33,7 +33,6 @@ import { hashPassword } from "@server/auth/password";
import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators"; import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators";
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { tierMatrix } from "../billing/tierMatrix"; import { tierMatrix } from "../billing/tierMatrix";
import { t } from "@faker-js/faker/dist/airline-DF6RqYmq";
export type ProxyResourcesResults = { export type ProxyResourcesResults = {
proxyResource: Resource; proxyResource: Resource;

View File

@@ -17,7 +17,7 @@ import {
ResourceHeaderAuthExtendedCompatibility, ResourceHeaderAuthExtendedCompatibility,
ResourcePassword, ResourcePassword,
ResourcePincode, ResourcePincode,
ResourceRule, ResourceRule
} from "@server/db"; } from "@server/db";
import config from "@server/lib/config"; import config from "@server/lib/config";
import { isIpInCidr, stripPortFromHost } from "@server/lib/ip"; import { isIpInCidr, stripPortFromHost } from "@server/lib/ip";
@@ -40,6 +40,7 @@ import { logRequestAudit } from "./logRequestAudit";
import cache from "@server/lib/cache"; import cache from "@server/lib/cache";
import { APP_VERSION } from "@server/lib/consts"; import { APP_VERSION } from "@server/lib/consts";
import { isSubscribed } from "#private/lib/isSubscribed"; import { isSubscribed } from "#private/lib/isSubscribed";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
const verifyResourceSessionSchema = z.object({ const verifyResourceSessionSchema = z.object({
sessions: z.record(z.string(), z.string()).optional(), sessions: z.record(z.string(), z.string()).optional(),
@@ -796,7 +797,10 @@ async function notAllowed(
) { ) {
let loginPage: LoginPage | null = null; let loginPage: LoginPage | null = null;
if (orgId) { if (orgId) {
const subscribed = await isSubscribed(orgId); const subscribed = await isSubscribed(
orgId,
tierMatrix.loginPageDomain
);
if (subscribed) { if (subscribed) {
loginPage = await getOrgLoginPage(orgId); loginPage = await getOrgLoginPage(orgId);
} }
@@ -850,7 +854,7 @@ async function headerAuthChallenged(
) { ) {
let loginPage: LoginPage | null = null; let loginPage: LoginPage | null = null;
if (orgId) { if (orgId) {
const subscribed = await isSubscribed(orgId); const subscribed = await isSubscribed(orgId, tierMatrix.loginPageDomain);
if (subscribed) { if (subscribed) {
loginPage = await getOrgLoginPage(orgId); loginPage = await getOrgLoginPage(orgId);
} }
@@ -1037,7 +1041,11 @@ export function isPathAllowed(pattern: string, path: string): boolean {
const MAX_RECURSION_DEPTH = 100; const MAX_RECURSION_DEPTH = 100;
// Recursive function to try different wildcard matches // Recursive function to try different wildcard matches
function matchSegments(patternIndex: number, pathIndex: number, depth: number = 0): boolean { function matchSegments(
patternIndex: number,
pathIndex: number,
depth: number = 0
): boolean {
// Check recursion depth limit // Check recursion depth limit
if (depth > MAX_RECURSION_DEPTH) { if (depth > MAX_RECURSION_DEPTH) {
logger.warn( logger.warn(
@@ -1123,7 +1131,11 @@ export function isPathAllowed(pattern: string, path: string): boolean {
logger.debug( logger.debug(
`${indent}Segment with wildcard matches: "${currentPatternPart}" matches "${currentPathPart}"` `${indent}Segment with wildcard matches: "${currentPatternPart}" matches "${currentPathPart}"`
); );
return matchSegments(patternIndex + 1, pathIndex + 1, depth + 1); return matchSegments(
patternIndex + 1,
pathIndex + 1,
depth + 1
);
} }
logger.debug( logger.debug(

View File

@@ -15,6 +15,7 @@ import config from "@server/lib/config";
import { decrypt } from "@server/lib/crypto"; import { decrypt } from "@server/lib/crypto";
import { build } from "@server/build"; import { build } from "@server/build";
import { isSubscribed } from "#dynamic/lib/isSubscribed"; import { isSubscribed } from "#dynamic/lib/isSubscribed";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
const paramsSchema = z const paramsSchema = z
.object({ .object({
@@ -112,7 +113,10 @@ export async function generateOidcUrl(
} }
if (build === "saas") { if (build === "saas") {
const subscribed = await isSubscribed(orgId); const subscribed = await isSubscribed(
orgId,
tierMatrix.orgOidc
);
if (!subscribed) { if (!subscribed) {
return next( return next(
createHttpError( createHttpError(

View File

@@ -24,6 +24,7 @@ import { createCertificate } from "#dynamic/routers/certificates/createCertifica
import { validateAndConstructDomain } from "@server/lib/domainUtils"; import { validateAndConstructDomain } from "@server/lib/domainUtils";
import { build } from "@server/build"; import { build } from "@server/build";
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
const updateResourceParamsSchema = z.strictObject({ const updateResourceParamsSchema = z.strictObject({
resourceId: z.string().transform(Number).pipe(z.int().positive()) resourceId: z.string().transform(Number).pipe(z.int().positive())
@@ -341,7 +342,7 @@ async function updateHttpResource(
headers = null; headers = null;
} }
const isLicensed = await isLicensedOrSubscribed(resource.orgId); const isLicensed = await isLicensedOrSubscribed(resource.orgId, tierMatrix.maintencePage);
if (!isLicensed) { if (!isLicensed) {
updateData.maintenanceModeEnabled = undefined; updateData.maintenanceModeEnabled = undefined;
updateData.maintenanceModeType = undefined; updateData.maintenanceModeType = undefined;

View File

@@ -12,6 +12,7 @@ import { eq, and } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { build } from "@server/build"; import { build } from "@server/build";
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
const createRoleParamsSchema = z.strictObject({ const createRoleParamsSchema = z.strictObject({
orgId: z.string() orgId: z.string()
@@ -100,7 +101,7 @@ export async function createRole(
); );
} }
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId, tierMatrix.deviceApprovals);
if (!isLicensed) { if (!isLicensed) {
roleData.requireDeviceApproval = undefined; roleData.requireDeviceApproval = undefined;
} }

View File

@@ -10,6 +10,7 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
const updateRoleParamsSchema = z.strictObject({ const updateRoleParamsSchema = z.strictObject({
roleId: z.string().transform(Number).pipe(z.int().positive()) roleId: z.string().transform(Number).pipe(z.int().positive())
@@ -110,7 +111,7 @@ export async function updateRole(
); );
} }
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId, tierMatrix.deviceApprovals);
if (!isLicensed) { if (!isLicensed) {
updateData.requireDeviceApproval = undefined; updateData.requireDeviceApproval = undefined;
} }

View File

@@ -15,6 +15,7 @@ import { FeatureId } from "@server/lib/billing";
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 { isSubscribed } from "#dynamic/lib/isSubscribed";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
const paramsSchema = z.strictObject({ const paramsSchema = z.strictObject({
orgId: z.string().nonempty() orgId: z.string().nonempty()
@@ -127,7 +128,10 @@ export async function createOrgUser(
); );
} else if (type === "oidc") { } else if (type === "oidc") {
if (build === "saas") { if (build === "saas") {
const subscribed = await isSubscribed(orgId); const subscribed = await isSubscribed(
orgId,
tierMatrix.orgOidc
);
if (subscribed) { if (subscribed) {
return next( return next(
createHttpError( createHttpError(