diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 53bc96ec..217510f6 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -3,8 +3,6 @@ import { createGroup, deleteGroup, getAllGroups, getGroup, getGroupSubmissions, import { GroupDTO } from '@dwengo-1/common/interfaces/group'; import { requireFields } from './error-helper.js'; import { BadRequestException } from '../exceptions/bad-request-exception.js'; -import { EntityDTO } from '@mikro-orm/core'; -import { Group } from '../entities/assignments/group.entity.js'; function checkGroupFields(classId: string, assignmentId: number, groupId: number): void { requireFields({ classId, assignmentId, groupId }); @@ -35,7 +33,11 @@ export async function putGroupHandler(req: Request, res: Response): Promise>); + // Only members field can be changed + const members = req.body.members; + requireFields({ members }); + + const group = await putGroup(classId, assignmentId, groupId, { members } as Partial); res.json({ group }); } diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 0c73c8c5..382780d8 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -7,8 +7,17 @@ import { GroupDTO, GroupDTOId } from '@dwengo-1/common/interfaces/group'; import { SubmissionDTO, SubmissionDTOId } from '@dwengo-1/common/interfaces/submission'; import { fetchAssignment } from './assignments.js'; import { NotFoundException } from '../exceptions/not-found-exception.js'; -import { putObject } from './service-helper.js'; import { fetchStudents } from './students.js'; +import { fetchClass } from './classes.js'; +import { BadRequestException } from '../exceptions/bad-request-exception.js'; +import { Student } from '../entities/users/student.entity.js'; +import { Class } from '../entities/classes/class.entity.js'; + +async function assertMembersInClass(members: Student[], cls: Class): Promise { + if (!members.every((student) => cls.students.contains(student))) { + throw new BadRequestException('Student does not belong to class'); + } +} export async function fetchGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise { const assignment = await fetchAssignment(classId, assignmentNumber); @@ -28,15 +37,18 @@ export async function getGroup(classId: string, assignmentNumber: number, groupN return mapToGroupDTO(group, group.assignment.within); } -export async function putGroup( - classId: string, - assignmentNumber: number, - groupNumber: number, - groupData: Partial> -): Promise { +export async function putGroup(classId: string, assignmentNumber: number, groupNumber: number, groupData: Partial): Promise { const group = await fetchGroup(classId, assignmentNumber, groupNumber); - await putObject(group, groupData, getGroupRepository()); + const memberUsernames = groupData.members as string[]; + const members = await fetchStudents(memberUsernames); + + const cls = await fetchClass(classId); + await assertMembersInClass(members, cls); + + const groupRepository = getGroupRepository(); + groupRepository.assign(group, { members } as Partial>); + await groupRepository.getEntityManager().persistAndFlush(group); return mapToGroupDTO(group, group.assignment.within); } @@ -63,6 +75,9 @@ export async function createGroup(groupData: GroupDTO, classid: string, assignme const memberUsernames = (groupData.members as string[]) || []; const members = await fetchStudents(memberUsernames); + const cls = await fetchClass(classid); + await assertMembersInClass(members, cls); + const assignment = await fetchAssignment(classid, assignmentNumber); const groupRepository = getGroupRepository(); diff --git a/backend/tests/test_assets/assignments/groups.testdata.ts b/backend/tests/test_assets/assignments/groups.testdata.ts index 16674843..4361383b 100644 --- a/backend/tests/test_assets/assignments/groups.testdata.ts +++ b/backend/tests/test_assets/assignments/groups.testdata.ts @@ -61,7 +61,7 @@ export function makeTestGroups(em: EntityManager, students: Student[], assignmen */ group1ConditionalLearningPath = em.create(Group, { assignment: getConditionalPathAssignment(), - groupNumber: 1, + groupNumber: 21005, members: [getTestleerling1()], }); diff --git a/frontend/src/components/MenuBar.vue b/frontend/src/components/MenuBar.vue index 0954707f..e3734976 100644 --- a/frontend/src/components/MenuBar.vue +++ b/frontend/src/components/MenuBar.vue @@ -11,7 +11,7 @@ const { t, locale } = useI18n(); const role = auth.authState.activeRole; - const router = useRouter(); + const _router = useRouter(); // Zonder '_' gaf dit een linter error voor unused variable const name: string = auth.authState.user!.profile.name!; const initials: string = name