diff --git a/backend/src/services/project-env/project-env-service.ts b/backend/src/services/project-env/project-env-service.ts index 7fbe7343e..bf0bb18af 100644 --- a/backend/src/services/project-env/project-env-service.ts +++ b/backend/src/services/project-env/project-env-service.ts @@ -177,6 +177,18 @@ export const projectEnvServiceFactory = ({ } } + const envs = await projectEnvDAL.find({ projectId }); + const project = await projectDAL.findById(projectId); + const plan = await licenseService.getPlan(project.orgId); + if (plan.environmentLimit !== null && envs.length > plan.environmentLimit) { + // case: limit imposed on number of environments allowed + // case: number of environments used exceeds the number of environments allowed + throw new BadRequestError({ + message: + "Failed to update environment due to environment limit exceeded. To update an environment, please upgrade your plan or remove unused environments." + }); + } + const env = await projectEnvDAL.transaction(async (tx) => { if (position) { const existingEnvWithPosition = await projectEnvDAL.findOne({ projectId, position }, tx); diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx index 3da07b923..159bda918 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx @@ -12,9 +12,15 @@ import { Td, Th, THead, + Tooltip, Tr } from "@app/components/v2"; -import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; +import { + ProjectPermissionActions, + ProjectPermissionSub, + useSubscription, + useWorkspace +} from "@app/context"; import { useUpdateWsEnvironment } from "@app/hooks/api"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -35,6 +41,7 @@ type Props = { export const EnvironmentTable = ({ handlePopUpOpen }: Props) => { const { currentWorkspace } = useWorkspace(); + const { subscription } = useSubscription(); const updateEnvironment = useUpdateWsEnvironment(); @@ -61,6 +68,16 @@ export const EnvironmentTable = ({ handlePopUpOpen }: Props) => { } }; + const isMoreEnvironmentsAllowed = + subscription?.environmentLimit && currentWorkspace?.environments + ? currentWorkspace.environments.length <= subscription.environmentLimit + : true; + + const environmentsOverPlanLimit = + subscription?.environmentLimit && currentWorkspace?.environments + ? currentWorkspace.environments.length - subscription.environmentLimit + : 0; + return ( @@ -122,18 +139,26 @@ export const EnvironmentTable = ({ handlePopUpOpen }: Props) => { a={ProjectPermissionSub.Environments} > {(isAllowed) => ( - { - handlePopUpOpen("updateEnv", { name, slug, id }); - }} - isDisabled={!isAllowed} - colorSchema="primary" - variant="plain" - ariaLabel="update" + - - + { + handlePopUpOpen("updateEnv", { name, slug, id }); + }} + isDisabled={!isAllowed || !isMoreEnvironmentsAllowed} + colorSchema="primary" + variant="plain" + ariaLabel="update" + > + + + )}