diff --git a/.gitea/workflows/build-pr.yml b/.gitea/workflows/build-pr.yml deleted file mode 100644 index ffb5436..0000000 --- a/.gitea/workflows/build-pr.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Build PR - -on: # test - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - -jobs: - build: - name: Build and analyze - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 21 - uses: actions/setup-java@v1 - with: - java-version: 21 - - name: Cache SonarQube packages - uses: actions/cache@v4 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Cache Gradle packages - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: ${{ runner.os }}-gradle - - name: Coverage - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - run: ./gradlew test jacocoTestReport sonar - - name: Build and analyze - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - run: ./gradlew build sonar --info -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }} -Dsonar.pullrequest.key=${{github.event.pull_request.number}} \ No newline at end of file diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml deleted file mode 100644 index 5e9e1cf..0000000 --- a/.gitea/workflows/build.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Build - -on: - push: - branches: - - main - -jobs: - build: - name: Build and analyze - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 21 - uses: actions/setup-java@v1 - with: - java-version: 21 - - name: Cache SonarQube packages - uses: actions/cache@v4 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - name: Cache Gradle packages - uses: actions/cache@v4 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: ${{ runner.os }}-gradle - - name: Coverage - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - run: ./gradlew test jacocoTestReport sonar - - name: Build and analyze - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - run: ./gradlew build sonar --info \ No newline at end of file diff --git a/Readme.md b/Readme.md index 1e0c8d8..bcfc727 100644 --- a/Readme.md +++ b/Readme.md @@ -3,9 +3,6 @@ ![Gitea Release](https://img.shields.io/gitea/v/release/jank/LF8?gitea_url=https%3A%2F%2Fgit.kjan.de&style=plastic) ![Gitea Last Commit](https://img.shields.io/gitea/last-commit/jank/LF8?gitea_url=https%3A%2F%2Fgit.kjan.de&style=plastic) -## Code analysis coverage issues and results of linting MAY be found here: -https://sonarqube.kjan.de/dashboard?id=LF8&codeScope=overall - # Starter für das LF08 Projekt ## Requirements diff --git a/build.gradle.kts b/build.gradle.kts index 80769b3..9c30a46 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,85 +1,62 @@ -plugins { - java - id("org.springframework.boot") version "3.3.4" - id("io.spring.dependency-management") version "1.1.6" - id("checkstyle") - id("org.sonarqube") version "6.0.1.5171" - id("jacoco") -} - -tasks.jacocoTestReport { - dependsOn(tasks.test) // Ensure tests are run before generating the report - reports { - xml.required = true - csv.required = true - } -} - -sonar { - properties { - property("sonar.projectKey", "LF8") - property("sonar.projectName", "LF8") - } -} - -tasks.withType { - reports { - // Disable HTML report - html.required.set(false) - - // Disable XML report - xml.required.set(false) - } -} - -group = "de.szut" -version = "0.0.1-SNAPSHOT" - -tasks.test { - useJUnitPlatform() - - // Activate the 'test' profile for Spring during tests - systemProperty("spring.profiles.active", "test") -} - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(21) - } -} - -configurations { - compileOnly { - extendsFrom(configurations.annotationProcessor.get()) - } -} - -repositories { - mavenCentral() -} - -val springDocVersion = "2.6.0" -val oauth2Version = "3.3.4" - -dependencies { - implementation("org.springframework.boot:spring-boot-starter-data-jpa") - implementation("org.springframework.boot:spring-boot-starter-web") - implementation("org.springframework.boot:spring-boot-starter-validation") - implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:$springDocVersion") - implementation("org.springframework.boot:spring-boot-starter-security") - implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server:$oauth2Version") - implementation("org.springframework.boot:spring-boot-starter-oauth2-client:$oauth2Version") - - testImplementation("com.h2database:h2") - testImplementation("org.springframework.boot:spring-boot-starter-test") - - compileOnly("org.projectlombok:lombok") - annotationProcessor("org.projectlombok:lombok") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - runtimeOnly("org.postgresql:postgresql") -} - -tasks.withType { - useJUnitPlatform() - finalizedBy(tasks.jacocoTestReport) // Run JaCoCo report after tests -} \ No newline at end of file +plugins { + java + id("org.springframework.boot") version "3.3.4" + id("io.spring.dependency-management") version "1.1.6" + id("checkstyle") +} + +tasks.withType { + reports { + // Disable HTML report + html.required.set(false) + + // Disable XML report + xml.required.set(false) + } +} + +group = "de.szut" +version = "0.0.1-SNAPSHOT" + +tasks.test { + useJUnitPlatform() + + // Activate the 'test' profile for Spring during tests + systemProperty("spring.profiles.active", "test") +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +configurations { + compileOnly { + extendsFrom(configurations.annotationProcessor.get()) + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-validation") + compileOnly("org.projectlombok:lombok") + annotationProcessor("org.projectlombok:lombok") + testImplementation("org.springframework.boot:spring-boot-starter-test") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + implementation("org.springframework.boot:spring-boot-starter-security") + implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.3.4") + implementation("org.springframework.boot:spring-boot-starter-oauth2-client:3.3.4") + runtimeOnly("org.postgresql:postgresql") + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0") + testImplementation("com.h2database:h2") +} + +tasks.withType { + useJUnitPlatform() +} diff --git a/docker/local/docker-compose.yml b/docker/local/docker-compose.yml index add2420..7b556ef 100644 --- a/docker/local/docker-compose.yml +++ b/docker/local/docker-compose.yml @@ -7,7 +7,7 @@ volumes: services: postgres_for_lf8_starter: container_name: lf8_starter_postgres_container - image: postgres:17.0 + image: postgres:16.4 volumes: - lf8_starter_postgres_data:/var/lib/postgresql/data environment: diff --git a/requests/project/createProject.http b/requests/createProject.http similarity index 72% rename from requests/project/createProject.http rename to requests/createProject.http index 1e044b5..885c49e 100644 --- a/requests/project/createProject.http +++ b/requests/createProject.http @@ -1,15 +1,15 @@ -### GET request to example server -POST http://localhost:8080/projects -Authorization: Bearer {{auth_token}} -Content-Type: application/json - -{ - "name": "name", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Peter File", - "comment": "goal of project", - "start_date": "02.01.2020", - "planned_end_date": "01.01.2023" +### GET request to example server +POST http://localhost:8080/projects +Authorization: Bearer {{auth_token}} +Content-Type: application/json + +{ + "name": "name", + "leading_employee": 1, + "employees": [2, 3], + "contractor": 4, + "contractor_name": "Peter File", + "comment": "goal of project", + "start_date": "01.01.2000", + "planned_end_date": "01.01.2001" } \ No newline at end of file diff --git a/requests/employee/createEmployee.http b/requests/employee/createEmployee.http deleted file mode 100644 index b3f4591..0000000 --- a/requests/employee/createEmployee.http +++ /dev/null @@ -1,15 +0,0 @@ -POST https://employee.szut.dev/employees -Authorization: Bearer {{auth_token}} -Content-Type: application/json - -{ - "firstName": "Jan1", - "lastName": "Klattenhoff1", - "street": "Pirolweg 171", - "postcode": "27777", - "city": "Gandakersee1", - "phone": "0176849848161", - "skillSet": [ - "1" - ] -} \ No newline at end of file diff --git a/requests/employee/deleteEmployee.http b/requests/employee/deleteEmployee.http deleted file mode 100644 index cf1d827..0000000 --- a/requests/employee/deleteEmployee.http +++ /dev/null @@ -1,2 +0,0 @@ -DELETE https://employee.szut.dev/employees/310 -Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/requests/employee/getAllEmployees.http b/requests/employee/getAllEmployees.http deleted file mode 100644 index c3911be..0000000 --- a/requests/employee/getAllEmployees.http +++ /dev/null @@ -1,2 +0,0 @@ -GET https://employee.szut.dev/employees -Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/requests/employee/getEmployee.http b/requests/employee/getEmployee.http deleted file mode 100644 index 350a7fc..0000000 --- a/requests/employee/getEmployee.http +++ /dev/null @@ -1,2 +0,0 @@ -GET https://employee.szut.dev/employees/315 -Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/requests/employee/getProjects.http b/requests/employee/getProjects.http deleted file mode 100644 index 8689798..0000000 --- a/requests/employee/getProjects.http +++ /dev/null @@ -1,3 +0,0 @@ -GET http://localhost:8080/employees/315/projects -Authorization: Bearer {{auth_token}} -Content-Type: application/json \ No newline at end of file diff --git a/requests/project/getAllProjects.http b/requests/getAllProjects.http similarity index 98% rename from requests/project/getAllProjects.http rename to requests/getAllProjects.http index b56f68d..21a4ceb 100644 --- a/requests/project/getAllProjects.http +++ b/requests/getAllProjects.http @@ -1,3 +1,3 @@ -### GET request to example server -GET http://localhost:8080/projects +### GET request to example server +GET http://localhost:8080/projects Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/requests/project/addEmployeeToProject.http b/requests/project/addEmployeeToProject.http deleted file mode 100644 index 981839a..0000000 --- a/requests/project/addEmployeeToProject.http +++ /dev/null @@ -1,2 +0,0 @@ -POST http://localhost:8080/projects/1/employees/312 -Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/requests/project/getEmployeesFromProject.http b/requests/project/getEmployeesFromProject.http deleted file mode 100644 index d12dd96..0000000 --- a/requests/project/getEmployeesFromProject.http +++ /dev/null @@ -1,2 +0,0 @@ -GET http://localhost:8080/projects/2/employees -Authorization: Bearer {{auth_token}} \ No newline at end of file diff --git a/requests/project/getProject.http b/requests/project/getProject.http deleted file mode 100644 index 1074d4a..0000000 --- a/requests/project/getProject.http +++ /dev/null @@ -1,3 +0,0 @@ -### GET request to example server -GET http://localhost:8080/projects/1 -Authorization: Bearer {{auth_token}} diff --git a/requests/project/updateProject.http b/requests/project/updateProject.http deleted file mode 100644 index 13bf006..0000000 --- a/requests/project/updateProject.http +++ /dev/null @@ -1,15 +0,0 @@ -### GET request to example server -PUT http://localhost:8080/projects/1 -Authorization: Bearer {{auth_token}} -Content-Type: application/json - -{ - "name": "newName", - "leading_employee": 2, - "employees": [], - "contractor": 9, - "contractor_name": "New Contractor name", - "comment": "new goal of project", - "start_date": "01.01.2010", - "planned_end_date": "01.01.2021" -} \ No newline at end of file diff --git a/src/main/java/de/szut/lf8_starter/config/OpenAPIConfiguration.java b/src/main/java/de/szut/lf8_starter/config/OpenAPIConfiguration.java index 17f6bda..1b2282b 100644 --- a/src/main/java/de/szut/lf8_starter/config/OpenAPIConfiguration.java +++ b/src/main/java/de/szut/lf8_starter/config/OpenAPIConfiguration.java @@ -1,77 +1,60 @@ -package de.szut.lf8_starter.config; - - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; -import io.swagger.v3.oas.models.servers.Server; -import jakarta.servlet.ServletContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - - -@Configuration -public class OpenAPIConfiguration { - - private ServletContext context; - - public OpenAPIConfiguration(ServletContext context) { - this.context = context; - } - - - @Bean - public OpenAPI springShopOpenAPI( - // @Value("${info.app.version}") String appVersion, - ) { - final String securitySchemeName = "bearerAuth"; - - return new OpenAPI() - .addServersItem(new Server().url(this.context.getContextPath())) - .info(new Info() - .title("LF8 project starter") - .description(""" - ## Auth - - ## Authentication - - This Hello service uses JWTs to authenticate requests. You will receive a bearer token by making a POST-Request in IntelliJ on: - - ``` - POST http://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token - Content-Type: application/x-www-form-urlencoded - grant_type=password&client_id=employee-management-service&username=user&password=test - ``` - - or by CURL: - - ``` - curl -X POST 'http://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token' - --header 'Content-Type: application/x-www-form-urlencoded' - --data-urlencode 'grant_type=password' - --data-urlencode 'client_id=employee-management-service' - --data-urlencode 'username=user' - --data-urlencode 'password=test' - ``` - - To get a bearer-token in Postman, you have to follow the instructions in - [Postman-Documentation](https://documenter.getpostman.com/view/7294517/SzmfZHnd). - """) - .version("0.1")) - .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) - .components( - new Components() - .addSecuritySchemes(securitySchemeName, - new SecurityScheme() - .name(securitySchemeName) - .type(SecurityScheme.Type.HTTP) - .scheme("bearer") - .bearerFormat("JWT") - ) - ); - } - - -} +package de.szut.lf8_starter.config; + + + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import jakarta.servlet.ServletContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class OpenAPIConfiguration { + + private ServletContext context; + + public OpenAPIConfiguration(ServletContext context) { + this.context = context; + } + + + @Bean + public OpenAPI springShopOpenAPI( + // @Value("${info.app.version}") String appVersion, + ) { + final String securitySchemeName = "bearerAuth"; + + return new OpenAPI() + .addServersItem(new Server().url(this.context.getContextPath())) + .info(new Info() + .title("LF8 project starter") + .description("\n## Auth\n" + + "\n## Authentication\n" + "\nThis Hello service uses JWTs to authenticate requests. You will receive a bearer token by making a POST-Request in IntelliJ on:\n\n" + + "\n" + + "```\nPOST http://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token\nContent-Type: application/x-www-form-urlencoded\ngrant_type=password&client_id=employee-management-service&username=user&password=test\n```\n" + + "\n" + + "\nor by CURL\n" + + "```\ncurl -X POST 'http://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token'\n--header 'Content-Type: application/x-www-form-urlencoded'\n--data-urlencode 'grant_type=password'\n--data-urlencode 'client_id=employee-management-service'\n--data-urlencode 'username=user'\n--data-urlencode 'password=test'\n```\n" + + "\nTo get a bearer-token in Postman, you have to follow the instructions in \n [Postman-Documentation](https://documenter.getpostman.com/view/7294517/SzmfZHnd).") + + .version("0.1")) + .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) + .components( + new Components() + .addSecuritySchemes(securitySchemeName, + new SecurityScheme() + .name(securitySchemeName) + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + ) + ); + } + + +} diff --git a/src/main/java/de/szut/lf8_starter/config/SampleDataCreator.java b/src/main/java/de/szut/lf8_starter/config/SampleDataCreator.java index 373ea11..9a7b889 100644 --- a/src/main/java/de/szut/lf8_starter/config/SampleDataCreator.java +++ b/src/main/java/de/szut/lf8_starter/config/SampleDataCreator.java @@ -1,33 +1,33 @@ -package de.szut.lf8_starter.config; - - -import de.szut.lf8_starter.hello.HelloEntity; -import de.szut.lf8_starter.hello.HelloRepository; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -@Component -public class SampleDataCreator implements ApplicationRunner { - - private HelloRepository repository; - - public SampleDataCreator(HelloRepository repository) { - this.repository = repository; - } - - public void run(ApplicationArguments args) { - repository.save(new HelloEntity("Hallo Welt!")); - repository.save(new HelloEntity("Schöner Tag heute")); - repository.save(new HelloEntity("FooBar")); - - } - - @Bean - public RestTemplate restTemplate() { - return new RestTemplate(); - } - -} +package de.szut.lf8_starter.config; + + +import de.szut.lf8_starter.hello.HelloEntity; +import de.szut.lf8_starter.hello.HelloRepository; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +public class SampleDataCreator implements ApplicationRunner { + + private HelloRepository repository; + + public SampleDataCreator(HelloRepository repository) { + this.repository = repository; + } + + public void run(ApplicationArguments args) { + repository.save(new HelloEntity("Hallo Welt!")); + repository.save(new HelloEntity("Schöner Tag heute")); + repository.save(new HelloEntity("FooBar")); + + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + +} diff --git a/src/main/java/de/szut/lf8_starter/employee/EmployeeService.java b/src/main/java/de/szut/lf8_starter/employee/EmployeeService.java deleted file mode 100644 index d126288..0000000 --- a/src/main/java/de/szut/lf8_starter/employee/EmployeeService.java +++ /dev/null @@ -1,73 +0,0 @@ -package de.szut.lf8_starter.employee; - -import de.szut.lf8_starter.exceptionHandling.ResourceNotFoundException; -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectRepository; -import de.szut.lf8_starter.project.dto.employee.GetEmployeeDto; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import de.szut.lf8_starter.project.mapper.ProjectMapper; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.stereotype.Service; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestTemplate; - -import java.util.ArrayList; -import java.util.List; - -@Service -public class EmployeeService { - private final RestTemplate restTemplate; - private final ProjectRepository projectRepository; - private final ProjectMapper projectMapper; - - public EmployeeService(RestTemplate restTemplate, ProjectRepository projectRepository, ProjectMapper projectMapper) { - this.restTemplate = restTemplate; - this.projectRepository = projectRepository; - this.projectMapper = projectMapper; - } - - public boolean employeeExists(String accessToken, Long employeeId) { - HttpHeaders headers = new HttpHeaders(); - headers.setBearerAuth(accessToken.replace("Bearer ", "")); - - HttpEntity requestEntity = new HttpEntity<>(headers); - - String url = "https://employee.szut.dev/employees/" + employeeId; - - try { - restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); - } catch (HttpClientErrorException.NotFound e) { - return false; - } - - return true; - } - - public GetEmployeeDto getEmployee(String accessToken, Long employeeId) { - HttpHeaders headers = new HttpHeaders(); - headers.setBearerAuth(accessToken.replace("Bearer ", "")); - - HttpEntity requestEntity = new HttpEntity<>(headers); - - String url = "https://employee.szut.dev/employees/" + employeeId; - - try { - return restTemplate.exchange(url, HttpMethod.GET, requestEntity, GetEmployeeDto.class).getBody(); - } catch (HttpClientErrorException.NotFound e) { - throw new ResourceNotFoundException("Employee not found"); - } - } - - public List getProjects(Long employeeId) { - ArrayList projects = this.projectRepository.findAllByEmployeeId(employeeId); - ArrayList projectDtos = new ArrayList<>(); - - for (ProjectEntity project : projects) { - projectDtos.add(this.projectMapper.mapToGetDto(project)); - } - - return projectDtos; - } -} diff --git a/src/main/java/de/szut/lf8_starter/exceptionHandling/GlobalExceptionHandler.java b/src/main/java/de/szut/lf8_starter/exceptionHandling/GlobalExceptionHandler.java index 5327d4f..68a15a7 100644 --- a/src/main/java/de/szut/lf8_starter/exceptionHandling/GlobalExceptionHandler.java +++ b/src/main/java/de/szut/lf8_starter/exceptionHandling/GlobalExceptionHandler.java @@ -1,59 +1,51 @@ -package de.szut.lf8_starter.exceptionHandling; - -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import jakarta.validation.ConstraintViolationException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; - -import java.util.Date; - -@ControllerAdvice -@ApiResponses(value = { - @ApiResponse(responseCode = "500", description = "invalid JSON posted", - content = @Content) -}) -public class GlobalExceptionHandler { - - @ExceptionHandler(ResourceNotFoundException.class) - public ResponseEntity handleHelloEntityNotFoundException(ResourceNotFoundException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity handleAllOtherExceptions(Exception ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getClass() + " " + ex.getMessage(), request.getDescription(false)); - - return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - - return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(HttpMessageNotReadableException.class) - public ResponseEntity handleHttpMessageNotReadableException(HttpMessageNotReadableException ex, WebRequest request) { - ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); - - return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(ConstraintViolationException.class) - public ResponseEntity handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) { - String errorMessage = ex.getConstraintViolations().stream().findFirst().get().getMessage(); - - ErrorDetails errorDetails = new ErrorDetails(new Date(), errorMessage, request.getDescription(false)); - - return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); - } -} +package de.szut.lf8_starter.exceptionHandling; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.ConstraintViolationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; + +import java.util.Date; + +@ControllerAdvice +@ApiResponses(value = { + @ApiResponse(responseCode = "500", description = "invalid JSON posted", + content = @Content) +}) +public class GlobalExceptionHandler { + + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity handleHelloEntityNotFoundException(ResourceNotFoundException ex, WebRequest request) { + ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); + return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleAllOtherExceptions(Exception ex, WebRequest request) { + ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getClass() + " " + ex.getMessage(), request.getDescription(false)); + + return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, WebRequest request) { + ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); + + return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(ConstraintViolationException.class) + public ResponseEntity handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) { + String errorMessage = ex.getConstraintViolations().stream().findFirst().get().getMessage(); + + ErrorDetails errorDetails = new ErrorDetails(new Date(), errorMessage, request.getDescription(false)); + + return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/de/szut/lf8_starter/hello/HelloController.java b/src/main/java/de/szut/lf8_starter/hello/HelloController.java index f6baab4..0f665f2 100644 --- a/src/main/java/de/szut/lf8_starter/hello/HelloController.java +++ b/src/main/java/de/szut/lf8_starter/hello/HelloController.java @@ -1,62 +1,99 @@ -package de.szut.lf8_starter.hello; - - -import de.szut.lf8_starter.exceptionHandling.ResourceNotFoundException; -import de.szut.lf8_starter.hello.dto.HelloCreateDto; -import de.szut.lf8_starter.hello.dto.HelloGetDto; -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 jakarta.validation.Valid; -import org.springframework.http.HttpStatus; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequestMapping(value = "hello") -@PreAuthorize("hasAnyAuthority('user')") -public class HelloController { - private final HelloService service; - private final HelloMapper helloMapper; - - public HelloController(HelloService service, HelloMapper mappingService) { - this.service = service; - this.helloMapper = mappingService; - } - - @Operation(summary = "creates a new hello with its id and message") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "created hello", - content = {@Content(mediaType = "application/json", - schema = @Schema(implementation = HelloGetDto.class))}), - @ApiResponse(responseCode = "400", description = "invalid JSON posted", - content = @Content), - @ApiResponse(responseCode = "401", description = "not authorized", - content = @Content)}) - @PostMapping - public HelloGetDto create(@RequestBody @Valid HelloCreateDto helloCreateDto) { - HelloEntity helloEntity = this.helloMapper.mapCreateDtoToEntity(helloCreateDto); - helloEntity = this.service.create(helloEntity); - return this.helloMapper.mapToGetDto(helloEntity); - } - - @Operation(summary = "deletes a Hello by id") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "delete successful"), - @ApiResponse(responseCode = "401", description = "not authorized", - content = @Content), - @ApiResponse(responseCode = "404", description = "resource not found", - content = @Content)}) - @DeleteMapping("/{id}") - @ResponseStatus(code = HttpStatus.NO_CONTENT) - public void deleteHelloById(@PathVariable long id) { - var entity = this.service.readById(id); - if (entity == null) { - throw new ResourceNotFoundException("HelloEntity not found on id = " + id); - } else { - this.service.delete(entity); - } - } -} +package de.szut.lf8_starter.hello; + + +import de.szut.lf8_starter.exceptionHandling.ResourceNotFoundException; +import de.szut.lf8_starter.hello.dto.HelloCreateDto; +import de.szut.lf8_starter.hello.dto.HelloGetDto; +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 jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequestMapping(value = "hello") +@PreAuthorize("hasAnyAuthority('user')") +public class HelloController { + private final HelloService service; + private final HelloMapper helloMapper; + + public HelloController(HelloService service, HelloMapper mappingService) { + this.service = service; + this.helloMapper = mappingService; + } + + @Operation(summary = "creates a new hello with its id and message") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "created hello", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = HelloGetDto.class))}), + @ApiResponse(responseCode = "400", description = "invalid JSON posted", + content = @Content), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content)}) + @PostMapping + public HelloGetDto create(@RequestBody @Valid HelloCreateDto helloCreateDto) { + HelloEntity helloEntity = this.helloMapper.mapCreateDtoToEntity(helloCreateDto); + helloEntity = this.service.create(helloEntity); + return this.helloMapper.mapToGetDto(helloEntity); + } + + @Operation(summary = "delivers a list of hellos") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "list of hellos", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = HelloGetDto.class))}), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content)}) + @GetMapping + public List findAll() { + return this.service + .readAll() + .stream() + .map(e -> this.helloMapper.mapToGetDto(e)) + .collect(Collectors.toList()); + } + + @Operation(summary = "deletes a Hello by id") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "delete successful"), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content), + @ApiResponse(responseCode = "404", description = "resource not found", + content = @Content)}) + @DeleteMapping("/{id}") + @ResponseStatus(code = HttpStatus.NO_CONTENT) + public void deleteHelloById(@PathVariable long id) { + var entity = this.service.readById(id); + if (entity == null) { + throw new ResourceNotFoundException("HelloEntity not found on id = " + id); + } else { + this.service.delete(entity); + } + } + + @Operation(summary = "find hellos by message") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "List of hellos who have the given message", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = HelloGetDto.class))}), + @ApiResponse(responseCode = "404", description = "qualification description does not exist", + content = @Content), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content)}) + @GetMapping("/findByMessage") + public List findAllEmployeesByQualification(@RequestParam String message) { + return this.service + .findByMessage(message) + .stream() + .map(e -> this.helloMapper.mapToGetDto(e)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/szut/lf8_starter/hello/HelloEntity.java b/src/main/java/de/szut/lf8_starter/hello/HelloEntity.java index f238e2f..1b42cfc 100644 --- a/src/main/java/de/szut/lf8_starter/hello/HelloEntity.java +++ b/src/main/java/de/szut/lf8_starter/hello/HelloEntity.java @@ -1,27 +1,27 @@ -package de.szut.lf8_starter.hello; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Setter -@Entity -@Table(name = "hello") -public class HelloEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; - - private String message; - - public HelloEntity(String message) { - this.message = message; - } -} - +package de.szut.lf8_starter.hello; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "hello") +public class HelloEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String message; + + public HelloEntity(String message) { + this.message = message; + } +} + diff --git a/src/main/java/de/szut/lf8_starter/hello/HelloMapper.java b/src/main/java/de/szut/lf8_starter/hello/HelloMapper.java index 5639671..d4feb7e 100644 --- a/src/main/java/de/szut/lf8_starter/hello/HelloMapper.java +++ b/src/main/java/de/szut/lf8_starter/hello/HelloMapper.java @@ -1,20 +1,20 @@ -package de.szut.lf8_starter.hello; - - -import de.szut.lf8_starter.hello.dto.HelloCreateDto; -import de.szut.lf8_starter.hello.dto.HelloGetDto; -import org.springframework.stereotype.Service; - -@Service -public class HelloMapper { - - public HelloGetDto mapToGetDto(HelloEntity entity) { - return new HelloGetDto(entity.getId(), entity.getMessage()); - } - - public HelloEntity mapCreateDtoToEntity(HelloCreateDto dto) { - var entity = new HelloEntity(); - entity.setMessage(dto.getMessage()); - return entity; - } -} +package de.szut.lf8_starter.hello; + + +import de.szut.lf8_starter.hello.dto.HelloCreateDto; +import de.szut.lf8_starter.hello.dto.HelloGetDto; +import org.springframework.stereotype.Service; + +@Service +public class HelloMapper { + + public HelloGetDto mapToGetDto(HelloEntity entity) { + return new HelloGetDto(entity.getId(), entity.getMessage()); + } + + public HelloEntity mapCreateDtoToEntity(HelloCreateDto dto) { + var entity = new HelloEntity(); + entity.setMessage(dto.getMessage()); + return entity; + } +} diff --git a/src/main/java/de/szut/lf8_starter/hello/HelloRepository.java b/src/main/java/de/szut/lf8_starter/hello/HelloRepository.java index a030a27..77c76e4 100644 --- a/src/main/java/de/szut/lf8_starter/hello/HelloRepository.java +++ b/src/main/java/de/szut/lf8_starter/hello/HelloRepository.java @@ -1,12 +1,12 @@ -package de.szut.lf8_starter.hello; - - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; - -public interface HelloRepository extends JpaRepository { - - - List findByMessage(String message); -} +package de.szut.lf8_starter.hello; + + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface HelloRepository extends JpaRepository { + + + List findByMessage(String message); +} diff --git a/src/main/java/de/szut/lf8_starter/hello/HelloService.java b/src/main/java/de/szut/lf8_starter/hello/HelloService.java index b608ee2..eb254e8 100644 --- a/src/main/java/de/szut/lf8_starter/hello/HelloService.java +++ b/src/main/java/de/szut/lf8_starter/hello/HelloService.java @@ -1,40 +1,40 @@ -package de.szut.lf8_starter.hello; - -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Optional; - -@Service -public class HelloService { - private final HelloRepository repository; - - public HelloService(HelloRepository repository) { - this.repository = repository; - } - - public HelloEntity create(HelloEntity entity) { - return this.repository.save(entity); - } - - public List readAll() { - return this.repository.findAll(); - } - - public HelloEntity readById(long id) { - Optional optionalQualification = this.repository.findById(id); - if (optionalQualification.isEmpty()) { - return null; - } - return optionalQualification.get(); - } - - - public void delete(HelloEntity entity) { - this.repository.delete(entity); - } - - public List findByMessage(String message) { - return this.repository.findByMessage(message); - } -} +package de.szut.lf8_starter.hello; + +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class HelloService { + private final HelloRepository repository; + + public HelloService(HelloRepository repository) { + this.repository = repository; + } + + public HelloEntity create(HelloEntity entity) { + return this.repository.save(entity); + } + + public List readAll() { + return this.repository.findAll(); + } + + public HelloEntity readById(long id) { + Optional optionalQualification = this.repository.findById(id); + if (optionalQualification.isEmpty()) { + return null; + } + return optionalQualification.get(); + } + + + public void delete(HelloEntity entity) { + this.repository.delete(entity); + } + + public List findByMessage(String message) { + return this.repository.findByMessage(message); + } +} diff --git a/src/main/java/de/szut/lf8_starter/hello/dto/HelloCreateDto.java b/src/main/java/de/szut/lf8_starter/hello/dto/HelloCreateDto.java index e0622d5..fe47d1e 100644 --- a/src/main/java/de/szut/lf8_starter/hello/dto/HelloCreateDto.java +++ b/src/main/java/de/szut/lf8_starter/hello/dto/HelloCreateDto.java @@ -1,20 +1,20 @@ -package de.szut.lf8_starter.hello.dto; - -import com.fasterxml.jackson.annotation.JsonCreator; -import jakarta.validation.constraints.Size; -import lombok.Getter; -import lombok.Setter; - - -@Getter -@Setter -public class HelloCreateDto { - - @Size(min = 3, message = "at least length of 3") - private String message; - - @JsonCreator - public HelloCreateDto(String message) { - this.message = message; - } -} +package de.szut.lf8_starter.hello.dto; + +import com.fasterxml.jackson.annotation.JsonCreator; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class HelloCreateDto { + + @Size(min = 3, message = "at least length of 3") + private String message; + + @JsonCreator + public HelloCreateDto(String message) { + this.message = message; + } +} diff --git a/src/main/java/de/szut/lf8_starter/hello/dto/HelloGetDto.java b/src/main/java/de/szut/lf8_starter/hello/dto/HelloGetDto.java index 1cc51b2..babac4f 100644 --- a/src/main/java/de/szut/lf8_starter/hello/dto/HelloGetDto.java +++ b/src/main/java/de/szut/lf8_starter/hello/dto/HelloGetDto.java @@ -1,17 +1,17 @@ -package de.szut.lf8_starter.hello.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -@AllArgsConstructor -@Getter -@Setter -public class HelloGetDto { - - private long id; - - private String message; - -} - +package de.szut.lf8_starter.hello.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class HelloGetDto { + + private long id; + + private String message; + +} + diff --git a/src/main/java/de/szut/lf8_starter/project/CreateProjectAction.java b/src/main/java/de/szut/lf8_starter/project/CreateProjectAction.java new file mode 100644 index 0000000..4158fee --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/CreateProjectAction.java @@ -0,0 +1,39 @@ +package de.szut.lf8_starter.project; + +import de.szut.lf8_starter.project.dto.CreateProjectDto; +import de.szut.lf8_starter.project.dto.GetProjectDto; +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 jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping(value = "/projects") +public class CreateProjectAction { + private final ProjectService projectService; + private final ProjectMapper projectMapper; + + public CreateProjectAction(ProjectService projectService, ProjectMapper mappingService) { + this.projectService = projectService; + this.projectMapper = mappingService; + } + + @Operation(summary = "Creates a new Project") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "created project", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class))}), + @ApiResponse(responseCode = "400", description = "invalid JSON posted", content = @Content), + @ApiResponse(responseCode = "401", description = "not authorized", content = @Content)}) + @PostMapping + @ResponseStatus(code = HttpStatus.CREATED) + public GetProjectDto create(@RequestBody @Valid CreateProjectDto createProjectDto) { + ProjectEntity projectEntity = this.projectMapper.mapCreateDtoToEntity(createProjectDto); + + projectEntity = this.projectService.create(projectEntity); + + return this.projectMapper.mapToGetDto(projectEntity); + } +} diff --git a/src/main/java/de/szut/lf8_starter/project/action/crud/GetAllProjectsAction.java b/src/main/java/de/szut/lf8_starter/project/ProjectController.java similarity index 56% rename from src/main/java/de/szut/lf8_starter/project/action/crud/GetAllProjectsAction.java rename to src/main/java/de/szut/lf8_starter/project/ProjectController.java index 97f5b9a..61ee843 100644 --- a/src/main/java/de/szut/lf8_starter/project/action/crud/GetAllProjectsAction.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectController.java @@ -1,36 +1,32 @@ -package de.szut.lf8_starter.project.action.crud; +package de.szut.lf8_starter.project; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import de.szut.lf8_starter.project.mapper.ProjectMapper; +import de.szut.lf8_starter.project.dto.GetProjectDto; 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.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping(value = "projects") -public class GetAllProjectsAction { +public class ProjectController { private final ProjectService service; private final ProjectMapper projectMapper; - - public GetAllProjectsAction(ProjectService service, 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 = GetProjectDto.class)) - }), - @ApiResponse(responseCode = "401", description = "not authorized", content = @Content)}) + @ApiResponse(responseCode = "200", description = "all projects", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = GetProjectDto.class))}), + @ApiResponse(responseCode = "401", description = "not authorized", + content = @Content)}) @GetMapping public List findAll() { return this.service diff --git a/src/main/java/de/szut/lf8_starter/project/ProjectEntity.java b/src/main/java/de/szut/lf8_starter/project/ProjectEntity.java index 6aa7127..d9c35a1 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectEntity.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectEntity.java @@ -25,7 +25,7 @@ public class ProjectEntity { private long leadingEmployee; - @ElementCollection(fetch = FetchType.EAGER) + @ElementCollection private List employees; private long contractor; 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..fa60491 --- /dev/null +++ b/src/main/java/de/szut/lf8_starter/project/ProjectMapper.java @@ -0,0 +1,41 @@ +package de.szut.lf8_starter.project; + +import de.szut.lf8_starter.project.dto.CreateProjectDto; +import de.szut.lf8_starter.project.dto.GetProjectDto; +import org.springframework.stereotype.Service; + +@Service +public class ProjectMapper { + public ProjectEntity mapCreateDtoToEntity(CreateProjectDto createProjectDto) { + ProjectEntity projectEntity = new ProjectEntity(); + + projectEntity.setName(createProjectDto.getName()); + projectEntity.setComment(createProjectDto.getComment()); + projectEntity.setLeadingEmployee(createProjectDto.getLeadingEmployee()); + projectEntity.setEmployees(createProjectDto.getEmployees()); + projectEntity.setContractor(createProjectDto.getContractor()); + projectEntity.setContractorName(createProjectDto.getContractorName()); + projectEntity.setStartDate(createProjectDto.getStartDate()); + projectEntity.setPlannedEndDate(createProjectDto.getPlannedEndDate()); + projectEntity.setEndDate(createProjectDto.getEndDate()); + + return projectEntity; + } + + 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()); + getProjectDto.setEmployees(projectEntity.getEmployees()); + getProjectDto.setContractor(projectEntity.getContractor()); + getProjectDto.setContractorName(projectEntity.getContractorName()); + getProjectDto.setStartDate(projectEntity.getStartDate()); + getProjectDto.setPlannedEndDate(projectEntity.getPlannedEndDate()); + getProjectDto.setEndDate(projectEntity.getEndDate()); + + return getProjectDto; + } +} 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 3b9dfb0..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,14 +1,8 @@ package de.szut.lf8_starter.project; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.ArrayList; - @Repository public interface ProjectRepository extends JpaRepository { - @Query("SELECT p FROM ProjectEntity p WHERE :employeeId MEMBER OF p.employees") - ArrayList findAllByEmployeeId(@Param("employeeId") Long employeeId); } 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 5a50454..4dc8688 100644 --- a/src/main/java/de/szut/lf8_starter/project/ProjectService.java +++ b/src/main/java/de/szut/lf8_starter/project/ProjectService.java @@ -1,50 +1,22 @@ -package de.szut.lf8_starter.project; - -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Optional; - -@Service -public class ProjectService { - private final ProjectRepository projectRepository; - - public ProjectService(ProjectRepository projectRepository) { - this.projectRepository = projectRepository; - } - - public ProjectEntity create(ProjectEntity projectEntity) { - return this.projectRepository.save(projectEntity); - } - - public List readAll() { - return this.projectRepository.findAll(); - } - - public Optional findById(Long id) { - return projectRepository.findById(id); - } - - public void update(ProjectEntity project) { - this.projectRepository.save(project); - } - - public void delete(Long id) { - this.projectRepository.deleteById(id); - } - - public boolean isOverlapping(GetProjectDto getProjectDto, ProjectEntity existingProjectEntity) { - return isDateRangeOverlapping(getProjectDto, existingProjectEntity) || isDateEqual(getProjectDto, existingProjectEntity); - } - - private boolean isDateRangeOverlapping(GetProjectDto getProjectDto, ProjectEntity existingProjectEntity) { - return getProjectDto.getStartDate().isBefore(existingProjectEntity.getPlannedEndDate()) - && getProjectDto.getPlannedEndDate().isAfter(existingProjectEntity.getStartDate()); - } - - private boolean isDateEqual(GetProjectDto getProjectDto, ProjectEntity existingProjectEntity) { - return getProjectDto.getStartDate().isEqual(existingProjectEntity.getStartDate()) - || getProjectDto.getPlannedEndDate().isEqual(existingProjectEntity.getPlannedEndDate()); - } -} +package de.szut.lf8_starter.project; + +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ProjectService { + private final ProjectRepository projectRepository; + + public ProjectService(ProjectRepository projectRepository) { + this.projectRepository = projectRepository; + } + + 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/action/crud/CreateProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/crud/CreateProjectAction.java deleted file mode 100644 index 8319011..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/crud/CreateProjectAction.java +++ /dev/null @@ -1,63 +0,0 @@ -package de.szut.lf8_starter.project.action.crud; - -import de.szut.lf8_starter.employee.EmployeeService; -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.project.CreateProjectDto; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import de.szut.lf8_starter.project.mapper.ProjectMapper; -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 jakarta.validation.Valid; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequestMapping(value = "/projects") -public class CreateProjectAction { - private final EmployeeService employeeService; - private final ProjectService projectService; - private final ProjectMapper projectMapper; - - public CreateProjectAction(EmployeeService employeeService, ProjectService projectService, ProjectMapper mappingService) { - this.employeeService = employeeService; - this.projectService = projectService; - this.projectMapper = mappingService; - } - - @Operation(summary = "Creates a new Project") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "created project", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class))}), - @ApiResponse(responseCode = "400", description = "invalid JSON posted", content = @Content), - @ApiResponse(responseCode = "401", description = "not authorized", content = @Content), - @ApiResponse(responseCode = "409", description = "Project dates conflict", content = @Content) - }) - @PostMapping - @ResponseStatus(code = HttpStatus.CREATED) - public ResponseEntity create( - @RequestBody @Valid CreateProjectDto createProjectDto, - @RequestHeader("Authorization") String accessToken - ) { - ProjectEntity project = this.projectMapper.mapCreateDtoToEntity(createProjectDto); - - for (Long employeeId : createProjectDto.getEmployees()) { - if (!this.employeeService.employeeExists(accessToken, employeeId)) { - return new ResponseEntity<>("Employee with ID: " + employeeId + " not found", HttpStatus.NOT_FOUND); - } - - for (GetProjectDto getProjectDto : this.employeeService.getProjects(employeeId)) { - if (projectService.isOverlapping(getProjectDto, project)) { - return new ResponseEntity<>("Project dates conflict with an existing project for Employee with ID: " + employeeId, HttpStatus.CONFLICT); - } - } - } - - this.projectService.create(project); - - return new ResponseEntity<>(this.projectMapper.mapToGetDto(project), HttpStatus.CREATED); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/crud/GetProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/crud/GetProjectAction.java deleted file mode 100644 index 041a26d..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/crud/GetProjectAction.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.szut.lf8_starter.project.action.crud; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import de.szut.lf8_starter.project.mapper.ProjectMapper; -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.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; - -@RestController -@RequestMapping(value = "projects") -public class GetProjectAction { - private final ProjectService projectService; - private final ProjectMapper projectMapper; - - public GetProjectAction(ProjectService projectService, ProjectMapper projectMapper) { - this.projectService = projectService; - this.projectMapper = projectMapper; - } - - @Operation(summary = "Find project by ID") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Project found", content = { - @Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class)) - }), - @ApiResponse(responseCode = "404", description = "Project not found", content = @Content) - }) - @GetMapping("/{id}") - public ResponseEntity findArticleById(@PathVariable Long id) { - Optional project = this.projectService.findById(id); - - if (project.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - return new ResponseEntity<>(this.projectMapper.mapToGetDto(project.get()), HttpStatus.OK); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/crud/RemoveProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/crud/RemoveProjectAction.java deleted file mode 100644 index 49aebab..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/crud/RemoveProjectAction.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.szut.lf8_starter.project.action.crud; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; - -@RestController -@RequestMapping(value = "projects") -public class RemoveProjectAction { - private final ProjectService projectService; - - public RemoveProjectAction(ProjectService projectService) { - this.projectService = projectService; - } - - @Operation(summary = "Remove project by ID") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "Project deleted", content = {}), - @ApiResponse(responseCode = "404", description = "Project not found", content = @Content) - }) - @DeleteMapping("/{id}") - public ResponseEntity findArticleById(@PathVariable Long id) { - Optional project = this.projectService.findById(id); - if (project.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - this.projectService.delete(id); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/crud/UpdateProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/crud/UpdateProjectAction.java deleted file mode 100644 index 3a169cf..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/crud/UpdateProjectAction.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.szut.lf8_starter.project.action.crud; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import de.szut.lf8_starter.project.dto.project.UpdateProjectDto; -import de.szut.lf8_starter.project.mapper.ProjectMapper; -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 jakarta.validation.Valid; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.Optional; - -@RestController -@RequestMapping(value = "/projects") -public class UpdateProjectAction { - private final ProjectService projectService; - private final ProjectMapper projectMapper; - - public UpdateProjectAction(ProjectService projectService, ProjectMapper mappingService) { - this.projectService = projectService; - this.projectMapper = mappingService; - } - - @Operation(summary = "Update a project by ID") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Project updated successfully", - content = @Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class))), - @ApiResponse(responseCode = "404", description = "Project not found", content = @Content) - }) - @PutMapping("/{id}") - public ResponseEntity updateSupplier(@PathVariable Long id, @Valid @RequestBody UpdateProjectDto updateProjectDto) { - Optional project = this.projectService.findById(id); - - if (project.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - ProjectEntity updatedProject = this.projectMapper.mapUpdateDtoToEntity(updateProjectDto, project.get()); - this.projectService.update(updatedProject); - - return new ResponseEntity<>(this.projectMapper.mapToGetDto(updatedProject), HttpStatus.OK); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/employee/AddEmployeeToProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/employee/AddEmployeeToProjectAction.java deleted file mode 100644 index d9862e8..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/employee/AddEmployeeToProjectAction.java +++ /dev/null @@ -1,65 +0,0 @@ -package de.szut.lf8_starter.project.action.employee; - -import de.szut.lf8_starter.employee.EmployeeService; -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; - -@RestController -public class AddEmployeeToProjectAction { - private final ProjectService projectService; - private final EmployeeService employeeService; - - public AddEmployeeToProjectAction(ProjectService projectService, EmployeeService employeeService) { - this.projectService = projectService; - this.employeeService = employeeService; - } - - @Operation(summary = "Add an employee to a project") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "Employee added to project"), - @ApiResponse(responseCode = "404", description = "Project or employee not found", content = @Content), - @ApiResponse(responseCode = "409", description = "Project dates conflict", content = @Content) - }) - @PostMapping("/projects/{projectId}/employees/{employeeId}") - public ResponseEntity create( - @PathVariable Long projectId, - @PathVariable Long employeeId, - @RequestHeader("Authorization") String accessToken - ) { - Optional optionalProject = this.projectService.findById(projectId); - - if (optionalProject.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - ProjectEntity projectEntity = optionalProject.get(); - - if (!this.employeeService.employeeExists(accessToken, employeeId)) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - for (GetProjectDto getProjectDto : this.employeeService.getProjects(employeeId)) { - if (this.projectService.isOverlapping(getProjectDto, projectEntity)) { - return new ResponseEntity<>("Project dates conflict with an existing project for Employee with ID: " + employeeId, HttpStatus.CONFLICT); - } - } - - projectEntity.getEmployees().add(employeeId); - this.projectService.update(projectEntity); - - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/employee/GetEmployeeFromProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/employee/GetEmployeeFromProjectAction.java deleted file mode 100644 index f9d339c..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/employee/GetEmployeeFromProjectAction.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.szut.lf8_starter.project.action.employee; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import de.szut.lf8_starter.project.dto.employee.GetEmployeesFromProjectDto; -import de.szut.lf8_starter.project.mapper.EmployeeFromProjectMapper; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Optional; - -@RestController -public class GetEmployeeFromProjectAction { - private final ProjectService projectService; - private final EmployeeFromProjectMapper employeeFromProjectMapper; - - public GetEmployeeFromProjectAction(ProjectService projectService, EmployeeFromProjectMapper employeeFromProjectMapper) { - this.projectService = projectService; - this.employeeFromProjectMapper = employeeFromProjectMapper; - } - - @Operation(summary = "Get all employees from project") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Outputs projects with employees"), - @ApiResponse(responseCode = "404", description = "Project not found", content = @Content) - }) - @GetMapping("/projects/{projectId}/employees") - public ResponseEntity create( - @PathVariable Long projectId, - @RequestHeader("Authorization") String accessToken - ) { - Optional project = projectService.findById(projectId); - - if (project.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - GetEmployeesFromProjectDto getEmployeesFromProjectDto = this.employeeFromProjectMapper - .mapToGetEmployeesFromProjectDto(project.get(), accessToken); - - return new ResponseEntity<>(getEmployeesFromProjectDto, HttpStatus.OK); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/employee/GetProjectsFromEmployee.java b/src/main/java/de/szut/lf8_starter/project/action/employee/GetProjectsFromEmployee.java deleted file mode 100644 index baa4dea..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/employee/GetProjectsFromEmployee.java +++ /dev/null @@ -1,39 +0,0 @@ -package de.szut.lf8_starter.project.action.employee; - -import de.szut.lf8_starter.employee.EmployeeService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class GetProjectsFromEmployee { - private final EmployeeService employeeService; - - public GetProjectsFromEmployee(EmployeeService employeeService) { - this.employeeService = employeeService; - } - - @Operation(summary = "Get all projects from employee") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Get all projects from employee", content = @Content), - @ApiResponse(responseCode = "404", description = "Employee not found", content = @Content) - }) - @GetMapping("/employees/{employeeId}/projects") - public ResponseEntity create( - @PathVariable Long employeeId, - @RequestHeader("Authorization") String accessToken - ) { - if (!this.employeeService.employeeExists(accessToken, employeeId)) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - return new ResponseEntity<>(this.employeeService.getProjects(employeeId), HttpStatus.OK); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/action/employee/RemoveEmployeeFromProjectAction.java b/src/main/java/de/szut/lf8_starter/project/action/employee/RemoveEmployeeFromProjectAction.java deleted file mode 100644 index 4fec8e7..0000000 --- a/src/main/java/de/szut/lf8_starter/project/action/employee/RemoveEmployeeFromProjectAction.java +++ /dev/null @@ -1,52 +0,0 @@ -package de.szut.lf8_starter.project.action.employee; - -import de.szut.lf8_starter.employee.EmployeeService; -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.Optional; - -@RestController -public class RemoveEmployeeFromProjectAction { - private final ProjectService projectService; - private final EmployeeService employeeService; - - public RemoveEmployeeFromProjectAction(ProjectService projectService, EmployeeService employeeService) { - this.projectService = projectService; - this.employeeService = employeeService; - } - - @Operation(summary = "Remove an employee from a project") - @ApiResponses(value = { - @ApiResponse(responseCode = "204", description = "Employee removed from project"), - @ApiResponse(responseCode = "404", description = "Project or employee not found", content = @Content) - }) - @DeleteMapping("/projects/{projectId}/employees/{employeeId}") - public ResponseEntity remove( - @PathVariable Long projectId, - @PathVariable Long employeeId, - @RequestHeader("Authorization") String accessToken - ) { - Optional project = this.projectService.findById(projectId); - - if (project.isEmpty()) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - if (!this.employeeService.employeeExists(accessToken, employeeId)) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - project.get().getEmployees().remove(employeeId); - this.projectService.update(project.get()); - - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/project/CreateProjectDto.java b/src/main/java/de/szut/lf8_starter/project/dto/CreateProjectDto.java similarity index 92% rename from src/main/java/de/szut/lf8_starter/project/dto/project/CreateProjectDto.java rename to src/main/java/de/szut/lf8_starter/project/dto/CreateProjectDto.java index 8e2a2aa..64d22b7 100644 --- a/src/main/java/de/szut/lf8_starter/project/dto/project/CreateProjectDto.java +++ b/src/main/java/de/szut/lf8_starter/project/dto/CreateProjectDto.java @@ -1,45 +1,45 @@ -package de.szut.lf8_starter.project.dto.project; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Getter; -import lombok.Setter; - -import java.time.LocalDate; -import java.util.List; - -@Getter -@Setter -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class CreateProjectDto { - @NotBlank - private String name; - - @NotNull - private long leadingEmployee; - - private List employees; - - @NotNull - private long contractor; - - @NotBlank - private String contractorName; - - @NotBlank - private String comment; - - @JsonFormat(pattern = "dd.MM.yyyy") - @NotNull - private LocalDate startDate; - - @JsonFormat(pattern = "dd.MM.yyyy") - @NotNull - private LocalDate plannedEndDate; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate endDate; -} +package de.szut.lf8_starter.project.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDate; +import java.util.List; + +@Getter +@Setter +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class CreateProjectDto { + @NotBlank + private String name; + + @NotNull + private long leadingEmployee; + + private List employees; + + @NotNull + private long contractor; + + @NotBlank + private String contractorName; + + @NotBlank + private String comment; + + @JsonFormat(pattern = "dd.MM.yyyy") + @NotNull + private LocalDate startDate; + + @JsonFormat(pattern = "dd.MM.yyyy") + @NotNull + private LocalDate plannedEndDate; + + @JsonFormat(pattern = "dd.MM.yyyy") + private LocalDate endDate; +} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/project/GetProjectDto.java b/src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java similarity index 82% rename from src/main/java/de/szut/lf8_starter/project/dto/project/GetProjectDto.java rename to src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java index 89f043b..250a6a0 100644 --- a/src/main/java/de/szut/lf8_starter/project/dto/project/GetProjectDto.java +++ b/src/main/java/de/szut/lf8_starter/project/dto/GetProjectDto.java @@ -1,32 +1,34 @@ -package de.szut.lf8_starter.project.dto.project; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.Getter; -import lombok.Setter; - -import java.time.LocalDate; -import java.util.List; - -@Getter -@Setter -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class GetProjectDto { - private long id; - private String name; - private long leadingEmployee; - private List employees; - private long contractor; - private String contractorName; - private String comment; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate startDate; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate plannedEndDate; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate endDate; -} +package de.szut.lf8_starter.project.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDate; +import java.util.List; + +@Getter +@Setter +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class GetProjectDto { + private long id; + private String name; + private long leadingEmployee; + private List employees; + private long contractor; + private String contractorName; + private String comment; + + @JsonFormat(pattern = "dd.MM.yyyy") + private LocalDate startDate; + + @JsonFormat(pattern = "dd.MM.yyyy") + private LocalDate plannedEndDate; + + @JsonFormat(pattern = "dd.MM.yyyy") + private LocalDate endDate; +} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/employee/EmployeeDto.java b/src/main/java/de/szut/lf8_starter/project/dto/employee/EmployeeDto.java deleted file mode 100644 index cc4e872..0000000 --- a/src/main/java/de/szut/lf8_starter/project/dto/employee/EmployeeDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.szut.lf8_starter.project.dto.employee; - -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; - -@Getter -@Setter -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class EmployeeDto { - private long id; - private String firstName; - private String lastName; - private String street; - private String postcode; - private String city; - private String phone; - private List skillSet; -} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/employee/GetEmployeeDto.java b/src/main/java/de/szut/lf8_starter/project/dto/employee/GetEmployeeDto.java deleted file mode 100644 index fdb13a1..0000000 --- a/src/main/java/de/szut/lf8_starter/project/dto/employee/GetEmployeeDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.szut.lf8_starter.project.dto.employee; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class GetEmployeeDto { - private long id; - private GetSkillDto[] skillSet; -} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/employee/GetEmployeesFromProjectDto.java b/src/main/java/de/szut/lf8_starter/project/dto/employee/GetEmployeesFromProjectDto.java deleted file mode 100644 index df24a76..0000000 --- a/src/main/java/de/szut/lf8_starter/project/dto/employee/GetEmployeesFromProjectDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.szut.lf8_starter.project.dto.employee; - -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.Getter; -import lombok.Setter; - -import java.util.ArrayList; - -@Getter -@Setter -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class GetEmployeesFromProjectDto { - private long projectId; - private String projectDescription; - private ArrayList employees; -} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/employee/GetSkillDto.java b/src/main/java/de/szut/lf8_starter/project/dto/employee/GetSkillDto.java deleted file mode 100644 index ba91c03..0000000 --- a/src/main/java/de/szut/lf8_starter/project/dto/employee/GetSkillDto.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.szut.lf8_starter.project.dto.employee; - -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class GetSkillDto { - private String skill; -} diff --git a/src/main/java/de/szut/lf8_starter/project/dto/project/UpdateProjectDto.java b/src/main/java/de/szut/lf8_starter/project/dto/project/UpdateProjectDto.java deleted file mode 100644 index 943a62b..0000000 --- a/src/main/java/de/szut/lf8_starter/project/dto/project/UpdateProjectDto.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.szut.lf8_starter.project.dto.project; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.Getter; -import lombok.Setter; - -import java.time.LocalDate; -import java.util.List; - -@Getter -@Setter -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class UpdateProjectDto { - private String name; - - private Long leadingEmployee; - - private List employees; - - private Long contractor; - - private String contractorName; - - private String comment; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate startDate; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate plannedEndDate; - - @JsonFormat(pattern = "dd.MM.yyyy") - private LocalDate endDate; -} diff --git a/src/main/java/de/szut/lf8_starter/project/mapper/EmployeeFromProjectMapper.java b/src/main/java/de/szut/lf8_starter/project/mapper/EmployeeFromProjectMapper.java deleted file mode 100644 index 039f23c..0000000 --- a/src/main/java/de/szut/lf8_starter/project/mapper/EmployeeFromProjectMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.szut.lf8_starter.project.mapper; - -import de.szut.lf8_starter.employee.EmployeeService; -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.dto.employee.GetEmployeeDto; -import de.szut.lf8_starter.project.dto.employee.GetEmployeesFromProjectDto; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; - -@Service -public class EmployeeFromProjectMapper { - private final EmployeeService employeeService; - - public EmployeeFromProjectMapper(EmployeeService employeeService) { - this.employeeService = employeeService; - } - - public GetEmployeesFromProjectDto mapToGetEmployeesFromProjectDto(ProjectEntity projectEntity, String accessToken) { - GetEmployeesFromProjectDto getEmployeesFromProjectDto = new GetEmployeesFromProjectDto(); - getEmployeesFromProjectDto.setProjectId(projectEntity.getId()); - getEmployeesFromProjectDto.setProjectDescription(projectEntity.getComment()); - - ArrayList employeeDtos = new ArrayList<>(); - for (long id : projectEntity.getEmployees()) { - GetEmployeeDto getEmployeeDto = this.employeeService.getEmployee(accessToken, id); - - employeeDtos.add(getEmployeeDto); - } - - getEmployeesFromProjectDto.setEmployees(employeeDtos); - - return getEmployeesFromProjectDto; - } -} diff --git a/src/main/java/de/szut/lf8_starter/project/mapper/ProjectMapper.java b/src/main/java/de/szut/lf8_starter/project/mapper/ProjectMapper.java deleted file mode 100644 index 0d3b0af..0000000 --- a/src/main/java/de/szut/lf8_starter/project/mapper/ProjectMapper.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.szut.lf8_starter.project.mapper; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.dto.project.CreateProjectDto; -import de.szut.lf8_starter.project.dto.project.GetProjectDto; -import de.szut.lf8_starter.project.dto.project.UpdateProjectDto; -import org.springframework.stereotype.Service; - -@Service -public class ProjectMapper { - public ProjectEntity mapCreateDtoToEntity(CreateProjectDto createProjectDto) { - ProjectEntity projectEntity = new ProjectEntity(); - - projectEntity.setName(createProjectDto.getName()); - projectEntity.setComment(createProjectDto.getComment()); - projectEntity.setLeadingEmployee(createProjectDto.getLeadingEmployee()); - projectEntity.setEmployees(createProjectDto.getEmployees()); - projectEntity.setContractor(createProjectDto.getContractor()); - projectEntity.setContractorName(createProjectDto.getContractorName()); - projectEntity.setStartDate(createProjectDto.getStartDate()); - projectEntity.setPlannedEndDate(createProjectDto.getPlannedEndDate()); - projectEntity.setEndDate(createProjectDto.getEndDate()); - - return projectEntity; - } - - 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()); - getProjectDto.setEmployees(projectEntity.getEmployees()); - getProjectDto.setContractor(projectEntity.getContractor()); - getProjectDto.setContractorName(projectEntity.getContractorName()); - getProjectDto.setStartDate(projectEntity.getStartDate()); - getProjectDto.setPlannedEndDate(projectEntity.getPlannedEndDate()); - getProjectDto.setEndDate(projectEntity.getEndDate()); - - return getProjectDto; - } - - public ProjectEntity mapUpdateDtoToEntity(UpdateProjectDto updateProjectDto, ProjectEntity projectEntity) { - projectEntity.setName(updateProjectDto.getName() != null ? updateProjectDto.getName() : projectEntity.getName()); - projectEntity.setLeadingEmployee(updateProjectDto.getLeadingEmployee() != null ? updateProjectDto.getLeadingEmployee() : projectEntity.getLeadingEmployee()); - projectEntity.setContractor(updateProjectDto.getContractor() != null ? updateProjectDto.getContractor() : projectEntity.getContractor()); - projectEntity.setContractorName(updateProjectDto.getContractorName() != null ? updateProjectDto.getContractorName() : projectEntity.getContractorName()); - projectEntity.setComment(updateProjectDto.getComment() != null ? updateProjectDto.getComment() : projectEntity.getComment()); - projectEntity.setStartDate(updateProjectDto.getStartDate() != null ? updateProjectDto.getStartDate() : projectEntity.getStartDate()); - projectEntity.setPlannedEndDate(updateProjectDto.getPlannedEndDate() != null ? updateProjectDto.getPlannedEndDate() : projectEntity.getPlannedEndDate()); - projectEntity.setEndDate(updateProjectDto.getEndDate() != null ? updateProjectDto.getEndDate() : projectEntity.getEndDate()); - - if (updateProjectDto.getEmployees() != null) { - projectEntity.getEmployees().clear(); - - projectEntity.setEmployees(updateProjectDto.getEmployees()); - } - - return projectEntity; - } -} diff --git a/src/main/java/de/szut/lf8_starter/security/KeycloakLogoutHandler.java b/src/main/java/de/szut/lf8_starter/security/KeycloakLogoutHandler.java index b35df69..8555ef9 100644 --- a/src/main/java/de/szut/lf8_starter/security/KeycloakLogoutHandler.java +++ b/src/main/java/de/szut/lf8_starter/security/KeycloakLogoutHandler.java @@ -1,49 +1,49 @@ -package de.szut.lf8_starter.security; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.core.oidc.user.OidcUser; -import org.springframework.security.web.authentication.logout.LogoutHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponentsBuilder; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -@Slf4j -@Component -public class KeycloakLogoutHandler implements LogoutHandler { - - - private final RestTemplate restTemplate; - - public KeycloakLogoutHandler(RestTemplate restTemplate) { - this.restTemplate = restTemplate; - } - - @Override - public void logout(HttpServletRequest request, HttpServletResponse response, Authentication auth) { - logout(auth); - } - - public void logout(Authentication auth) { - logoutFromKeycloak((OidcUser) auth.getPrincipal()); - } - - private void logoutFromKeycloak(OidcUser user) { - String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout"; - UriComponentsBuilder builder = UriComponentsBuilder - .fromUriString(endSessionEndpoint) - .queryParam("id_token_hint", user.getIdToken().getTokenValue()); - - ResponseEntity logoutResponse = restTemplate.getForEntity(builder.toUriString(), String.class); - if (logoutResponse.getStatusCode().is2xxSuccessful()) { - log.info("Successfulley logged out from Keycloak"); - } else { - log.error("Could not propagate logout to Keycloak"); - } - } - -} +package de.szut.lf8_starter.security; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Slf4j +@Component +public class KeycloakLogoutHandler implements LogoutHandler { + + + private final RestTemplate restTemplate; + + public KeycloakLogoutHandler(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication auth) { + logout(request, auth); + } + + public void logout(HttpServletRequest request, Authentication auth) { + logoutFromKeycloak((OidcUser) auth.getPrincipal()); + } + + private void logoutFromKeycloak(OidcUser user) { + String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout"; + UriComponentsBuilder builder = UriComponentsBuilder + .fromUriString(endSessionEndpoint) + .queryParam("id_token_hint", user.getIdToken().getTokenValue()); + + ResponseEntity logoutResponse = restTemplate.getForEntity(builder.toUriString(), String.class); + if (logoutResponse.getStatusCode().is2xxSuccessful()) { + log.info("Successfulley logged out from Keycloak"); + } else { + log.error("Could not propagate logout to Keycloak"); + } + } + +} 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 99fbc5d..8ab3fd8 100644 --- a/src/main/java/de/szut/lf8_starter/security/KeycloakSecurityConfig.java +++ b/src/main/java/de/szut/lf8_starter/security/KeycloakSecurityConfig.java @@ -1,87 +1,98 @@ -package de.szut.lf8_starter.security; - -import java.util.*; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.session.SessionRegistry; -import org.springframework.security.core.session.SessionRegistryImpl; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; -import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; -import org.springframework.security.web.session.HttpSessionEventPublisher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; - -@Configuration -@EnableWebSecurity -class KeycloakSecurityConfig { - - private static final String REALM_ACCESS_CLAIM = "realm_access"; - private static final String ROLES_CLAIM = "roles"; - - KeycloakSecurityConfig() { - } - - @Bean - public SessionRegistry sessionRegistry() { - return new SessionRegistryImpl(); - } - - @Bean - protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { - return new RegisterSessionAuthenticationStrategy(sessionRegistry()); - } - - @Bean - public HttpSessionEventPublisher httpSessionEventPublisher() { - return new HttpSessionEventPublisher(); - } - - - @Bean - public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception { - - http.authorizeHttpRequests(auth -> auth - .requestMatchers(new AntPathRequestMatcher("/welcome")) - .permitAll() - .requestMatchers( - new AntPathRequestMatcher("/swagger"), - new AntPathRequestMatcher("/swagger-ui/**"), - new AntPathRequestMatcher("/v3/api-docs/**")) - .permitAll() - .requestMatchers(new AntPathRequestMatcher("/hello/**")) - .hasRole("user") - .requestMatchers(new AntPathRequestMatcher("/roles")) - .authenticated() - .requestMatchers(new AntPathRequestMatcher("/")) - .permitAll() - .anyRequest() - .authenticated()).oauth2ResourceServer(spec -> spec.jwt(Customizer.withDefaults())); - return http.build(); - } - - @Bean - public JwtAuthenticationConverter jwtAuthenticationConverter() { - JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); - jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwt -> { - List grantedAuthorities = new ArrayList<>(); - - Map realmAccess = jwt.getClaim(REALM_ACCESS_CLAIM); - if (realmAccess != null && realmAccess.containsKey(ROLES_CLAIM)) { - List roles = (List) realmAccess.get(ROLES_CLAIM); - for (String role : roles) { - grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + role)); - } - } - - return grantedAuthorities; - }); - return jwtAuthenticationConverter; - } -} +package de.szut.lf8_starter.security; + +import java.util.*; +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; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; +import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority; +import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; +import org.springframework.security.web.session.HttpSessionEventPublisher; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +class KeycloakSecurityConfig { + + private static final String GROUPS = "groups"; + private static final String REALM_ACCESS_CLAIM = "realm_access"; + private static final String ROLES_CLAIM = "roles"; + + private final KeycloakLogoutHandler keycloakLogoutHandler; + + KeycloakSecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) { + this.keycloakLogoutHandler = keycloakLogoutHandler; + } + + @Bean + public SessionRegistry sessionRegistry() { + return new SessionRegistryImpl(); + } + + @Bean + protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { + return new RegisterSessionAuthenticationStrategy(sessionRegistry()); + } + + @Bean + public HttpSessionEventPublisher httpSessionEventPublisher() { + return new HttpSessionEventPublisher(); + } + + + @Bean + public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception { + + http.authorizeHttpRequests(auth -> auth + .requestMatchers(new AntPathRequestMatcher("/welcome")) + .permitAll() + .requestMatchers( + new AntPathRequestMatcher("/swagger"), + new AntPathRequestMatcher("/swagger-ui/**"), + new AntPathRequestMatcher("/v3/api-docs/**")) + .permitAll() + .requestMatchers(new AntPathRequestMatcher("/hello/**")) + .hasRole("user") + .requestMatchers(new AntPathRequestMatcher("/roles")) + .authenticated() + .requestMatchers(new AntPathRequestMatcher("/")) + .permitAll() + .anyRequest() + .authenticated()).oauth2ResourceServer(spec -> spec.jwt(Customizer.withDefaults())); + return http.build(); + } + + @Bean + public JwtAuthenticationConverter jwtAuthenticationConverter() { + JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); + jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwt -> { + List grantedAuthorities = new ArrayList<>(); + + Map realmAccess = jwt.getClaim("realm_access"); + if (realmAccess != null && realmAccess.containsKey("roles")) { + List roles = (List) realmAccess.get("roles"); + for (String role : roles) { + grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + role)); + } + } + + return grantedAuthorities; + }); + return jwtAuthenticationConverter; + } +} diff --git a/src/main/java/de/szut/lf8_starter/welcome/WelcomeController.java b/src/main/java/de/szut/lf8_starter/welcome/WelcomeController.java index 41293bc..6ed067b 100644 --- a/src/main/java/de/szut/lf8_starter/welcome/WelcomeController.java +++ b/src/main/java/de/szut/lf8_starter/welcome/WelcomeController.java @@ -1,25 +1,27 @@ -package de.szut.lf8_starter.welcome; - -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collection; - -@RestController -public class WelcomeController { - - @GetMapping("/welcome") - public String welcome() { - return "welcome to lf8_starter"; - } - - @GetMapping("/roles") - public ResponseEntity> getRoles(Authentication authentication) { - return ResponseEntity.ok((Collection) authentication.getAuthorities()); - } - - -} +package de.szut.lf8_starter.welcome; + + + +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; + +@RestController +public class WelcomeController { + + @GetMapping("/welcome") + public String welcome() { + return "welcome to lf8_starter"; + } + + @GetMapping("/roles") + public ResponseEntity getRoles(Authentication authentication) { + return ResponseEntity.ok(authentication.getAuthorities()); + } + + +} diff --git a/src/test/java/de/szut/lf8_starter/Lf8StarterApplicationTests.java b/src/test/java/de/szut/lf8_starter/Lf8StarterApplicationTests.java index 942f2cb..b5c7f7b 100644 --- a/src/test/java/de/szut/lf8_starter/Lf8StarterApplicationTests.java +++ b/src/test/java/de/szut/lf8_starter/Lf8StarterApplicationTests.java @@ -2,6 +2,7 @@ package de.szut.lf8_starter; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; @SpringBootTest class Lf8StarterApplicationTests { diff --git a/src/test/java/de/szut/lf8_starter/integration/project/AddEmployeeToProjectTest.java b/src/test/java/de/szut/lf8_starter/integration/project/AddEmployeeToProjectTest.java deleted file mode 100644 index 3efc563..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/AddEmployeeToProjectTest.java +++ /dev/null @@ -1,160 +0,0 @@ -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.http.*; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class AddEmployeeToProjectTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private RestTemplate restTemplate; - - @Autowired - private ProjectRepository projectRepository; - - @Test - void addEmployeeToProjectTest() throws Exception { - ProjectEntity project = new ProjectEntity(); - 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); - - - mockMvc.perform(post("/projects/{projectId}/employees/{employeeId}", 1, 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); - - ProjectEntity updatedProject = projectRepository.findById(1L).get(); - - assert updatedProject.getEmployees().contains(312L); - } - - @Test - void addEmployeeToPastProjectTest() throws Exception { - ProjectEntity project = new ProjectEntity(); - project.setComment("past project"); - project.setContractor(1); - project.setContractorName("contractorName"); - project.setPlannedEndDate(LocalDate.of(1991, 1, 1)); - project.setLeadingEmployee(1); - project.setName("past project"); - project.setStartDate(LocalDate.of(1990, 1, 1)); - project.setEmployees(List.of(1L, 2L, 3L)); - this.projectRepository.save(project); - - mockMvc.perform(post("/projects/{projectId}/employees/{employeeId}", project.getId(), 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); - - ProjectEntity updatedProject = projectRepository.findById(project.getId()).get(); - - assert updatedProject.getEmployees().contains(312L); - } - - @Test - void addEmployeeToFutureProjectTest() throws Exception { - ProjectEntity project = new ProjectEntity(); - project.setComment("future project"); - project.setContractor(1); - project.setContractorName("contractorName"); - project.setPlannedEndDate(LocalDate.of(2101, 1, 1)); - project.setLeadingEmployee(1); - project.setName("future project"); - project.setStartDate(LocalDate.of(2100, 1, 1)); - project.setEmployees(List.of(1L, 2L, 3L)); - this.projectRepository.save(project); - - mockMvc.perform(post("/projects/{projectId}/employees/{employeeId}", project.getId(), 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); - - ProjectEntity updatedProject = projectRepository.findById(project.getId()).get(); - - assert updatedProject.getEmployees().contains(312L); - } - - @Test - void addEmployeeToProjectWithOverlappingDatesTest() throws Exception { - ProjectEntity project1 = new ProjectEntity(); - project1.setComment("project 1"); - project1.setContractor(1); - project1.setContractorName("contractorName"); - project1.setPlannedEndDate(LocalDate.of(2023, 1, 1)); - project1.setLeadingEmployee(1); - project1.setName("project 1"); - project1.setStartDate(LocalDate.of(2022, 1, 1)); - project1.setEmployees(List.of(1L, 2L, 3L)); - this.projectRepository.save(project1); - - ProjectEntity project2 = new ProjectEntity(); - project2.setComment("project 2"); - project2.setContractor(1); - project2.setContractorName("contractorName"); - project2.setPlannedEndDate(LocalDate.of(2023, 6, 1)); - project2.setLeadingEmployee(1); - project2.setName("project 2"); - project2.setStartDate(LocalDate.of(2022, 6, 1)); - project2.setEmployees(List.of(1L, 2L, 3L)); - this.projectRepository.save(project2); - - mockMvc.perform(post("/projects/{projectId}/employees/{employeeId}", project1.getId(), 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); - - mockMvc.perform(post("/projects/{projectId}/employees/{employeeId}", project2.getId(), 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isConflict()); - } - - private String getBearerToken() { - String url = "https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "password"); - map.add("client_id", "employee-management-service"); - map.add("username", "user"); - map.add("password", "test"); - - HttpEntity> request = new HttpEntity<>(map, headers); - - ResponseEntity response = this.restTemplate.exchange(url, HttpMethod.POST, request, Map.class); - - return Objects.requireNonNull(response.getBody()).get("access_token").toString(); - } -} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/CreateProjectActionTest.java b/src/test/java/de/szut/lf8_starter/integration/project/CreateProjectActionTest.java index 881b71a..06d02b6 100644 --- a/src/test/java/de/szut/lf8_starter/integration/project/CreateProjectActionTest.java +++ b/src/test/java/de/szut/lf8_starter/integration/project/CreateProjectActionTest.java @@ -1,236 +1,71 @@ -package de.szut.lf8_starter.integration.project; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectRepository; -import org.json.JSONObject; -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.http.*; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class CreateProjectActionTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private ProjectRepository projectRepository; - @Autowired - private RestTemplate restTemplate; - - @Test - void createProjectTest() throws Exception { - String content = """ - { - "name": "name", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Peter File", - "comment": "goal of project", - "start_date": "01.01.2000", - "planned_end_date": "01.01.2001" - } - """; - - final String contentAsString = this.mockMvc.perform( - post("/projects") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isCreated()) - .andExpect(jsonPath("name", is("name"))) - .andExpect(jsonPath("leading_employee", is(1))) - .andExpect(jsonPath("employees", is(List.of(312)))) - .andExpect(jsonPath("contractor", is(4))) - .andExpect(jsonPath("contractor_name", is("Peter File"))) - .andExpect(jsonPath("comment", is("goal of project"))) - .andExpect(jsonPath("start_date", is("01.01.2000"))) - .andExpect(jsonPath("planned_end_date", is("01.01.2001"))) - .andReturn() - .getResponse() - .getContentAsString(); - - final long id = Long.parseLong(new JSONObject(contentAsString).get("id").toString()); - - final Optional project = this.projectRepository.findById(id); - assertThat(project.get().getName()).isEqualTo("name"); - assertThat(project.get().getLeadingEmployee()).isEqualTo(1); - assertThat(project.get().getContractor()).isEqualTo(4); - assertThat(project.get().getContractorName()).isEqualTo("Peter File"); - assertThat(project.get().getComment()).isEqualTo("goal of project"); - assertThat(project.get().getStartDate()).isEqualTo(LocalDate.of(2000, 1, 1)); - assertThat(project.get().getPlannedEndDate()).isEqualTo(LocalDate.of(2001, 1, 1)); - } - - @Test - void createProjectShouldReturnConflictResponseOnConflictingProjects() throws Exception { - String content = """ - { - "name": "name", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Peter File", - "comment": "goal of project", - "start_date": "01.01.2000", - "planned_end_date": "01.01.2001" - } - """; - - this.mockMvc.perform( - post("/projects") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isCreated()); - - this.mockMvc.perform( - post("/projects") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isConflict()); - } - - @Test - void createProjectWithPastStartDate() throws Exception { - String content = """ - { - "name": "past project", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Past Contractor", - "comment": "past project", - "start_date": "01.01.1990", - "planned_end_date": "01.01.1991" - } - """; - - this.mockMvc.perform( - post("/projects") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isCreated()) - .andExpect(jsonPath("name", is("past project"))) - .andExpect(jsonPath("start_date", is("01.01.1990"))) - .andExpect(jsonPath("planned_end_date", is("01.01.1991"))); - } - - @Test - void createProjectWithFutureStartDate() throws Exception { - String content = """ - { - "name": "future project", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Future Contractor", - "comment": "future project", - "start_date": "01.01.2100", - "planned_end_date": "01.01.2101" - } - """; - - this.mockMvc.perform( - post("/projects") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isCreated()) - .andExpect(jsonPath("name", is("future project"))) - .andExpect(jsonPath("start_date", is("01.01.2100"))) - .andExpect(jsonPath("planned_end_date", is("01.01.2101"))); - } - - @Test - void createProjectWithOverlappingDates() throws Exception { - String content1 = """ - { - "name": "project 1", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Contractor 1", - "comment": "project 1", - "start_date": "01.01.2022", - "planned_end_date": "01.01.2023" - } - """; - - String content2 = """ - { - "name": "project 2", - "leading_employee": 1, - "employees": [312], - "contractor": 4, - "contractor_name": "Contractor 2", - "comment": "project 2", - "start_date": "01.06.2022", - "planned_end_date": "01.06.2023" - } - """; - - this.mockMvc.perform( - post("/projects") - .content(content1) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isCreated()); - - this.mockMvc.perform( - post("/projects") - .content(content2) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ) - .andExpect(status().isConflict()); - } - - private String getBearerToken() { - String url = "https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "password"); - map.add("client_id", "employee-management-service"); - map.add("username", "user"); - map.add("password", "test"); - - HttpEntity> request = new HttpEntity<>(map, headers); - - ResponseEntity response = this.restTemplate.exchange(url, HttpMethod.POST, request, Map.class); - - return Objects.requireNonNull(response.getBody()).get("access_token").toString(); - } -} - +package de.szut.lf8_starter.integration.project; + +import de.szut.lf8_starter.project.ProjectRepository; +import org.json.JSONObject; +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.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDate; +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc(addFilters = false) +public class CreateProjectActionTest { + @Autowired + private MockMvc mockMvc; + @Autowired + private ProjectRepository projectRepository; + + @Test + void createProjectTest() throws Exception { + String content = """ + { + "name": "name", + "leading_employee": 1, + "employees": [2, 3], + "contractor": 4, + "contractor_name": "Peter File", + "comment": "goal of project", + "start_date": "01.01.2000", + "planned_end_date": "01.01.2001" + } + """; + + final var contentAsString = this.mockMvc.perform( + post("/projects").content(content).contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isCreated()) + .andExpect(jsonPath("name", is("name"))) + .andExpect(jsonPath("leading_employee", is(1))) + .andExpect(jsonPath("employees", is(Arrays.asList(2, 3)))) + .andExpect(jsonPath("contractor", is(4))) + .andExpect(jsonPath("contractor_name", is("Peter File"))) + .andExpect(jsonPath("comment", is("goal of project"))) + .andExpect(jsonPath("start_date", is("01.01.2000"))) + .andExpect(jsonPath("planned_end_date", is("01.01.2001"))) + .andReturn() + .getResponse() + .getContentAsString(); + + final var id = Long.parseLong(new JSONObject(contentAsString).get("id").toString()); + + final var project = this.projectRepository.findById(id); + assertThat(project.get().getName()).isEqualTo("name"); + assertThat(project.get().getLeadingEmployee()).isEqualTo(1); + assertThat(project.get().getContractor()).isEqualTo(4); + assertThat(project.get().getContractorName()).isEqualTo("Peter File"); + assertThat(project.get().getComment()).isEqualTo("goal of project"); + assertThat(project.get().getStartDate()).isEqualTo(LocalDate.of(2000, 1, 1)); + assertThat(project.get().getPlannedEndDate()).isEqualTo(LocalDate.of(2001, 1, 1)); + } +} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/GetEmployeesFromProjectTest.java b/src/test/java/de/szut/lf8_starter/integration/project/GetEmployeesFromProjectTest.java deleted file mode 100644 index 8b73e06..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/GetEmployeesFromProjectTest.java +++ /dev/null @@ -1,84 +0,0 @@ -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.http.*; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -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 -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class GetEmployeesFromProjectTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private ProjectRepository projectRepository; - @Autowired - private RestTemplate restTemplate; - - @Test - void getEmployeesFromProjectTest() throws Exception { - ProjectEntity 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(315L)); - this.projectRepository.save(project); - - this.mockMvc.perform(get("/projects/1/employees") - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ).andExpect(status().isOk()) - .andExpect(jsonPath("project_id").value(1)) - .andExpect(jsonPath("project_description").value("comment")) - .andExpect(jsonPath("employees[0].id").value(315)) - .andExpect(jsonPath("employees[0].skillSet[0].skill").value("Product Owner")); - } - - @Test - void getEmployeesFromProjectShouldReturnNotFoundResponseWhenProjectIsNotFound() throws Exception { - this.mockMvc.perform(get("/projects/1111/employees") - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ).andExpect(status().isNotFound()); - } - - private String getBearerToken() { - String url = "https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "password"); - map.add("client_id", "employee-management-service"); - map.add("username", "user"); - map.add("password", "test"); - - HttpEntity> request = new HttpEntity<>(map, headers); - - ResponseEntity response = this.restTemplate.exchange(url, HttpMethod.POST, request, Map.class); - - return Objects.requireNonNull(response.getBody()).get("access_token").toString(); - } -} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/GetProjectActionTest.java b/src/test/java/de/szut/lf8_starter/integration/project/GetProjectActionTest.java deleted file mode 100644 index c3d2235..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/GetProjectActionTest.java +++ /dev/null @@ -1,61 +0,0 @@ -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.test.annotation.DirtiesContext; -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 -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class GetProjectActionTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private ProjectRepository projectRepository; - - @Test - void getProjectTest() throws Exception { - ProjectEntity 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/1")) - .andExpect(status().isOk()) - .andExpect(jsonPath("id").value(1)) - .andExpect(jsonPath("comment").value("comment")) - .andExpect(jsonPath("contractor").value(1)) - .andExpect(jsonPath("contractor_name").value("contractorName")) - .andExpect(jsonPath("end_date").value("01.01.2024")) - .andExpect(jsonPath("leading_employee").value(1)) - .andExpect(jsonPath("name").value("name")) - .andExpect(jsonPath("start_date").value("01.01.2021")) - .andExpect(jsonPath("employees").isArray()) - .andExpect(jsonPath("employees", hasSize(3))); - } - - @Test - void getProjectShouldReturnNotFoundResponseWhenProjectIsNotFound() throws Exception { - this.mockMvc.perform(get("/projects/1111")).andExpect(status().isNotFound()); - } -} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/GetProjectsFromEmployeeTest.java b/src/test/java/de/szut/lf8_starter/integration/project/GetProjectsFromEmployeeTest.java deleted file mode 100644 index f7282ee..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/GetProjectsFromEmployeeTest.java +++ /dev/null @@ -1,88 +0,0 @@ -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.http.*; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -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 -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class GetProjectsFromEmployeeTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private ProjectRepository projectRepository; - @Autowired - private RestTemplate restTemplate; - - @Test - void getProjectsFromEmployeeTest() throws Exception { - ProjectEntity 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(315L)); - this.projectRepository.save(project); - - this.mockMvc.perform(get("/employees/315/projects") - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ).andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id").value(1)) - .andExpect(jsonPath("$[0].name").value("name")) - .andExpect(jsonPath("$[0].leading_employee").value(1)) - .andExpect(jsonPath("$[0].employees[0]").value(315)) - .andExpect(jsonPath("$[0].contractor").value(1)) - .andExpect(jsonPath("$[0].contractor_name").value("contractorName")) - .andExpect(jsonPath("$[0].comment").value("comment")) - .andExpect(jsonPath("$[0].start_date").value("01.01.2021")); - } - - @Test - void GetProjectsFromEmployeeShouldReturnNotFoundResponseWhenEmployeeIsNotFound() throws Exception { - this.mockMvc.perform(get("/employees/1111/projects") - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - ).andExpect(status().isNotFound()); - } - - private String getBearerToken() { - String url = "https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "password"); - map.add("client_id", "employee-management-service"); - map.add("username", "user"); - map.add("password", "test"); - - HttpEntity> request = new HttpEntity<>(map, headers); - - ResponseEntity response = this.restTemplate.exchange(url, HttpMethod.POST, request, Map.class); - - return Objects.requireNonNull(response.getBody()).get("access_token").toString(); - } -} 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/ProjectFindAllSuccessTest.java b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllSuccessTest.java index e424a92..22981bb 100644 --- a/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllSuccessTest.java +++ b/src/test/java/de/szut/lf8_starter/integration/project/ProjectFindAllSuccessTest.java @@ -1,58 +1,56 @@ -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.test.annotation.DirtiesContext; -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 = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class ProjectFindAllSuccessTest { - @Autowired - private ProjectRepository projectRepository; - - @Autowired - private MockMvc mockMvc; - - @Test - void findAllProjectsTest() throws Exception { - ProjectEntity 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")) - .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].contractor_name").value("contractorName")) - .andExpect(jsonPath("$[0].end_date").value("01.01.2024")) - .andExpect(jsonPath("$[0].leading_employee").value(1)) - .andExpect(jsonPath("$[0].name").value("name")) - .andExpect(jsonPath("$[0].start_date").value("01.01.2021")) - .andExpect(jsonPath("$[0].employees").isArray()) - .andExpect(jsonPath("$[0].employees", hasSize(3))); - } -} +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.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 = false) +public class ProjectFindAllSuccessTest { + @Autowired + private ProjectRepository projectRepository; + + @Autowired + private MockMvc mockMvc; + + @Test + void findAllProjectsTest() 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")) + .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].contractor_name").value("contractorName")) + .andExpect(jsonPath("$[0].end_date").value("01.01.2024")) + .andExpect(jsonPath("$[0].leading_employee").value(1)) + .andExpect(jsonPath("$[0].name").value("name")) + .andExpect(jsonPath("$[0].start_date").value("01.01.2021")) + .andExpect(jsonPath("$[0].employees").isArray()) + .andExpect(jsonPath("$[0].employees", hasSize(3))); + } +} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/RemoveEmployeeFromProjectIntegrationTest.java b/src/test/java/de/szut/lf8_starter/integration/project/RemoveEmployeeFromProjectIntegrationTest.java deleted file mode 100644 index 4008ddb..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/RemoveEmployeeFromProjectIntegrationTest.java +++ /dev/null @@ -1,87 +0,0 @@ -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.http.*; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class RemoveEmployeeFromProjectIntegrationTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private RestTemplate restTemplate; - - @Autowired - private ProjectRepository projectRepository; - - @Test - void removeEmployeeFromProject() throws Exception { - ProjectEntity project = new ProjectEntity(); - 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, 312L)); - this.projectRepository.save(project); - - - mockMvc.perform(delete("/projects/{projectId}/employees/{employeeId}", 1, 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNoContent()); - - ProjectEntity updatedProject = projectRepository.findById(1L).get(); - - assert !updatedProject.getEmployees().contains(312L); - } - - private String getBearerToken() { - String url = "https://keycloak.szut.dev/auth/realms/szut/protocol/openid-connect/token"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap map = new LinkedMultiValueMap<>(); - map.add("grant_type", "password"); - map.add("client_id", "employee-management-service"); - map.add("username", "user"); - map.add("password", "test"); - - HttpEntity> request = new HttpEntity<>(map, headers); - - ResponseEntity response = this.restTemplate.exchange(url, HttpMethod.POST, request, Map.class); - - return Objects.requireNonNull(response.getBody()).get("access_token").toString(); - } - - @Test - void removeEmployeeShouldReturn404IfProjectNotFound() throws Exception { - mockMvc.perform(delete("/projects/{projectId}/employees/{employeeId}", 1987234987, 312) - .header(HttpHeaders.AUTHORIZATION, getBearerToken()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNotFound()); - } -} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/RemoveProjectActionTest.java b/src/test/java/de/szut/lf8_starter/integration/project/RemoveProjectActionTest.java deleted file mode 100644 index 0dd94fe..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/RemoveProjectActionTest.java +++ /dev/null @@ -1,49 +0,0 @@ -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.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; - -import java.time.LocalDate; -import java.util.List; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class RemoveProjectActionTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private ProjectRepository projectRepository; - - @Test - void deleteProjectTest() throws Exception { - ProjectEntity project = new ProjectEntity(); - 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(delete("/projects/" + project.getId())) - .andExpect(status().isNoContent()); - } - - @Test - void deleteProjectShouldReturnNotFoundResponseWhenProjectIsNotFound() throws Exception { - this.mockMvc.perform(get("/projects/2987")).andExpect(status().isNotFound()); - } -} diff --git a/src/test/java/de/szut/lf8_starter/integration/project/UpdateProjectActionTest.java b/src/test/java/de/szut/lf8_starter/integration/project/UpdateProjectActionTest.java deleted file mode 100644 index 74d889b..0000000 --- a/src/test/java/de/szut/lf8_starter/integration/project/UpdateProjectActionTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package de.szut.lf8_starter.integration.project; - -import de.szut.lf8_starter.project.ProjectEntity; -import de.szut.lf8_starter.project.ProjectRepository; -import org.json.JSONObject; -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.http.MediaType; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.web.servlet.MockMvc; - -import java.time.LocalDate; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -@AutoConfigureMockMvc(addFilters = false) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class UpdateProjectActionTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private ProjectRepository projectRepository; - - @Test - void updateProjectShouldUpdateProject() throws Exception { - ProjectEntity 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); - - String content = """ - { - "name": "updatedName", - "leading_employee": 2, - "employees": [3, 4, 5], - "contractor": 6, - "contractor_name": "Updated Contractor name", - "comment": "new goal of project", - "start_date": "01.01.2021", - "planned_end_date": "01.01.2022" - } - """; - - final String contentAsString = this.mockMvc.perform( - put("/projects/1").content(content).contentType(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk()) - .andExpect(jsonPath("name", is("updatedName"))) - .andExpect(jsonPath("leading_employee", is(2))) - .andExpect(jsonPath("employees", is(Arrays.asList(3, 4, 5)))) - .andExpect(jsonPath("contractor", is(6))) - .andExpect(jsonPath("contractor_name", is("Updated Contractor name"))) - .andExpect(jsonPath("comment", is("new goal of project"))) - .andExpect(jsonPath("start_date", is("01.01.2021"))) - .andExpect(jsonPath("planned_end_date", is("01.01.2022"))) - .andReturn() - .getResponse() - .getContentAsString(); - - final long id = Long.parseLong(new JSONObject(contentAsString).get("id").toString()); - - final Optional existingProject = this.projectRepository.findById(id); - assertThat(existingProject.get().getName()).isEqualTo("updatedName"); - assertThat(existingProject.get().getLeadingEmployee()).isEqualTo(2); - assertThat(existingProject.get().getContractor()).isEqualTo(6); - assertThat(existingProject.get().getContractorName()).isEqualTo("Updated Contractor name"); - assertThat(existingProject.get().getComment()).isEqualTo("new goal of project"); - assertThat(existingProject.get().getStartDate()).isEqualTo(LocalDate.of(2021, 1, 1)); - assertThat(existingProject.get().getPlannedEndDate()).isEqualTo(LocalDate.of(2022, 1, 1)); - - } - - @Test - void updateProjectShouldUpdateProjectPartially() throws Exception { - ProjectEntity project = new ProjectEntity(); - project.setId(1); - project.setName("name"); - project.setLeadingEmployee(1); - project.setContractor(1); - project.setComment("comment"); - project.setEmployees(List.of(1L, 2L, 3L)); - project.setContractorName("contractorName"); - project.setStartDate(LocalDate.of(2021, 1, 1)); - project.setPlannedEndDate(LocalDate.of(2023, 1, 1)); - project.setEndDate(LocalDate.of(2024, 1, 1)); - this.projectRepository.save(project); - - String content = """ - {} - """; - - final String contentAsString = this.mockMvc.perform( - put("/projects/1").content(content).contentType(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk()) - .andExpect(jsonPath("name", is("name"))) - .andExpect(jsonPath("leading_employee", is(1))) - .andExpect(jsonPath("employees", is(List.of(1, 2, 3)))) - .andExpect(jsonPath("contractor", is(1))) - .andExpect(jsonPath("contractor_name", is("contractorName"))) - .andExpect(jsonPath("comment", is("comment"))) - .andExpect(jsonPath("start_date", is("01.01.2021"))) - .andExpect(jsonPath("planned_end_date", is("01.01.2023"))) - .andExpect(jsonPath("end_date", is("01.01.2024"))) - .andReturn() - .getResponse() - .getContentAsString(); - - final long id = Long.parseLong(new JSONObject(contentAsString).get("id").toString()); - - final Optional existingProject = this.projectRepository.findById(id); - assertThat(existingProject.get().getName()).isEqualTo("name"); - assertThat(existingProject.get().getLeadingEmployee()).isEqualTo(1); - assertThat(existingProject.get().getContractor()).isEqualTo(1); - assertThat(existingProject.get().getContractorName()).isEqualTo("contractorName"); - assertThat(existingProject.get().getComment()).isEqualTo("comment"); - assertThat(existingProject.get().getStartDate()).isEqualTo(LocalDate.of(2021, 1, 1)); - assertThat(existingProject.get().getPlannedEndDate()).isEqualTo(LocalDate.of(2023, 1, 1)); - assertThat(existingProject.get().getEndDate()).isEqualTo(LocalDate.of(2024, 1, 1)); - } - - @Test - void updateProjectShouldReturnNotFoundResponseWhenProjectIsNotFound() throws Exception { - this.mockMvc.perform(put("/projects/98723498798").content("{}").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isNotFound()); - } -} diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties deleted file mode 100644 index f45162f..0000000 --- a/src/test/resources/application-test.properties +++ /dev/null @@ -1,6 +0,0 @@ -spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.jpa.hibernate.ddl-auto=create-drop \ No newline at end of file