Merge pull request #4577 from Infisical/feat/ENG-3724

Add project permission cache
This commit is contained in:
carlosmonastyrski
2025-09-29 10:01:33 -03:00
committed by GitHub
13 changed files with 291 additions and 30 deletions
@@ -37,13 +37,16 @@ type TGroupProjectServiceFactoryDep = {
TGroupProjectMembershipRoleDALFactory,
"create" | "transaction" | "insertMany" | "delete"
>;
userGroupMembershipDAL: Pick<TUserGroupMembershipDALFactory, "findGroupMembersNotInProject">;
userGroupMembershipDAL: Pick<TUserGroupMembershipDALFactory, "findGroupMembersNotInProject" | "find">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "findProjectGhostUser" | "findById">;
projectKeyDAL: Pick<TProjectKeyDALFactory, "findLatestProjectKey" | "delete" | "insertMany" | "transaction">;
projectRoleDAL: Pick<TProjectRoleDALFactory, "find">;
projectBotDAL: TProjectBotDALFactory;
groupDAL: Pick<TGroupDALFactory, "findOne" | "findAllGroupPossibleMembers">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRole">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getProjectPermissionByRole" | "invalidateProjectPermissionCache"
>;
};
export type TGroupProjectServiceFactory = ReturnType<typeof groupProjectServiceFactory>;
@@ -263,6 +266,8 @@ export const groupProjectServiceFactory = ({
return groupProjectMembership;
});
await permissionService.invalidateProjectPermissionCache(projectId);
return projectGroup;
};
@@ -372,6 +377,8 @@ export const groupProjectServiceFactory = ({
return groupProjectMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
});
await permissionService.invalidateProjectPermissionCache(projectId);
return updatedRoles;
};
@@ -404,14 +411,18 @@ export const groupProjectServiceFactory = ({
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Delete, ProjectPermissionSub.Groups);
const deletedProjectGroup = await groupProjectDAL.transaction(async (tx) => {
const groupMembers = await userGroupMembershipDAL.findGroupMembersNotInProject(group.id, project.id, tx);
const groupMembersNotInProject = await userGroupMembershipDAL.findGroupMembersNotInProject(
group.id,
project.id,
tx
);
if (groupMembers.length) {
if (groupMembersNotInProject.length) {
await projectKeyDAL.delete(
{
projectId: project.id,
$in: {
receiverId: groupMembers.map(({ user: { id } }) => id)
receiverId: groupMembersNotInProject.map(({ user: { id } }) => id)
}
},
tx
@@ -422,6 +433,8 @@ export const groupProjectServiceFactory = ({
return projectGroup;
});
await permissionService.invalidateProjectPermissionCache(projectId);
return deletedProjectGroup;
};
@@ -35,7 +35,10 @@ type TIdentityProjectServiceFactoryDep = {
projectDAL: Pick<TProjectDALFactory, "findById">;
projectRoleDAL: Pick<TProjectRoleDALFactory, "find">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRole">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getProjectPermissionByRole" | "invalidateProjectPermissionCache"
>;
};
export type TIdentityProjectServiceFactory = ReturnType<typeof identityProjectServiceFactory>;
@@ -165,6 +168,9 @@ export const identityProjectServiceFactory = ({
const identityRoles = await identityProjectMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
return { ...identityProjectMembership, roles: identityRoles };
});
await permissionService.invalidateProjectPermissionCache(projectId);
return projectIdentity;
};
@@ -272,6 +278,8 @@ export const identityProjectServiceFactory = ({
return identityProjectMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
});
await permissionService.invalidateProjectPermissionCache(projectId);
return updatedRoles;
};
@@ -302,6 +310,9 @@ export const identityProjectServiceFactory = ({
);
const [deletedIdentity] = await identityProjectDAL.delete({ identityId, projectId });
await permissionService.invalidateProjectPermissionCache(projectId);
return deletedIdentity;
};
@@ -43,7 +43,10 @@ import {
import { TProjectUserMembershipRoleDALFactory } from "./project-user-membership-role-dal";
type TProjectMembershipServiceFactoryDep = {
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRole">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getProjectPermissionByRole" | "invalidateProjectPermissionCache"
>;
smtpService: TSmtpService;
projectBotDAL: TProjectBotDALFactory;
projectMembershipDAL: TProjectMembershipDALFactory;
@@ -239,6 +242,8 @@ export const projectMembershipServiceFactory = ({
);
});
await permissionService.invalidateProjectPermissionCache(projectId);
if (sendEmails) {
await notificationService.createUserNotifications(
orgMembers.map((member) => ({
@@ -371,6 +376,8 @@ export const projectMembershipServiceFactory = ({
return projectUserMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
});
await permissionService.invalidateProjectPermissionCache(projectId);
return updatedRoles;
};
@@ -414,6 +421,9 @@ export const projectMembershipServiceFactory = ({
);
return deletedMembership;
});
await permissionService.invalidateProjectPermissionCache(projectId);
return membership;
};
@@ -515,6 +525,9 @@ export const projectMembershipServiceFactory = ({
return deletedMemberships;
});
await permissionService.invalidateProjectPermissionCache(projectId);
return memberships;
};
@@ -35,7 +35,10 @@ type TProjectRoleServiceFactoryDep = {
identityDAL: Pick<TIdentityDALFactory, "findById">;
userDAL: Pick<TUserDALFactory, "findById">;
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findProjectById">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getUserProjectPermission">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getUserProjectPermission" | "invalidateProjectPermissionCache"
>;
identityProjectMembershipRoleDAL: TIdentityProjectMembershipRoleDALFactory;
projectUserMembershipRoleDAL: TProjectUserMembershipRoleDALFactory;
};
@@ -162,6 +165,8 @@ export const projectRoleServiceFactory = ({
});
if (!updatedRole) throw new NotFoundError({ message: "Project role not found", name: "Update role" });
await permissionService.invalidateProjectPermissionCache(projectRole.projectId);
return { ...updatedRole, permissions: unpackPermissions(updatedRole.permissions) };
};
@@ -197,6 +202,8 @@ export const projectRoleServiceFactory = ({
const deletedRole = await projectRoleDAL.deleteById(roleId);
if (!deletedRole) throw new NotFoundError({ message: "Project role not found", name: "Delete role" });
await permissionService.invalidateProjectPermissionCache(projectRole.projectId);
return { ...deletedRole, permissions: unpackPermissions(deletedRole.permissions) };
};