mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-07 11:16:37 +00:00
Add pricing matrix
This commit is contained in:
36
server/lib/billing/tierMatrix.ts
Normal file
36
server/lib/billing/tierMatrix.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
export enum TierFeature {
|
||||||
|
OrgOidc = "orgOidc",
|
||||||
|
CustomAuthenticationDomain = "customAuthenticationDomain",
|
||||||
|
DeviceApprovals = "deviceApprovals",
|
||||||
|
LoginPageBranding = "loginPageBranding",
|
||||||
|
LogExport = "logExport",
|
||||||
|
AccessLogs = "accessLogs",
|
||||||
|
ActionLogs = "actionLogs",
|
||||||
|
RotateCredentials = "rotateCredentials",
|
||||||
|
MaintencePage = "maintencePage",
|
||||||
|
DevicePosture = "devicePosture",
|
||||||
|
TwoFactorEnforcement = "twoFactorEnforcement",
|
||||||
|
SessionDurationPolicies = "sessionDurationPolicies",
|
||||||
|
PasswordExpirationPolicies = "passwordExpirationPolicies"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tierMatrix: Record<TierFeature, string[]> = {
|
||||||
|
[TierFeature.OrgOidc]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.CustomAuthenticationDomain]: [
|
||||||
|
"tier1",
|
||||||
|
"tier2",
|
||||||
|
"tier3",
|
||||||
|
"enterprise"
|
||||||
|
],
|
||||||
|
[TierFeature.DeviceApprovals]: ["tier1", "tier3", "enterprise"],
|
||||||
|
[TierFeature.LoginPageBranding]: ["tier1", "tier3", "enterprise"],
|
||||||
|
[TierFeature.LogExport]: ["tier3", "enterprise"],
|
||||||
|
[TierFeature.AccessLogs]: ["tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.ActionLogs]: ["tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.RotateCredentials]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.MaintencePage]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.DevicePosture]: ["tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.TwoFactorEnforcement]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.SessionDurationPolicies]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||||
|
[TierFeature.PasswordExpirationPolicies]: ["tier1", "tier2", "tier3", "enterprise"]
|
||||||
|
};
|
||||||
@@ -32,7 +32,8 @@ import { resourcePassword } from "@server/db";
|
|||||||
import { hashPassword } from "@server/auth/password";
|
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 { build } from "@server/build";
|
import { tierMatrix } from "../billing/tierMatrix";
|
||||||
|
import { t } from "@faker-js/faker/dist/airline-DF6RqYmq";
|
||||||
|
|
||||||
export type ProxyResourcesResults = {
|
export type ProxyResourcesResults = {
|
||||||
proxyResource: Resource;
|
proxyResource: Resource;
|
||||||
@@ -212,7 +213,7 @@ export async function updateProxyResources(
|
|||||||
} else {
|
} else {
|
||||||
// Update existing resource
|
// Update existing resource
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId, tierMatrix.maintencePage);
|
||||||
if (!isLicensed) {
|
if (!isLicensed) {
|
||||||
resourceData.maintenance = undefined;
|
resourceData.maintenance = undefined;
|
||||||
}
|
}
|
||||||
@@ -648,7 +649,7 @@ export async function updateProxyResources(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId, tierMatrix.maintencePage);
|
||||||
if (!isLicensed) {
|
if (!isLicensed) {
|
||||||
resourceData.maintenance = undefined;
|
resourceData.maintenance = undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { sendTerminateClient } from "@server/routers/client/terminate";
|
|||||||
import { and, eq, notInArray, type InferInsertModel } from "drizzle-orm";
|
import { and, eq, notInArray, type InferInsertModel } from "drizzle-orm";
|
||||||
import { rebuildClientAssociationsFromClient } from "./rebuildClientAssociations";
|
import { rebuildClientAssociationsFromClient } from "./rebuildClientAssociations";
|
||||||
import { OlmErrorCodes } from "@server/routers/olm/error";
|
import { OlmErrorCodes } from "@server/routers/olm/error";
|
||||||
|
import { tierMatrix } from "./billing/tierMatrix";
|
||||||
|
|
||||||
export async function calculateUserClientsForOrgs(
|
export async function calculateUserClientsForOrgs(
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -189,7 +190,8 @@ export async function calculateUserClientsForOrgs(
|
|||||||
const niceId = await getUniqueClientName(orgId);
|
const niceId = await getUniqueClientName(orgId);
|
||||||
|
|
||||||
const isOrgLicensed = await isLicensedOrSubscribed(
|
const isOrgLicensed = await isLicensedOrSubscribed(
|
||||||
userOrg.orgId
|
userOrg.orgId,
|
||||||
|
tierMatrix.deviceApprovals
|
||||||
);
|
);
|
||||||
const requireApproval =
|
const requireApproval =
|
||||||
build !== "oss" &&
|
build !== "oss" &&
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function verifyValidSubscription(tiers: string[]) {
|
|||||||
|
|
||||||
const { tier, active } = await getOrgTierData(orgId);
|
const { tier, active } = await getOrgTierData(orgId);
|
||||||
const isTier = tiers.includes(tier || "");
|
const isTier = tiers.includes(tier || "");
|
||||||
if (!isTier || !active) {
|
if (!active) {
|
||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(
|
||||||
HttpCode.FORBIDDEN,
|
HttpCode.FORBIDDEN,
|
||||||
@@ -53,6 +53,14 @@ export function verifyValidSubscription(tiers: string[]) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (!isTier) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.FORBIDDEN,
|
||||||
|
"Organization subscription tier does not have access to this feature"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import {
|
|||||||
authenticated as a,
|
authenticated as a,
|
||||||
authRouter as aa
|
authRouter as aa
|
||||||
} from "@server/routers/external";
|
} from "@server/routers/external";
|
||||||
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
|
||||||
export const authenticated = a;
|
export const authenticated = a;
|
||||||
export const unauthenticated = ua;
|
export const unauthenticated = ua;
|
||||||
@@ -76,7 +77,7 @@ unauthenticated.post(
|
|||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/org/:orgId/idp/oidc",
|
"/org/:orgId/idp/oidc",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.orgOidc),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.createIdp),
|
verifyUserHasAction(ActionsEnum.createIdp),
|
||||||
logActionAudit(ActionsEnum.createIdp),
|
logActionAudit(ActionsEnum.createIdp),
|
||||||
@@ -86,7 +87,7 @@ authenticated.put(
|
|||||||
authenticated.post(
|
authenticated.post(
|
||||||
"/org/:orgId/idp/:idpId/oidc",
|
"/org/:orgId/idp/:idpId/oidc",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription(),
|
verifyValidSubscription(tierMatrix.orgOidc),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyIdpAccess,
|
verifyIdpAccess,
|
||||||
verifyUserHasAction(ActionsEnum.updateIdp),
|
verifyUserHasAction(ActionsEnum.updateIdp),
|
||||||
@@ -279,7 +280,7 @@ authenticated.delete(
|
|||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/org/:orgId/login-page",
|
"/org/:orgId/login-page",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.customAuthenticationDomain),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.createLoginPage),
|
verifyUserHasAction(ActionsEnum.createLoginPage),
|
||||||
logActionAudit(ActionsEnum.createLoginPage),
|
logActionAudit(ActionsEnum.createLoginPage),
|
||||||
@@ -289,7 +290,7 @@ authenticated.put(
|
|||||||
authenticated.post(
|
authenticated.post(
|
||||||
"/org/:orgId/login-page/:loginPageId",
|
"/org/:orgId/login-page/:loginPageId",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.customAuthenticationDomain),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyLoginPageAccess,
|
verifyLoginPageAccess,
|
||||||
verifyUserHasAction(ActionsEnum.updateLoginPage),
|
verifyUserHasAction(ActionsEnum.updateLoginPage),
|
||||||
@@ -318,7 +319,7 @@ authenticated.get(
|
|||||||
authenticated.get(
|
authenticated.get(
|
||||||
"/org/:orgId/approvals",
|
"/org/:orgId/approvals",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.deviceApprovals),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.listApprovals),
|
verifyUserHasAction(ActionsEnum.listApprovals),
|
||||||
logActionAudit(ActionsEnum.listApprovals),
|
logActionAudit(ActionsEnum.listApprovals),
|
||||||
@@ -335,7 +336,7 @@ authenticated.get(
|
|||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/org/:orgId/approvals/:approvalId",
|
"/org/:orgId/approvals/:approvalId",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.deviceApprovals),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.updateApprovals),
|
verifyUserHasAction(ActionsEnum.updateApprovals),
|
||||||
logActionAudit(ActionsEnum.updateApprovals),
|
logActionAudit(ActionsEnum.updateApprovals),
|
||||||
@@ -345,7 +346,7 @@ authenticated.put(
|
|||||||
authenticated.get(
|
authenticated.get(
|
||||||
"/org/:orgId/login-page-branding",
|
"/org/:orgId/login-page-branding",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.loginPageBranding),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.getLoginPage),
|
verifyUserHasAction(ActionsEnum.getLoginPage),
|
||||||
logActionAudit(ActionsEnum.getLoginPage),
|
logActionAudit(ActionsEnum.getLoginPage),
|
||||||
@@ -355,7 +356,7 @@ authenticated.get(
|
|||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/org/:orgId/login-page-branding",
|
"/org/:orgId/login-page-branding",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.loginPageBranding),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.updateLoginPage),
|
verifyUserHasAction(ActionsEnum.updateLoginPage),
|
||||||
logActionAudit(ActionsEnum.updateLoginPage),
|
logActionAudit(ActionsEnum.updateLoginPage),
|
||||||
@@ -365,7 +366,6 @@ authenticated.put(
|
|||||||
authenticated.delete(
|
authenticated.delete(
|
||||||
"/org/:orgId/login-page-branding",
|
"/org/:orgId/login-page-branding",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.deleteLoginPage),
|
verifyUserHasAction(ActionsEnum.deleteLoginPage),
|
||||||
logActionAudit(ActionsEnum.deleteLoginPage),
|
logActionAudit(ActionsEnum.deleteLoginPage),
|
||||||
@@ -433,7 +433,7 @@ authenticated.post(
|
|||||||
authenticated.get(
|
authenticated.get(
|
||||||
"/org/:orgId/logs/action",
|
"/org/:orgId/logs/action",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.actionLogs),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.exportLogs),
|
verifyUserHasAction(ActionsEnum.exportLogs),
|
||||||
logs.queryActionAuditLogs
|
logs.queryActionAuditLogs
|
||||||
@@ -442,7 +442,7 @@ authenticated.get(
|
|||||||
authenticated.get(
|
authenticated.get(
|
||||||
"/org/:orgId/logs/action/export",
|
"/org/:orgId/logs/action/export",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.logExport),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.exportLogs),
|
verifyUserHasAction(ActionsEnum.exportLogs),
|
||||||
logActionAudit(ActionsEnum.exportLogs),
|
logActionAudit(ActionsEnum.exportLogs),
|
||||||
@@ -452,7 +452,7 @@ authenticated.get(
|
|||||||
authenticated.get(
|
authenticated.get(
|
||||||
"/org/:orgId/logs/access",
|
"/org/:orgId/logs/access",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.accessLogs),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.exportLogs),
|
verifyUserHasAction(ActionsEnum.exportLogs),
|
||||||
logs.queryAccessAuditLogs
|
logs.queryAccessAuditLogs
|
||||||
@@ -461,7 +461,7 @@ authenticated.get(
|
|||||||
authenticated.get(
|
authenticated.get(
|
||||||
"/org/:orgId/logs/access/export",
|
"/org/:orgId/logs/access/export",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.logExport),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.exportLogs),
|
verifyUserHasAction(ActionsEnum.exportLogs),
|
||||||
logActionAudit(ActionsEnum.exportLogs),
|
logActionAudit(ActionsEnum.exportLogs),
|
||||||
@@ -472,7 +472,7 @@ authenticated.post(
|
|||||||
"/re-key/:clientId/regenerate-client-secret",
|
"/re-key/:clientId/regenerate-client-secret",
|
||||||
verifyClientAccess, // this is first to set the org id
|
verifyClientAccess, // this is first to set the org id
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.rotateCredentials),
|
||||||
verifyUserHasAction(ActionsEnum.reGenerateSecret),
|
verifyUserHasAction(ActionsEnum.reGenerateSecret),
|
||||||
reKey.reGenerateClientSecret
|
reKey.reGenerateClientSecret
|
||||||
);
|
);
|
||||||
@@ -481,7 +481,7 @@ authenticated.post(
|
|||||||
"/re-key/:siteId/regenerate-site-secret",
|
"/re-key/:siteId/regenerate-site-secret",
|
||||||
verifySiteAccess, // this is first to set the org id
|
verifySiteAccess, // this is first to set the org id
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.rotateCredentials),
|
||||||
verifyUserHasAction(ActionsEnum.reGenerateSecret),
|
verifyUserHasAction(ActionsEnum.reGenerateSecret),
|
||||||
reKey.reGenerateSiteSecret
|
reKey.reGenerateSiteSecret
|
||||||
);
|
);
|
||||||
@@ -489,7 +489,7 @@ authenticated.post(
|
|||||||
authenticated.put(
|
authenticated.put(
|
||||||
"/re-key/:orgId/regenerate-remote-exit-node-secret",
|
"/re-key/:orgId/regenerate-remote-exit-node-secret",
|
||||||
verifyValidLicense,
|
verifyValidLicense,
|
||||||
verifyValidSubscription,
|
verifyValidSubscription(tierMatrix.rotateCredentials),
|
||||||
verifyOrgAccess,
|
verifyOrgAccess,
|
||||||
verifyUserHasAction(ActionsEnum.reGenerateSecret),
|
verifyUserHasAction(ActionsEnum.reGenerateSecret),
|
||||||
reKey.reGenerateExitNodeSecret
|
reKey.reGenerateExitNodeSecret
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { OpenAPITags, registry } from "@server/openApi";
|
|||||||
import { getUserDeviceName } from "@server/db/names";
|
import { getUserDeviceName } from "@server/db/names";
|
||||||
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 getClientSchema = z.strictObject({
|
const getClientSchema = z.strictObject({
|
||||||
clientId: z
|
clientId: z
|
||||||
@@ -327,7 +328,8 @@ export async function getClient(
|
|||||||
client.currentFingerprint
|
client.currentFingerprint
|
||||||
);
|
);
|
||||||
const isOrgLicensed = await isLicensedOrSubscribed(
|
const isOrgLicensed = await isLicensedOrSubscribed(
|
||||||
client.clients.orgId
|
client.clients.orgId,
|
||||||
|
tierMatrix.devicePosture
|
||||||
);
|
);
|
||||||
const postureData: PostureData | null = rawPosture
|
const postureData: PostureData | null = rawPosture
|
||||||
? isOrgLicensed
|
? isOrgLicensed
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import config from "@server/lib/config";
|
|||||||
import { APP_VERSION } from "@server/lib/consts";
|
import { APP_VERSION } from "@server/lib/consts";
|
||||||
|
|
||||||
export const newtGetTokenBodySchema = z.object({
|
export const newtGetTokenBodySchema = z.object({
|
||||||
newtId: z.string(),
|
// newtId: z.string(),
|
||||||
secret: z.string(),
|
secret: z.string(),
|
||||||
token: z.string().optional()
|
token: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import { OpenAPITags, registry } from "@server/openApi";
|
|||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { cache } from "@server/lib/cache";
|
import { cache } from "@server/lib/cache";
|
||||||
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
import { getOrgTierData } from "#dynamic/lib/billing";
|
||||||
|
|
||||||
const updateOrgParamsSchema = z.strictObject({
|
const updateOrgParamsSchema = z.strictObject({
|
||||||
orgId: z.string()
|
orgId: z.string()
|
||||||
@@ -87,26 +88,83 @@ export async function updateOrg(
|
|||||||
|
|
||||||
const { orgId } = parsedParams.data;
|
const { orgId } = parsedParams.data;
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
// Check 2FA enforcement feature
|
||||||
if (!isLicensed) {
|
const has2FAFeature = await isLicensedOrSubscribed(
|
||||||
|
orgId,
|
||||||
|
tierMatrix[TierFeature.TwoFactorEnforcement]
|
||||||
|
);
|
||||||
|
if (!has2FAFeature) {
|
||||||
parsedBody.data.requireTwoFactor = undefined;
|
parsedBody.data.requireTwoFactor = undefined;
|
||||||
parsedBody.data.maxSessionLengthHours = undefined;
|
|
||||||
parsedBody.data.passwordExpiryDays = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const subscribed = await isSubscribed(orgId);
|
// Check session duration policies feature
|
||||||
if (
|
const hasSessionDurationFeature = await isLicensedOrSubscribed(
|
||||||
build == "saas" &&
|
orgId,
|
||||||
subscribed &&
|
tierMatrix[TierFeature.SessionDurationPolicies]
|
||||||
parsedBody.data.settingsLogRetentionDaysRequest &&
|
);
|
||||||
parsedBody.data.settingsLogRetentionDaysRequest > 30
|
if (!hasSessionDurationFeature) {
|
||||||
) {
|
parsedBody.data.maxSessionLengthHours = undefined;
|
||||||
return next(
|
}
|
||||||
createHttpError(
|
|
||||||
HttpCode.FORBIDDEN,
|
// Check password expiration policies feature
|
||||||
"You are not allowed to set log retention days greater than 30 with your current subscription"
|
const hasPasswordExpirationFeature = await isLicensedOrSubscribed(
|
||||||
)
|
orgId,
|
||||||
);
|
tierMatrix[TierFeature.PasswordExpirationPolicies]
|
||||||
|
);
|
||||||
|
if (!hasPasswordExpirationFeature) {
|
||||||
|
parsedBody.data.passwordExpiryDays = undefined;
|
||||||
|
}
|
||||||
|
if (build == "saas") {
|
||||||
|
const { tier } = await getOrgTierData(orgId);
|
||||||
|
|
||||||
|
// Determine max allowed retention days based on tier
|
||||||
|
let maxRetentionDays: number | null = null;
|
||||||
|
if (!tier) {
|
||||||
|
maxRetentionDays = 0;
|
||||||
|
} else if (tier === "tier1") {
|
||||||
|
maxRetentionDays = 7;
|
||||||
|
} else if (tier === "tier2") {
|
||||||
|
maxRetentionDays = 30;
|
||||||
|
} else if (tier === "tier3") {
|
||||||
|
maxRetentionDays = 90;
|
||||||
|
}
|
||||||
|
// For enterprise tier, no check (maxRetentionDays remains null)
|
||||||
|
|
||||||
|
if (maxRetentionDays !== null) {
|
||||||
|
if (
|
||||||
|
parsedBody.data.settingsLogRetentionDaysRequest !== undefined &&
|
||||||
|
parsedBody.data.settingsLogRetentionDaysRequest > maxRetentionDays
|
||||||
|
) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.FORBIDDEN,
|
||||||
|
`You are not allowed to set log retention days greater than ${maxRetentionDays} with your current subscription`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
parsedBody.data.settingsLogRetentionDaysAccess !== undefined &&
|
||||||
|
parsedBody.data.settingsLogRetentionDaysAccess > maxRetentionDays
|
||||||
|
) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.FORBIDDEN,
|
||||||
|
`You are not allowed to set log retention days greater than ${maxRetentionDays} with your current subscription`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
parsedBody.data.settingsLogRetentionDaysAction !== undefined &&
|
||||||
|
parsedBody.data.settingsLogRetentionDaysAction > maxRetentionDays
|
||||||
|
) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.FORBIDDEN,
|
||||||
|
`You are not allowed to set log retention days greater than ${maxRetentionDays} with your current subscription`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedOrg = await db
|
const updatedOrg = await db
|
||||||
|
|||||||
Reference in New Issue
Block a user