From f1e9e3a8d64fa78d9e92d5770bd9aefef0a3dbfd Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 14:04:39 +0200 Subject: [PATCH 1/5] fix: verbod op toevoegen van student aan groep wanneer die student niet in de klas zit --- backend/src/services/groups.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 0c73c8c5..1a957772 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -9,6 +9,8 @@ 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'; export async function fetchGroup(classId: string, assignmentNumber: number, groupNumber: number): Promise { const assignment = await fetchAssignment(classId, assignmentNumber); @@ -60,9 +62,15 @@ export async function getExistingGroupFromGroupDTO(groupData: GroupDTO): Promise } export async function createGroup(groupData: GroupDTO, classid: string, assignmentNumber: number): Promise { + const cls = await fetchClass(classid); + const memberUsernames = (groupData.members as string[]) || []; const members = await fetchStudents(memberUsernames); + if (!members.every(student => cls.students.contains(student))) { + throw new BadRequestException("It is not allowed to add a student to a group when the student is not part of the class"); + } + const assignment = await fetchAssignment(classid, assignmentNumber); const groupRepository = getGroupRepository(); From 6fe20dc2fed920a81eebf85e0b7f7e4575457d35 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 14:21:25 +0200 Subject: [PATCH 2/5] fix: verboden om PUT request naar group te sturen met studenten die niet tot klas behoren --- backend/src/controllers/groups.ts | 6 +++++- backend/src/services/groups.ts | 27 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 53bc96ec..2f755e21 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -35,7 +35,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 1a957772..1b98b4f3 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -11,6 +11,14 @@ 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); @@ -34,11 +42,19 @@ export async function putGroup( classId: string, assignmentNumber: number, groupNumber: number, - groupData: Partial> + 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); } @@ -62,14 +78,11 @@ export async function getExistingGroupFromGroupDTO(groupData: GroupDTO): Promise } export async function createGroup(groupData: GroupDTO, classid: string, assignmentNumber: number): Promise { - const cls = await fetchClass(classid); - const memberUsernames = (groupData.members as string[]) || []; const members = await fetchStudents(memberUsernames); - if (!members.every(student => cls.students.contains(student))) { - throw new BadRequestException("It is not allowed to add a student to a group when the student is not part of the class"); - } + const cls = await fetchClass(classid); + await assertMembersInClass(members, cls) const assignment = await fetchAssignment(classid, assignmentNumber); From 283c2e6f78807d13e961370728f9155168a52636 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 14:21:51 +0200 Subject: [PATCH 3/5] fix: group test asset met lage id veranderd naar hoge id --- backend/tests/test_assets/assignments/groups.testdata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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()], }); From f35802f3c3f9f7e80c965da0a00df36266b9d04e Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 22 Apr 2025 14:26:00 +0200 Subject: [PATCH 4/5] fix: fixed linter issues --- backend/src/controllers/groups.ts | 4 +--- backend/src/services/groups.ts | 1 - frontend/src/components/MenuBar.vue | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 2f755e21..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,7 @@ export async function putGroupHandler(req: Request, res: Response): Promise Date: Tue, 22 Apr 2025 12:31:04 +0000 Subject: [PATCH 5/5] style: fix linting issues met Prettier --- backend/src/services/groups.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 8e2ee9ab..382780d8 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -14,8 +14,8 @@ 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"); + if (!members.every((student) => cls.students.contains(student))) { + throw new BadRequestException('Student does not belong to class'); } } @@ -37,12 +37,7 @@ 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); const memberUsernames = groupData.members as string[]; @@ -81,7 +76,7 @@ export async function createGroup(groupData: GroupDTO, classid: string, assignme const members = await fetchStudents(memberUsernames); const cls = await fetchClass(classid); - await assertMembersInClass(members, cls) + await assertMembersInClass(members, cls); const assignment = await fetchAssignment(classid, assignmentNumber);