package com.securityc4po.api.project import com.fasterxml.jackson.annotation.JsonFormat import com.securityc4po.api.ResponseBody import com.securityc4po.api.pentest.PentestStatus import org.springframework.data.mongodb.core.index.Indexed import java.math.RoundingMode import java.text.DecimalFormat import java.time.Instant import java.util.UUID data class Project( @Indexed(background = true, unique = true) val id: String = UUID.randomUUID().toString(), 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 tester: String? = null, val projectPentests: List = emptyList(), val createdBy: String ) fun buildProject(body: ProjectRequestBody, projectEntity: ProjectEntity): Project{ return Project( id = projectEntity.data.id, client = body.client, title = body.title, createdAt = projectEntity.data.createdAt, tester = body.tester, projectPentests = projectEntity.data.projectPentests, createdBy = projectEntity.data.createdBy ) } fun Project.toProjectResponseBody(): ResponseBody { return mapOf( "id" to id, "client" to client, "title" to title, "createdAt" to createdAt, "tester" to tester, /* ToDo: Calculate percentage in BE type: float */ "testingProgress" to calculateProgress(), "createdBy" to createdBy ) } fun Project.toProjectDeleteResponseBody(): ResponseBody { return mapOf( "id" to id ) } fun Project.calculateProgress(): Float { // Total number of pentests listet in the OWASP testing guide // https://owasp.org/www-project-web-security-testing-guide/assets/archive/OWASP_Testing_Guide_v4.pdf val TOTALPENTESTS = 95 return if (projectPentests.isEmpty()) 0F else { var completedPentests = 0 projectPentests.forEach { projectPentest -> if (projectPentest.status == PentestStatus.TRIAGED) { completedPentests++ } } val df = DecimalFormat("#.##") df.roundingMode = RoundingMode.DOWN val progress = completedPentests / TOTALPENTESTS df.format(progress).toFloat() } } data class ProjectOverview( val projects: List ) data class ProjectRequestBody( val client: String, val title: String, val tester: String ) /** * Validates if a [ProjectRequestBody] is valid * * @return Boolean describing if the body is valid */ fun ProjectRequestBody.isValid(): Boolean { return when { this.client.isBlank() -> false this.title.isBlank() -> false this.tester.isBlank() -> false else -> true } } fun ProjectRequestBody.toProject(): Project { return Project( id = UUID.randomUUID().toString(), client = this.client, title = this.title, createdAt = Instant.now().toString(), tester = this.tester, // ToDo: Should be changed to SUB from Token after adding AUTH Header createdBy = UUID.randomUUID().toString() ) }