clean up paid features check

This commit is contained in:
miloschwartz
2026-01-22 11:16:16 -08:00
committed by Owen Schwartz
parent 9a5bcb9099
commit 92331d7a33
10 changed files with 140 additions and 86 deletions

View File

@@ -4,13 +4,13 @@
}, },
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"[jsonc]": { "[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "vscode.json-language-features"
}, },
"[javascript]": { "[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "vscode.typescript-language-features"
}, },
"[typescriptreact]": { "[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"

View File

@@ -31,7 +31,7 @@ import { pickPort } from "@server/routers/target/helpers";
import { resourcePassword } from "@server/db"; 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 "../isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { build } from "@server/build"; import { build } from "@server/build";
export type ProxyResourcesResults = { export type ProxyResourcesResults = {
@@ -213,11 +213,7 @@ export async function updateProxyResources(
// Update existing resource // Update existing resource
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId);
if (build == "enterprise" && !isLicensed) { if (!isLicensed) {
logger.warn(
"Server is not licensed! Clearing set maintenance screen values"
);
// null the maintenance mode fields if not licensed
resourceData.maintenance = undefined; resourceData.maintenance = undefined;
} }
@@ -653,11 +649,7 @@ export async function updateProxyResources(
} }
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId);
if (build == "enterprise" && !isLicensed) { if (!isLicensed) {
logger.warn(
"Server is not licensed! Clearing set maintenance screen values"
);
// null the maintenance mode fields if not licensed
resourceData.maintenance = undefined; resourceData.maintenance = undefined;
} }

View File

@@ -14,7 +14,7 @@ import {
} from "@server/db"; } from "@server/db";
import { getUniqueClientName } from "@server/db/names"; import { getUniqueClientName } from "@server/db/names";
import { getNextAvailableClientSubnet } from "@server/lib/ip"; import { getNextAvailableClientSubnet } from "@server/lib/ip";
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import logger from "@server/logger"; import logger from "@server/logger";
import { sendTerminateClient } from "@server/routers/client/terminate"; 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";

View File

@@ -1,17 +1,3 @@
import { build } from "@server/build";
import license from "#dynamic/license/license";
import { getOrgTierData } from "#dynamic/lib/billing";
import { TierId } from "@server/lib/billing/tiers";
export async function isLicensedOrSubscribed(orgId: string): Promise<boolean> { export async function isLicensedOrSubscribed(orgId: string): Promise<boolean> {
if (build === "enterprise") { return false;
return await license.isUnlocked();
}
if (build === "saas") {
const { tier } = await getOrgTierData(orgId);
return tier === TierId.STANDARD;
}
return true;
} }

View File

@@ -0,0 +1,30 @@
/*
* This file is part of a proprietary work.
*
* Copyright (c) 2025 Fossorial, Inc.
* All rights reserved.
*
* This file is licensed under the Fossorial Commercial License.
* You may not use this file except in compliance with the License.
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
*
* This file is not licensed under the AGPLv3.
*/
import { build } from "@server/build";
import license from "#private/license/license";
import { getOrgTierData } from "#private/lib/billing";
import { TierId } from "@server/lib/billing/tiers";
export async function isLicensedOrSubscribed(orgId: string): Promise<boolean> {
if (build === "enterprise") {
return await license.isUnlocked();
}
if (build === "saas") {
const { tier } = await getOrgTierData(orgId);
return tier === TierId.STANDARD;
}
return false;
}

View File

@@ -12,7 +12,7 @@ import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; 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 "@server/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
const getClientSchema = z.strictObject({ const getClientSchema = z.strictObject({
clientId: z clientId: z
@@ -78,58 +78,108 @@ function getPlatformPostureData(
// Windows: Hard drive encryption, Firewall, Auto updates, TPM availability, Windows Antivirus status // Windows: Hard drive encryption, Firewall, Auto updates, TPM availability, Windows Antivirus status
if (normalizedPlatform === "windows") { if (normalizedPlatform === "windows") {
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) { if (
fingerprint.diskEncrypted !== null &&
fingerprint.diskEncrypted !== undefined
) {
posture.diskEncrypted = fingerprint.diskEncrypted; posture.diskEncrypted = fingerprint.diskEncrypted;
} }
if (fingerprint.firewallEnabled !== null && fingerprint.firewallEnabled !== undefined) { if (
fingerprint.firewallEnabled !== null &&
fingerprint.firewallEnabled !== undefined
) {
posture.firewallEnabled = fingerprint.firewallEnabled; posture.firewallEnabled = fingerprint.firewallEnabled;
} }
if (fingerprint.tpmAvailable !== null && fingerprint.tpmAvailable !== undefined) { if (
fingerprint.tpmAvailable !== null &&
fingerprint.tpmAvailable !== undefined
) {
posture.tpmAvailable = fingerprint.tpmAvailable; posture.tpmAvailable = fingerprint.tpmAvailable;
} }
if (fingerprint.windowsAntivirusEnabled !== null && fingerprint.windowsAntivirusEnabled !== undefined) { if (
posture.windowsAntivirusEnabled = fingerprint.windowsAntivirusEnabled; fingerprint.windowsAntivirusEnabled !== null &&
fingerprint.windowsAntivirusEnabled !== undefined
) {
posture.windowsAntivirusEnabled =
fingerprint.windowsAntivirusEnabled;
} }
} }
// macOS: Hard drive encryption, Biometric configuration, Firewall, System Integrity Protection (SIP), Gatekeeper, Firewall stealth mode // macOS: Hard drive encryption, Biometric configuration, Firewall, System Integrity Protection (SIP), Gatekeeper, Firewall stealth mode
else if (normalizedPlatform === "macos") { else if (normalizedPlatform === "macos") {
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) { if (
fingerprint.diskEncrypted !== null &&
fingerprint.diskEncrypted !== undefined
) {
posture.diskEncrypted = fingerprint.diskEncrypted; posture.diskEncrypted = fingerprint.diskEncrypted;
} }
if (fingerprint.biometricsEnabled !== null && fingerprint.biometricsEnabled !== undefined) { if (
fingerprint.biometricsEnabled !== null &&
fingerprint.biometricsEnabled !== undefined
) {
posture.biometricsEnabled = fingerprint.biometricsEnabled; posture.biometricsEnabled = fingerprint.biometricsEnabled;
} }
if (fingerprint.firewallEnabled !== null && fingerprint.firewallEnabled !== undefined) { if (
fingerprint.firewallEnabled !== null &&
fingerprint.firewallEnabled !== undefined
) {
posture.firewallEnabled = fingerprint.firewallEnabled; posture.firewallEnabled = fingerprint.firewallEnabled;
} }
if (fingerprint.macosSipEnabled !== null && fingerprint.macosSipEnabled !== undefined) { if (
fingerprint.macosSipEnabled !== null &&
fingerprint.macosSipEnabled !== undefined
) {
posture.macosSipEnabled = fingerprint.macosSipEnabled; posture.macosSipEnabled = fingerprint.macosSipEnabled;
} }
if (fingerprint.macosGatekeeperEnabled !== null && fingerprint.macosGatekeeperEnabled !== undefined) { if (
fingerprint.macosGatekeeperEnabled !== null &&
fingerprint.macosGatekeeperEnabled !== undefined
) {
posture.macosGatekeeperEnabled = fingerprint.macosGatekeeperEnabled; posture.macosGatekeeperEnabled = fingerprint.macosGatekeeperEnabled;
} }
if (fingerprint.macosFirewallStealthMode !== null && fingerprint.macosFirewallStealthMode !== undefined) { if (
posture.macosFirewallStealthMode = fingerprint.macosFirewallStealthMode; fingerprint.macosFirewallStealthMode !== null &&
fingerprint.macosFirewallStealthMode !== undefined
) {
posture.macosFirewallStealthMode =
fingerprint.macosFirewallStealthMode;
} }
if (fingerprint.autoUpdatesEnabled !== null && fingerprint.autoUpdatesEnabled !== undefined) { if (
fingerprint.autoUpdatesEnabled !== null &&
fingerprint.autoUpdatesEnabled !== undefined
) {
posture.autoUpdatesEnabled = fingerprint.autoUpdatesEnabled; posture.autoUpdatesEnabled = fingerprint.autoUpdatesEnabled;
} }
} }
// Linux: Hard drive encryption, Firewall, AppArmor, SELinux, TPM availability // Linux: Hard drive encryption, Firewall, AppArmor, SELinux, TPM availability
else if (normalizedPlatform === "linux") { else if (normalizedPlatform === "linux") {
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) { if (
fingerprint.diskEncrypted !== null &&
fingerprint.diskEncrypted !== undefined
) {
posture.diskEncrypted = fingerprint.diskEncrypted; posture.diskEncrypted = fingerprint.diskEncrypted;
} }
if (fingerprint.firewallEnabled !== null && fingerprint.firewallEnabled !== undefined) { if (
fingerprint.firewallEnabled !== null &&
fingerprint.firewallEnabled !== undefined
) {
posture.firewallEnabled = fingerprint.firewallEnabled; posture.firewallEnabled = fingerprint.firewallEnabled;
} }
if (fingerprint.linuxAppArmorEnabled !== null && fingerprint.linuxAppArmorEnabled !== undefined) { if (
fingerprint.linuxAppArmorEnabled !== null &&
fingerprint.linuxAppArmorEnabled !== undefined
) {
posture.linuxAppArmorEnabled = fingerprint.linuxAppArmorEnabled; posture.linuxAppArmorEnabled = fingerprint.linuxAppArmorEnabled;
} }
if (fingerprint.linuxSELinuxEnabled !== null && fingerprint.linuxSELinuxEnabled !== undefined) { if (
fingerprint.linuxSELinuxEnabled !== null &&
fingerprint.linuxSELinuxEnabled !== undefined
) {
posture.linuxSELinuxEnabled = fingerprint.linuxSELinuxEnabled; posture.linuxSELinuxEnabled = fingerprint.linuxSELinuxEnabled;
} }
if (fingerprint.tpmAvailable !== null && fingerprint.tpmAvailable !== undefined) { if (
fingerprint.tpmAvailable !== null &&
fingerprint.tpmAvailable !== undefined
) {
posture.tpmAvailable = fingerprint.tpmAvailable; posture.tpmAvailable = fingerprint.tpmAvailable;
} }
} }
@@ -139,7 +189,10 @@ function getPlatformPostureData(
} }
// Android: Screen lock, Biometric configuration, Hard drive encryption // Android: Screen lock, Biometric configuration, Hard drive encryption
else if (normalizedPlatform === "android") { else if (normalizedPlatform === "android") {
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) { if (
fingerprint.diskEncrypted !== null &&
fingerprint.diskEncrypted !== undefined
) {
posture.diskEncrypted = fingerprint.diskEncrypted; posture.diskEncrypted = fingerprint.diskEncrypted;
} }
} }
@@ -253,7 +306,6 @@ export async function getClient(
// Build posture data if available (platform-specific) // Build posture data if available (platform-specific)
// Only return posture data if org is licensed/subscribed // Only return posture data if org is licensed/subscribed
let postureData: PostureData | null = null; let postureData: PostureData | null = null;
if (build !== "oss") {
const isOrgLicensed = await isLicensedOrSubscribed( const isOrgLicensed = await isLicensedOrSubscribed(
client.clients.orgId client.clients.orgId
); );
@@ -263,7 +315,6 @@ export async function getClient(
client.currentFingerprint client.currentFingerprint
); );
} }
}
const data: GetClientResponse = { const data: GetClientResponse = {
...client.clients, ...client.clients,

View File

@@ -13,7 +13,7 @@ import { build } from "@server/build";
import { getOrgTierData } from "#dynamic/lib/billing"; import { getOrgTierData } from "#dynamic/lib/billing";
import { TierId } from "@server/lib/billing/tiers"; import { TierId } from "@server/lib/billing/tiers";
import { cache } from "@server/lib/cache"; import { cache } from "@server/lib/cache";
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
const updateOrgParamsSchema = z.strictObject({ const updateOrgParamsSchema = z.strictObject({
orgId: z.string() orgId: z.string()
@@ -89,7 +89,7 @@ export async function updateOrg(
const { orgId } = parsedParams.data; const { orgId } = parsedParams.data;
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId);
if (build == "enterprise" && !isLicensed) { if (!isLicensed) {
parsedBody.data.requireTwoFactor = undefined; parsedBody.data.requireTwoFactor = undefined;
parsedBody.data.maxSessionLengthHours = undefined; parsedBody.data.maxSessionLengthHours = undefined;
parsedBody.data.passwordExpiryDays = undefined; parsedBody.data.passwordExpiryDays = undefined;

View File

@@ -23,7 +23,7 @@ import { OpenAPITags } from "@server/openApi";
import { createCertificate } from "#dynamic/routers/certificates/createCertificate"; import { createCertificate } from "#dynamic/routers/certificates/createCertificate";
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 "@server/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
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())
@@ -342,11 +342,7 @@ async function updateHttpResource(
} }
const isLicensed = await isLicensedOrSubscribed(resource.orgId); const isLicensed = await isLicensedOrSubscribed(resource.orgId);
if (build == "enterprise" && !isLicensed) { if (!isLicensed) {
logger.warn(
"Server is not licensed! Clearing set maintenance screen values"
);
// null the maintenance mode fields if not licensed
updateData.maintenanceModeEnabled = undefined; updateData.maintenanceModeEnabled = undefined;
updateData.maintenanceModeType = undefined; updateData.maintenanceModeType = undefined;
updateData.maintenanceTitle = undefined; updateData.maintenanceTitle = undefined;

View File

@@ -11,7 +11,7 @@ import { ActionsEnum } from "@server/auth/actions";
import { eq, and } from "drizzle-orm"; 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 "@server/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
const createRoleParamsSchema = z.strictObject({ const createRoleParamsSchema = z.strictObject({
orgId: z.string() orgId: z.string()
@@ -101,7 +101,7 @@ export async function createRole(
} }
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId);
if (build === "oss" || !isLicensed) { if (!isLicensed) {
roleData.requireDeviceApproval = undefined; roleData.requireDeviceApproval = undefined;
} }

View File

@@ -8,8 +8,7 @@ import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { build } from "@server/build"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
const updateRoleParamsSchema = z.strictObject({ const updateRoleParamsSchema = z.strictObject({
@@ -112,7 +111,7 @@ export async function updateRole(
} }
const isLicensed = await isLicensedOrSubscribed(orgId); const isLicensed = await isLicensedOrSubscribed(orgId);
if (build === "oss" || !isLicensed) { if (!isLicensed) {
updateData.requireDeviceApproval = undefined; updateData.requireDeviceApproval = undefined;
} }