From 8c80d70f2ee15a3ad2dd85481ea2de52f89675d1 Mon Sep 17 00:00:00 2001 From: Chris Lemaire <c.lemaire@student.tudelft.nl> Date: Wed, 20 May 2020 10:50:04 +0200 Subject: [PATCH] Add StudentGroup endpoints for getting by person --- build.gradle.kts | 2 +- .../controller/StudentGroupController.java | 43 +++++++++++ .../repository/StudentGroupRepository.java | 53 ++++++++++++- ...StudentGroupControllerIntegrationTest.java | 74 ++++++++++++++++++- 4 files changed, 169 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6a0124b9..ea25b273 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ val lombokVersion = "1.18.12" val springDocVersion = "1.2.32" val jacksonVersion = "2.10.4" val joolVersion = "0.9.12" -val guavaVersion = "r05" +val guavaVersion = "29.0-jre" val queryDslVersion = "4.2.1" // The repositories used to lookup dependencies. diff --git a/src/main/java/nl/tudelft/labracore/controller/StudentGroupController.java b/src/main/java/nl/tudelft/labracore/controller/StudentGroupController.java index eb345f62..ad0b060e 100644 --- a/src/main/java/nl/tudelft/labracore/controller/StudentGroupController.java +++ b/src/main/java/nl/tudelft/labracore/controller/StudentGroupController.java @@ -31,6 +31,7 @@ import nl.tudelft.labracore.dto.view.structured.summary.RoleSummaryDTO; import nl.tudelft.labracore.repository.StudentGroupRepository; import nl.tudelft.labracore.service.RoleService; import nl.tudelft.labracore.service.StudentGroupService; +import nl.tudelft.librador.dto.view.View; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -250,4 +251,46 @@ public class StudentGroupController { return sgs.getRoleOfMember(personId, id); } + /** + * Gets all groups for a given person. + * + * @param personId The id of the person to lookup. + * @return The list of groups the given person is in. + */ + @GetMapping("/by-person/{personId}") + @PreAuthorize("hasAuthority('STUDENT_GROUP_READ')") + public List<StudentGroupSummaryDTO> getGroupsForPerson(@PathVariable Long personId) { + return View.convertList(sgr.findAllByPersonIn(personId), StudentGroupSummaryDTO.class); + } + + /** + * Gets all groups for a given person within the given course. + * + * @param personId The id of the person to lookup. + * @param courseId The id of the course to lookup. + * @return The list of groups in the given course the given person is in. + */ + @GetMapping("/by-person-and-course/{personId}/{courseId}") + @PreAuthorize("hasAuthority('STUDENT_GROUP_READ')") + public List<StudentGroupSummaryDTO> getGroupsForPersonAndCourse(@PathVariable Long personId, + @PathVariable Long courseId) { + return View.convertList(sgr.findAllByCourseAndPersonIn(personId, courseId), + StudentGroupSummaryDTO.class); + } + + /** + * Gets all groups for a given person within the given module. + * + * @param personId The id of the person to lookup. + * @param moduleId The id of the module to lookup. + * @return The list of groups in the given module the given person is in. + */ + @GetMapping("/by-person-and-module/{personId}/{moduleId}") + @PreAuthorize("hasAuthority('STUDENT_GROUP_READ')") + public List<StudentGroupSummaryDTO> getGroupsForPersonAndModule(@PathVariable Long personId, + @PathVariable Long moduleId) { + return View.convertList(sgr.findAllByModuleAndPersonIn(personId, moduleId), + StudentGroupSummaryDTO.class); + } + } diff --git a/src/main/java/nl/tudelft/labracore/repository/StudentGroupRepository.java b/src/main/java/nl/tudelft/labracore/repository/StudentGroupRepository.java index 35bcddc5..c9bbe7c2 100644 --- a/src/main/java/nl/tudelft/labracore/repository/StudentGroupRepository.java +++ b/src/main/java/nl/tudelft/labracore/repository/StudentGroupRepository.java @@ -17,15 +17,33 @@ */ package nl.tudelft.labracore.repository; +import static com.querydsl.jpa.JPAExpressions.select; +import static nl.tudelft.labracore.model.QRole.role; +import static nl.tudelft.labracore.model.QStudentGroup.studentGroup; + import java.util.List; import nl.tudelft.labracore.model.Module; import nl.tudelft.labracore.model.StudentGroup; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.rest.webmvc.ResourceNotFoundException; -public interface StudentGroupRepository extends JpaRepository<StudentGroup, Long> { +import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.dsl.BooleanExpression; + +public interface StudentGroupRepository + extends JpaRepository<StudentGroup, Long>, QuerydslPredicateExecutor<StudentGroup> { + + /** + * Override findAll definition using a list as the iterable to store results in. + * + * @param predicate The predicate to execute. + * @return The resulting iterable of StudentGroups. + */ + @Override + List<StudentGroup> findAll(Predicate predicate); /** * Finds the studentGroup by id or throws a ResourceNotFoundException. @@ -55,4 +73,37 @@ public interface StudentGroupRepository extends JpaRepository<StudentGroup, Long */ List<StudentGroup> findAllByModule_Id(Long id); + /** + * @param personId The id of the person to find groups for. + * @return The groups that the person is in. + */ + default List<StudentGroup> findAllByPersonIn(Long personId) { + BooleanExpression q = studentGroup.members.any().person.id.eq(personId); + return findAll(q); + } + + /** + * @param personId The id of the person to lookup. + * @param courseId The id of the course to lookup. + * @return All groups that contain the given person in the given course. + */ + default List<StudentGroup> findAllByCourseAndPersonIn(Long personId, Long courseId) { + BooleanExpression q = studentGroup.members.any().id.in( + select(role.id).from(role).where( + role.edition.course.id.eq(courseId).and( + role.id.personId.eq(personId)))); + return findAll(q); + } + + /** + * @param personId The id of the person to lookup. + * @param moduleId The id of the module to lookup. + * @return All groups that contain the given person in the given module. + */ + default List<StudentGroup> findAllByModuleAndPersonIn(Long personId, Long moduleId) { + BooleanExpression q = studentGroup.module.id.eq(moduleId).and( + studentGroup.members.any().id.personId.eq(personId)); + return findAll(q); + } + } diff --git a/src/test/java/nl/tudelft/labracore/controller/StudentGroupControllerIntegrationTest.java b/src/test/java/nl/tudelft/labracore/controller/StudentGroupControllerIntegrationTest.java index f137767b..7838ad41 100644 --- a/src/test/java/nl/tudelft/labracore/controller/StudentGroupControllerIntegrationTest.java +++ b/src/test/java/nl/tudelft/labracore/controller/StudentGroupControllerIntegrationTest.java @@ -23,6 +23,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.ArrayList; import java.util.stream.Stream; import javax.transaction.Transactional; @@ -31,12 +32,18 @@ import nl.tudelft.labracore.TestLabracoreApplication; import nl.tudelft.labracore.dto.create.StudentGroupCreateDTO; import nl.tudelft.labracore.dto.helper.GroupGenerateDTO; import nl.tudelft.labracore.dto.patch.StudentGroupPatchDTO; +import nl.tudelft.labracore.dto.view.other.StudentGroupSummaryDTO; +import nl.tudelft.labracore.model.Course; +import nl.tudelft.labracore.model.Person; import nl.tudelft.labracore.model.StudentGroup; +import nl.tudelft.labracore.repository.CourseRepository; import nl.tudelft.labracore.repository.ModuleRepository; import nl.tudelft.labracore.repository.StudentGroupRepository; import nl.tudelft.labracore.test.RestControllerTest; import nl.tudelft.labracore.test.TestDatabaseLoader; +import nl.tudelft.librador.dto.view.View; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -63,9 +70,25 @@ class StudentGroupControllerIntegrationTest extends RestControllerTest { @Autowired private StudentGroupRepository sgr; + @Autowired + private CourseRepository cr; + @Autowired private ModuleRepository mr; + private StudentGroup sg1; + private StudentGroup sg2; + private Person p; + private Course c; + + @BeforeEach + void setUp() { + sg1 = sgr.getOne(dbLoader.getBattle_g1().getId()); + sg2 = sgr.getOne(dbLoader.getPrep_g1().getId()); + p = sg1.getMembers().get(0).getPerson(); + c = cr.getOne(dbLoader.getBeatingHive().getId()); + } + @Test @WithUserDetails("All-access Key") void addGroupValidatesDTO() throws Exception { @@ -113,6 +136,52 @@ class StudentGroupControllerIntegrationTest extends RestControllerTest { .equals(group.getModule().getId()))); } + private static class StudentGroupSummaryList extends ArrayList<StudentGroupSummaryDTO> { + } + + @Test + @WithUserDetails("All-access Key") + void getGroupsForPersonWorks() throws Exception { + mockMvc.perform(get("/api/studentGroup/by-person/{p}", p.getId())) + .andExpect(status().isOk()) + .andExpect(jsonContent(StudentGroupSummaryList.class) + .test(l -> assertThat(l).containsExactlyInAnyOrder( + View.convert(sg1, StudentGroupSummaryDTO.class), + View.convert(sg2, StudentGroupSummaryDTO.class)))); + } + + @Test + @WithUserDetails("All-access Key") + void getGroupsForPersonAndCourseWorks() throws Exception { + mockMvc.perform(get("/api/studentGroup/by-person-and-course/{p}/{c}", p.getId(), + sg1.getModule().getEdition().getCourse().getId())) + .andExpect(status().isOk()) + .andExpect(jsonContent(StudentGroupSummaryList.class) + .test(l -> assertThat(l).containsExactlyInAnyOrder( + View.convert(sg1, StudentGroupSummaryDTO.class), + View.convert(sg2, StudentGroupSummaryDTO.class)))); + } + + @Test + @WithUserDetails("All-access Key") + void getGroupsForPersonAndCourseFilters() throws Exception { + mockMvc.perform(get("/api/studentGroup/by-person-and-course/{p}/{c}", p.getId(), c.getId())) + .andExpect(status().isOk()) + .andExpect(jsonContent(StudentGroupSummaryList.class) + .test(l -> assertThat(l).isEmpty())); + } + + @Test + @WithUserDetails("All-access Key") + void getGroupsForPersonAndModuleWorks() throws Exception { + mockMvc.perform( + get("/api/studentGroup/by-person-and-module/{p}/{m}", p.getId(), sg1.getModule().getId())) + .andExpect(status().isOk()) + .andExpect(jsonContent(StudentGroupSummaryList.class) + .test(l -> assertThat(l).containsExactlyInAnyOrder( + View.convert(sg1, StudentGroupSummaryDTO.class)))); + } + @WithUserDetails("No-access Key") @MethodSource("protectedEndpoints") @ParameterizedTest @@ -139,6 +208,9 @@ class StudentGroupControllerIntegrationTest extends RestControllerTest { patch("/api/studentGroup/3/capacity/1"), get("/api/studentGroup/1/locked"), get("/api/studentGroup/1/locked_student/2"), - get("/api/studentGroup/1/role/2")); + get("/api/studentGroup/1/role/2"), + get("/api/studentGroup/by-person/1"), + get("/api/studentGroup/by-person-and-course/1/1"), + get("/api/studentGroup/by-person-and-module/1/1")); } } -- GitLab