feat: As a user I want to get project data by projectId that is filled with all the necessary data for report creation
This commit is contained in:
parent
280948c470
commit
bb544c71a0
|
@ -20,7 +20,7 @@
|
|||
(click)="onClickEditPentestProject()">
|
||||
<fa-icon [icon]="fa.faEdit"
|
||||
class="element-icon fa-lg"></fa-icon>
|
||||
<span class="element-text">{{ 'global.action.edit' | translate }}</span>
|
||||
<!--<span class="element-text">{{ 'global.action.edit' | translate }}</span>-->
|
||||
</button>
|
||||
</nb-action>
|
||||
<nb-action>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
</nb-form-field>
|
||||
</div>
|
||||
<!-- Severity Layout -->
|
||||
<!-- Severity Form Field -->
|
||||
<!-- Severity Dropdown -->
|
||||
<div fxFlex class="severity-dialog">
|
||||
<label for="{{formArray[1].fieldName}}" class="label">
|
||||
{{formArray[1].labelKey | translate}}
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
}
|
||||
|
||||
.severity-0 {
|
||||
background-color: nb-theme(color-success-default);
|
||||
}
|
||||
.severity-1 {
|
||||
background-color: nb-theme(color-info-default);
|
||||
|
|
|
@ -110,7 +110,7 @@ export class FindingDialogComponent implements OnInit {
|
|||
let severityFillStatus;
|
||||
switch (value) {
|
||||
case 0: {
|
||||
severityFillStatus = 'basic';
|
||||
severityFillStatus = 'success';
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
|
@ -126,7 +126,7 @@ export class FindingDialogComponent implements OnInit {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
severityFillStatus = 'control';
|
||||
severityFillStatus = 'basic';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
.project-dialog {
|
||||
width: 40rem !important;
|
||||
height: 42.25rem;
|
||||
height: 42.5rem;
|
||||
|
||||
.project-dialog-header {
|
||||
height: 8vh;
|
||||
|
@ -32,6 +32,13 @@
|
|||
height: 8rem;
|
||||
}
|
||||
|
||||
.form-textarea:disabled {
|
||||
width: 26.75rem !important;
|
||||
// width: 30rem !important;
|
||||
background-color: nb-theme(color-basic-transparent-focus);
|
||||
height: 8rem;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
float: left;
|
||||
color: nb-theme(color-danger-default);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<ng-container [ngSwitch]="currentSeverity">
|
||||
<nb-tag-list>
|
||||
<nb-tag *ngSwitchCase="severity.LOW" status="basic" appearance="filled"
|
||||
<nb-tag *ngSwitchCase="severity.LOW" status="success" appearance="filled"
|
||||
text="{{getTranslationKey() | translate}}"></nb-tag>
|
||||
<nb-tag *ngSwitchCase="severity.MEDIUM" status="info" appearance="filled"
|
||||
text=" {{getTranslationKey() | translate}}"></nb-tag>
|
||||
|
|
|
@ -53,6 +53,40 @@
|
|||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "getProjectById",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICItdG1lbEV0ZHhGTnRSMW9aNXlRdE5jaFFpX0RVN2VNeV9YcU44aXY0S3hzIn0.eyJleHAiOjE2NzY5NzMxMTAsImlhdCI6MTY3Njk3MjgxMCwianRpIjoiNDFkMDAwNzEtNjAyYy00NmEzLThjYjctMTJlZTExYWYyZDBhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL2M0cG9fcmVhbG1fbG9jYWwiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMTBlMDZkN2EtOGRkMC00ZWNkLTg5NjMtMDU2YjQ1MDc5YzRmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYzRwb19sb2NhbCIsInNlc3Npb25fc3RhdGUiOiI5MTA5ZWU0Ni03OGEzLTRmMDUtODdhYi03NzIxNGJmNzNlZWMiLCJhbGxvd2VkLW9yaWdpbnMiOlsiKiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYzRwb191c2VyIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImM0cG9fbG9jYWwiOnsicm9sZXMiOlsidXNlciJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiOTEwOWVlNDYtNzhhMy00ZjA1LTg3YWItNzcyMTRiZjczZWVjIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoidGVzdCB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidHR0IiwiZ2l2ZW5fbmFtZSI6InRlc3QiLCJmYW1pbHlfbmFtZSI6InVzZXIifQ.hZhUBi4cGQdn3lZ1Xm1Kz2WpboiBBJCFrtODD_c4N0ZiymB0MWVc1jXzU1fQ25mZ_I9VJXqg97x_gnCM7mKJrncFxs6cj75zIeH3so1BhlcDf7q2pjIkCH1yCerPWSLtrK2pWyxTr1GyO1Cp_wqQms_7_rmpzajLzmqBGKF8vd4yAk8kHmBoGBJhRU_gVCsDnIe74in3a032---IgCJ2XA0E5yxP9oBe6_9xPuCsk82YDihbfK1ZEO-9YZt0g1Iv3y30-hG10eflftWJEMSi8Bso4H_2WSJLqy4YRuGQR0EKDiomM0deVCK9IkuaoIsdIZ8kd65YuxSnj-_ue17QTA",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "undefined",
|
||||
"type": "any"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "http://localhost:8443/projects/5a4f126c-9471-43b8-80b9-6eb02b7c35d0",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8443",
|
||||
"path": [
|
||||
"projects",
|
||||
"5a4f126c-9471-43b8-80b9-6eb02b7c35d0"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "saveProject",
|
||||
"request": {
|
||||
|
@ -699,6 +733,40 @@
|
|||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "getCompletedPentestById",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICItdG1lbEV0ZHhGTnRSMW9aNXlRdE5jaFFpX0RVN2VNeV9YcU44aXY0S3hzIn0.eyJleHAiOjE2NzY5Nzk1NjYsImlhdCI6MTY3Njk3OTI2NiwianRpIjoiNzZlYTI3N2MtNmNiMC00OGQyLTgxNzktMDEyZDE2MWU5M2EzIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL2M0cG9fcmVhbG1fbG9jYWwiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMTBlMDZkN2EtOGRkMC00ZWNkLTg5NjMtMDU2YjQ1MDc5YzRmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYzRwb19sb2NhbCIsInNlc3Npb25fc3RhdGUiOiI0ZWI0NjQwYi00MmEyLTQwZDQtOGY0Yy1lZDViN2FkNTM3YjciLCJhbGxvd2VkLW9yaWdpbnMiOlsiKiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYzRwb191c2VyIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImM0cG9fbG9jYWwiOnsicm9sZXMiOlsidXNlciJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiNGViNDY0MGItNDJhMi00MGQ0LThmNGMtZWQ1YjdhZDUzN2I3IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoidGVzdCB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidHR0IiwiZ2l2ZW5fbmFtZSI6InRlc3QiLCJmYW1pbHlfbmFtZSI6InVzZXIifQ.utN710Mq5OBUb3FBktvOZSbvRV4Mgsiel0EiNt-1hcgg_J83e_Gc2Szk1L4KZteFPjpWcvwrj_J9JdyECu2H23TbDVvtx9yU3CIFikWjwAH75YK08h0Sqv6aGZza0t7fqMe1PIeN70bV_cIvWGA6OdwwGmE3mrllBcCHrnq7_45APig7jT6-tJplt8Lf2zTf9sMm5PhvqtPL78rLdtgnLXstxr1kAKsbcc8RKOPh65ve1sBMNH8uXgCER8JDPngam5Jt-iZ6m6g_Bmy6RJWFApfFj1mE1dGoVQCsUhGkWZnApIy0PDFGs6UtsNM0pLOxuG9vQjeeq6R_IAq9Zo_3eA",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "undefined",
|
||||
"type": "any"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "http://localhost:8443/pentests/11601f51-bc17-47fd-847d-0c53df5405b5",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "8443",
|
||||
"path": [
|
||||
"pentests",
|
||||
"11601f51-bc17-47fd-847d-0c53df5405b5"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "savePentest",
|
||||
"request": {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.securityc4po.api.pentest
|
||||
|
||||
import com.securityc4po.api.ResponseBody
|
||||
import com.securityc4po.api.pentest.comment.Comment
|
||||
import com.securityc4po.api.pentest.finding.Finding
|
||||
import org.springframework.data.mongodb.core.index.Indexed
|
||||
import java.util.UUID
|
||||
|
||||
|
@ -51,6 +53,28 @@ fun Pentest.toPentestResponseBody(): ResponseBody {
|
|||
)
|
||||
}
|
||||
|
||||
data class CompletedPentest(
|
||||
val id: String,
|
||||
val projectId: String,
|
||||
val category: PentestCategory,
|
||||
val refNumber: String,
|
||||
val status: PentestStatus,
|
||||
var findings: MutableList<Finding>,
|
||||
var comments: MutableList<Comment>
|
||||
)
|
||||
|
||||
fun CompletedPentest.toCompletedPentestResponseBody(): ResponseBody {
|
||||
return mapOf(
|
||||
"id" to id,
|
||||
"projectId" to projectId,
|
||||
"category" to category,
|
||||
"refNumber" to refNumber,
|
||||
"status" to status,
|
||||
"findings" to findings,
|
||||
"comments" to comments
|
||||
)
|
||||
}
|
||||
|
||||
data class PentestRequestBody(
|
||||
val projectId: String,
|
||||
val refNumber: String,
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
|||
import com.securityc4po.api.extensions.getLoggerFor
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import com.securityc4po.api.ResponseBody
|
||||
import com.securityc4po.api.pentest.comment.CommentService
|
||||
import com.securityc4po.api.pentest.finding.FindingService
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.http.ResponseEntity.noContent
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
@ -18,7 +20,7 @@ import reactor.core.publisher.Mono
|
|||
methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH]
|
||||
)
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
class PentestController(private val pentestService: PentestService) {
|
||||
class PentestController(private val pentestService: PentestService, private val pentestReportService: PentestReportService) {
|
||||
|
||||
var logger = getLoggerFor<PentestController>()
|
||||
|
||||
|
@ -37,15 +39,14 @@ class PentestController(private val pentestService: PentestService) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Todo: Add API
|
||||
@GetMapping
|
||||
fun getPentestById(
|
||||
@RequestParam("pentestId") pentestId: String
|
||||
): Mono<ResponseEntity<List<ResponseBody>>> {
|
||||
return pentestService.getPentest(pentestId).map {
|
||||
ResponseEntity.ok(it)
|
||||
@GetMapping("/{pentestId}")
|
||||
fun getCompletedPentestById(
|
||||
@PathVariable(value = "pentestId") pentestId: String
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return pentestReportService.getCompletedPentest(pentestId).map {
|
||||
ResponseEntity.ok(it.toCompletedPentestResponseBody())
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@PostMapping("/{projectId}")
|
||||
fun savePentest(
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.securityc4po.api.pentest
|
|||
import com.securityc4po.api.BaseEntity
|
||||
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.pentest.comment.Comment
|
||||
import com.securityc4po.api.pentest.finding.Finding
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.springframework.data.mongodb.core.mapping.Document
|
||||
|
||||
|
@ -23,6 +25,18 @@ fun PentestEntity.toPentest(): Pentest {
|
|||
)
|
||||
}
|
||||
|
||||
fun PentestEntity.toCompletedPentest(): CompletedPentest {
|
||||
return CompletedPentest(
|
||||
this.data.id,
|
||||
this.data.projectId,
|
||||
this.data.category,
|
||||
this.data.refNumber,
|
||||
this.data.status,
|
||||
mutableListOf<Finding>(),
|
||||
mutableListOf<Comment>()
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION, MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
fun List<PentestEntity>.toPentests(): List<Pentest> {
|
||||
return this.map {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package com.securityc4po.api.pentest
|
||||
|
||||
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.configuration.error.handler.EntityNotFoundException
|
||||
import com.securityc4po.api.configuration.error.handler.Errorcode
|
||||
import com.securityc4po.api.extensions.getLoggerFor
|
||||
import com.securityc4po.api.pentest.comment.CommentService
|
||||
import com.securityc4po.api.pentest.finding.Finding
|
||||
import com.securityc4po.api.pentest.finding.FindingService
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.springframework.stereotype.Service
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.core.scheduler.Schedulers
|
||||
import reactor.kotlin.core.publisher.switchIfEmpty
|
||||
import reactor.kotlin.core.publisher.toMono
|
||||
|
||||
@Service
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION, MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
class PentestReportService(
|
||||
private val pentestRepository: PentestRepository,
|
||||
private val findingService: FindingService,
|
||||
private val commentService: CommentService
|
||||
) {
|
||||
|
||||
var logger = getLoggerFor<PentestReportService>()
|
||||
|
||||
/**
|
||||
* Get [CompletedPentest]s by pentestId
|
||||
*
|
||||
* @return [CompletedPentest]
|
||||
*/
|
||||
fun getCompletedPentest(pentestId: String): Mono<CompletedPentest> {
|
||||
return pentestRepository.findPentestById(pentestId).publishOn(Schedulers.boundedElastic())
|
||||
.flatMap { pentestEntity ->
|
||||
val completedPentest = pentestEntity.toCompletedPentest()
|
||||
// Add all findings to completed Pentest
|
||||
this.findingService.getFindingsByIds(pentestEntity.data.findingIds).flatMap { listOfFindings ->
|
||||
completedPentest.findings.addAll(listOfFindings)
|
||||
// Add all comments to completed Pentest
|
||||
this.commentService.getCommentsByIds(pentestEntity.data.commentIds).map { listOfComments ->
|
||||
completedPentest.comments.addAll(listOfComments)
|
||||
// Return completed Pentest
|
||||
return@map completedPentest
|
||||
}
|
||||
}
|
||||
}.switchIfEmpty {
|
||||
logger.warn("Pentest for id $pentestId not found. Collecting pentest information not possible.")
|
||||
val msg = "Pentest for id $pentestId not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,8 @@ import com.securityc4po.api.configuration.error.handler.*
|
|||
import com.securityc4po.api.configuration.error.handler.InvalidModelException
|
||||
import com.securityc4po.api.configuration.error.handler.TransactionInterruptedException
|
||||
import com.securityc4po.api.extensions.getLoggerFor
|
||||
import com.securityc4po.api.pentest.comment.CommentService
|
||||
import com.securityc4po.api.pentest.finding.FindingService
|
||||
import com.securityc4po.api.project.*
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.springframework.stereotype.Service
|
||||
|
@ -15,7 +17,10 @@ import java.time.Instant
|
|||
|
||||
@Service
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION, MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
class PentestService(private val pentestRepository: PentestRepository, private val projectService: ProjectService) {
|
||||
class PentestService(
|
||||
private val pentestRepository: PentestRepository,
|
||||
private val projectService: ProjectService
|
||||
) {
|
||||
|
||||
var logger = getLoggerFor<PentestService>()
|
||||
|
||||
|
@ -25,12 +30,7 @@ class PentestService(private val pentestRepository: PentestRepository, private v
|
|||
* @return list of [Pentest]
|
||||
*/
|
||||
fun getPentestsForCategory(projectId: String, category: PentestCategory): Mono<List<Pentest>> {
|
||||
return pentestRepository.findPentestByProjectIdAndCategory(projectId, category)/*.switchIfEmpty {
|
||||
logger.warn("Pentests for project id $projectId not found. Collecting pentests not possible.")
|
||||
val msg = "Pentests for project id $projectId not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
|
||||
throw ex
|
||||
}*/.collectList().map {
|
||||
return pentestRepository.findPentestByProjectIdAndCategory(projectId, category).collectList().map {
|
||||
it.map { pentestEntity -> pentestEntity.toPentest() }
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class PentestService(private val pentestRepository: PentestRepository, private v
|
|||
}.flatMap { currentPentestEntity: PentestEntity ->
|
||||
currentPentestEntity.lastModified = Instant.now()
|
||||
currentPentestEntity.data = buildPentest(body, currentPentestEntity)
|
||||
pentestRepository.save(currentPentestEntity).flatMap {newPentestEntity: PentestEntity ->
|
||||
pentestRepository.save(currentPentestEntity).flatMap { newPentestEntity: PentestEntity ->
|
||||
val pentest = newPentestEntity.toPentest()
|
||||
// After successfully saving pentest add id and status to project
|
||||
val projectPentest = ProjectPentest(pentestId = pentest.id, status = pentest.status)
|
||||
|
@ -122,6 +122,34 @@ class PentestService(private val pentestRepository: PentestRepository, private v
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all [Finding]Id's by pentestId
|
||||
*
|
||||
* @return list of [String]
|
||||
*/
|
||||
fun getFindingIdsByPentestId(pentestId: String): Mono<List<String>> {
|
||||
return this.pentestRepository.findPentestById(pentestId).switchIfEmpty {
|
||||
logger.warn("Pentest with id $pentestId not found. Collecting findings not possible.")
|
||||
val msg = "Pentest with id $pentestId not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
|
||||
throw ex
|
||||
}.map { pentestEntity -> pentestEntity.data.findingIds }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all [Comment]Id's by pentestId
|
||||
*
|
||||
* @return list of [String]
|
||||
*/
|
||||
fun getCommentIdsByPentestId(pentestId: String): Mono<List<String>> {
|
||||
return this.pentestRepository.findPentestById(pentestId).switchIfEmpty {
|
||||
logger.warn("Pentest with id $pentestId not found. Collecting comments not possible.")
|
||||
val msg = "Pentest with id $pentestId not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
|
||||
throw ex
|
||||
}.map { pentestEntity -> pentestEntity.data.commentIds }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update [Pentest] for Finding
|
||||
*
|
||||
|
@ -188,20 +216,6 @@ class PentestService(private val pentestRepository: PentestRepository, private v
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all [Finding]Id's by pentestId
|
||||
*
|
||||
* @return list of [String]
|
||||
*/
|
||||
fun getFindingIdsByPentestId(pentestId: String): Mono<List<String>> {
|
||||
return this.pentestRepository.findPentestById(pentestId).switchIfEmpty {
|
||||
logger.warn("Pentest with id $pentestId not found. Collecting findings not possible.")
|
||||
val msg = "Pentest with id $pentestId not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
|
||||
throw ex
|
||||
}.map { pentestEntity -> pentestEntity.data.findingIds }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update [Pentest] for Comment
|
||||
*
|
||||
|
@ -234,20 +248,6 @@ class PentestService(private val pentestRepository: PentestRepository, private v
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all [Comment]Id's by pentestId
|
||||
*
|
||||
* @return list of [String]
|
||||
*/
|
||||
fun getCommentIdsByPentestId(pentestId: String): Mono<List<String>> {
|
||||
return this.pentestRepository.findPentestById(pentestId).switchIfEmpty {
|
||||
logger.warn("Pentest with id $pentestId not found. Collecting comments not possible.")
|
||||
val msg = "Pentest with id $pentestId not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
|
||||
throw ex
|
||||
}.map { pentestEntity -> pentestEntity.data.commentIds }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update [Pentest] for Comment
|
||||
*
|
||||
|
|
|
@ -2,7 +2,10 @@ package com.securityc4po.api.project
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat
|
||||
import com.securityc4po.api.ResponseBody
|
||||
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.pentest.PentestStatus
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.springframework.data.mongodb.core.index.Indexed
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
@ -49,6 +52,20 @@ fun Project.toProjectResponseBody(): ResponseBody {
|
|||
)
|
||||
}
|
||||
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION, MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
fun Project.toProjectCompletedPentestResponseBody(): ResponseBody {
|
||||
return mapOf(
|
||||
"id" to id,
|
||||
"client" to client,
|
||||
"title" to title,
|
||||
"createdAt" to createdAt,
|
||||
"tester" to tester,
|
||||
"summary" to summary,
|
||||
"projectPentests" to projectPentests.filter { pentest -> pentest.status == PentestStatus.COMPLETED },
|
||||
"createdBy" to createdBy
|
||||
)
|
||||
}
|
||||
|
||||
fun Project.toProjectDeleteResponseBody(): ResponseBody {
|
||||
return mapOf(
|
||||
"id" to id
|
||||
|
|
|
@ -34,7 +34,17 @@ class ProjectController(private val projectService: ProjectService) {
|
|||
}
|
||||
}
|
||||
|
||||
// ToDo: Add getProjectReportDataById Endpoint with return type ProjectReport
|
||||
@GetMapping("/{projectId}")
|
||||
fun getProjectById(
|
||||
@PathVariable(value = "projectId") projectId: String
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return projectService.getProjectById(projectId).map {
|
||||
it.toProjectCompletedPentestResponseBody()
|
||||
}.map {
|
||||
if (it.isEmpty()) ResponseEntity.noContent().build()
|
||||
else ResponseEntity.ok(it)
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
fun saveProject(
|
||||
|
|
|
@ -35,6 +35,23 @@ class ProjectService(private val projectRepository: ProjectRepository) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get [Project] by id
|
||||
*
|
||||
* @throws [EntityNotFoundException] if there is no [Project] in collection
|
||||
* @return [Project]
|
||||
*/
|
||||
fun getProjectById(projectId: String): Mono<Project> {
|
||||
return projectRepository.findProjectById(projectId).map {
|
||||
it.toProject()
|
||||
}.switchIfEmpty {
|
||||
val msg = "Project not found."
|
||||
val ex = EntityNotFoundException(msg, Errorcode.ProjectNotFound)
|
||||
logger.warn(msg, ex)
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save [Project]
|
||||
*
|
||||
|
|
|
@ -101,6 +101,20 @@
|
|||
{
|
||||
"name": "getReportPDFforProjectById",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICItdG1lbEV0ZHhGTnRSMW9aNXlRdE5jaFFpX0RVN2VNeV9YcU44aXY0S3hzIn0.eyJleHAiOjE2NzY5ODY0NTgsImlhdCI6MTY3Njk4NjE1OCwianRpIjoiMzk2NjcwM2UtMTk4My00MWU4LTkyNjAtYjhmNDExOWRmYzYwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL2M0cG9fcmVhbG1fbG9jYWwiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMTBlMDZkN2EtOGRkMC00ZWNkLTg5NjMtMDU2YjQ1MDc5YzRmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYzRwb19sb2NhbCIsInNlc3Npb25fc3RhdGUiOiIxZDBmMTk4YS03MTg5LTQ4ZmItYWQ0Ny00NTllNjVkOWU3ZjciLCJhbGxvd2VkLW9yaWdpbnMiOlsiKiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYzRwb191c2VyIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImM0cG9fbG9jYWwiOnsicm9sZXMiOlsidXNlciJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiMWQwZjE5OGEtNzE4OS00OGZiLWFkNDctNDU5ZTY1ZDllN2Y3IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoidGVzdCB1c2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidHR0IiwiZ2l2ZW5fbmFtZSI6InRlc3QiLCJmYW1pbHlfbmFtZSI6InVzZXIifQ.m1aOgFK_8ADYS6EdPLWT_wQNTsptSM9XipQQcttSd1lZKdZu6FgFVRSsW39fdgVLGurKxaglGoNgsywGDeomPS7hJuowzmYIEoDZr13MXCBqX9-YAsEDbwvrGcUI4jVXwKl8E-rTLpl3c5Ckj4tbDeUD3EuLk7yTYbkUnijqwsFlZpwJ_gbjZAfNiZCZpJlvh95cQKvFBbyzP7sfxkYikzpxY-1UHSUpoHBxJaOcJ6hoh-PIQVUw-8mvuoOyd5dMmavl5njvijr716_2loj6B6YHLueHIGlenI5Aob9DEOcL17SXivvcEyM5xTKyfqx3Jt1XY7jQ8mOIT4_iqxTc_w",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "undefined",
|
||||
"type": "any"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
|
@ -110,7 +124,7 @@
|
|||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "http://localhost:8444/reports/195809ed-9722-4ad5-a84b-0099a9a01652/pdf",
|
||||
"raw": "http://localhost:8444/reports/5a4f126c-9471-43b8-80b9-6eb02b7c35d0/pdf",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
|
@ -118,7 +132,7 @@
|
|||
"port": "8444",
|
||||
"path": [
|
||||
"reports",
|
||||
"195809ed-9722-4ad5-a84b-0099a9a01652",
|
||||
"5a4f126c-9471-43b8-80b9-6eb02b7c35d0",
|
||||
"pdf"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority
|
|||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import java.util.stream.Collectors
|
||||
|
||||
class Appuser internal constructor() : UserDetails {
|
||||
class Appuser internal constructor(sub: String, username: String, val token: String) : UserDetails {
|
||||
|
||||
override fun getAuthorities(): Collection<GrantedAuthority> {
|
||||
return listOf("user").stream().map {
|
||||
|
|
|
@ -9,20 +9,25 @@ import org.springframework.security.core.GrantedAuthority
|
|||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.oauth2.jwt.Jwt
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.kotlin.core.publisher.toMono
|
||||
import java.util.stream.Collectors
|
||||
|
||||
class AppuserJwtAuthConverter(private val appuserDetailsService: UserAccountDetailsService) :
|
||||
class AppuserJwtAuthConverter :
|
||||
Converter<Jwt, Mono<AbstractAuthenticationToken>> {
|
||||
|
||||
override fun convert(jwt: Jwt): Mono<AbstractAuthenticationToken> {
|
||||
val authorities = extractAuthorities(jwt)
|
||||
/*val authorities = extractAuthorities(jwt)
|
||||
// val sub = extractSub(jwt)
|
||||
val username = extractUserName(jwt)
|
||||
return appuserDetailsService
|
||||
.findByUsername(username)
|
||||
.map { user ->
|
||||
UsernamePasswordAuthenticationToken(user, "n/a", authorities);
|
||||
}
|
||||
}*/
|
||||
val authorities = extractAuthorities(jwt)
|
||||
val sub = extractSub(jwt)
|
||||
val username = extractUserName(jwt)
|
||||
return UsernamePasswordAuthenticationToken(Appuser(sub, username, jwt.tokenValue!!), "n/a", authorities).toMono()
|
||||
}
|
||||
|
||||
private fun extractSub(jwt: Jwt): String {
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
package com.securityc4po.reporting.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()
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ import org.springframework.web.cors.CorsConfiguration
|
|||
@EnableReactiveMethodSecurity
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
class WebSecurityConfiguration(private val userAccountDetailsService: UserAccountDetailsService) {
|
||||
class WebSecurityConfiguration {
|
||||
|
||||
@Value("\${external.issuer-uri}")
|
||||
var externalIssuerUri: String? = null
|
||||
|
@ -59,9 +59,10 @@ class WebSecurityConfiguration(private val userAccountDetailsService: UserAccoun
|
|||
|
||||
@Bean
|
||||
fun appuserJwtAuthenticationConverter(): AppuserJwtAuthConverter {
|
||||
return AppuserJwtAuthConverter(userAccountDetailsService)
|
||||
return AppuserJwtAuthConverter()
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
@Profile("COMPOSE")
|
||||
fun jwtDecoder(): ReactiveJwtDecoder {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.securityc4po.reporting.remote
|
||||
|
||||
import com.securityc4po.reporting.http.ApplicationHeaders
|
||||
import com.securityc4po.reporting.remote.model.PentestReport
|
||||
import com.securityc4po.reporting.remote.model.api.Project
|
||||
import com.securityc4po.reporting.remote.model.ProjectReport
|
||||
import org.springframework.core.ParameterizedTypeReference
|
||||
import org.springframework.stereotype.Component
|
||||
|
@ -28,10 +30,10 @@ class APIClient(
|
|||
* @param token of String
|
||||
* @return of [ProjectReport]
|
||||
*/
|
||||
fun retrieveProjectDataById(projectId: String, token: String): Mono<ProjectReport> {
|
||||
fun retrieveProjectDataById(projectId: String, token: String): Mono<Project> {
|
||||
val projectByProjectIdUriBuilder = UriComponentsBuilder
|
||||
.fromPath(apiClientCfg.projectReport.path)
|
||||
.queryParam("projectId", projectId)
|
||||
.fromPath(apiClientCfg.projects.path)
|
||||
.pathSegment(projectId)
|
||||
|
||||
return webClient.get()
|
||||
.uri(projectByProjectIdUriBuilder.toUriString())
|
||||
|
@ -39,6 +41,27 @@ class APIClient(
|
|||
it.add(ApplicationHeaders.AUTHORIZATION, "Bearer $token")
|
||||
}
|
||||
.retrieve()
|
||||
.bodyToMono(object : ParameterizedTypeReference<ProjectReport>() {})
|
||||
.bodyToMono(object : ParameterizedTypeReference<Project>() {})
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the [PentestReport] data from api service getProjectReportDataById()
|
||||
*
|
||||
* @param pentestId String id
|
||||
* @param token of String
|
||||
* @return of [PentestReport]
|
||||
*/
|
||||
fun retrievePentestDataById(pentestId: String, token: String): Mono<PentestReport> {
|
||||
val projectByProjectIdUriBuilder = UriComponentsBuilder
|
||||
.fromPath(apiClientCfg.pentests.path)
|
||||
.pathSegment(pentestId)
|
||||
|
||||
return webClient.get()
|
||||
.uri(projectByProjectIdUriBuilder.toUriString())
|
||||
.headers {
|
||||
it.add(ApplicationHeaders.AUTHORIZATION, "Bearer $token")
|
||||
}
|
||||
.retrieve()
|
||||
.bodyToMono(object : ParameterizedTypeReference<PentestReport>() {})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,7 @@ import java.net.URL
|
|||
class APIClientCfg {
|
||||
lateinit var url: URL
|
||||
var projects = ApiPath()
|
||||
var projectReport = ApiPath()
|
||||
var pentests = ApiPath()
|
||||
val findings = ApiPath()
|
||||
val comments = ApiPath()
|
||||
}
|
||||
|
||||
class ApiPath {
|
||||
|
|
|
@ -1,20 +1,62 @@
|
|||
package com.securityc4po.reporting.remote
|
||||
|
||||
import com.securityc4po.reporting.remote.model.ProjectReport
|
||||
import com.securityc4po.reporting.extensions.getLoggerFor
|
||||
import com.securityc4po.reporting.remote.model.*
|
||||
import com.securityc4po.reporting.remote.model.api.*
|
||||
import org.springframework.stereotype.Service
|
||||
import reactor.core.publisher.Flux
|
||||
import reactor.core.publisher.Mono
|
||||
|
||||
@Service
|
||||
class APIService(private val apiClient: APIClient) {
|
||||
|
||||
var logger = getLoggerFor<APIService>()
|
||||
|
||||
/**
|
||||
* Requests the complete project report data by project id
|
||||
*
|
||||
* @param id of String
|
||||
* @param token of String
|
||||
* @return [ProjectReport]
|
||||
*/
|
||||
fun requestProjectReportDataById(projectId: String, token: String): Mono<ProjectReport> {
|
||||
var completedProjectReport: ProjectReport
|
||||
return this.requestProjectDataById(projectId, token).flatMap { project: Project ->
|
||||
// Setup completed [ProjectReport] object
|
||||
completedProjectReport = project.toProjectReport()
|
||||
// Request completed pentest data and add id to [ProjectReport] object
|
||||
project.projectPentests?.let {
|
||||
Flux.fromIterable(it.asIterable()).parallel().flatMap { projectPentest ->
|
||||
this.requestPentestDataById(projectPentest.pentestId, token).map { completedPentest ->
|
||||
completedPentest
|
||||
}
|
||||
}.sequential().collectList()
|
||||
}?.map {
|
||||
completedProjectReport.projectPentestReport.addAll(it)
|
||||
completedProjectReport
|
||||
} ?: Mono.just(completedProjectReport)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the project data by id
|
||||
*
|
||||
* @param id of String
|
||||
* @param token of String
|
||||
* @return [ProjectReport]
|
||||
* @return [Project]
|
||||
*/
|
||||
fun requestProjectDataById(projectId: String, token: String): Mono<ProjectReport> {
|
||||
fun requestProjectDataById(projectId: String, token: String): Mono<Project> {
|
||||
return apiClient.retrieveProjectDataById(projectId, token)
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the pentest report data by pentest id
|
||||
*
|
||||
* @param id of String
|
||||
* @param token of String
|
||||
* @return [PentestReport]
|
||||
*/
|
||||
fun requestPentestDataById(pentestId: String, token: String): Mono<PentestReport> {
|
||||
return apiClient.retrievePentestDataById(pentestId, token)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,14 @@
|
|||
package com.securityc4po.reporting.remote.model
|
||||
|
||||
import com.securityc4po.reporting.remote.model.api.Comment
|
||||
import com.securityc4po.reporting.remote.model.api.Finding
|
||||
import com.securityc4po.reporting.remote.model.api.PentestStatus
|
||||
|
||||
data class PentestReport(
|
||||
val id: String,
|
||||
val category: String, // ToDo: Change to be PentestCategory enum if it can be read by Jasper
|
||||
val category: String,
|
||||
val refNumber: String,
|
||||
val findings: List<Finding>,
|
||||
val comments: List<Comment>,
|
||||
var status: PentestStatus
|
||||
)
|
||||
|
||||
enum class PentestStatus {
|
||||
NOT_STARTED,
|
||||
DISABLED,
|
||||
OPEN,
|
||||
IN_PROGRESS,
|
||||
COMPLETED
|
||||
}
|
||||
|
||||
enum class PentestCategory {
|
||||
INFORMATION_GATHERING,
|
||||
CONFIGURATION_AND_DEPLOY_MANAGEMENT_TESTING,
|
||||
IDENTITY_MANAGEMENT_TESTING,
|
||||
AUTHENTICATION_TESTING,
|
||||
AUTHORIZATION_TESTING,
|
||||
SESSION_MANAGEMENT_TESTING,
|
||||
INPUT_VALIDATION_TESTING,
|
||||
ERROR_HANDLING,
|
||||
CRYPTOGRAPHY,
|
||||
BUSINESS_LOGIC_TESTING,
|
||||
CLIENT_SIDE_TESTING
|
||||
}
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package com.securityc4po.reporting.remote.model
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat
|
||||
import java.time.Instant
|
||||
|
||||
data class ProjectReport(
|
||||
val id: String,
|
||||
val client: String,
|
||||
val title: String,
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
val createdAt: String = Instant.now().toString(),
|
||||
val createdAt: String,
|
||||
val tester: String,
|
||||
val summary: String? = null,
|
||||
var projectPentestReport: List<PentestReport> = emptyList(),
|
||||
var projectPentestReport: MutableList<PentestReport> = mutableListOf<PentestReport>(),
|
||||
val createdBy: String
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.reporting.remote.model
|
||||
package com.securityc4po.reporting.remote.model.api
|
||||
|
||||
data class Comment (
|
||||
val id: String,
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.reporting.remote.model
|
||||
package com.securityc4po.reporting.remote.model.api
|
||||
|
||||
data class Finding (
|
||||
val id: String,
|
|
@ -0,0 +1,9 @@
|
|||
package com.securityc4po.reporting.remote.model.api
|
||||
|
||||
enum class PentestStatus {
|
||||
NOT_STARTED,
|
||||
DISABLED,
|
||||
OPEN,
|
||||
IN_PROGRESS,
|
||||
COMPLETED
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.securityc4po.reporting.remote.model.api
|
||||
|
||||
import com.securityc4po.reporting.remote.model.PentestReport
|
||||
import com.securityc4po.reporting.remote.model.ProjectReport
|
||||
|
||||
data class Project(
|
||||
val id: String,
|
||||
val client: String,
|
||||
val title: String,
|
||||
val createdAt: String,
|
||||
val tester: String,
|
||||
val summary: String? = null,
|
||||
var projectPentests: List<ProjectPentest>? = emptyList(),
|
||||
val createdBy: String
|
||||
)
|
||||
|
||||
fun Project.toProjectReport(): ProjectReport {
|
||||
return ProjectReport(
|
||||
id = this.id,
|
||||
client = this.client,
|
||||
title = this.title,
|
||||
createdAt = this.createdAt,
|
||||
tester = this.tester,
|
||||
summary = this.summary,
|
||||
projectPentestReport = mutableListOf<PentestReport>(),
|
||||
createdBy = this.createdBy
|
||||
)
|
||||
}
|
||||
|
||||
data class ProjectPentest(
|
||||
val pentestId: String,
|
||||
var status: String
|
||||
)
|
|
@ -6,7 +6,6 @@ import com.securityc4po.reporting.configuration.security.Appuser
|
|||
import com.securityc4po.reporting.extensions.getLoggerFor
|
||||
import com.securityc4po.reporting.remote.APIService
|
||||
import com.securityc4po.reporting.remote.model.ProjectReport
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.http.ResponseEntity.notFound
|
||||
|
@ -34,13 +33,14 @@ class ReportController(private val apiService: APIService, private val reportSer
|
|||
)
|
||||
fun downloadPentestReportPDF(@PathVariable(value = "projectId") projectId: String, @AuthenticationPrincipal user: Appuser): Mono<ResponseEntity<ByteArray>> {
|
||||
// Todo: Create Report with Jasper
|
||||
// this.apiService.requestProjectDataById(projectId, user.token)
|
||||
return this.apiService.requestProjectReportDataById(projectId, user.token).flatMap {projectReport ->
|
||||
/* ToDo: remove if jsonProjectReportCollection not needed for report generation */
|
||||
val jsonProjectReportString: String =
|
||||
File("./src/test/resources/ProjectReportData.json").readText(Charsets.UTF_8)
|
||||
val jsonProjectReportCollection: ProjectReport =
|
||||
jacksonObjectMapper().readValue<ProjectReport>(jsonProjectReportString)
|
||||
// Setup headers
|
||||
return this.reportService.createReport(jsonProjectReportCollection, "pdf").map { reportClassLoaderFilePath ->
|
||||
/* jsonProjectReportCollection */
|
||||
this.reportService.createReport(projectReport, "pdf").map { reportClassLoaderFilePath ->
|
||||
ResponseEntity.ok().body(reportClassLoaderFilePath)
|
||||
}.switchIfEmpty {
|
||||
Mono.just(notFound().build<ByteArray>())
|
||||
|
@ -48,6 +48,7 @@ class ReportController(private val apiService: APIService, private val reportSer
|
|||
this.reportService.cleanUpFiles()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ToDo: Add download API for csv report
|
||||
/*
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.securityc4po.reporting.report
|
|||
|
||||
import com.securityc4po.reporting.extensions.getLoggerFor
|
||||
import com.securityc4po.reporting.remote.model.*
|
||||
import com.securityc4po.reporting.remote.model.api.Comment
|
||||
import com.securityc4po.reporting.remote.model.api.Finding
|
||||
import net.sf.jasperreports.engine.*
|
||||
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
|
||||
import org.apache.commons.io.FileUtils
|
||||
|
@ -326,19 +328,16 @@ class ReportService {
|
|||
for (i in 0 until projectReportCollection.projectPentestReport.size) {
|
||||
val projectSinglePentestReportDataSource: JRBeanCollectionDataSource =
|
||||
JRBeanCollectionDataSource(mutableListOf(projectReportCollection.projectPentestReport[i]))
|
||||
// Setup Sub-dataset for Findings of Pentest
|
||||
val pentestFindingsDataSource: JRBeanCollectionDataSource =
|
||||
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport[i].findings)
|
||||
// Setup Sub-dataset for Comments of Pentest
|
||||
// val pentestCommentsDataSource =
|
||||
// Setup Parameter & add Sub-datasets
|
||||
val parameters = HashMap<String, Any>()
|
||||
// Setup Sub-dataset for Findings of Pentest
|
||||
parameters["PentestFindingsDataSource"] =
|
||||
if (projectReportCollection.projectPentestReport[i].findings.isNotEmpty()) {
|
||||
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport[i].findings)
|
||||
} else {
|
||||
JRBeanCollectionDataSource(emptyList<Finding>())
|
||||
}
|
||||
// Setup Sub-dataset for Comments of Pentest
|
||||
parameters["PentestCommentsDataSource"] =
|
||||
if (projectReportCollection.projectPentestReport[i].comments.isNotEmpty()) {
|
||||
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport[i].comments)
|
||||
|
|
|
@ -14,10 +14,7 @@ management.endpoints.web.exposure.include=info, health, metrics
|
|||
## C4PO_ApiService ##
|
||||
api.client.url=http://localhost:8443/
|
||||
api.client.projects.path=projects
|
||||
api.client.projectReport.path=projects/report
|
||||
api.client.pentests.path=pentests
|
||||
api.client.findings.path=pentests/findings
|
||||
api.client.comments.path=pentests/comments
|
||||
|
||||
## IdentityProvider (Keycloak) ##
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/auth/realms/c4po_realm_local
|
||||
|
|
Loading…
Reference in New Issue