diff --git a/backend/src/ee/routes/v1/group-router.ts b/backend/src/ee/routes/v1/group-router.ts index 11c5d6fba..d606aedd0 100644 --- a/backend/src/ee/routes/v1/group-router.ts +++ b/backend/src/ee/routes/v1/group-router.ts @@ -42,6 +42,31 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => { } }); + server.route({ + url: "/:id", + method: "GET", + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + params: z.object({ + id: z.string() + }), + response: { + 200: GroupsSchema + } + }, + handler: async (req) => { + const group = await server.services.group.getGroupById({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + id: req.params.id + }); + + return group; + } + }); + server.route({ url: "/:id", method: "PATCH", diff --git a/backend/src/ee/services/group/group-service.ts b/backend/src/ee/services/group/group-service.ts index 05fafe180..48942c52a 100644 --- a/backend/src/ee/services/group/group-service.ts +++ b/backend/src/ee/services/group/group-service.ts @@ -3,7 +3,7 @@ import slugify from "@sindresorhus/slugify"; import { OrgMembershipRole, TOrgRoles } from "@app/db/schemas"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; -import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors"; +import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { alphaNumericNanoId } from "@app/lib/nanoid"; import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal"; import { TOrgDALFactory } from "@app/services/org/org-dal"; @@ -21,6 +21,7 @@ import { TAddUserToGroupDTO, TCreateGroupDTO, TDeleteGroupDTO, + TGetGroupByIdDTO, TListGroupUsersDTO, TRemoveUserFromGroupDTO, TUpdateGroupDTO @@ -29,7 +30,7 @@ import { TUserGroupMembershipDALFactory } from "./user-group-membership-dal"; type TGroupServiceFactoryDep = { userDAL: Pick; - groupDAL: Pick; + groupDAL: Pick; groupProjectDAL: Pick; orgDAL: Pick; userGroupMembershipDAL: Pick< @@ -186,6 +187,30 @@ export const groupServiceFactory = ({ return group; }; + const getGroupById = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TGetGroupByIdDTO) => { + if (!actorOrgId) { + throw new BadRequestError({ message: "Failed to read group without organization" }); + } + + const { permission } = await permissionService.getOrgPermission( + actor, + actorId, + actorOrgId, + actorAuthMethod, + actorOrgId + ); + ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Groups); + + const group = await groupDAL.findById(id); + if (!group) { + throw new NotFoundError({ + message: `Cannot find group with ID ${id}` + }); + } + + return group; + }; + const listGroupUsers = async ({ id, offset, @@ -336,6 +361,7 @@ export const groupServiceFactory = ({ deleteGroup, listGroupUsers, addUserToGroup, - removeUserFromGroup + removeUserFromGroup, + getGroupById }; }; diff --git a/backend/src/ee/services/group/group-types.ts b/backend/src/ee/services/group/group-types.ts index 125765a1c..a6c80ef43 100644 --- a/backend/src/ee/services/group/group-types.ts +++ b/backend/src/ee/services/group/group-types.ts @@ -29,6 +29,10 @@ export type TDeleteGroupDTO = { id: string; } & TGenericPermission; +export type TGetGroupByIdDTO = { + id: string; +} & TGenericPermission; + export type TListGroupUsersDTO = { id: string; offset: number;