mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #2024 from Infisical/revert-2023-revert-1995-identity-based-pricing
Add support for Identity-Based Pricing"
This commit is contained in:
@@ -5,3 +5,4 @@ frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/M
|
|||||||
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:292
|
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:292
|
||||||
docs/self-hosting/configuration/envars.mdx:generic-api-key:106
|
docs/self-hosting/configuration/envars.mdx:generic-api-key:106
|
||||||
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:451
|
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:451
|
||||||
|
docs/mint.json:generic-api-key:651
|
||||||
|
|||||||
@@ -456,6 +456,21 @@ export const ldapConfigServiceFactory = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
const plan = await licenseService.getPlan(orgId);
|
||||||
|
if (plan?.memberLimit && plan.membersUsed >= plan.memberLimit) {
|
||||||
|
// limit imposed on number of members allowed / number of members used exceeds the number of members allowed
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to create new member via LDAP due to member limit reached. Upgrade plan to add more members."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plan?.identityLimit && plan.identitiesUsed >= plan.identityLimit) {
|
||||||
|
// limit imposed on number of identities allowed / number of identities used exceeds the number of identities allowed
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to create new member via LDAP due to member limit reached. Upgrade plan to add more members."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
userAlias = await userDAL.transaction(async (tx) => {
|
userAlias = await userDAL.transaction(async (tx) => {
|
||||||
let newUser: TUsers | undefined;
|
let newUser: TUsers | undefined;
|
||||||
if (serverCfg.trustSamlEmails) {
|
if (serverCfg.trustSamlEmails) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ export const getDefaultOnPremFeatures = () => {
|
|||||||
workspacesUsed: 0,
|
workspacesUsed: 0,
|
||||||
memberLimit: null,
|
memberLimit: null,
|
||||||
membersUsed: 0,
|
membersUsed: 0,
|
||||||
|
identityLimit: null,
|
||||||
|
identitiesUsed: 0,
|
||||||
environmentLimit: null,
|
environmentLimit: null,
|
||||||
environmentsUsed: 0,
|
environmentsUsed: 0,
|
||||||
secretVersioning: true,
|
secretVersioning: true,
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
membersUsed: 0,
|
membersUsed: 0,
|
||||||
environmentLimit: null,
|
environmentLimit: null,
|
||||||
environmentsUsed: 0,
|
environmentsUsed: 0,
|
||||||
|
identityLimit: null,
|
||||||
|
identitiesUsed: 0,
|
||||||
dynamicSecret: false,
|
dynamicSecret: false,
|
||||||
secretVersioning: true,
|
secretVersioning: true,
|
||||||
pitRecovery: false,
|
pitRecovery: false,
|
||||||
|
|||||||
@@ -19,11 +19,44 @@ export const licenseDALFactory = (db: TDbClient) => {
|
|||||||
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
||||||
.where(`${TableName.Users}.isGhost`, false)
|
.where(`${TableName.Users}.isGhost`, false)
|
||||||
.count();
|
.count();
|
||||||
return doc?.[0].count;
|
return Number(doc?.[0].count);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new DatabaseError({ error, name: "Count of Org Members" });
|
throw new DatabaseError({ error, name: "Count of Org Members" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return { countOfOrgMembers };
|
const countOrgUsersAndIdentities = async (orgId: string | null, tx?: Knex) => {
|
||||||
|
try {
|
||||||
|
// count org users
|
||||||
|
const userDoc = await (tx || db)(TableName.OrgMembership)
|
||||||
|
.where({ status: OrgMembershipStatus.Accepted })
|
||||||
|
.andWhere((bd) => {
|
||||||
|
if (orgId) {
|
||||||
|
void bd.where({ orgId });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
||||||
|
.where(`${TableName.Users}.isGhost`, false)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
const userCount = Number(userDoc?.[0].count);
|
||||||
|
|
||||||
|
// count org identities
|
||||||
|
const identityDoc = await (tx || db)(TableName.IdentityOrgMembership)
|
||||||
|
.where((bd) => {
|
||||||
|
if (orgId) {
|
||||||
|
void bd.where({ orgId });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
|
||||||
|
const identityCount = Number(identityDoc?.[0].count);
|
||||||
|
|
||||||
|
return userCount + identityCount;
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "Count of Org Users + Identities" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { countOfOrgMembers, countOrgUsersAndIdentities };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ export const licenseServiceFactory = ({
|
|||||||
LICENSE_SERVER_CLOUD_PLAN_TTL,
|
LICENSE_SERVER_CLOUD_PLAN_TTL,
|
||||||
JSON.stringify(currentPlan)
|
JSON.stringify(currentPlan)
|
||||||
);
|
);
|
||||||
|
|
||||||
return currentPlan;
|
return currentPlan;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -204,16 +205,22 @@ export const licenseServiceFactory = ({
|
|||||||
const org = await orgDAL.findOrgById(orgId);
|
const org = await orgDAL.findOrgById(orgId);
|
||||||
if (!org) throw new BadRequestError({ message: "Org not found" });
|
if (!org) throw new BadRequestError({ message: "Org not found" });
|
||||||
|
|
||||||
const count = await licenseDAL.countOfOrgMembers(orgId);
|
const quantity = await licenseDAL.countOfOrgMembers(orgId);
|
||||||
|
const quantityIdentities = await licenseDAL.countOrgUsersAndIdentities(orgId);
|
||||||
if (org?.customerId) {
|
if (org?.customerId) {
|
||||||
await licenseServerCloudApi.request.patch(`/api/license-server/v1/customers/${org.customerId}/cloud-plan`, {
|
await licenseServerCloudApi.request.patch(`/api/license-server/v1/customers/${org.customerId}/cloud-plan`, {
|
||||||
quantity: count
|
quantity,
|
||||||
|
quantityIdentities
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await keyStore.deleteItem(FEATURE_CACHE_KEY(orgId));
|
await keyStore.deleteItem(FEATURE_CACHE_KEY(orgId));
|
||||||
} else if (instanceType === InstanceType.EnterpriseOnPrem) {
|
} else if (instanceType === InstanceType.EnterpriseOnPrem) {
|
||||||
const usedSeats = await licenseDAL.countOfOrgMembers(null);
|
const usedSeats = await licenseDAL.countOfOrgMembers(null);
|
||||||
await licenseServerOnPremApi.request.patch(`/api/license/v1/license`, { usedSeats });
|
const usedIdentitySeats = await licenseDAL.countOrgUsersAndIdentities(null);
|
||||||
|
await licenseServerOnPremApi.request.patch(`/api/license/v1/license`, {
|
||||||
|
usedSeats,
|
||||||
|
usedIdentitySeats
|
||||||
|
});
|
||||||
}
|
}
|
||||||
await refreshPlan(orgId);
|
await refreshPlan(orgId);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export type TFeatureSet = {
|
|||||||
dynamicSecret: false;
|
dynamicSecret: false;
|
||||||
memberLimit: null;
|
memberLimit: null;
|
||||||
membersUsed: 0;
|
membersUsed: 0;
|
||||||
|
identityLimit: null;
|
||||||
|
identitiesUsed: 0;
|
||||||
environmentLimit: null;
|
environmentLimit: null;
|
||||||
environmentsUsed: 0;
|
environmentsUsed: 0;
|
||||||
secretVersioning: true;
|
secretVersioning: true;
|
||||||
|
|||||||
@@ -380,6 +380,21 @@ export const samlConfigServiceFactory = ({
|
|||||||
return foundUser;
|
return foundUser;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
const plan = await licenseService.getPlan(orgId);
|
||||||
|
if (plan?.memberLimit && plan.membersUsed >= plan.memberLimit) {
|
||||||
|
// limit imposed on number of members allowed / number of members used exceeds the number of members allowed
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to create new member via SAML due to member limit reached. Upgrade plan to add more members."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plan?.identityLimit && plan.identitiesUsed >= plan.identityLimit) {
|
||||||
|
// limit imposed on number of identities allowed / number of identities used exceeds the number of identities allowed
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to create new member via SAML due to member limit reached. Upgrade plan to add more members."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
user = await userDAL.transaction(async (tx) => {
|
user = await userDAL.transaction(async (tx) => {
|
||||||
let newUser: TUsers | undefined;
|
let newUser: TUsers | undefined;
|
||||||
if (serverCfg.trustSamlEmails) {
|
if (serverCfg.trustSamlEmails) {
|
||||||
|
|||||||
@@ -806,7 +806,8 @@ export const registerRoutes = async (
|
|||||||
const identityService = identityServiceFactory({
|
const identityService = identityServiceFactory({
|
||||||
permissionService,
|
permissionService,
|
||||||
identityDAL,
|
identityDAL,
|
||||||
identityOrgMembershipDAL
|
identityOrgMembershipDAL,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
const identityAccessTokenService = identityAccessTokenServiceFactory({
|
const identityAccessTokenService = identityAccessTokenServiceFactory({
|
||||||
identityAccessTokenDAL,
|
identityAccessTokenDAL,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
|
||||||
import { OrgMembershipRole, TableName, TOrgRoles } from "@app/db/schemas";
|
import { OrgMembershipRole, TableName, TOrgRoles } from "@app/db/schemas";
|
||||||
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||||
@@ -16,6 +17,7 @@ type TIdentityServiceFactoryDep = {
|
|||||||
identityDAL: TIdentityDALFactory;
|
identityDAL: TIdentityDALFactory;
|
||||||
identityOrgMembershipDAL: TIdentityOrgDALFactory;
|
identityOrgMembershipDAL: TIdentityOrgDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission" | "getOrgPermissionByRole">;
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission" | "getOrgPermissionByRole">;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TIdentityServiceFactory = ReturnType<typeof identityServiceFactory>;
|
export type TIdentityServiceFactory = ReturnType<typeof identityServiceFactory>;
|
||||||
@@ -23,7 +25,8 @@ export type TIdentityServiceFactory = ReturnType<typeof identityServiceFactory>;
|
|||||||
export const identityServiceFactory = ({
|
export const identityServiceFactory = ({
|
||||||
identityDAL,
|
identityDAL,
|
||||||
identityOrgMembershipDAL,
|
identityOrgMembershipDAL,
|
||||||
permissionService
|
permissionService,
|
||||||
|
licenseService
|
||||||
}: TIdentityServiceFactoryDep) => {
|
}: TIdentityServiceFactoryDep) => {
|
||||||
const createIdentity = async ({
|
const createIdentity = async ({
|
||||||
name,
|
name,
|
||||||
@@ -45,6 +48,14 @@ export const identityServiceFactory = ({
|
|||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
|
||||||
if (!hasRequiredPriviledges) throw new BadRequestError({ message: "Failed to create a more privileged identity" });
|
if (!hasRequiredPriviledges) throw new BadRequestError({ message: "Failed to create a more privileged identity" });
|
||||||
|
|
||||||
|
const plan = await licenseService.getPlan(orgId);
|
||||||
|
if (plan?.identityLimit && plan.identitiesUsed >= plan.identityLimit) {
|
||||||
|
// limit imposed on number of identities allowed / number of identities used exceeds the number of identities allowed
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to create identity due to identity limit reached. Upgrade plan to create more identities."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const identity = await identityDAL.transaction(async (tx) => {
|
const identity = await identityDAL.transaction(async (tx) => {
|
||||||
const newIdentity = await identityDAL.create({ name }, tx);
|
const newIdentity = await identityDAL.create({ name }, tx);
|
||||||
await identityOrgMembershipDAL.create(
|
await identityOrgMembershipDAL.create(
|
||||||
@@ -58,6 +69,7 @@ export const identityServiceFactory = ({
|
|||||||
);
|
);
|
||||||
return newIdentity;
|
return newIdentity;
|
||||||
});
|
});
|
||||||
|
await licenseService.updateSubscriptionOrgMemberCount(orgId);
|
||||||
|
|
||||||
return identity;
|
return identity;
|
||||||
};
|
};
|
||||||
@@ -168,6 +180,9 @@ export const identityServiceFactory = ({
|
|||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
||||||
|
|
||||||
const deletedIdentity = await identityDAL.deleteById(id);
|
const deletedIdentity = await identityDAL.deleteById(id);
|
||||||
|
|
||||||
|
await licenseService.updateSubscriptionOrgMemberCount(identityOrgMembership.orgId);
|
||||||
|
|
||||||
return { ...deletedIdentity, orgId: identityOrgMembership.orgId };
|
return { ...deletedIdentity, orgId: identityOrgMembership.orgId };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -420,13 +420,20 @@ export const orgServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const plan = await licenseService.getPlan(orgId);
|
const plan = await licenseService.getPlan(orgId);
|
||||||
if (plan.memberLimit !== null && plan.membersUsed >= plan.memberLimit) {
|
if (plan?.memberLimit && plan.membersUsed >= plan.memberLimit) {
|
||||||
// case: limit imposed on number of members allowed
|
// limit imposed on number of members allowed / number of members used exceeds the number of members allowed
|
||||||
// case: number of members used exceeds the number of members allowed
|
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
message: "Failed to invite member due to member limit reached. Upgrade plan to invite more members."
|
message: "Failed to invite member due to member limit reached. Upgrade plan to invite more members."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (plan?.identityLimit && plan.identitiesUsed >= plan.identityLimit) {
|
||||||
|
// limit imposed on number of identities allowed / number of identities used exceeds the number of identities allowed
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to invite member due to member limit reached. Upgrade plan to invite more members."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const invitee = await orgDAL.transaction(async (tx) => {
|
const invitee = await orgDAL.transaction(async (tx) => {
|
||||||
const inviteeUser = await userDAL.findUserByUsername(inviteeEmail, tx);
|
const inviteeUser = await userDAL.findUserByUsername(inviteeEmail, tx);
|
||||||
if (inviteeUser) {
|
if (inviteeUser) {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ export type SubscriptionPlan = {
|
|||||||
id: string;
|
id: string;
|
||||||
membersUsed: number;
|
membersUsed: number;
|
||||||
memberLimit: number;
|
memberLimit: number;
|
||||||
|
identitiesUsed: number;
|
||||||
|
identityLimit: number;
|
||||||
auditLogs: boolean;
|
auditLogs: boolean;
|
||||||
dynamicSecret: boolean;
|
dynamicSecret: boolean;
|
||||||
auditLogsRetentionDays: number;
|
auditLogsRetentionDays: number;
|
||||||
|
|||||||
@@ -4,8 +4,13 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
import { Button, DeleteActionModal, UpgradePlanModal } from "@app/components/v2";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
import {
|
||||||
|
OrgPermissionActions,
|
||||||
|
OrgPermissionSubjects,
|
||||||
|
useOrganization,
|
||||||
|
useSubscription
|
||||||
|
} from "@app/context";
|
||||||
import { withPermission } from "@app/hoc";
|
import { withPermission } from "@app/hoc";
|
||||||
import { useDeleteIdentity } from "@app/hooks/api";
|
import { useDeleteIdentity } from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
@@ -17,10 +22,10 @@ import { IdentityUniversalAuthClientSecretModal } from "./IdentityUniversalAuthC
|
|||||||
|
|
||||||
export const IdentitySection = withPermission(
|
export const IdentitySection = withPermission(
|
||||||
() => {
|
() => {
|
||||||
|
const { subscription } = useSubscription();
|
||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
|
|
||||||
|
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentity();
|
const { mutateAsync: deleteMutateAsync } = useDeleteIdentity();
|
||||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||||
"identity",
|
"identity",
|
||||||
@@ -31,6 +36,10 @@ export const IdentitySection = withPermission(
|
|||||||
"upgradePlan"
|
"upgradePlan"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
|
const isMoreIdentitiesAllowed = subscription?.identityLimit
|
||||||
|
? subscription.identitiesUsed < subscription.identityLimit
|
||||||
|
: true;
|
||||||
|
|
||||||
const onDeleteIdentitySubmit = async (identityId: string) => {
|
const onDeleteIdentitySubmit = async (identityId: string) => {
|
||||||
try {
|
try {
|
||||||
await deleteMutateAsync({
|
await deleteMutateAsync({
|
||||||
@@ -81,7 +90,15 @@ export const IdentitySection = withPermission(
|
|||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
onClick={() => handlePopUpOpen("identity")}
|
onClick={() => {
|
||||||
|
if (!isMoreIdentitiesAllowed) {
|
||||||
|
handlePopUpOpen("upgradePlan", {
|
||||||
|
description: "You can add more identities if you upgrade your Infisical plan."
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handlePopUpOpen("identity");
|
||||||
|
}}
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Create identity
|
Create identity
|
||||||
@@ -118,6 +135,11 @@ export const IdentitySection = withPermission(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
text={(popUp.upgradePlan?.data as { description: string })?.description}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import { AddOrgMemberModal } from "./AddOrgMemberModal";
|
|||||||
import { OrgMembersTable } from "./OrgMembersTable";
|
import { OrgMembersTable } from "./OrgMembersTable";
|
||||||
|
|
||||||
export const OrgMembersSection = () => {
|
export const OrgMembersSection = () => {
|
||||||
|
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
const orgId = currentOrg?.id ?? "";
|
const orgId = currentOrg?.id ?? "";
|
||||||
@@ -39,9 +38,13 @@ export const OrgMembersSection = () => {
|
|||||||
|
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteOrgMembership();
|
const { mutateAsync: deleteMutateAsync } = useDeleteOrgMembership();
|
||||||
|
|
||||||
const isMoreUsersNotAllowed = subscription?.memberLimit
|
const isMoreUsersAllowed = subscription?.memberLimit
|
||||||
? subscription.membersUsed >= subscription.memberLimit
|
? subscription.membersUsed < subscription.memberLimit
|
||||||
: false;
|
: true;
|
||||||
|
|
||||||
|
const isMoreIdentitiesAllowed = subscription?.identityLimit
|
||||||
|
? subscription.identitiesUsed < subscription.identityLimit
|
||||||
|
: true;
|
||||||
|
|
||||||
const handleAddMemberModal = () => {
|
const handleAddMemberModal = () => {
|
||||||
if (currentOrg?.authEnforced) {
|
if (currentOrg?.authEnforced) {
|
||||||
@@ -52,13 +55,14 @@ export const OrgMembersSection = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMoreUsersNotAllowed) {
|
if (!isMoreUsersAllowed || !isMoreIdentitiesAllowed) {
|
||||||
handlePopUpOpen("upgradePlan", {
|
handlePopUpOpen("upgradePlan", {
|
||||||
description: "You can add more members if you upgrade your Infisical plan."
|
description: "You can add more members if you upgrade your Infisical plan."
|
||||||
});
|
});
|
||||||
} else {
|
return;
|
||||||
handlePopUpOpen("addMember");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlePopUpOpen("addMember");
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRemoveMemberSubmit = async (orgMembershipId: string) => {
|
const onRemoveMemberSubmit = async (orgMembershipId: string) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user