From 92647341a9453c5416ea8fccca14f8384c8543cd Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Wed, 14 Jun 2023 11:52:48 +0100 Subject: [PATCH] Update getPlan with workspace-specific consideration and add environmentLimit to returned plan --- .../controllers/v1/membershipOrgController.ts | 2 +- .../src/controllers/v1/workspaceController.ts | 2 +- .../controllers/v1/organizationsController.ts | 3 ++- backend/src/ee/routes/v1/organizations.ts | 3 ++- backend/src/ee/services/EELicenseService.ts | 24 ++++++++++++------- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/backend/src/controllers/v1/membershipOrgController.ts b/backend/src/controllers/v1/membershipOrgController.ts index eafd7fae2..0d4c1436d 100644 --- a/backend/src/controllers/v1/membershipOrgController.ts +++ b/backend/src/controllers/v1/membershipOrgController.ts @@ -99,7 +99,7 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => { throw new Error('Failed to validate organization membership'); } - const plan = await EELicenseService.getOrganizationPlan(organizationId); + const plan = await EELicenseService.getPlan(organizationId); if (plan.memberLimit !== null) { // case: limit imposed on number of members allowed diff --git a/backend/src/controllers/v1/workspaceController.ts b/backend/src/controllers/v1/workspaceController.ts index 796a7bebc..2faac0d68 100644 --- a/backend/src/controllers/v1/workspaceController.ts +++ b/backend/src/controllers/v1/workspaceController.ts @@ -116,7 +116,7 @@ export const createWorkspace = async (req: Request, res: Response) => { throw new Error("Failed to validate organization membership"); } - const plan = await EELicenseService.getOrganizationPlan(organizationId); + const plan = await EELicenseService.getPlan(organizationId); if (plan.workspaceLimit !== null) { // case: limit imposed on number of workspaces allowed diff --git a/backend/src/ee/controllers/v1/organizationsController.ts b/backend/src/ee/controllers/v1/organizationsController.ts index 2dd212e77..2d2867d71 100644 --- a/backend/src/ee/controllers/v1/organizationsController.ts +++ b/backend/src/ee/controllers/v1/organizationsController.ts @@ -8,8 +8,9 @@ import { EELicenseService } from '../../services'; */ export const getOrganizationPlan = async (req: Request, res: Response) => { const { organizationId } = req.params; + const workspaceId = req.query.workspaceId as string; - const plan = await EELicenseService.getOrganizationPlan(organizationId); + const plan = await EELicenseService.getPlan(organizationId, workspaceId); return res.status(200).send({ plan, diff --git a/backend/src/ee/routes/v1/organizations.ts b/backend/src/ee/routes/v1/organizations.ts index fd9fd08e9..711b5a17f 100644 --- a/backend/src/ee/routes/v1/organizations.ts +++ b/backend/src/ee/routes/v1/organizations.ts @@ -5,7 +5,7 @@ import { requireOrganizationAuth, validateRequest } from '../../../middleware'; -import { param, body } from 'express-validator'; +import { param, body, query } from 'express-validator'; import { organizationsController } from '../../controllers/v1'; import { OWNER, ADMIN, MEMBER, ACCEPTED @@ -21,6 +21,7 @@ router.get( acceptedStatuses: [ACCEPTED] }), param('organizationId').exists().trim(), + query('workspaceId').optional().isString(), validateRequest, organizationsController.getOrganizationPlan ); diff --git a/backend/src/ee/services/EELicenseService.ts b/backend/src/ee/services/EELicenseService.ts index c98a5a449..85a27de99 100644 --- a/backend/src/ee/services/EELicenseService.ts +++ b/backend/src/ee/services/EELicenseService.ts @@ -22,6 +22,8 @@ interface FeatureSet { workspacesUsed: number; memberLimit: number | null; membersUsed: number; + environmentLimit: number | null; + environmentsUsed: number; secretVersioning: boolean; pitRecovery: boolean; rbac: boolean; @@ -51,6 +53,8 @@ class EELicenseService { workspacesUsed: 0, memberLimit: null, membersUsed: 0, + environmentLimit: null, + environmentsUsed: 0, secretVersioning: true, pitRecovery: true, rbac: true, @@ -69,10 +73,10 @@ class EELicenseService { }); } - public async getOrganizationPlan(organizationId: string): Promise { + public async getPlan(organizationId: string, workspaceId?: string): Promise { try { if (this.instanceType === 'cloud') { - const cachedPlan = this.localFeatureSet.get(organizationId); + const cachedPlan = this.localFeatureSet.get(`${organizationId}-${workspaceId ?? ''}`); if (cachedPlan) { return cachedPlan; } @@ -80,12 +84,16 @@ class EELicenseService { const organization = await Organization.findById(organizationId); if (!organization) throw OrganizationNotFoundError(); - const { data: { currentPlan } } = await licenseServerKeyRequest.get( - `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan` - ); + let url = `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan`; + + if (workspaceId) { + url += `?workspaceId=${workspaceId}`; + } + + const { data: { currentPlan } } = await licenseServerKeyRequest.get(url); // cache fetched plan for organization - this.localFeatureSet.set(organizationId, currentPlan); + this.localFeatureSet.set(`${organizationId}-${workspaceId ?? ''}`, currentPlan); return currentPlan; } @@ -96,10 +104,10 @@ class EELicenseService { return this.globalFeatureSet; } - public async refreshOrganizationPlan(organizationId: string) { + public async refreshOrganizationPlan(organizationId: string, workspaceId?: string) { if (this.instanceType === 'cloud') { this.localFeatureSet.del(organizationId); - await this.getOrganizationPlan(organizationId); + await this.getPlan(organizationId, workspaceId); } }