diff --git a/server/private/routers/orgIdp/unassociateOrgIdp.ts b/server/private/routers/orgIdp/unassociateOrgIdp.ts index 0b5c1ed51..d9c0bfc8f 100644 --- a/server/private/routers/orgIdp/unassociateOrgIdp.ts +++ b/server/private/routers/orgIdp/unassociateOrgIdp.ts @@ -23,6 +23,7 @@ import { and, eq, sql } from "drizzle-orm"; import { removeUserFromOrg } from "@server/lib/userOrg"; import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs"; import { OpenAPITags, registry } from "@server/openApi"; +import { isOrgRebuildRateLimited } from "@server/lib/rebuildClientAssociations"; const paramsSchema = z .object({ @@ -90,6 +91,15 @@ export async function unassociateOrgIdp( ); } + if (await isOrgRebuildRateLimited(org.orgId)) { + return next( + createHttpError( + HttpCode.TOO_MANY_REQUESTS, + "Too many concurrent rebuild operations for this organization. Please retry after a moment." + ) + ); + } + const orgUsersFromIdp = await db .select({ userId: userOrgs.userId, diff --git a/server/routers/user/acceptInvite.ts b/server/routers/user/acceptInvite.ts index ef7ddcdbd..37ac69f59 100644 --- a/server/routers/user/acceptInvite.ts +++ b/server/routers/user/acceptInvite.ts @@ -21,6 +21,7 @@ import { FeatureId } from "@server/lib/billing"; import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs"; import { build } from "@server/build"; import { assignUserToOrg } from "@server/lib/userOrg"; +import { isOrgRebuildRateLimited } from "@server/lib/rebuildClientAssociations"; const acceptInviteBodySchema = z.strictObject({ token: z.string(), @@ -147,6 +148,15 @@ export async function acceptInvite( ); } + if (await isOrgRebuildRateLimited(org.orgId)) { + return next( + createHttpError( + HttpCode.TOO_MANY_REQUESTS, + "Too many concurrent rebuild operations for this organization. Please retry after a moment." + ) + ); + } + const inviteRoleRows = await db .select({ roleId: userInviteRoles.roleId }) .from(userInviteRoles) diff --git a/server/routers/user/createOrgUser.ts b/server/routers/user/createOrgUser.ts index c6f25e085..b20881198 100644 --- a/server/routers/user/createOrgUser.ts +++ b/server/routers/user/createOrgUser.ts @@ -19,6 +19,7 @@ import { isSubscribed } from "#dynamic/lib/isSubscribed"; import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix"; import { assignUserToOrg } from "@server/lib/userOrg"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; +import { isOrgRebuildRateLimited } from "@server/lib/rebuildClientAssociations"; const paramsSchema = z.strictObject({ orgId: z.string().nonempty() @@ -229,6 +230,15 @@ export async function createOrgUser( ); } + if (await isOrgRebuildRateLimited(org.orgId)) { + return next( + createHttpError( + HttpCode.TOO_MANY_REQUESTS, + "Too many concurrent rebuild operations for this organization. Please retry after a moment." + ) + ); + } + const [idpRes] = await db .select() .from(idp) diff --git a/server/routers/user/removeUserOrg.ts b/server/routers/user/removeUserOrg.ts index 902aeed84..abaf6b3e6 100644 --- a/server/routers/user/removeUserOrg.ts +++ b/server/routers/user/removeUserOrg.ts @@ -1,29 +1,17 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; -import { - db, - orgs, - resources, - siteResources, - sites, - UserOrg, - userSiteResources, - primaryDb -} from "@server/db"; -import { userOrgs, userResources, users, userSites } from "@server/db"; -import { and, count, eq, exists, inArray } from "drizzle-orm"; +import { db, orgs } from "@server/db"; +import { userOrgs } from "@server/db"; +import { and, eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; import createHttpError from "http-errors"; import logger from "@server/logger"; import { fromError } from "zod-validation-error"; import { OpenAPITags, registry } from "@server/openApi"; -import { usageService } from "@server/lib/billing/usageService"; -import { FeatureId } from "@server/lib/billing"; -import { build } from "@server/build"; -import { UserType } from "@server/types/UserTypes"; import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs"; import { removeUserFromOrg } from "@server/lib/userOrg"; +import { isOrgRebuildRateLimited } from "@server/lib/rebuildClientAssociations"; const removeUserSchema = z.strictObject({ userId: z.string(), @@ -93,6 +81,15 @@ export async function removeUserOrg( ); } + if (await isOrgRebuildRateLimited(orgId)) { + return next( + createHttpError( + HttpCode.TOO_MANY_REQUESTS, + "Too many concurrent rebuild operations for this organization. Please retry after a moment." + ) + ); + } + const [org] = await db .select() .from(orgs)