fix(groups): unique names, requested changes

This commit is contained in:
Daniel Hougaard
2025-01-16 17:38:54 +01:00
parent 4e68304262
commit ef87086272
5 changed files with 57 additions and 44 deletions
+47 -35
View File
@@ -32,7 +32,7 @@ type TGroupServiceFactoryDep = {
userDAL: Pick<TUserDALFactory, "find" | "findUserEncKeyByUserIdsBatch" | "transaction" | "findOne">; userDAL: Pick<TUserDALFactory, "find" | "findUserEncKeyByUserIdsBatch" | "transaction" | "findOne">;
groupDAL: Pick< groupDAL: Pick<
TGroupDALFactory, TGroupDALFactory,
"create" | "findOne" | "update" | "delete" | "findAllGroupPossibleMembers" | "findById" "create" | "findOne" | "update" | "delete" | "findAllGroupPossibleMembers" | "findById" | "transaction"
>; >;
groupProjectDAL: Pick<TGroupProjectDALFactory, "find">; groupProjectDAL: Pick<TGroupProjectDALFactory, "find">;
orgDAL: Pick<TOrgDALFactory, "findMembership" | "countAllOrgMembers">; orgDAL: Pick<TOrgDALFactory, "findMembership" | "countAllOrgMembers">;
@@ -88,19 +88,26 @@ export const groupServiceFactory = ({
if (!hasRequiredPriviledges) if (!hasRequiredPriviledges)
throw new ForbiddenRequestError({ message: "Failed to create a more privileged group" }); throw new ForbiddenRequestError({ message: "Failed to create a more privileged group" });
const existingGroup = await groupDAL.findOne({ orgId: actorOrgId, name }); const group = await groupDAL.transaction(async (tx) => {
if (existingGroup) { const existingGroup = await groupDAL.findOne({ orgId: actorOrgId, name }, tx);
throw new BadRequestError({ if (existingGroup) {
message: `Failed to create group with name '${name}'. Group with the same name already exists` throw new BadRequestError({
}); message: `Failed to create group with name '${name}'. Group with the same name already exists`
} });
}
const group = await groupDAL.create({ const newGroup = await groupDAL.create(
name, {
slug: slug || slugify(`${name}-${alphaNumericNanoId(4)}`), name,
orgId: actorOrgId, slug: slug || slugify(`${name}-${alphaNumericNanoId(4)}`),
role: isCustomRole ? OrgMembershipRole.Custom : role, orgId: actorOrgId,
roleId: customRole?.id role: isCustomRole ? OrgMembershipRole.Custom : role,
roleId: customRole?.id
},
tx
);
return newGroup;
}); });
return group; return group;
@@ -152,31 +159,36 @@ export const groupServiceFactory = ({
if (isCustomRole) customRole = customOrgRole; if (isCustomRole) customRole = customOrgRole;
} }
if (name) { const updatedGroup = await groupDAL.transaction(async (tx) => {
const existingGroup = await groupDAL.findOne({ orgId: actorOrgId, name }); if (name) {
const existingGroup = await groupDAL.findOne({ orgId: actorOrgId, name }, tx);
if (existingGroup && existingGroup.id !== id) { if (existingGroup && existingGroup.id !== id) {
throw new BadRequestError({ throw new BadRequestError({
message: `Failed to update group with name '${name}'. Group with the same name already exists` message: `Failed to update group with name '${name}'. Group with the same name already exists`
}); });
}
} }
}
const [updatedGroup] = await groupDAL.update( const [updated] = await groupDAL.update(
{ {
id: group.id id: group.id
}, },
{ {
name, name,
slug: slug ? slugify(slug) : undefined, slug: slug ? slugify(slug) : undefined,
...(role ...(role
? { ? {
role: customRole ? OrgMembershipRole.Custom : role, role: customRole ? OrgMembershipRole.Custom : role,
roleId: customRole?.id ?? null roleId: customRole?.id ?? null
} }
: {}) : {})
} },
); tx
);
return updated;
});
return updatedGroup; return updatedGroup;
}; };
+7 -4
View File
@@ -790,10 +790,13 @@ export const scimServiceFactory = ({
}); });
const newGroup = await groupDAL.transaction(async (tx) => { const newGroup = await groupDAL.transaction(async (tx) => {
const conflictingGroup = await groupDAL.findOne({ const conflictingGroup = await groupDAL.findOne(
name: displayName, {
orgId name: displayName,
}); orgId
},
tx
);
if (conflictingGroup) { if (conflictingGroup) {
throw new ScimRequestError({ throw new ScimRequestError({
+1 -1
View File
@@ -474,7 +474,7 @@ export const PROJECTS = {
}, },
ADD_GROUP_TO_PROJECT: { ADD_GROUP_TO_PROJECT: {
projectId: "The ID of the project to add the group to.", projectId: "The ID of the project to add the group to.",
groupId: "The ID of the group to add to the project.", groupIdOrName: "The ID or name of the group to add to the project.",
role: "The role for the group to assume in the project." role: "The role for the group to assume in the project."
}, },
UPDATE_GROUP_IN_PROJECT: { UPDATE_GROUP_IN_PROJECT: {
@@ -30,7 +30,7 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
], ],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(PROJECTS.ADD_GROUP_TO_PROJECT.projectId), projectId: z.string().trim().describe(PROJECTS.ADD_GROUP_TO_PROJECT.projectId),
groupIdOrName: z.string().trim().describe(PROJECTS.ADD_GROUP_TO_PROJECT.groupId) groupIdOrName: z.string().trim().describe(PROJECTS.ADD_GROUP_TO_PROJECT.groupIdOrName)
}), }),
body: z body: z
.object({ .object({
@@ -80,10 +80,8 @@ export const groupProjectServiceFactory = ({
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Groups);
const isUuid = isUuidV4(groupIdOrName);
let group: TGroups | null = null; let group: TGroups | null = null;
if (isUuid) { if (isUuidV4(groupIdOrName)) {
group = await groupDAL.findOne({ orgId: actorOrgId, id: groupIdOrName }); group = await groupDAL.findOne({ orgId: actorOrgId, id: groupIdOrName });
} }
if (!group) { if (!group) {