From 0ce5aaf61c6a3f9443fa7491eb973850809bf5dc Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Fri, 15 Sep 2023 11:44:48 -0400 Subject: [PATCH] add role deduplication logic --- backend/src/utils/setup/backfillData.ts | 50 +++++++++++++++++++------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/backend/src/utils/setup/backfillData.ts b/backend/src/utils/setup/backfillData.ts index ffd0c4adc..d6108874b 100644 --- a/backend/src/utils/setup/backfillData.ts +++ b/backend/src/utils/setup/backfillData.ts @@ -696,6 +696,9 @@ export const backfillPermission = async () => { .populate<{ workspace: IWorkspace }>("workspace") .lean(); + // group memberships that need the same permission set + const roleMap = new Map(); + for (const membership of memberships) { // get permissions of members except secret permission const customPermissions = memberProjectPermissions.rules.filter( @@ -711,16 +714,17 @@ export const backfillPermission = async () => { if (ability === "read") secretAccessRule[environmentSlug].read = false; }); + const secretPermissions: any = []; Object.entries(secretAccessRule).forEach(([envSlug, { read, write }]) => { if (read) { - customPermissions.push({ + secretPermissions.push({ subject: ProjectPermissionSub.Secrets, action: ProjectPermissionActions.Read, conditions: { environment: envSlug } }); } if (write) { - customPermissions.push( + secretPermissions.push( { subject: ProjectPermissionSub.Secrets, action: ProjectPermissionActions.Edit, @@ -740,23 +744,44 @@ export const backfillPermission = async () => { } }); + const key = `${JSON.stringify(secretPermissions)}-${membership.workspace.organization.toString()}-${membership.workspace._id.toString()}`; // group roles that have same permission with in the same org and workspace + const value = roleMap.get(key); + if (value) { + value.membershipIds.push(membership._id.toString()); + value.organizationId = membership.workspace.organization.toString() + value.workspaceId = membership.workspace._id.toString() + } else { + roleMap.set(key, { membershipIds: [membership._id.toString()], permissions: [...customPermissions, ...secretPermissions], organizationId: membership.workspace.organization.toString(), workspaceId: membership.workspace._id.toString() }); + } + } + + for (const [key, value] of roleMap.entries()) { + const { membershipIds, permissions, workspaceId, organizationId } = value + const role = new Role({ name: "Migrated Role", - organization: membership.workspace.organization, - workspace: membership.workspace._id, + organization: organizationId, + workspace: workspaceId, + description: "This role was auto generated by Infisical with the release of our new permission system", isOrgRole: false, slug: `custom-role-${crypto.randomBytes(3).toString("hex")}`, - permissions: customPermissions + permissions: permissions }); + await role.save(); - await Membership.findByIdAndUpdate(membership._id, { - $set: { - role: CUSTOM, - customRole: role - } - }); + + for (const id of membershipIds) { + await Membership.findByIdAndUpdate(id, { // document db doesn't support update many so we must loop + $set: { + role: CUSTOM, + customRole: role + } + }); + } } + console.log("Backfill: Finished converting old denied permission in workspace to viewers"); + await MembershipOrg.updateMany( { role: OWNER @@ -767,5 +792,6 @@ export const backfillPermission = async () => { } } ); - console.log("Backfill: Finishing converting old denied permission in workspace to viewers"); + + console.log("Backfill: Finished converting owner role to member"); };