Implement create project route

This commit is contained in:
Phan Huy Tran 2024-09-25 12:51:01 +02:00 committed by Phan Huy Tran
parent 25d7d30a7d
commit f1d17a59a5
11 changed files with 567 additions and 482 deletions

View file

@ -1,60 +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("\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")
)
);
}
}
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")
)
);
}
}

View file

@ -0,0 +1,43 @@
package de.szut.lf8_starter.project;
import com.fasterxml.jackson.annotation.JsonFormat;
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
public class GetProjectDto {
@NotBlank
private String name;
@NotNull
private long leadingEmployee;
private List<Long> employees;
@NotNull
private long contractor;
@NotBlank
private String contractorName;
@NotBlank
private String comment;
@NotNull
@JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate startDate;
@NotNull
@JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate plannedEndDate;
@NotNull
@JsonFormat(pattern = "dd.MM.yyyy")
private LocalDate endDate;
}

View file

@ -0,0 +1,42 @@
package de.szut.lf8_starter.project.dto;
import de.szut.lf8_starter.project.GetProjectDto;
import de.szut.lf8_starter.project.ProjectEntity;
import de.szut.lf8_starter.project.ProjectMapper;
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.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.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@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
public GetProjectDto create(@RequestBody @Valid CreateProjectDto createProjectDto) {
ProjectEntity projectEntity = this.projectMapper.mapCreateDtoToEntity(createProjectDto);
projectEntity = this.projectService.create(projectEntity);
return this.projectMapper.mapToGetDto(projectEntity);
}
}

View file

@ -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(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<String> 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<String> 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");
}
}
}