feat: As a developer I want to create new Projects
This commit is contained in:
parent
c7160d5340
commit
a54f064692
|
@ -10,6 +10,9 @@
|
|||
"item": [
|
||||
{
|
||||
"name": "getProjects",
|
||||
"protocolProfileBehavior": {
|
||||
"disableBodyPruning": true
|
||||
},
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "oauth2",
|
||||
|
@ -38,6 +41,43 @@
|
|||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8443/projects",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8443",
|
||||
"path": [
|
||||
"projects"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "saveProject",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"client\": \"Novatec\",\n \"title\": \"log4j Pentest\",\n \"tester\": \"Stipe\",\n \"createyBy\": \"10e06d7a-8dd0-4ecd-8963-056b45079c4f\"\n}",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:8443/projects",
|
||||
"protocol": "http",
|
||||
|
|
|
@ -39,10 +39,28 @@ include::{snippets}/getProjects/http-response.adoc[]
|
|||
|
||||
include::{snippets}/getProjects/response-fields.adoc[]
|
||||
|
||||
=== Save project
|
||||
|
||||
To save a project, call the POST request /projects
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/saveProject/http-request.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/saveProject/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/saveProject/response-fields.adoc[]
|
||||
|
||||
== Change History
|
||||
|
||||
|===
|
||||
|Date |Change
|
||||
|2021-12-22
|
||||
|Added POST endpoint to save Projects
|
||||
|2021-02-14
|
||||
|Added GET endpoint to receive Projects
|
||||
|2021-02-12
|
||||
|
|
|
@ -37,3 +37,21 @@ fun ProjectOverview.toProjectOverviewResponseBody(): ResponseBody {
|
|||
"projects" to projects
|
||||
)
|
||||
}
|
||||
|
||||
data class ProjectRequestBody(
|
||||
val client: String,
|
||||
val title: String,
|
||||
val tester: String? = null,
|
||||
val createdBy: String
|
||||
)
|
||||
|
||||
fun ProjectRequestBody.toProject(): Project {
|
||||
return Project(
|
||||
id = UUID.randomUUID().toString(),
|
||||
client = this.client,
|
||||
title = this.title,
|
||||
createdAt = Instant.now().toString(),
|
||||
tester = this.tester,
|
||||
createdBy = this.createdBy
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import reactor.core.publisher.Mono
|
|||
origins = [],
|
||||
allowCredentials = "false",
|
||||
allowedHeaders = ["*"],
|
||||
methods = [RequestMethod.GET]
|
||||
methods = [RequestMethod.GET, RequestMethod.POST]
|
||||
)
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
class ProjectController(private val projectService: ProjectService) {
|
||||
|
@ -23,12 +23,21 @@ class ProjectController(private val projectService: ProjectService) {
|
|||
|
||||
@GetMapping
|
||||
fun getProjects(): Mono<ResponseEntity<List<ResponseBody>>> {
|
||||
return projectService.getProjects().map {
|
||||
it.map {
|
||||
return projectService.getProjects().map { projectList ->
|
||||
projectList.map {
|
||||
it.toProjectResponseBody()
|
||||
}
|
||||
}.map {
|
||||
ResponseEntity.ok(it)
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
fun saveProject(
|
||||
@RequestBody body: ProjectRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.projectService.saveProject(body).map {
|
||||
ResponseEntity.accepted().body(it.toProjectResponseBody())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,4 +23,14 @@ class ProjectService(private val projectRepository: ProjectRepository) {
|
|||
it.map { projectEntity -> projectEntity.toProject() }
|
||||
}
|
||||
}
|
||||
|
||||
fun saveProject(body: ProjectRequestBody): Mono<Project> {
|
||||
val project = body.toProject()
|
||||
val projectEntity = ProjectEntity(project)
|
||||
return projectRepository.insert(projectEntity).map {
|
||||
it.toProject()
|
||||
}.doOnError {
|
||||
logger.warn("Project could not be stored in Database. Thrown exception: ", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.springframework.restdocs.operation.preprocess.Preprocessors
|
|||
import org.springframework.restdocs.payload.JsonFieldType
|
||||
import org.springframework.restdocs.payload.PayloadDocumentation
|
||||
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
|
||||
import reactor.core.publisher.Mono
|
||||
|
||||
@SuppressFBWarnings(
|
||||
SIC_INNER_SHOULD_BE_STATIC,
|
||||
|
@ -90,6 +91,43 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveProject {
|
||||
@Test
|
||||
fun saveProject() {
|
||||
webTestClient.post().uri("/projects")
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(project), ProjectRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(project))
|
||||
.consumeWith(WebTestClientRestDocumentation.document("{methodName}",
|
||||
Preprocessors.preprocessRequest(Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING).description("The id of the requested project"),
|
||||
PayloadDocumentation.fieldWithPath("client").type(JsonFieldType.STRING).description("The name of the client of the requested project"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING).description("The title of the requested project"),
|
||||
PayloadDocumentation.fieldWithPath("createdAt").type(JsonFieldType.STRING).description("The date where the project was created at"),
|
||||
PayloadDocumentation.fieldWithPath("tester").type(JsonFieldType.STRING).description("The user that is assigned as a tester in the project"),
|
||||
PayloadDocumentation.fieldWithPath("createdBy").type(JsonFieldType.STRING).description("The id of the user that created the project")
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
val project = ProjectRequestBody(
|
||||
client = "Novatec",
|
||||
title = "log4j Pentest",
|
||||
tester = "Stipe",
|
||||
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
|
||||
)
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
val projectOne = Project(
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.springframework.boot.web.server.LocalServerPort
|
|||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.data.mongodb.core.query.Query
|
||||
import org.springframework.test.web.reactive.server.WebTestClient
|
||||
import reactor.core.publisher.Mono
|
||||
import java.time.Duration
|
||||
|
||||
@SuppressFBWarnings(
|
||||
|
@ -87,6 +88,33 @@ class ProjectControllerIntTest : BaseIntTest() {
|
|||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveProject {
|
||||
@Test
|
||||
fun `save project successfully`() {
|
||||
webTestClient.post().uri("/projects")
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(project), ProjectRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(project))
|
||||
.jsonPath("$.client").isEqualTo("Novatec")
|
||||
.jsonPath("$.title").isEqualTo("log4j Pentest")
|
||||
.jsonPath("$.tester").isEqualTo("Stipe")
|
||||
.jsonPath("$.createdBy").isEqualTo("f8aab31f-4925-4242-a6fa-f98135b4b032")
|
||||
}
|
||||
|
||||
val project = Project(
|
||||
id = "4f6567a8-76fd-487b-8602-f82d0ca4d1f9",
|
||||
client = "Novatec",
|
||||
title = "log4j Pentest",
|
||||
createdAt = "2021-04-10T18:05:00Z",
|
||||
tester = "Stipe",
|
||||
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
|
||||
)
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
val projectOne = Project(
|
||||
|
|
|
@ -22,7 +22,6 @@ class ProjectServiceTest {
|
|||
inner class GetProjects {
|
||||
@Test
|
||||
fun `happy path - getProjects successfully`() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue