From ee90ff7a5ece7c2f0fa24de518a42161237f5c69 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 12:05:12 +0200 Subject: [PATCH 01/10] feat(project): add ProjectController, Service, Mapper, and DTO --- .../project/ProjectController.java | 38 +++++++++++++++++++ .../lf8_starter/project/ProjectMapper.java | 21 ++++++++++ .../lf8_starter/project/ProjectService.java | 21 ++++++++++ .../project/dto/ProjectGetDto.java | 29 ++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 src/main/java/de/szut/lf8_starter/project/ProjectController.java create mode 100644 src/main/java/de/szut/lf8_starter/project/ProjectMapper.java create mode 100644 src/main/java/de/szut/lf8_starter/project/ProjectService.java create mode 100644 src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectController.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java new file mode 100644 index 0000000..259efff --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -0,0 +1,38 @@ +package de.szut.lf8_starter.project; + +import de.szut.lf8_starter.project.dto.ProjectGetDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(value = "projects") +public class ProjectController { + private final ProjectService service; + private final ProjectMapper projectMapper; + public ProjectController(ProjectService service, ProjectMapper projectMapper) { + this.service = service; + this.projectMapper = projectMapper; + } + + @Operation(summary = "returns all projects") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "all projects", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ProjectGetDto.class))}), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content)}) + @GetMapping + public List findAll() { + return this.service + .readAll() + .stream() + .map(this.projectMapper::mapToGetDto) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java b/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java new file mode 100644 index 0000000..1846038 --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java @@ -0,0 +1,21 @@ +package de.szut.lf8_starter.project; + +import de.szut.lf8_starter.project.dto.ProjectGetDto; +import org.springframework.stereotype.Service; + +@Service +public class ProjectMapper { + public ProjectGetDto mapToGetDto(ProjectEntity entity) { + return new ProjectGetDto( + entity.getId(), + entity.getName(), + entity.getLeadingEmployee(), + entity.getEmployees(), + entity.getContractor(), + entity.getContractorName(), + entity.getComment(), + entity.getStartDate(), + entity.getEndDate() + ); + } +} diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectService.java b/src/main/java/de/szut/lf8_starter/project/ProjectService.java new file mode 100644 index 0000000..8aeedfa --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/ProjectService.java @@ -0,0 +1,21 @@ +package de.szut.lf8_starter.project; + +import de.szut.lf8_starter.hello.HelloEntity; +import de.szut.lf8_starter.hello.HelloRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class ProjectService { + private final ProjectRepository repository; + + public ProjectService(ProjectRepository repository) { + this.repository = repository; + } + + public List readAll() { + return this.repository.findAll(); + } +} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java b/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java new file mode 100644 index 0000000..4d53212 --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java @@ -0,0 +1,29 @@ +package de.szut.lf8_starter.project.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.time.LocalDate; +import java.util.List; + +@Data +@AllArgsConstructor +public class ProjectGetDto { + private long id; + + private String name; + + private long leadingEmployee; + + private List employees; + + private long contractor; + + private String contractorName; + + private String comment; + + private LocalDate startDate; + + private LocalDate endDate; +} -- 2.45.2 From f33721f16d425b042e99662d1cfbe17a1179eb51 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 12:07:18 +0200 Subject: [PATCH 02/10] style(ProjectController): fix missing newline at end of file --- .../java/de/szut/lf8_starter/project/ProjectController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectController.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java index 259efff..e39c274 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectController.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -35,4 +35,4 @@ public class ProjectController { .map(this.projectMapper::mapToGetDto) .toList(); } -} \ No newline at end of file +} -- 2.45.2 From 6d5f67f7ca2f0d955bfd713f50050a48d1265ee3 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 13:01:54 +0200 Subject: [PATCH 03/10] feat: add authentication helper and project findAll test --- .../project/ProjectRepository.java | 2 + .../project/utils/AuthenticationHelper.java | 35 +++++++++++ .../integration/project/ProjectFindAll.java | 61 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java create mode 100644 src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java b/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java index 9798fc8..6f7e33f 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java @@ -1,6 +1,8 @@ package de.szut.lf8_starter.project; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface ProjectRepository extends JpaRepository { } diff --git a/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java b/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java new file mode 100644 index 0000000..2a9d397 --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java @@ -0,0 +1,35 @@ +package de.szut.lf8_starter.project.utils; + +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +public interface AuthenticationHelper { + + default String getAuthenticationToken(TestRestTemplate restTemplate) { + MultiValueMap authParams = new LinkedMultiValueMap<>(); + authParams.add("grant_type", "password"); + authParams.add("client_id", "employee-management-service"); + authParams.add("username", "user"); + authParams.add("password", "test"); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "application/x-www-form-urlencoded"); + + HttpEntity> request = new HttpEntity<>(authParams, headers); + ResponseEntity authResponse = restTemplate.postForEntity("https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token", request, String.class); + + // Extract the token from the response + String responseBody = authResponse.getBody(); + assert responseBody != null; + + return "Bearer " + extractToken(responseBody); + } + + private String extractToken(String responseBody) { + return responseBody.substring(responseBody.indexOf("access_token\":\"") + 15, responseBody.indexOf("\"", responseBody.indexOf("access_token\":\"") + 15)); + } +} \ No newline at end of file diff --git a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java new file mode 100644 index 0000000..ab87527 --- /dev/null +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java @@ -0,0 +1,61 @@ +package de.szut.lf8_starter.integration.project; + +import de.szut.lf8_starter.project.ProjectEntity; +import de.szut.lf8_starter.project.ProjectRepository; +import de.szut.lf8_starter.project.utils.AuthenticationHelper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDate; +import java.util.List; + +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +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; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class ProjectFindAll implements AuthenticationHelper { + @Autowired + private ProjectRepository projectRepository; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void findAllProjects() throws Exception { + var project = new ProjectEntity(); + project.setId(1); + project.setComment("comment"); + project.setContractor(1); + project.setContractorName("contractorName"); + project.setEndDate(LocalDate.of(2024, 1, 1)); + project.setLeadingEmployee(1); + project.setName("name"); + project.setStartDate(LocalDate.of(2021, 1, 1)); + project.setEmployees(List.of(1L,2L,3L)); + this.projectRepository.save(project); + + this.mockMvc.perform(get("/projects").header("Authorization", getAuthenticationToken(restTemplate))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(1))) + .andExpect(jsonPath("$[0].id").value(1)) + .andExpect(jsonPath("$[0].comment").value("comment")) + .andExpect(jsonPath("$[0].contractor").value(1)) + .andExpect(jsonPath("$[0].contractorName").value("contractorName")) + .andExpect(jsonPath("$[0].endDate").value("2024-01-01")) + .andExpect(jsonPath("$[0].leadingEmployee").value(1)) + .andExpect(jsonPath("$[0].name").value("name")) + .andExpect(jsonPath("$[0].startDate").value("2021-01-01")) + .andExpect(jsonPath("$[0].employees").isArray()) + .andExpect(jsonPath("$[0].employees", hasSize(3))); + } +} -- 2.45.2 From 6ca01de6135b4378e0008d0f309595249ca156a1 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 12:05:12 +0200 Subject: [PATCH 04/10] feat(project): add ProjectController, Service, Mapper, and DTO --- .../project/ProjectController.java | 38 +++++++++++++++++++ .../project/dto/ProjectGetDto.java | 29 ++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/main/java/de/szut/lf8_starter/project/ProjectController.java create mode 100644 src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectController.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java new file mode 100644 index 0000000..259efff --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -0,0 +1,38 @@ +package de.szut.lf8_starter.project; + +import de.szut.lf8_starter.project.dto.ProjectGetDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(value = "projects") +public class ProjectController { + private final ProjectService service; + private final ProjectMapper projectMapper; + public ProjectController(ProjectService service, ProjectMapper projectMapper) { + this.service = service; + this.projectMapper = projectMapper; + } + + @Operation(summary = "returns all projects") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "all projects", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ProjectGetDto.class))}), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content)}) + @GetMapping + public List findAll() { + return this.service + .readAll() + .stream() + .map(this.projectMapper::mapToGetDto) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java b/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java new file mode 100644 index 0000000..4d53212 --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java @@ -0,0 +1,29 @@ +package de.szut.lf8_starter.project.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.time.LocalDate; +import java.util.List; + +@Data +@AllArgsConstructor +public class ProjectGetDto { + private long id; + + private String name; + + private long leadingEmployee; + + private List employees; + + private long contractor; + + private String contractorName; + + private String comment; + + private LocalDate startDate; + + private LocalDate endDate; +} -- 2.45.2 From c23781c61cdd875a346f1ff9e15841b3a32992db Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 12:07:18 +0200 Subject: [PATCH 05/10] style(ProjectController): fix missing newline at end of file --- .../java/de/szut/lf8_starter/project/ProjectController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectController.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java index 259efff..e39c274 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectController.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -35,4 +35,4 @@ public class ProjectController { .map(this.projectMapper::mapToGetDto) .toList(); } -} \ No newline at end of file +} -- 2.45.2 From 277b8c73e2096d44e995655cee6cef7b1c9a51c5 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 13:01:54 +0200 Subject: [PATCH 06/10] feat: add authentication helper and project findAll test --- .../project/ProjectRepository.java | 2 + .../project/utils/AuthenticationHelper.java | 35 +++++++++++ .../integration/project/ProjectFindAll.java | 61 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java create mode 100644 src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java b/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java index 9798fc8..6f7e33f 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectRepository.java @@ -1,6 +1,8 @@ package de.szut.lf8_starter.project; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface ProjectRepository extends JpaRepository { } diff --git a/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java b/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java new file mode 100644 index 0000000..2a9d397 --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java @@ -0,0 +1,35 @@ +package de.szut.lf8_starter.project.utils; + +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +public interface AuthenticationHelper { + + default String getAuthenticationToken(TestRestTemplate restTemplate) { + MultiValueMap authParams = new LinkedMultiValueMap<>(); + authParams.add("grant_type", "password"); + authParams.add("client_id", "employee-management-service"); + authParams.add("username", "user"); + authParams.add("password", "test"); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "application/x-www-form-urlencoded"); + + HttpEntity> request = new HttpEntity<>(authParams, headers); + ResponseEntity authResponse = restTemplate.postForEntity("https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token", request, String.class); + + // Extract the token from the response + String responseBody = authResponse.getBody(); + assert responseBody != null; + + return "Bearer " + extractToken(responseBody); + } + + private String extractToken(String responseBody) { + return responseBody.substring(responseBody.indexOf("access_token\":\"") + 15, responseBody.indexOf("\"", responseBody.indexOf("access_token\":\"") + 15)); + } +} \ No newline at end of file diff --git a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java new file mode 100644 index 0000000..ab87527 --- /dev/null +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java @@ -0,0 +1,61 @@ +package de.szut.lf8_starter.integration.project; + +import de.szut.lf8_starter.project.ProjectEntity; +import de.szut.lf8_starter.project.ProjectRepository; +import de.szut.lf8_starter.project.utils.AuthenticationHelper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDate; +import java.util.List; + +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +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; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class ProjectFindAll implements AuthenticationHelper { + @Autowired + private ProjectRepository projectRepository; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void findAllProjects() throws Exception { + var project = new ProjectEntity(); + project.setId(1); + project.setComment("comment"); + project.setContractor(1); + project.setContractorName("contractorName"); + project.setEndDate(LocalDate.of(2024, 1, 1)); + project.setLeadingEmployee(1); + project.setName("name"); + project.setStartDate(LocalDate.of(2021, 1, 1)); + project.setEmployees(List.of(1L,2L,3L)); + this.projectRepository.save(project); + + this.mockMvc.perform(get("/projects").header("Authorization", getAuthenticationToken(restTemplate))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(1))) + .andExpect(jsonPath("$[0].id").value(1)) + .andExpect(jsonPath("$[0].comment").value("comment")) + .andExpect(jsonPath("$[0].contractor").value(1)) + .andExpect(jsonPath("$[0].contractorName").value("contractorName")) + .andExpect(jsonPath("$[0].endDate").value("2024-01-01")) + .andExpect(jsonPath("$[0].leadingEmployee").value(1)) + .andExpect(jsonPath("$[0].name").value("name")) + .andExpect(jsonPath("$[0].startDate").value("2021-01-01")) + .andExpect(jsonPath("$[0].employees").isArray()) + .andExpect(jsonPath("$[0].employees", hasSize(3))); + } +} -- 2.45.2 From df8624c5ee270f64476acda481a4d9d6cb046c68 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 13:13:40 +0200 Subject: [PATCH 07/10] feat(project): update findAll to use GetProjectDto type --- .../project/ProjectController.java | 3 +- .../lf8_starter/project/ProjectService.java | 6 ++++ .../project/utils/AuthenticationHelper.java | 35 ------------------- .../integration/project/ProjectFindAll.java | 5 ++- 4 files changed, 10 insertions(+), 39 deletions(-) delete mode 100644 src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectController.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java index e39c274..fe0991b 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectController.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -1,5 +1,6 @@ package de.szut.lf8_starter.project; +import de.szut.lf8_starter.project.dto.GetProjectDto; import de.szut.lf8_starter.project.dto.ProjectGetDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -28,7 +29,7 @@ public class ProjectController { @ApiResponse(responseCode = "401", description = "not authorized", content = @Content)}) @GetMapping - public List findAll() { + public List findAll() { return this.service .readAll() .stream() diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectService.java b/src/main/java/de/szut/lf8_starter/project/ProjectService.java index a12228f..4dc8688 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectService.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectService.java @@ -2,6 +2,8 @@ package de.szut.lf8_starter.project; import org.springframework.stereotype.Service; +import java.util.List; + @Service public class ProjectService { private final ProjectRepository projectRepository; @@ -13,4 +15,8 @@ public class ProjectService { public ProjectEntity create(ProjectEntity projectEntity) { return this.projectRepository.save(projectEntity); } + + public List readAll() { + return this.projectRepository.findAll(); + } } diff --git a/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java b/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java deleted file mode 100644 index 2a9d397..0000000 --- a/src/main/java/de/szut/lf8_starter/project/utils/AuthenticationHelper.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.szut.lf8_starter.project.utils; - -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -public interface AuthenticationHelper { - - default String getAuthenticationToken(TestRestTemplate restTemplate) { - MultiValueMap authParams = new LinkedMultiValueMap<>(); - authParams.add("grant_type", "password"); - authParams.add("client_id", "employee-management-service"); - authParams.add("username", "user"); - authParams.add("password", "test"); - - HttpHeaders headers = new HttpHeaders(); - headers.set("Content-Type", "application/x-www-form-urlencoded"); - - HttpEntity> request = new HttpEntity<>(authParams, headers); - ResponseEntity authResponse = restTemplate.postForEntity("https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token", request, String.class); - - // Extract the token from the response - String responseBody = authResponse.getBody(); - assert responseBody != null; - - return "Bearer " + extractToken(responseBody); - } - - private String extractToken(String responseBody) { - return responseBody.substring(responseBody.indexOf("access_token\":\"") + 15, responseBody.indexOf("\"", responseBody.indexOf("access_token\":\"") + 15)); - } -} \ No newline at end of file diff --git a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java index ab87527..0409f36 100644 --- a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java @@ -2,7 +2,6 @@ package de.szut.lf8_starter.integration.project; import de.szut.lf8_starter.project.ProjectEntity; import de.szut.lf8_starter.project.ProjectRepository; -import de.szut.lf8_starter.project.utils.AuthenticationHelper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -20,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc -public class ProjectFindAll implements AuthenticationHelper { +public class ProjectFindAll { @Autowired private ProjectRepository projectRepository; @@ -44,7 +43,7 @@ public class ProjectFindAll implements AuthenticationHelper { project.setEmployees(List.of(1L,2L,3L)); this.projectRepository.save(project); - this.mockMvc.perform(get("/projects").header("Authorization", getAuthenticationToken(restTemplate))) + this.mockMvc.perform(get("/projects")) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasSize(1))) .andExpect(jsonPath("$[0].id").value(1)) -- 2.45.2 From bee9d307fac33759361f3cd61eaf91a9e1fdf84d Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 13:16:01 +0200 Subject: [PATCH 08/10] ci: update Gradle commands in workflow configuration --- .gitea/workflows/qs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/qs.yml b/.gitea/workflows/qs.yml index d962ad2..04b9983 100644 --- a/.gitea/workflows/qs.yml +++ b/.gitea/workflows/qs.yml @@ -23,7 +23,7 @@ jobs: - name: "Prepare Gradle" run: gradle clean - name: "Check" - run: gradle testClasses + run: gradle test - name: "Stop Gradle" run: gradle --stop checkstyle: @@ -45,6 +45,6 @@ jobs: - name: "Prepare Gradle" run: gradle clean - name: "Check" - run: gradle check + run: gradle checkstyleMain --scan - name: "Stop Gradle" run: gradle --stop -- 2.45.2 From 5ae5aca0765791eace6d5150feb55c61c42b4d3f Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 13:27:28 +0200 Subject: [PATCH 09/10] feat(project): update project DTO and controller mapping --- .../project/ProjectController.java | 3 +- .../lf8_starter/project/ProjectMapper.java | 1 + .../project/dto/GetProjectDto.java | 2 ++ .../project/dto/ProjectGetDto.java | 29 ------------------- .../security/KeycloakSecurityConfig.java | 1 + .../integration/project/ProjectFindAll.java | 7 +++-- 6 files changed, 9 insertions(+), 34 deletions(-) delete mode 100644 src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectController.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java index fe0991b..61ee843 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectController.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -1,7 +1,6 @@ package de.szut.lf8_starter.project; import de.szut.lf8_starter.project.dto.GetProjectDto; -import de.szut.lf8_starter.project.dto.ProjectGetDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -25,7 +24,7 @@ public class ProjectController { @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "all projects", content = {@Content(mediaType = "application/json", - schema = @Schema(implementation = ProjectGetDto.class))}), + schema = @Schema(implementation = GetProjectDto.class))}), @ApiResponse(responseCode = "401", description = "not authorized", content = @Content)}) @GetMapping diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java b/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java index 6567749..fa60491 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java @@ -25,6 +25,7 @@ public class ProjectMapper { public GetProjectDto mapToGetDto(ProjectEntity projectEntity) { GetProjectDto getProjectDto = new GetProjectDto(); + getProjectDto.setId(projectEntity.getId()); getProjectDto.setName(projectEntity.getName()); getProjectDto.setComment(projectEntity.getComment()); getProjectDto.setLeadingEmployee(projectEntity.getLeadingEmployee()); diff --git a/src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java b/src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java index cc337c7..c90cd50 100644 --- a/src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java +++ b/src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java @@ -12,6 +12,8 @@ import java.util.List; @Getter @Setter public class GetProjectDto { + private long id; + @NotBlank private String name; diff --git a/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java b/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java deleted file mode 100644 index 4d53212..0000000 --- a/src/main/java/de/szut/lf8_starter/project/dto/ProjectGetDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.szut.lf8_starter.project.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.time.LocalDate; -import java.util.List; - -@Data -@AllArgsConstructor -public class ProjectGetDto { - private long id; - - private String name; - - private long leadingEmployee; - - private List employees; - - private long contractor; - - private String contractorName; - - private String comment; - - private LocalDate startDate; - - private LocalDate endDate; -} diff --git a/src/main/java/de/szut/lf8_starter/security/KeycloakSecurityConfig.java b/src/main/java/de/szut/lf8_starter/security/KeycloakSecurityConfig.java index ea9e354..8ab3fd8 100644 --- a/src/main/java/de/szut/lf8_starter/security/KeycloakSecurityConfig.java +++ b/src/main/java/de/szut/lf8_starter/security/KeycloakSecurityConfig.java @@ -5,6 +5,7 @@ import java.util.stream.Collectors; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.http.HttpMethod; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; diff --git a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java index 0409f36..361e585 100644 --- a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java @@ -5,6 +5,7 @@ import de.szut.lf8_starter.project.ProjectRepository; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.test.web.servlet.MockMvc; @@ -18,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@AutoConfigureMockMvc +@AutoConfigureMockMvc(addFilters = false) public class ProjectFindAll { @Autowired private ProjectRepository projectRepository; @@ -50,10 +51,10 @@ public class ProjectFindAll { .andExpect(jsonPath("$[0].comment").value("comment")) .andExpect(jsonPath("$[0].contractor").value(1)) .andExpect(jsonPath("$[0].contractorName").value("contractorName")) - .andExpect(jsonPath("$[0].endDate").value("2024-01-01")) + .andExpect(jsonPath("$[0].endDate").value("01.01.2024")) .andExpect(jsonPath("$[0].leadingEmployee").value(1)) .andExpect(jsonPath("$[0].name").value("name")) - .andExpect(jsonPath("$[0].startDate").value("2021-01-01")) + .andExpect(jsonPath("$[0].startDate").value("01.01.2021")) .andExpect(jsonPath("$[0].employees").isArray()) .andExpect(jsonPath("$[0].employees", hasSize(3))); } -- 2.45.2 From 65142d0a4ad9af85a9dc5baf9316d46ba0586ada Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Wed, 25 Sep 2024 13:32:55 +0200 Subject: [PATCH 10/10] test: add integration test for unauthorized project access --- .../ProjectFindAllNotAuthenticated.java | 37 +++++++++++++++++++ ...indAll.java => ProjectFindAllSuccess.java} | 3 +- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllNotAuthenticated.java rename src/test/java/de/szut/lf8_starter/integration/project/{ProjectFindAll.java => ProjectFindAllSuccess.java} (96%) diff --git a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllNotAuthenticated.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllNotAuthenticated.java new file mode 100644 index 0000000..8c62848 --- /dev/null +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllNotAuthenticated.java @@ -0,0 +1,37 @@ +package de.szut.lf8_starter.integration.project; + +import de.szut.lf8_starter.project.ProjectEntity; +import de.szut.lf8_starter.project.ProjectRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDate; +import java.util.List; + +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +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; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc(addFilters = true) +public class ProjectFindAllNotAuthenticated { + @Autowired + private ProjectRepository projectRepository; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void findAllProjects() throws Exception { + this.mockMvc.perform(get("/projects")) + .andExpect(status().isUnauthorized()); + } +} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllSuccess.java similarity index 96% rename from src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java rename to src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllSuccess.java index 361e585..906b63f 100644 --- a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAll.java +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllSuccess.java @@ -5,7 +5,6 @@ import de.szut.lf8_starter.project.ProjectRepository; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.test.web.servlet.MockMvc; @@ -20,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc(addFilters = false) -public class ProjectFindAll { +public class ProjectFindAllSuccess { @Autowired private ProjectRepository projectRepository; -- 2.45.2