mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: made project role multi support for org invite
This commit is contained in:
@@ -21,7 +21,7 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
projects: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
projectRoleSlug: z.string().default(ProjectMembershipRole.Member)
|
||||
projectRoleSlug: z.string().array().default([ProjectMembershipRole.Member])
|
||||
})
|
||||
.array()
|
||||
.optional(),
|
||||
|
||||
@@ -48,7 +48,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
projects: [
|
||||
{
|
||||
id: req.params.projectId,
|
||||
projectRoleSlug: ProjectMembershipRole.Member
|
||||
projectRoleSlug: [ProjectMembershipRole.Member]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
SecretKeyEncoding,
|
||||
TableName,
|
||||
TProjectMemberships,
|
||||
TProjectUserMembershipRolesInsert,
|
||||
TUsers
|
||||
} from "@app/db/schemas";
|
||||
import { TProjects } from "@app/db/schemas/projects";
|
||||
@@ -88,7 +89,7 @@ type TOrgServiceFactoryDep = {
|
||||
"getPlan" | "updateSubscriptionOrgMemberCount" | "generateOrgCustomerId" | "removeOrgCustomer"
|
||||
>;
|
||||
projectUserAdditionalPrivilegeDAL: Pick<TProjectUserAdditionalPrivilegeDALFactory, "delete">;
|
||||
projectRoleDAL: Pick<TProjectRoleDALFactory, "findOne">;
|
||||
projectRoleDAL: Pick<TProjectRoleDALFactory, "find">;
|
||||
userGroupMembershipDAL: Pick<TUserGroupMembershipDALFactory, "findUserGroupMembershipsInProject">;
|
||||
projectBotDAL: Pick<TProjectBotDALFactory, "findOne">;
|
||||
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "insertMany">;
|
||||
@@ -652,12 +653,15 @@ export const orgServiceFactory = ({
|
||||
if (!userWithEncryptionKeyInvitedToProject.length) continue;
|
||||
|
||||
// validate custom project role
|
||||
const invitedProjectRole =
|
||||
invitedProjects.find((el) => el.id === project.id)?.projectRoleSlug || ProjectMembershipRole.Member;
|
||||
const isCustomProjectRole = !Object.values(ProjectMembershipRole).includes(
|
||||
invitedProjectRole as ProjectMembershipRole
|
||||
const invitedProjectRoles = invitedProjects.find((el) => el.id === project.id)?.projectRoleSlug || [
|
||||
ProjectMembershipRole.Member
|
||||
];
|
||||
|
||||
const customProjectRoles = invitedProjectRoles.filter(
|
||||
(role) => !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole)
|
||||
);
|
||||
if (isCustomProjectRole) {
|
||||
const hasCustomRole = Boolean(customProjectRoles.length);
|
||||
if (hasCustomRole) {
|
||||
if (!plan?.rbac)
|
||||
throw new BadRequestError({
|
||||
message:
|
||||
@@ -665,6 +669,17 @@ export const orgServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const customRoles = hasCustomRole
|
||||
? await projectRoleDAL.find({
|
||||
projectId,
|
||||
$in: { slug: customProjectRoles.map((role) => role) }
|
||||
})
|
||||
: [];
|
||||
if (customRoles.length !== customProjectRoles.length)
|
||||
throw new BadRequestError({ message: "Custom role not found" });
|
||||
|
||||
const customRolesGroupBySlug = groupBy(customRoles, ({ slug }) => slug);
|
||||
|
||||
const ghostUser = await projectDAL.findProjectGhostUser(projectId, tx);
|
||||
if (!ghostUser) {
|
||||
throw new BadRequestError({
|
||||
@@ -698,7 +713,7 @@ export const orgServiceFactory = ({
|
||||
userPrivateKey: botPrivateKey,
|
||||
members: userWithEncryptionKeyInvitedToProject.map((userEnc) => ({
|
||||
orgMembershipId: userEnc.userId,
|
||||
projectMembershipRole: invitedProjectRole as ProjectMembershipRole,
|
||||
projectMembershipRole: ProjectMembershipRole.Admin,
|
||||
userPublicKey: userEnc.publicKey
|
||||
}))
|
||||
});
|
||||
@@ -712,17 +727,18 @@ export const orgServiceFactory = ({
|
||||
);
|
||||
newProjectMemberships.push(...projectMemberships);
|
||||
|
||||
let customRoleId: string;
|
||||
const projectRole = isCustomProjectRole ? ProjectMembershipRole.Custom : invitedProjectRole;
|
||||
if (isCustomProjectRole) {
|
||||
const customRole = await projectRoleDAL.findOne({ slug: invitedProjectRole, projectId });
|
||||
if (!customRole) throw new BadRequestError({ name: "Invite membership", message: "Project role not found" });
|
||||
customRoleId = customRole.id;
|
||||
}
|
||||
await projectUserMembershipRoleDAL.insertMany(
|
||||
projectMemberships.map(({ id }) => ({ projectMembershipId: id, role: projectRole, customRoleId })),
|
||||
tx
|
||||
);
|
||||
const sanitizedProjectMembershipRoles: TProjectUserMembershipRolesInsert[] = [];
|
||||
invitedProjectRoles.forEach((projectRole) => {
|
||||
const isCustomRole = Boolean(customRolesGroupBySlug?.[projectRole]?.[0]);
|
||||
projectMemberships.forEach((membership) => {
|
||||
sanitizedProjectMembershipRoles.push({
|
||||
projectMembershipId: membership.id,
|
||||
role: isCustomRole ? ProjectMembershipRole.Custom : projectRole,
|
||||
customRoleId: customRolesGroupBySlug[projectRole] ? customRolesGroupBySlug[projectRole][0].id : null
|
||||
});
|
||||
});
|
||||
});
|
||||
await projectUserMembershipRoleDAL.insertMany(sanitizedProjectMembershipRoles, tx);
|
||||
|
||||
await projectKeyDAL.insertMany(
|
||||
newWsMembers.map((el) => ({
|
||||
|
||||
@@ -34,7 +34,7 @@ export type TInviteUserToOrgDTO = {
|
||||
organizationRoleSlug: string;
|
||||
projects?: {
|
||||
id: string;
|
||||
projectRoleSlug?: string;
|
||||
projectRoleSlug?: string[];
|
||||
}[];
|
||||
};
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ export type DeletOrgMembershipDTO = {
|
||||
|
||||
export type AddUserToOrgDTO = {
|
||||
inviteeEmails: string[];
|
||||
projects?: { id: string; projectRoleSlug: string }[];
|
||||
projects?: { id: string; projectRoleSlug: string[] }[];
|
||||
organizationRoleSlug: string;
|
||||
organizationId: string;
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ export const AddOrgMemberModal = ({
|
||||
organizationId: currentOrg?.id,
|
||||
inviteeEmails: emails.split(",").map((email) => email.trim()),
|
||||
organizationRoleSlug,
|
||||
projects: projectIds.map((id) => ({ id, projectRoleSlug }))
|
||||
projects: projectIds.map((id) => ({ id, projectRoleSlug: [projectRoleSlug] }))
|
||||
});
|
||||
|
||||
setCompleteInviteLinks(data?.completeInviteLinks ?? null);
|
||||
|
||||
@@ -101,9 +101,7 @@ export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
members?.forEach((member) => {
|
||||
wsUserUsernames.set(member.user.username, true);
|
||||
});
|
||||
return (orgUsers || []).filter(
|
||||
({ status, user: u }) => status === "accepted" && !wsUserUsernames.has(u.username)
|
||||
);
|
||||
return (orgUsers || []).filter(({ user: u }) => !wsUserUsernames.has(u.username));
|
||||
}, [orgUsers, members]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user