Compare commits

...

1 Commits

Author SHA1 Message Date
Marcel Haag a883e052e8 feat: As an user I want to see only the projects I created 2023-06-05 10:25:56 +02:00
12 changed files with 89 additions and 61 deletions

View File

@ -5,7 +5,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UserDetails
class Appuser internal constructor() : UserDetails { class Appuser internal constructor(sub: String, username: String, val token: String) : UserDetails {
var userSub = sub
var userName = username
override fun getAuthorities(): Collection<GrantedAuthority> { override fun getAuthorities(): Collection<GrantedAuthority> {
return listOf("user").stream().map { return listOf("user").stream().map {
@ -17,12 +20,17 @@ class Appuser internal constructor() : UserDetails {
}.collect(Collectors.toList()) }.collect(Collectors.toList())
} }
fun getSub(): String {
return userSub
}
override fun getPassword(): String { override fun getPassword(): String {
return "n/a" return "n/a"
} }
override fun getUsername(): String { override fun getUsername(): String {
return "n/a" return userName
} }
override fun isAccountNonExpired(): Boolean { override fun isAccountNonExpired(): Boolean {

View File

@ -9,20 +9,17 @@ import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.oauth2.jwt.Jwt import org.springframework.security.oauth2.jwt.Jwt
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toMono
import java.util.stream.Collectors import java.util.stream.Collectors
class AppuserJwtAuthConverter(private val appuserDetailsService: UserAccountDetailsService) : class AppuserJwtAuthConverter :
Converter<Jwt, Mono<AbstractAuthenticationToken>> { Converter<Jwt, Mono<AbstractAuthenticationToken>> {
override fun convert(jwt: Jwt): Mono<AbstractAuthenticationToken> { override fun convert(jwt: Jwt): Mono<AbstractAuthenticationToken> {
val authorities = extractAuthorities(jwt) val authorities = extractAuthorities(jwt)
// val sub = extractSub(jwt) val sub = extractSub(jwt)
val username = extractUserName(jwt) val username = extractUserName(jwt)
return appuserDetailsService return UsernamePasswordAuthenticationToken(Appuser(sub, username, jwt.tokenValue!!), "n/a", authorities).toMono()
.findByUsername(username)
.map { user ->
UsernamePasswordAuthenticationToken(user, "n/a", authorities);
}
} }
private fun extractSub(jwt: Jwt): String { private fun extractSub(jwt: Jwt): String {

View File

@ -1,14 +0,0 @@
package com.securityc4po.api.configuration.security
import org.springframework.security.core.userdetails.ReactiveUserDetailsService
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toMono
@Service
class UserAccountDetailsService : ReactiveUserDetailsService {
override fun findByUsername(username: String): Mono<UserDetails> {
return Appuser().toMono()
}
}

View File

@ -22,7 +22,7 @@ import org.springframework.web.cors.CorsConfiguration
@EnableReactiveMethodSecurity @EnableReactiveMethodSecurity
@Configuration @Configuration
@ComponentScan @ComponentScan
class WebSecurityConfiguration(private val userAccountDetailsService: UserAccountDetailsService) { class WebSecurityConfiguration {
@Value("\${external.issuer-uri}") @Value("\${external.issuer-uri}")
var externalIssuerUri: String? = null var externalIssuerUri: String? = null
@ -60,7 +60,7 @@ class WebSecurityConfiguration(private val userAccountDetailsService: UserAccoun
@Bean @Bean
fun appuserJwtAuthenticationConverter(): AppuserJwtAuthConverter { fun appuserJwtAuthenticationConverter(): AppuserJwtAuthConverter {
return AppuserJwtAuthConverter(userAccountDetailsService) return AppuserJwtAuthConverter()
} }
@Bean @Bean

View File

@ -24,7 +24,8 @@ data class Project(
val state: PentestState, val state: PentestState,
val version: String, val version: String,
var projectPentests: List<ProjectPentest> = emptyList(), var projectPentests: List<ProjectPentest> = emptyList(),
val createdBy: String @Indexed(background = true, unique = false)
var createdBy: String
) )
fun buildProject(body: ProjectRequestBody, projectEntity: ProjectEntity): Project { fun buildProject(body: ProjectRequestBody, projectEntity: ProjectEntity): Project {
@ -159,6 +160,21 @@ fun ProjectRequestBody.toProject(): Project {
// ToDo: Update version in backend automatically // ToDo: Update version in backend automatically
version = "1.0", version = "1.0",
// ToDo: Should be changed to SUB from Token after adding AUTH Header // ToDo: Should be changed to SUB from Token after adding AUTH Header
createdBy = UUID.randomUUID().toString() createdBy = ""
)
}
fun ProjectRequestBody.toNewProject(userId: String): Project {
return Project(
id = UUID.randomUUID().toString(),
client = this.client,
title = this.title,
createdAt = Instant.now().toString(),
tester = this.tester,
summary = this.summary,
state = this.state,
// ToDo: Update version in backend automatically
version = "1.0",
createdBy = userId
) )
} }

View File

@ -4,11 +4,13 @@ import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
import com.securityc4po.api.extensions.getLoggerFor import com.securityc4po.api.extensions.getLoggerFor
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import com.securityc4po.api.ResponseBody import com.securityc4po.api.ResponseBody
import com.securityc4po.api.configuration.security.Appuser
import com.securityc4po.api.pentest.PentestDeletionService import com.securityc4po.api.pentest.PentestDeletionService
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.switchIfEmpty import reactor.kotlin.core.publisher.switchIfEmpty
import org.springframework.security.core.annotation.AuthenticationPrincipal
@RestController @RestController
@RequestMapping("/projects") @RequestMapping("/projects")
@ -24,8 +26,12 @@ class ProjectController(private val projectService: ProjectService, private val
var logger = getLoggerFor<ProjectController>() var logger = getLoggerFor<ProjectController>()
@GetMapping @GetMapping
fun getProjects(): Mono<ResponseEntity<List<ResponseBody>>> { fun getProjects(
return projectService.getProjects().map { projectList -> @AuthenticationPrincipal user: Appuser
): Mono<ResponseEntity<List<ResponseBody>>> {
println("controller " + user.getSub())
return projectService.getProjects(user.getSub()).map { projectList ->
projectList.map { projectList.map {
it.toProjectResponseBody() it.toProjectResponseBody()
} }
@ -37,9 +43,10 @@ class ProjectController(private val projectService: ProjectService, private val
@GetMapping("/{projectId}") @GetMapping("/{projectId}")
fun getCompletedProjectById( fun getCompletedProjectById(
@PathVariable(value = "projectId") projectId: String @PathVariable(value = "projectId") projectId: String,
@AuthenticationPrincipal user: Appuser
): Mono<ResponseEntity<ResponseBody>> { ): Mono<ResponseEntity<ResponseBody>> {
return projectService.getProjectById(projectId).map { return projectService.getProjectById(projectId, user.getSub()).map {
it.toProjectCompletedPentestResponseBody() it.toProjectCompletedPentestResponseBody()
}.map { }.map {
if (it.isEmpty()) ResponseEntity.noContent().build() if (it.isEmpty()) ResponseEntity.noContent().build()
@ -49,9 +56,10 @@ class ProjectController(private val projectService: ProjectService, private val
@GetMapping("/evaluation/{projectId}") @GetMapping("/evaluation/{projectId}")
fun getProjectById( fun getProjectById(
@PathVariable(value = "projectId") projectId: String @PathVariable(value = "projectId") projectId: String,
@AuthenticationPrincipal user: Appuser
): Mono<ResponseEntity<ResponseBody>> { ): Mono<ResponseEntity<ResponseBody>> {
return projectService.getProjectById(projectId).map { return projectService.getProjectById(projectId, user.getSub()).map {
it.toProjectEvaluatedPentestResponseBody() it.toProjectEvaluatedPentestResponseBody()
}.map { }.map {
if (it.isEmpty()) ResponseEntity.noContent().build() if (it.isEmpty()) ResponseEntity.noContent().build()
@ -61,9 +69,10 @@ class ProjectController(private val projectService: ProjectService, private val
@PostMapping @PostMapping
fun saveProject( fun saveProject(
@RequestBody body: ProjectRequestBody @RequestBody body: ProjectRequestBody,
@AuthenticationPrincipal user: Appuser
): Mono<ResponseEntity<ResponseBody>> { ): Mono<ResponseEntity<ResponseBody>> {
return this.projectService.saveProject(body).map { return this.projectService.saveProject(body, user.getSub()).map {
ResponseEntity.accepted().body(it.toProjectResponseBody()) ResponseEntity.accepted().body(it.toProjectResponseBody())
} }
} }
@ -88,9 +97,10 @@ class ProjectController(private val projectService: ProjectService, private val
@PatchMapping("/{id}") @PatchMapping("/{id}")
fun updateProject( fun updateProject(
@PathVariable(value = "id") id: String, @PathVariable(value = "id") id: String,
@AuthenticationPrincipal user: Appuser,
@RequestBody body: ProjectRequestBody @RequestBody body: ProjectRequestBody
): Mono<ResponseEntity<ResponseBody>> { ): Mono<ResponseEntity<ResponseBody>> {
return this.projectService.updateProject(id, body).map { return this.projectService.updateProject(id, body, user.getSub()).map {
ResponseEntity.accepted().body(it.toProjectResponseBody()) ResponseEntity.accepted().body(it.toProjectResponseBody())
} }
} }

View File

@ -24,8 +24,8 @@ class ProjectService(private val projectRepository: ProjectRepository) {
* @throws [EntityNotFoundException] if there are no [Project]s in collection * @throws [EntityNotFoundException] if there are no [Project]s in collection
* @return list of [Project] * @return list of [Project]
*/ */
fun getProjects(): Mono<List<Project>> { fun getProjects(userSub: String): Mono<List<Project>> {
return projectRepository.findAll().collectList().map { return projectRepository.findAll().filter { project -> project.data.createdBy == userSub }.collectList().map {
it.map { projectEntity -> projectEntity.toProject() } it.map { projectEntity -> projectEntity.toProject() }
}.switchIfEmpty { }.switchIfEmpty {
val msg = "Projects not found." val msg = "Projects not found."
@ -41,8 +41,8 @@ class ProjectService(private val projectRepository: ProjectRepository) {
* @throws [EntityNotFoundException] if there is no [Project] in collection * @throws [EntityNotFoundException] if there is no [Project] in collection
* @return [Project] * @return [Project]
*/ */
fun getProjectById(projectId: String): Mono<Project> { fun getProjectById(projectId: String, userSub: String): Mono<Project> {
return projectRepository.findProjectById(projectId).map { return projectRepository.findProjectById(projectId).filter { project -> project.data.createdBy == userSub }.map {
it.toProject() it.toProject()
}.switchIfEmpty { }.switchIfEmpty {
val msg = "Project not found." val msg = "Project not found."
@ -59,7 +59,7 @@ class ProjectService(private val projectRepository: ProjectRepository) {
* @throws [TransactionInterruptedException] if the [Project] could not be stored * @throws [TransactionInterruptedException] if the [Project] could not be stored
* @return saved [Project] * @return saved [Project]
*/ */
fun saveProject(body: ProjectRequestBody): Mono<Project> { fun saveProject(body: ProjectRequestBody, userSub: String): Mono<Project> {
validate( validate(
require = body.isValid(), require = body.isValid(),
logging = { logger.warn("Project not valid.") }, logging = { logger.warn("Project not valid.") },
@ -68,6 +68,7 @@ class ProjectService(private val projectRepository: ProjectRepository) {
) )
) )
val project = body.toProject() val project = body.toProject()
project.createdBy = userSub
val projectEntity = ProjectEntity(project) val projectEntity = ProjectEntity(project)
return projectRepository.insert(projectEntity).map { return projectRepository.insert(projectEntity).map {
it.toProject() it.toProject()
@ -110,7 +111,7 @@ class ProjectService(private val projectRepository: ProjectRepository) {
* @throws [TransactionInterruptedException] if the [Project] could not be updated * @throws [TransactionInterruptedException] if the [Project] could not be updated
* @return updated [Project] * @return updated [Project]
*/ */
fun updateProject(id: String, body: ProjectRequestBody): Mono<Project> { fun updateProject(id: String, body: ProjectRequestBody, userSub: String): Mono<Project> {
validate( validate(
require = body.isValid(), require = body.isValid(),
logging = { logger.warn("Project not valid.") }, logging = { logger.warn("Project not valid.") },

View File

@ -74,6 +74,7 @@ abstract class BaseContainerizedTest {
var token = "n/a" var token = "n/a"
var tokenAdmin = "n/a" var tokenAdmin = "n/a"
var adminSub = "n/a"
var tokenUser = "n/a" var tokenUser = "n/a"
fun getAccessToken(username: String, password: String, clientId: String, realm: String): String { fun getAccessToken(username: String, password: String, clientId: String, realm: String): String {

View File

@ -98,7 +98,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
projectPentests = emptyList<ProjectPentest>(), projectPentests = emptyList<ProjectPentest>(),
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
val projectTwo = Project( val projectTwo = Project(
id = "61360a47-796b-4b3f-abf9-c46c668596c5", id = "61360a47-796b-4b3f-abf9-c46c668596c5",
@ -110,7 +110,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
projectPentests = emptyList<ProjectPentest>(), projectPentests = emptyList<ProjectPentest>(),
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
private fun getProjectsResponse() = listOf( private fun getProjectsResponse() = listOf(
@ -245,7 +245,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
projectPentests = emptyList<ProjectPentest>(), projectPentests = emptyList<ProjectPentest>(),
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
} }
@ -315,7 +315,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
projectPentests = emptyList<ProjectPentest>(), projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
} }
@ -331,7 +331,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
projectPentests = emptyList<ProjectPentest>(), projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
val projectTwo = Project( val projectTwo = Project(
id = "61360a47-796b-4b3f-abf9-c46c668596c5", id = "61360a47-796b-4b3f-abf9-c46c668596c5",
@ -343,7 +343,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
projectPentests = emptyList<ProjectPentest>(), projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
// persist test data in database // persist test data in database
mongoTemplate.save(ProjectEntity(projectOne)) mongoTemplate.save(ProjectEntity(projectOne))
@ -352,11 +352,13 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
private fun configureAdminToken() { private fun configureAdminToken() {
tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local") tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local")
adminSub = getSubClaim(tokenAdmin)
} }
private fun cleanUp() { private fun cleanUp() {
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java) mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
tokenAdmin = "n/a" tokenAdmin = "n/a"
adminSub = "n/a"
} }
} }

View File

@ -57,6 +57,8 @@ class ProjectControllerIntTest : BaseIntTest() {
inner class GetProjects { inner class GetProjects {
@Test @Test
fun `requesting projects successfully`() { fun `requesting projects successfully`() {
println("test " + adminSub)
webTestClient.get().uri("/projects") webTestClient.get().uri("/projects")
.header("Authorization", "Bearer $tokenAdmin") .header("Authorization", "Bearer $tokenAdmin")
.exchange() .exchange()
@ -74,7 +76,7 @@ class ProjectControllerIntTest : BaseIntTest() {
summary = "Lorem Ipsum", summary = "Lorem Ipsum",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
val projectTwo = Project( val projectTwo = Project(
id = "61360a47-796b-4b3f-abf9-c46c668596c5", id = "61360a47-796b-4b3f-abf9-c46c668596c5",
@ -85,7 +87,7 @@ class ProjectControllerIntTest : BaseIntTest() {
summary = "Lorem Ipsum", summary = "Lorem Ipsum",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
private fun getProjects() = listOf( private fun getProjects() = listOf(
@ -109,8 +111,7 @@ class ProjectControllerIntTest : BaseIntTest() {
.jsonPath("$.client").isEqualTo("Novatec") .jsonPath("$.client").isEqualTo("Novatec")
.jsonPath("$.title").isEqualTo("log4j Pentest") .jsonPath("$.title").isEqualTo("log4j Pentest")
.jsonPath("$.tester").isEqualTo("Stipe") .jsonPath("$.tester").isEqualTo("Stipe")
// ToDo: Should be changed to SUB from Token after adding AUTH Header .jsonPath("$.createdBy").isEqualTo("8f725a10-bdf5-4530-a185-4627fb092d78")
/*.jsonPath("$.createdBy").isEqualTo("f8aab31f-4925-4242-a6fa-f98135b4b032")*/
} }
val project = Project( val project = Project(
@ -122,7 +123,7 @@ class ProjectControllerIntTest : BaseIntTest() {
summary = "", summary = "",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "a8891ad2-5cf5-4519-a89e-9ef8eec9e10c" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
} }
@ -157,7 +158,7 @@ class ProjectControllerIntTest : BaseIntTest() {
tester = "Elliot", tester = "Elliot",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
} }
@ -185,7 +186,7 @@ class ProjectControllerIntTest : BaseIntTest() {
tester = "Stipe_updated", tester = "Stipe_updated",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "a8891ad2-5cf5-4519-a89e-9ef8eec9e10c" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
} }
@ -200,7 +201,7 @@ class ProjectControllerIntTest : BaseIntTest() {
summary = "Lorem Ipsum", summary = "Lorem Ipsum",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
val projectTwo = Project( val projectTwo = Project(
id = "61360a47-796b-4b3f-abf9-c46c668596c5", id = "61360a47-796b-4b3f-abf9-c46c668596c5",
@ -211,7 +212,7 @@ class ProjectControllerIntTest : BaseIntTest() {
summary = "Lorem Ipsum", summary = "Lorem Ipsum",
state = PentestState.NEW, state = PentestState.NEW,
version = "1.0", version = "1.0",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" createdBy = "8f725a10-bdf5-4530-a185-4627fb092d78"
) )
// persist test data in database // persist test data in database
mongoTemplate.save(ProjectEntity(projectOne)) mongoTemplate.save(ProjectEntity(projectOne))
@ -220,11 +221,13 @@ class ProjectControllerIntTest : BaseIntTest() {
private fun configureAdminToken() { private fun configureAdminToken() {
tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local") tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local")
adminSub = getSubClaim(tokenAdmin)
} }
private fun cleanUp() { private fun cleanUp() {
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java) mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
tokenAdmin = "n/a" tokenAdmin = "n/a"
adminSub = "n/a"
} }
} }

View File

@ -72,7 +72,7 @@
"status": "PAUSED" "status": "PAUSED"
} }
], ],
"createdBy": "2b4615ec-2f58-4d6a-8543-0c764d64455a" "createdBy": "16a52c3d-998b-4f2d-badb-1f369d95a690"
}, },
"_class": "com.securityc4po.api.project.ProjectEntity" "_class": "com.securityc4po.api.project.ProjectEntity"
},{ },{
@ -91,7 +91,7 @@
"state": "NEW", "state": "NEW",
"version": "1.0", "version": "1.0",
"projectPentests": [], "projectPentests": [],
"createdBy": "5e741fe5-591f-48d1-afef-4e59ff5d8f78" "createdBy": "16a52c3d-998b-4f2d-badb-1f369d95a690"
}, },
"_class": "com.securityc4po.api.project.ProjectEntity" "_class": "com.securityc4po.api.project.ProjectEntity"
},{ },{
@ -467,7 +467,7 @@
"status": "PAUSED" "status": "PAUSED"
} }
], ],
"createdBy": "20c3059c-0b3c-4d74-9449-472bd87f3544" "createdBy": "16a52c3d-998b-4f2d-badb-1f369d95a690"
}, },
"_class": "com.securityc4po.api.project.ProjectEntity" "_class": "com.securityc4po.api.project.ProjectEntity"
}] }]

View File

@ -27,7 +27,11 @@ class ReportController(private val apiService: APIService, private val reportSer
"/{projectId}/pdf/{reportLanguage}", "/{projectId}/pdf/{reportLanguage}",
produces = [MediaType.APPLICATION_PDF_VALUE] produces = [MediaType.APPLICATION_PDF_VALUE]
) )
fun downloadPentestReportPDF(@PathVariable(value = "projectId") projectId: String, @PathVariable(value = "reportLanguage") reportLanguage: String, @AuthenticationPrincipal user: Appuser): Mono<ResponseEntity<ByteArray>> { fun downloadPentestReportPDF(
@PathVariable(value = "projectId") projectId: String,
@PathVariable(value = "reportLanguage") reportLanguage: String,
@AuthenticationPrincipal user: Appuser
): Mono<ResponseEntity<ByteArray>> {
return this.apiService.requestProjectReportDataById(projectId, user.token).flatMap {projectReport -> return this.apiService.requestProjectReportDataById(projectId, user.token).flatMap {projectReport ->
this.reportService.createReport(projectReport, "pdf", reportLanguage).map { reportClassLoaderFilePath -> this.reportService.createReport(projectReport, "pdf", reportLanguage).map { reportClassLoaderFilePath ->
ResponseEntity.ok().body(reportClassLoaderFilePath) ResponseEntity.ok().body(reportClassLoaderFilePath)