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

View File

@@ -188,16 +188,29 @@ export const membershipUserServiceFactory = ({
});
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));
await factory.onCreateMembershipUserGuard(dto, newMembershipUsers);
const newMemberships = newMembershipUsers.map((user) => ({
scope: scopeData.scope,
...scopeDatabaseFields,
actorUserId: user.id,
status: scopeData.scope === AccessScope.Organization ? OrgMembershipStatus.Invited : undefined,
inviteEmail: scopeData.scope === AccessScope.Organization ? user.email : undefined
}));
const newMemberships = newMembershipUsers.map((user) => {
let status: OrgMembershipStatus | undefined;
if (scopeData.scope === AccessScope.Organization) {
if (isSubOrganization) {
status = OrgMembershipStatus.Accepted;
} 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 hasCustomRole = customInputRoles.length > 0;

View File

@@ -1,6 +1,6 @@
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 { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
@@ -122,16 +122,33 @@ export const newOrgMembershipUserFactory = ({
const signUpTokens: { email: string; link: string }[] = [];
const orgDetails = await orgDAL.findById(dto.permission.orgId);
if (orgDetails.rootOrgId) {
const emails = newUsers.map((el) => el.email).filter(Boolean);
await smtpService.sendMail({
template: SmtpTemplates.SubOrgInvite,
subjectLine: "Infisical sub-organization invitation",
recipients: emails as string[],
substitutions: {
subOrganizationName: orgDetails.slug,
callback_url: `${appCfg.SITE_URL}/organizations/${dto.permission.orgId}/projects`
// checking if the users have accepted the invitation in the root organization to send the email
const orgMembershipAccepted = await membershipUserDAL.find({
scope: AccessScope.Organization,
scopeOrgId: orgDetails.rootOrgId,
status: OrgMembershipStatus.Accepted,
$in: {
actorUserId: newUsers.map((el) => el.id)
}
});
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 {
await Promise.allSettled(
newUsers.map(async (el) => {