From d4feec1612b4fd8e6e5081e00e8a948cb9447e1d Mon Sep 17 00:00:00 2001 From: Dominik Halfkann Date: Sun, 28 Sep 2025 18:47:55 +0200 Subject: [PATCH 1/3] make gender property in dancer search optional When no gender has been specified in the search query, people of all genders should be returned. Also fixed a typo in the Gender enum. --- .../core/dto/DancerSearchRequestDto.java | 10 +++++ .../net/dancier/dancer/core/model/Gender.java | 2 +- .../dancer/dancers/DancerController.java | 11 +++--- .../dancer/dancers/DancerRepository.java | 7 ++++ .../dancier/dancer/dancers/DancerService.java | 11 +++++- .../dancer/core/EndToEndProfileTest.java | 3 +- .../dancer/dancers/DancerControllerTest.java | 39 ++++++++++++++++--- 7 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java diff --git a/src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java b/src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java new file mode 100644 index 00000000..d9c8126e --- /dev/null +++ b/src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java @@ -0,0 +1,10 @@ +package net.dancier.dancer.core.dto; + +import lombok.Data; +import net.dancier.dancer.core.model.Gender; + +@Data +public class DancerSearchRequestDto { + private Gender gender; + private int range = 20; +} diff --git a/src/main/java/net/dancier/dancer/core/model/Gender.java b/src/main/java/net/dancier/dancer/core/model/Gender.java index e0d70910..78ba9468 100644 --- a/src/main/java/net/dancier/dancer/core/model/Gender.java +++ b/src/main/java/net/dancier/dancer/core/model/Gender.java @@ -2,7 +2,7 @@ public enum Gender { MALE, - DIVERS, + DIVERSE, FEMALE, NA } diff --git a/src/main/java/net/dancier/dancer/dancers/DancerController.java b/src/main/java/net/dancier/dancer/dancers/DancerController.java index 40382aa5..21cb1bef 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerController.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerController.java @@ -1,10 +1,11 @@ package net.dancier.dancer.dancers; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import net.dancier.dancer.chat.dto.DancerDto; import net.dancier.dancer.chat.dto.DancerIdsDto; +import net.dancier.dancer.core.dto.DancerSearchRequestDto; import net.dancier.dancer.core.dto.PublicProfileDto; -import net.dancier.dancer.core.model.Gender; import net.dancier.dancer.security.AuthenticatedUser; import net.dancier.dancer.security.CurrentUser; import org.slf4j.Logger; @@ -29,11 +30,9 @@ public class DancerController { @Secured(ROLE_USER) public ResponseEntity> get( @CurrentUser AuthenticatedUser authenticatedUser, - @RequestParam Gender gender, - @RequestParam(defaultValue = "20") int range - ) { - log.info("Fetching list of dancers in {} km range with gender {} for user {}", range, gender, authenticatedUser.getUserId()); - return ResponseEntity.ok(dancerService.getDancerList(authenticatedUser, gender, range)); + @Valid DancerSearchRequestDto searchRequest) { + log.info("Fetching list of dancers in {} km range with gender {} for user {}", searchRequest.getRange(), searchRequest.getGender(), authenticatedUser.getUserId()); + return ResponseEntity.ok(dancerService.getDancerList(authenticatedUser, searchRequest.getGender(), searchRequest.getRange())); } @PostMapping("") diff --git a/src/main/java/net/dancier/dancer/dancers/DancerRepository.java b/src/main/java/net/dancier/dancer/dancers/DancerRepository.java index abcb9a6a..bd05b1ab 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerRepository.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerRepository.java @@ -22,4 +22,11 @@ List findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween( double upperLatitude ); + List findFirst500ByLongitudeBetweenAndLatitudeBetween( + double lowerLongitude, + double upperLongitude, + double lowerLatitude, + double upperLatitude + ); + } diff --git a/src/main/java/net/dancier/dancer/dancers/DancerService.java b/src/main/java/net/dancier/dancer/dancers/DancerService.java index 8803e7bf..e22f85eb 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerService.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerService.java @@ -54,8 +54,15 @@ public List getDancerList(AuthenticatedUser authenticatedUser, double upperLongitude = dancer.getLongitude() + longitudeRange; double lowerLongitude = dancer.getLongitude() - longitudeRange; - List resultList = dancerRepository.findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween( - gender, lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); + List resultList; + if (gender == null) { + // If no gender is provided, call the new repository method that doesn't filter by gender + resultList = dancerRepository.findFirst500ByLongitudeBetweenAndLatitudeBetween( + lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); + } else { + resultList = dancerRepository.findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween( + gender, lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); + } return resultList.stream() .map(PublicProfileDto::of) diff --git a/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java b/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java index 37c4e7ea..975645ef 100644 --- a/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java +++ b/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java @@ -16,7 +16,6 @@ import org.springframework.test.web.servlet.ResultActions; import java.time.LocalDate; -import java.util.Date; import java.util.Set; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -68,7 +67,7 @@ void fromVirginProfileToPopulatedProfile() throws Exception { danceProfileDto.setLeading(Leading.FOLLOW); - profileOfCurrentUserDto.setGender(Gender.DIVERS); + profileOfCurrentUserDto.setGender(Gender.DIVERSE); profileOfCurrentUserDto.setBirthDate(LocalDate.now()); profileOfCurrentUserDto.setAbleTo(Set.of(danceProfileDto)); profileOfCurrentUserDto.setWantsTo(Set.of(danceProfileDto)); diff --git a/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java b/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java index b427b376..c7b59f03 100644 --- a/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java +++ b/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java @@ -1,12 +1,13 @@ package net.dancier.dancer.dancers; import net.dancier.dancer.AbstractPostgreSQLEnabledTest; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.context.jdbc.Sql; import java.util.List; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.isA; + +import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -61,9 +62,35 @@ void getDancersUsingDefaultRange() throws Exception { @Test @WithUserDetails("user-with-a-profile@dancier.net") - void shouldFailIfGenderIsNotSet() throws Exception { - mockMvc .perform(get("/dancers") - .param("range", "20") - ).andExpect(status().isBadRequest()); + @DisplayName("Search with no specified gender should return all genders") + void getDancers_whenGenderIsOmitted_shouldReturnAllGenders() throws Exception { + mockMvc.perform(get("/dancers") + .param("range", "20") + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(2))) + .andExpect(jsonPath("$[*].gender", containsInAnyOrder("FEMALE", "MALE"))); + } + + @Test + @WithUserDetails("user-with-a-profile@dancier.net") + @DisplayName("Search that matches no dancers should return an empty list") + void getDancers_whenNoDancersMatch_shouldReturnEmptyList() throws Exception { + mockMvc.perform(get("/dancers") + .param("range", "200") + .param("gender", "DIVERSE") // Assuming no DIVERSE dancers are in the data.sql + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(0))); + } + + @Test + @DisplayName("Search without authentication should be rejected") + void getDancers_whenNotAuthenticated_shouldReturnUnauthorized() throws Exception { + mockMvc.perform(get("/dancers") + .param("range", "20") + .param("gender", "FEMALE") + ) + .andExpect(status().isForbidden()); } } From 0e25cc1a2a3f192f37b19d76deb0136312cdccf1 Mon Sep 17 00:00:00 2001 From: Dominik Halfkann Date: Sun, 28 Sep 2025 18:57:03 +0200 Subject: [PATCH 2/3] remove unnecessary code comment --- src/main/java/net/dancier/dancer/dancers/DancerService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/dancier/dancer/dancers/DancerService.java b/src/main/java/net/dancier/dancer/dancers/DancerService.java index e22f85eb..8f147851 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerService.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerService.java @@ -56,7 +56,6 @@ public List getDancerList(AuthenticatedUser authenticatedUser, List resultList; if (gender == null) { - // If no gender is provided, call the new repository method that doesn't filter by gender resultList = dancerRepository.findFirst500ByLongitudeBetweenAndLatitudeBetween( lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); } else { From a69633ec56290803344e69a6faf2cd0af32bae5c Mon Sep 17 00:00:00 2001 From: Dominik Halfkann Date: Sun, 19 Oct 2025 16:26:04 +0200 Subject: [PATCH 3/3] fix issues with docker-compose.yml --- docker-compose.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6b63e3af..9542e877 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: dancer: @@ -13,7 +11,7 @@ services: environment: # https://ckinan.com/blog/remote-debug-spring-boot-docker-intellij/: - SPRING_DATASOURCE_URL=jdbc:postgresql://dancer-db:5432/dancer - - SPRING_PROFILES_ACTIVE="dev" + - SPRING_PROFILES_ACTIVE=dev - JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 dancer-db: image: postgres:14 @@ -40,6 +38,8 @@ services: prometheus: image: prom/prometheus + depends_on: + - dancer ports: - "9090:9090" volumes: @@ -70,6 +70,8 @@ services: kafka-ui: container_name: kafka-ui image: tchiotludo/akhq:latest + depends_on: + - kafka healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/ui"] interval: 10s