mirror of
https://github.com/fosrl/pangolin.git
synced 2026-04-12 22:26:29 +00:00
Restrict namespaces to paid plans due to abuse
This commit is contained in:
@@ -19,7 +19,8 @@ export enum TierFeature {
|
||||
SshPam = "sshPam",
|
||||
FullRbac = "fullRbac",
|
||||
SiteProvisioningKeys = "siteProvisioningKeys", // handle downgrade by revoking keys if needed
|
||||
SIEM = "siem" // handle downgrade by disabling SIEM integrations
|
||||
SIEM = "siem", // handle downgrade by disabling SIEM integrations
|
||||
DomainNamespaces = "domainNamespaces" // handle downgrade by removing custom domain namespaces
|
||||
}
|
||||
|
||||
export const tierMatrix: Record<TierFeature, Tier[]> = {
|
||||
@@ -56,5 +57,6 @@ export const tierMatrix: Record<TierFeature, Tier[]> = {
|
||||
[TierFeature.SshPam]: ["tier1", "tier3", "enterprise"],
|
||||
[TierFeature.FullRbac]: ["tier1", "tier2", "tier3", "enterprise"],
|
||||
[TierFeature.SiteProvisioningKeys]: ["tier3", "enterprise"],
|
||||
[TierFeature.SIEM]: ["enterprise"]
|
||||
[TierFeature.SIEM]: ["enterprise"],
|
||||
[TierFeature.DomainNamespaces]: ["tier1", "tier2", "tier3", "enterprise"]
|
||||
};
|
||||
|
||||
@@ -22,11 +22,15 @@ import { OpenAPITags, registry } from "@server/openApi";
|
||||
import { db, domainNamespaces, resources } from "@server/db";
|
||||
import { inArray } from "drizzle-orm";
|
||||
import { CheckDomainAvailabilityResponse } from "@server/routers/domain/types";
|
||||
import { build } from "@server/build";
|
||||
import { isSubscribed } from "#private/lib/isSubscribed";
|
||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||
|
||||
const paramsSchema = z.strictObject({});
|
||||
|
||||
const querySchema = z.strictObject({
|
||||
subdomain: z.string()
|
||||
subdomain: z.string(),
|
||||
// orgId: build === "saas" ? z.string() : z.string().optional() // Required for saas, optional otherwise
|
||||
});
|
||||
|
||||
registry.registerPath({
|
||||
@@ -58,6 +62,23 @@ export async function checkDomainNamespaceAvailability(
|
||||
}
|
||||
const { subdomain } = parsedQuery.data;
|
||||
|
||||
// if (
|
||||
// build == "saas" &&
|
||||
// !isSubscribed(orgId!, tierMatrix.domainNamespaces)
|
||||
// ) {
|
||||
// // return not available
|
||||
// return response<CheckDomainAvailabilityResponse>(res, {
|
||||
// data: {
|
||||
// available: false,
|
||||
// options: []
|
||||
// },
|
||||
// success: true,
|
||||
// error: false,
|
||||
// message: "Your current subscription does not support custom domain namespaces. Please upgrade to access this feature.",
|
||||
// status: HttpCode.OK
|
||||
// });
|
||||
// }
|
||||
|
||||
const namespaces = await db.select().from(domainNamespaces);
|
||||
let possibleDomains = namespaces.map((ns) => {
|
||||
const desired = `${subdomain}.${ns.domainNamespaceId}`;
|
||||
|
||||
@@ -22,6 +22,9 @@ import { eq, sql } from "drizzle-orm";
|
||||
import logger from "@server/logger";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
import { isSubscribed } from "#private/lib/isSubscribed";
|
||||
import { build } from "@server/build";
|
||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||
|
||||
const paramsSchema = z.strictObject({});
|
||||
|
||||
@@ -37,7 +40,8 @@ const querySchema = z.strictObject({
|
||||
.optional()
|
||||
.default("0")
|
||||
.transform(Number)
|
||||
.pipe(z.int().nonnegative())
|
||||
.pipe(z.int().nonnegative()),
|
||||
// orgId: build === "saas" ? z.string() : z.string().optional() // Required for saas, optional otherwise
|
||||
});
|
||||
|
||||
async function query(limit: number, offset: number) {
|
||||
@@ -99,6 +103,26 @@ export async function listDomainNamespaces(
|
||||
);
|
||||
}
|
||||
|
||||
// if (
|
||||
// build == "saas" &&
|
||||
// !isSubscribed(orgId!, tierMatrix.domainNamespaces)
|
||||
// ) {
|
||||
// return response<ListDomainNamespacesResponse>(res, {
|
||||
// data: {
|
||||
// domainNamespaces: [],
|
||||
// pagination: {
|
||||
// total: 0,
|
||||
// limit,
|
||||
// offset
|
||||
// }
|
||||
// },
|
||||
// success: true,
|
||||
// error: false,
|
||||
// message: "No namespaces found. Your current subscription does not support custom domain namespaces. Please upgrade to access this feature.",
|
||||
// status: HttpCode.OK
|
||||
// });
|
||||
// }
|
||||
|
||||
const domainNamespacesList = await query(limit, offset);
|
||||
|
||||
const [{ count }] = await db
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { z } from "zod";
|
||||
import { db, loginPage } from "@server/db";
|
||||
import { db, domainNamespaces, loginPage } from "@server/db";
|
||||
import {
|
||||
domains,
|
||||
orgDomains,
|
||||
@@ -24,6 +24,8 @@ import { build } from "@server/build";
|
||||
import { createCertificate } from "#dynamic/routers/certificates/createCertificate";
|
||||
import { getUniqueResourceName } from "@server/db/names";
|
||||
import { validateAndConstructDomain } from "@server/lib/domainUtils";
|
||||
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||
|
||||
const createResourceParamsSchema = z.strictObject({
|
||||
orgId: z.string()
|
||||
@@ -193,6 +195,27 @@ async function createHttpResource(
|
||||
const subdomain = parsedBody.data.subdomain;
|
||||
const stickySession = parsedBody.data.stickySession;
|
||||
|
||||
if (
|
||||
build == "saas" &&
|
||||
!isSubscribed(orgId!, tierMatrix.domainNamespaces)
|
||||
) {
|
||||
// check if this domain id is a namespace domain and if so, reject
|
||||
const domain = await db
|
||||
.select()
|
||||
.from(domainNamespaces)
|
||||
.where(eq(domainNamespaces.domainId, domainId))
|
||||
.limit(1);
|
||||
|
||||
if (domain.length > 0) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.BAD_REQUEST,
|
||||
"Your current subscription does not support custom domain namespaces. Please upgrade to access this feature."
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate domain and construct full domain
|
||||
const domainResult = await validateAndConstructDomain(
|
||||
domainId,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { z } from "zod";
|
||||
import { db, loginPage } from "@server/db";
|
||||
import { db, domainNamespaces, loginPage } from "@server/db";
|
||||
import {
|
||||
domains,
|
||||
Org,
|
||||
@@ -25,6 +25,7 @@ import { validateAndConstructDomain } from "@server/lib/domainUtils";
|
||||
import { build } from "@server/build";
|
||||
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||
|
||||
const updateResourceParamsSchema = z.strictObject({
|
||||
resourceId: z.string().transform(Number).pipe(z.int().positive())
|
||||
@@ -318,6 +319,27 @@ async function updateHttpResource(
|
||||
if (updateData.domainId) {
|
||||
const domainId = updateData.domainId;
|
||||
|
||||
if (
|
||||
build == "saas" &&
|
||||
!isSubscribed(resource.orgId, tierMatrix.domainNamespaces)
|
||||
) {
|
||||
// check if this domain id is a namespace domain and if so, reject
|
||||
const domain = await db
|
||||
.select()
|
||||
.from(domainNamespaces)
|
||||
.where(eq(domainNamespaces.domainId, domainId))
|
||||
.limit(1);
|
||||
|
||||
if (domain.length > 0) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.BAD_REQUEST,
|
||||
"Your current subscription does not support custom domain namespaces. Please upgrade to access this feature."
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate domain and construct full domain
|
||||
const domainResult = await validateAndConstructDomain(
|
||||
domainId,
|
||||
@@ -366,7 +388,7 @@ async function updateHttpResource(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (build != "oss") {
|
||||
const existingLoginPages = await db
|
||||
.select()
|
||||
|
||||
Reference in New Issue
Block a user