fix: invite to sub-org

This commit is contained in:
Piyush Gupta
2025-12-06 21:39:29 +05:30
parent 72584d8353
commit 0aa5dd983c
2 changed files with 46 additions and 16 deletions
@@ -188,16 +188,29 @@ export const membershipUserServiceFactory = ({
}); });
if (existingMemberships.length === users.length) return { memberships: [] }; if (existingMemberships.length === users.length) return { memberships: [] };
const orgDetails = await orgDAL.findById(dto.permission.orgId);
const isSubOrganization = Boolean(orgDetails.rootOrgId);
const newMembershipUsers = users.filter((user) => !existingMemberships?.find((el) => el.actorUserId === user.id)); const newMembershipUsers = users.filter((user) => !existingMemberships?.find((el) => el.actorUserId === user.id));
await factory.onCreateMembershipUserGuard(dto, newMembershipUsers); await factory.onCreateMembershipUserGuard(dto, newMembershipUsers);
const newMemberships = newMembershipUsers.map((user) => ({ const newMemberships = newMembershipUsers.map((user) => {
scope: scopeData.scope, let status: OrgMembershipStatus | undefined;
...scopeDatabaseFields, if (scopeData.scope === AccessScope.Organization) {
actorUserId: user.id, if (isSubOrganization) {
status: scopeData.scope === AccessScope.Organization ? OrgMembershipStatus.Invited : undefined, status = OrgMembershipStatus.Accepted;
inviteEmail: scopeData.scope === AccessScope.Organization ? user.email : undefined } else {
})); status = OrgMembershipStatus.Invited;
}
}
return {
scope: scopeData.scope,
...scopeDatabaseFields,
actorUserId: user.id,
status,
inviteEmail: status === OrgMembershipStatus.Invited ? user.email : undefined
};
});
const customInputRoles = data.roles.filter((el) => factory.isCustomRole(el.role)); const customInputRoles = data.roles.filter((el) => factory.isCustomRole(el.role));
const hasCustomRole = customInputRoles.length > 0; const hasCustomRole = customInputRoles.length > 0;
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { AccessScope, OrganizationActionScope } from "@app/db/schemas"; import { AccessScope, OrganizationActionScope, OrgMembershipStatus } from "@app/db/schemas";
import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal"; import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; 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";
@@ -122,16 +122,33 @@ export const newOrgMembershipUserFactory = ({
const signUpTokens: { email: string; link: string }[] = []; const signUpTokens: { email: string; link: string }[] = [];
const orgDetails = await orgDAL.findById(dto.permission.orgId); const orgDetails = await orgDAL.findById(dto.permission.orgId);
if (orgDetails.rootOrgId) { if (orgDetails.rootOrgId) {
const emails = newUsers.map((el) => el.email).filter(Boolean); // checking if the users have accepted the invitation in the root organization to send the email
await smtpService.sendMail({ const orgMembershipAccepted = await membershipUserDAL.find({
template: SmtpTemplates.SubOrgInvite, scope: AccessScope.Organization,
subjectLine: "Infisical sub-organization invitation", scopeOrgId: orgDetails.rootOrgId,
recipients: emails as string[], status: OrgMembershipStatus.Accepted,
substitutions: { $in: {
subOrganizationName: orgDetails.slug, actorUserId: newUsers.map((el) => el.id)
callback_url: `${appCfg.SITE_URL}/organizations/${dto.permission.orgId}/projects`
} }
}); });
const orgMembershipAcceptedUserIds = orgMembershipAccepted.map((el) => el.actorUserId as string);
const emails = newUsers
.filter((el) => Boolean(el?.email) && orgMembershipAcceptedUserIds.includes(el.id))
.map((el) => el?.email as string);
if (emails.length) {
await smtpService.sendMail({
template: SmtpTemplates.SubOrgInvite,
subjectLine: "Infisical sub-organization invitation",
recipients: emails,
substitutions: {
subOrganizationName: orgDetails.slug,
callback_url: `${appCfg.SITE_URL}/organizations/${dto.permission.orgId}/projects`
}
});
}
} else { } else {
await Promise.allSettled( await Promise.allSettled(
newUsers.map(async (el) => { newUsers.map(async (el) => {