Compare commits

...

1 Commits

Author SHA1 Message Date
Marcel Haag 2e6f78c1f4 feat: As a user, I want to create reports only in PDF file format 2023-05-09 09:43:08 +02:00
16 changed files with 243 additions and 103 deletions

View File

@ -87,7 +87,6 @@ export class HeaderComponent implements OnInit {
if (menuBag.item.icon) { if (menuBag.item.icon) {
// tslint:disable-next-line:no-string-literal // tslint:disable-next-line:no-string-literal
if (menuBag.item.icon['icon'] === this.settingsIcon) { if (menuBag.item.icon['icon'] === this.settingsIcon) {
console.warn('Profile');
this.dialogService.openCustomDialog( this.dialogService.openCustomDialog(
ProfileSettingsComponent, ProfileSettingsComponent,
{ {
@ -98,7 +97,7 @@ export class HeaderComponent implements OnInit {
untilDestroyed(this) untilDestroyed(this)
).subscribe({ ).subscribe({
next: () => { next: () => {
console.warn('New Settings confirmed'); console.info('New Settings confirmed');
} }
}); });
} }

View File

@ -183,12 +183,12 @@
"title": "Titel", "title": "Titel",
"description": "Beschreibung", "description": "Beschreibung",
"impact": "Auswirkung", "impact": "Auswirkung",
"affectedUrls": "Betroffene URL's", "affectedUrls": "Betroffene URL's / API's",
"reproduction": "Reproduktion", "reproduction": "Reproduktion",
"mitigation": "Minderung", "mitigation": "Minderung",
"add": "Fund hinzufügen", "add": "Fund hinzufügen",
"add.url": "Betroffene URL hinzufügen", "add.url": "Betroffene URL / API hinzufügen",
"affectedUrls.placeholder": "Betroffene URL hier eingeben..", "affectedUrls.placeholder": "Betroffene URL oder API hier eingeben..",
"create": { "create": {
"header": "Neuen Fund erstellen" "header": "Neuen Fund erstellen"
}, },

View File

@ -183,12 +183,12 @@
"title": "Title", "title": "Title",
"description": "Description", "description": "Description",
"impact": "Impact", "impact": "Impact",
"affectedUrls": "Affected URL's", "affectedUrls": "Affected URL's / API's",
"reproduction": "Reproduction", "reproduction": "Reproduction",
"mitigation": "Mitigation", "mitigation": "Mitigation",
"add": "Add finding", "add": "Add finding",
"add.url": "Add affected Url", "add.url": "Add affected URL / API",
"affectedUrls.placeholder": "Enter affected URL here..", "affectedUrls.placeholder": "Enter affected URL or API here..",
"create": { "create": {
"header": "Create New Finding" "header": "Create New Finding"
}, },

View File

@ -13,7 +13,7 @@
<app-version-tag [version]="dialogData.options[0].additionalData?.version"></app-version-tag> <app-version-tag [version]="dialogData.options[0].additionalData?.version"></app-version-tag>
</div> </div>
<!--Chart Objective Component--> <!--Chart Objective Component-->
<div fxLayout="column" fxLayoutGap="2rem" fxLayoutAlign="center center"> <div fxLayout="column" fxLayoutGap="2rem" fxLayoutAlign="center center" class="objective-chart">
<app-objective-chart <app-objective-chart
[projectPentestData]="selectedEvaluatedProject$.getValue().projectPentests"></app-objective-chart> [projectPentestData]="selectedEvaluatedProject$.getValue().projectPentests"></app-objective-chart>
<span <span
@ -35,8 +35,8 @@
alt=""> alt="">
</nb-radio> </nb-radio>
</nb-radio-group> </nb-radio-group>
<!--Export Format Radio Selection--> <!--ToDo: Export Format Radio Selection only whne more than pdf is supported-->
<label class="export-format-label"> <!--<label class="export-format-label">
{{ 'report.dialog.formatLabel' | translate }} {{ 'report.dialog.formatLabel' | translate }}
</label> </label>
<nb-radio-group name="format" [formControl]="exportReportFormatControl" class="export-radio-buttons" <nb-radio-group name="format" [formControl]="exportReportFormatControl" class="export-radio-buttons"
@ -47,10 +47,10 @@
<nb-radio disabled value="{{exportFormats.CSV}}"> <nb-radio disabled value="{{exportFormats.CSV}}">
{{exportFormats.CSV}} {{exportFormats.CSV}}
</nb-radio> </nb-radio>
<nb-radio disabled value="{{exportFormats.HTML}}"> <nb-radio value="{{exportFormats.HTML}}">
{{exportFormats.HTML}} {{exportFormats.HTML}}
</nb-radio> </nb-radio>
</nb-radio-group> </nb-radio-group>-->
</div> </div>
</nb-card-body> </nb-card-body>
<nb-card-footer fxLayout="row" fxLayoutGap="1.5rem" fxLayoutAlign="end end"> <nb-card-footer fxLayout="row" fxLayoutGap="1.5rem" fxLayoutAlign="end end">

View File

@ -4,13 +4,18 @@
.export-report-dialog { .export-report-dialog {
width: 45.25rem !important; width: 45.25rem !important;
height: 56.25rem; height: 48.25rem;
.export-report-header { .export-report-header {
height: 8vh; height: 8vh;
font-size: 1.5rem; font-size: 1.5rem;
} }
.objective-chart {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
.languageContainer { .languageContainer {
display: flex; display: flex;
max-width: 8rem; max-width: 8rem;
@ -22,17 +27,19 @@
} }
} }
.hint {
padding-bottom: 0.5rem;
color: nb-theme(color-danger-default);
}
.export-radio-buttons { .export-radio-buttons {
float: left; float: left;
clear: none; clear: none;
margin-left: 1rem; margin-left: 1rem;
} }
.hint {
padding-bottom: 0.5rem;
color: nb-theme(color-danger-default);
}
nb-form-field { nb-form-field {
padding: 0.5rem 0 0.75rem; padding: 0.5rem 0 0.75rem;
} }

View File

@ -81,7 +81,6 @@ export class ExportReportDialogComponent implements OnInit {
} }
onClickExport(reportFormat: string, reportLanguage: string): void { onClickExport(reportFormat: string, reportLanguage: string): void {
console.warn('ToDo: Use format ', reportFormat);
// Get project id from dialog data // Get project id from dialog data
const projectId = this.dialogData.options[0].additionalData.id; const projectId = this.dialogData.options[0].additionalData.id;
// Loading is true as long as there is a response from the reporting service // Loading is true as long as there is a response from the reporting service
@ -89,7 +88,6 @@ export class ExportReportDialogComponent implements OnInit {
// Export pentest in choosen format // Export pentest in choosen format
switch (reportFormat) { switch (reportFormat) {
case ExportFormatOptions.PDF: { case ExportFormatOptions.PDF: {
// @ts-ignore
this.downloadPentestReport$ = this.reportingService.getReportPDFforProjectById(projectId, reportLanguage) this.downloadPentestReport$ = this.reportingService.getReportPDFforProjectById(projectId, reportLanguage)
.pipe( .pipe(
shareReplay(), shareReplay(),
@ -112,16 +110,6 @@ export class ExportReportDialogComponent implements OnInit {
}); });
break; break;
} }
case ExportFormatOptions.CSV: {
this.loading$.next(false);
this.notificationService.showPopup('report.popup.generation.failed', PopupType.FAILURE);
break;
}
case ExportFormatOptions.HTML: {
this.loading$.next(false);
this.notificationService.showPopup('report.popup.generation.failed', PopupType.FAILURE);
break;
}
default: { default: {
this.loading$.next(false); this.loading$.next(false);
this.notificationService.showPopup('report.popup.generation.failed', PopupType.FAILURE); this.notificationService.showPopup('report.popup.generation.failed', PopupType.FAILURE);

View File

@ -77,7 +77,6 @@ export class ProfileSettingsComponent implements OnInit {
this.userNameControl.setValue(user.username); this.userNameControl.setValue(user.username);
this.userFirstNameControl.setValue(user.firstName); this.userFirstNameControl.setValue(user.firstName);
this.userLastNameControl.setValue(user.lastName); this.userLastNameControl.setValue(user.lastName);
console.warn(this.user.getValue());
}, },
error: err => { error: err => {
console.error(err); console.error(err);
@ -121,6 +120,9 @@ export class ProfileSettingsComponent implements OnInit {
onClickLanguage(language: string): void { onClickLanguage(language: string): void {
this.translateService.use(language); this.translateService.use(language);
// ToDo: Update userAccount language property
const user = this.store.selectSnapshot(SessionState.userAccount);
this.store.dispatch(new UpdateUserSettings({...user, interfaceLang: language}));
} }
onClickConfirm(): void { onClickConfirm(): void {

View File

@ -1,15 +1,16 @@
import {Pipe, PipeTransform} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {formatDate} from '@angular/common'; import {formatDate} from '@angular/common';
import {Store} from '@ngxs/store'; import {Store} from '@ngxs/store';
import {SessionState} from '@shared/stores/session-state/session-state';
import {CustomPipe} from '@shared/models/custom-pipe.mode'; import {CustomPipe} from '@shared/models/custom-pipe.mode';
import {TranslateService} from '@ngx-translate/core';
@Pipe({ @Pipe({
name: 'dateTimeFormat' name: 'dateTimeFormat',
pure: false
}) })
export class DateTimeFormatPipe implements PipeTransform { export class DateTimeFormatPipe implements PipeTransform {
constructor(private store: Store) { constructor(private store: Store, private translateService: TranslateService) {
} }
/** /**
@ -22,18 +23,15 @@ export class DateTimeFormatPipe implements PipeTransform {
return '-'; return '-';
} }
const localeDateAndNumberFormat = this.store.selectSnapshot(SessionState.userAccount) ? const currentLanguage = this.translateService.currentLang;
// @ts-ignore
this.store.selectSnapshot(SessionState.userAccount.interfaceLang) : 'en-US';
if (!localeDateAndNumberFormat) { if (!currentLanguage) {
return formatDate(value, CustomPipe.DATE_TIME_FMT_EN, 'en-US'); return formatDate(value, CustomPipe.DATE_TIME_FMT_EN, 'en-US');
} }
if (localeDateAndNumberFormat === 'de-DE') { if (currentLanguage === 'de-DE') {
return formatDate(value, CustomPipe.DATE_TIME_FMT_DE, localeDateAndNumberFormat) + ' Uhr'; return formatDate(value, CustomPipe.DATE_TIME_FMT_DE, currentLanguage) + ' Uhr';
} }
// @ts-ignore // @ts-ignore
return formatDate(value, CustomPipe.DATE_TIME_FMT_EN, localeDateAndNumberFormat); return formatDate(value, CustomPipe.DATE_TIME_FMT_EN, currentLanguage);
} }
} }

View File

@ -23,7 +23,7 @@ export class DialogService {
additionalData: any additionalData: any
): NbDialogRef<T> { ): NbDialogRef<T> {
return this.dialog.open<T>(componentOrTemplateRef, { return this.dialog.open<T>(componentOrTemplateRef, {
closeOnEsc: false, closeOnEsc: true,
hasScroll: false, hasScroll: false,
autoFocus: true, autoFocus: true,
closeOnBackdropClick: false, closeOnBackdropClick: false,

View File

@ -18,7 +18,6 @@ export class ReportingService {
/** /**
* Get PDF Report by project id * Get PDF Report by project id
*/ */
// ToDo: Add language here
public getReportPDFforProjectById(projectId: string, reportLanguage: string): Observable<Loading<ArrayBuffer>> { public getReportPDFforProjectById(projectId: string, reportLanguage: string): Observable<Loading<ArrayBuffer>> {
return this.http.get(`${this.reportBaseURL}/${projectId}/pdf/${reportLanguage}`, return this.http.get(`${this.reportBaseURL}/${projectId}/pdf/${reportLanguage}`,
{ {
@ -29,12 +28,6 @@ export class ReportingService {
} }
).pipe(loadContent<ArrayBuffer>()); ).pipe(loadContent<ArrayBuffer>());
} }
/* ToDo: Remove report function without observing report progress
public getReportPDFforProjectById(projectId: string): Observable<ArrayBuffer> {
// @ts-ignore
return this.http.get<ArrayBuffer>(`${this.reportBaseURL}/${projectId}/pdf`, {responseType: 'arraybuffer'})
}*/
} }
export interface ReportDownloadConfiguration { export interface ReportDownloadConfiguration {

View File

@ -1,11 +1,8 @@
package com.securityc4po.reporting.report package com.securityc4po.reporting.report
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.securityc4po.reporting.configuration.security.Appuser import com.securityc4po.reporting.configuration.security.Appuser
import com.securityc4po.reporting.extensions.getLoggerFor import com.securityc4po.reporting.extensions.getLoggerFor
import com.securityc4po.reporting.remote.APIService import com.securityc4po.reporting.remote.APIService
import com.securityc4po.reporting.remote.model.ProjectReport
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.notFound import org.springframework.http.ResponseEntity.notFound
@ -13,7 +10,6 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal
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 java.io.File
@RestController @RestController
@RequestMapping("/reports") @RequestMapping("/reports")
@ -31,7 +27,6 @@ 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]
) )
// ToDo: Add language here
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 ->
@ -41,35 +36,4 @@ class ReportController(private val apiService: APIService, private val reportSer
} }
} }
} }
// ToDo: Add download API for csv report
/*
@GetMapping(
"/{projectId}/csv",
produces = ["text/csv"]
)
fun downloadPentestReportCSV() {
/* 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)
/* jsonProjectReportCollection */
}
*/
// ToDo: Add download API for html report
/*
@GetMapping(
"/{projectId}/html",
produces = ["text/html"]
)
fun downloadPentestReportHTML() {
/* 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)
/* jsonProjectReportCollection */
}
*/
} }

View File

@ -76,19 +76,18 @@ class ReportService {
lateinit var severityRatingTablePath: String lateinit var severityRatingTablePath: String
fun createReport(projectReportCollection: ProjectReport, reportFormat: String, reportLanguage: String): Mono<ByteArray> { fun createReport(projectReportCollection: ProjectReport, reportFormat: String, reportLanguage: String): Mono<ByteArray> {
logger.info("Use: " + reportLanguage)
// Setup PDFMergerUtility // Setup PDFMergerUtility
val mergedC4POPentestReport: PDFMergerUtility = PDFMergerUtility() val mergedC4POPentestReport: PDFMergerUtility = PDFMergerUtility()
// Setup ByteArrayOutputStream for "on the fly" file generation // Setup ByteArrayOutputStream for "on the fly" file generation
val pdfDocOutputstream = ByteArrayOutputStream() val penetstReportOutputstream = ByteArrayOutputStream()
// Try to create report files & merge them together // Try to create report files & merge them together
return createPentestReportFiles(projectReportCollection, reportFormat, reportLanguage, mergedC4POPentestReport).collectList() return createPentestReportFiles(projectReportCollection, reportFormat, reportLanguage, mergedC4POPentestReport).collectList()
.map { .map {
// Merge report files // Merge report files
mergedC4POPentestReport.destinationStream = pdfDocOutputstream mergedC4POPentestReport.destinationStream = penetstReportOutputstream
mergedC4POPentestReport.mergeDocuments(MemoryUsageSetting.setupTempFileOnly()) mergedC4POPentestReport.mergeDocuments(MemoryUsageSetting.setupTempFileOnly())
}.flatMap { }.flatMap {
return@flatMap Mono.just(pdfDocOutputstream.toByteArray()) return@flatMap Mono.just(penetstReportOutputstream.toByteArray())
}.doOnError { }.doOnError {
logger.error("Report generation failed.") logger.error("Report generation failed.")
} }
@ -113,13 +112,13 @@ class ReportService {
createAppendencies(reportFormat, resourceBundle) createAppendencies(reportFormat, resourceBundle)
).map { jasperObject -> ).map { jasperObject ->
if (jasperObject is ByteArray) { if (jasperObject is ByteArray) {
val pdfInputSteam = ByteArrayInputStream(jasperObject) val reportFilesInputSteam = ByteArrayInputStream(jasperObject)
mergedC4POPentestReport.addSource(pdfInputSteam) mergedC4POPentestReport.addSource(reportFilesInputSteam)
} else if (jasperObject is List<*>) { } else if (jasperObject is List<*>) {
jasperObject.forEach { jasperFile -> jasperObject.forEach { jasperFile ->
if (jasperFile is ByteArray) { if (jasperFile is ByteArray) {
val pdfInputSteam = ByteArrayInputStream(jasperFile) val reportFilesInputSteam = ByteArrayInputStream(jasperFile)
mergedC4POPentestReport.addSource(pdfInputSteam) mergedC4POPentestReport.addSource(reportFilesInputSteam)
} }
} }
} }

View File

@ -2,6 +2,7 @@
# Cover # Cover
title.cover_one=Penetrationstest title.cover_one=Penetrationstest
title.cover_two=Ergebnisbericht title.cover_two=Ergebnisbericht
date.format=dd.MM.yyyy
hint=Kein Teil dieses Dokuments darf ohne die ausdrückliche schriftliche Genehmigung des Testers an externe Quellen weitergegeben werden hint=Kein Teil dieses Dokuments darf ohne die ausdrückliche schriftliche Genehmigung des Testers an externe Quellen weitergegeben werden
# Table of contents # Table of contents
@ -26,11 +27,11 @@ title.comment=Kommentar:
title=Titel: title=Titel:
description=Beschreibung: description=Beschreibung:
impact=Auswirkung: impact=Auswirkung:
reproduction_steps=Reproduktion: reproduction_steps=Schritte zur Reproduktion:
mitigation=Minderung: mitigation=Minderung:
no_mitigation=Keine Schadensminderung zur Vermeidung, Minimierung oder Kompensation des festgestellten oder erforderlichen Befunds. no_mitigation=Keine Schadensminderung zur Vermeidung, Minimierung oder Kompensation des festgestellten oder erforderlichen Befunds.
affected_urls=Betroffene URL's: affected_urls=Betroffene URL's / API's:
no_affected_urls=Keine spezifischen URLs betroffen. no_affected_urls=Keine spezifischen URLs oder API's betroffen.
# Appendencies # Appendencies
title.appendencies=Anhänge title.appendencies=Anhänge
@ -38,7 +39,7 @@ title.findings_severities=Schweregrade der Funde
text.findings_severities=Jedem Befund wurde eine Schweregradbewertung von kritisch hoch, mittel oder niedrig zugewiesen. Die Bewertung basiert auf einer Bewertung der Priorität, mit der jeder Befund betrachtet werden sollte, und der potenziellen Auswirkungen, die jeder auf die Vertraulichkeit, Integrität und Verfügbarkeit hat. text.findings_severities=Jedem Befund wurde eine Schweregradbewertung von kritisch hoch, mittel oder niedrig zugewiesen. Die Bewertung basiert auf einer Bewertung der Priorität, mit der jeder Befund betrachtet werden sollte, und der potenziellen Auswirkungen, die jeder auf die Vertraulichkeit, Integrität und Verfügbarkeit hat.
title.risk_matrix=Risiko Matrix title.risk_matrix=Risiko Matrix
text.risk_matrix=Die Risikomatrix wird verwendet, um den potenziellen Schaden einer Gefahr basierend auf den Faktoren Wahrscheinlichkeit und Schweregrad zu bewerten. Die Wahrscheinlichkeits- und Schweregradbewertungen werden multipliziert, um einen Bewertungswert zu erhalten. Diese Punktzahl wird in den Risikobereichen nachgeschlagen, um das Risikoniveau zu bestimmen. Ein Beispiel für eine Gefahren-Risiko-Matrix ist unten angegeben: text.risk_matrix=Die Risikomatrix wird verwendet, um den potenziellen Schaden einer Gefahr basierend auf den Faktoren Wahrscheinlichkeit und Schweregrad zu bewerten. Die Wahrscheinlichkeits- und Schweregradbewertungen werden multipliziert, um einen Bewertungswert zu erhalten. Diese Punktzahl wird in den Risikobereichen nachgeschlagen, um das Risikoniveau zu bestimmen. Ein Beispiel für eine Gefahren-Risiko-Matrix ist unten angegeben:
example.risk_matrix=Beispiel: Wenn Wahrscheinlichkeit = Möglich (3) und Schweregrad = Erheblich (4), wird die Risikostufe durch Schweregrad * Wahrscheinlichkeit bestimmt, was 3*4 = 12 ist. Die Punktzahl 12 fällt in den Risikobereich 'Hoch'. example.risk_matrix=Beispiel: Wenn Wahrscheinlichkeit = Möglich (3) und Schweregrad = Erheblich (4), wird die Risikostufe durch Schweregrad * Wahrscheinlichkeit bestimmt, was 3*4 = 12 ist. Die Punktzahl 12 fällt in den Risikobereich 'High'.
# Risk Matrix Table Properties # Risk Matrix Table Properties
risk_score=Risiko-Score risk_score=Risiko-Score
to=bis to=bis

View File

@ -2,6 +2,7 @@
# Cover # Cover
title.cover_one=Penetration Test title.cover_one=Penetration Test
title.cover_two=Report of Findings title.cover_two=Report of Findings
date.format=MM/dd/yyyy
hint=No part of this document may be disclosed to outside sources without the explicit written authorization of the tester hint=No part of this document may be disclosed to outside sources without the explicit written authorization of the tester
# Table of contents # Table of contents
@ -29,8 +30,8 @@ impact=Impact:
reproduction_steps=Reproduction Steps: reproduction_steps=Reproduction Steps:
mitigation=Mitigation: mitigation=Mitigation:
no_mitigation=No mitigation to avoid, minimize or compensate the finding found or needed. no_mitigation=No mitigation to avoid, minimize or compensate the finding found or needed.
affected_urls=Affected URL's: affected_urls=Affected URL's / API's:
no_affected_urls=No specific URL's affected. no_affected_urls=No specific URL's or API's affected.
# Appendencies # Appendencies
title.appendencies=Appendencies title.appendencies=Appendencies

View File

@ -147,7 +147,7 @@
<textElement textAlignment="Right"> <textElement textAlignment="Right">
<font fontName="SansSerif" size="12" isBold="true" isItalic="true"/> <font fontName="SansSerif" size="12" isBold="true" isItalic="true"/>
</textElement> </textElement>
<textFieldExpression><![CDATA[(new SimpleDateFormat("dd/MM/yyyy").format($F{createdAt}))]]></textFieldExpression> <textFieldExpression><![CDATA[(new SimpleDateFormat($R{date.format}).format($F{createdAt}))]]></textFieldExpression>
</textField> </textField>
</band> </band>
</detail> </detail>
@ -177,7 +177,7 @@
<reportElement x="-20" y="-10" width="595" height="20" forecolor="#151B2E" backcolor="#151B2E" uuid="724a02c5-82c8-4a72-bf81-b77baa72c723"/> <reportElement x="-20" y="-10" width="595" height="20" forecolor="#151B2E" backcolor="#151B2E" uuid="724a02c5-82c8-4a72-bf81-b77baa72c723"/>
</rectangle> </rectangle>
<textField> <textField>
<reportElement x="0" y="-7" width="554" height="15" forecolor="#FFFFFF" uuid="32716a0d-4cec-4dc4-b766-f545dea11169"/> <reportElement x="-14" y="-7" width="584" height="15" forecolor="#FFFFFF" uuid="32716a0d-4cec-4dc4-b766-f545dea11169"/>
<textElement textAlignment="Center" verticalAlignment="Middle"> <textElement textAlignment="Center" verticalAlignment="Middle">
<font size="8" isBold="true"/> <font size="8" isBold="true"/>
</textElement> </textElement>

View File

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_Coverpage" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="1e81cc75-35cb-406c-934f-0bc56dfd965d">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportJasperData Template JSON Adapter"/>
<!-- Ignores Issue about not finding a specific font -->
<property name="net.sf.jasperreports.awt.ignore.missing.font" value="true"/>
<parameter name="CDATA_WATERMARK" class="java.lang.String"/>
<parameter name="CDATA_C4POCoverBackground" class="java.lang.String"/>
<queryString language="JSON">
<![CDATA[projectReportData]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="client" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="client"/>
<fieldDescription><![CDATA[client]]></fieldDescription>
</field>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="createdAt" class="java.util.Date">
<property name="net.sf.jasperreports.json.field.expression" value="createdAt"/>
<fieldDescription><![CDATA[createdAt]]></fieldDescription>
</field>
<field name="tester" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="tester"/>
<fieldDescription><![CDATA[tester]]></fieldDescription>
</field>
<field name="summary" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="summary"/>
<fieldDescription><![CDATA[summary]]></fieldDescription>
</field>
<field name="projectPentestReport" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="projectPentestReport"/>
<fieldDescription><![CDATA[projectPentestReport]]></fieldDescription>
</field>
<field name="createdBy" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdBy"/>
<fieldDescription><![CDATA[createdBy]]></fieldDescription>
</field>
<field name="version" class="java.lang.String"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="390" splitType="Stretch">
<image>
<reportElement x="-20" y="-20" width="595" height="409" uuid="7b8866c7-8b72-43a8-9428-2404a75e803e"/>
<imageExpression><![CDATA[$P{CDATA_C4POCoverBackground}]]></imageExpression>
</image>
<rectangle>
<reportElement x="-20" y="-20" width="595" height="280" forecolor="#151B2E" backcolor="rgba(35, 43, 68, 0.5882353)" uuid="7412dfc2-c785-4584-b8e9-120df2ef41f2"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<rectangle>
<reportElement x="-20" y="241" width="595" height="120" forecolor="#232B44" backcolor="#232B44" uuid="c3646ed4-24af-4969-990a-322ff29697a9"/>
</rectangle>
<textField textAdjust="StretchHeight">
<reportElement x="6" y="280" width="543" height="51" forecolor="#FFFFFF" uuid="563ae593-7ae8-47fc-8728-01da0a717aad"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="SansSerif" size="26" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{client}]]></textFieldExpression>
</textField>
<textField>
<reportElement mode="Transparent" x="5" y="0" width="544" height="219" forecolor="#FEFEFF" backcolor="#232B44" uuid="173fc927-62f1-4242-9c7e-638a21a9672f">
<property name="net.sf.jasperreports.export.accessibility.tag" value="h1"/>
<property name="net.sf.jasperreports.export.pdf.tag.table" value="full"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
<font fontName="SansSerif" size="36" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{title}]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="-2" y="220" width="577" height="40" forecolor="#232B44" backcolor="#151B2E" uuid="2d5d891c-1d0f-4d81-beab-6d6937f08b5b"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<ellipse>
<reportElement x="-20" y="220" width="38" height="40" backcolor="#151B2E" uuid="fefe65c4-59db-4810-9539-1865db235814"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<image>
<reportElement x="-14" y="224" width="31" height="37" uuid="ae84d484-ee44-436a-a0cd-e94a265ed665"/>
<imageExpression><![CDATA[$P{CDATA_WATERMARK}]]></imageExpression>
</image>
<staticText>
<reportElement mode="Transparent" x="22" y="226" width="82" height="20" forecolor="#FEFEFF" backcolor="#151B2E" uuid="b40755db-f42b-47cf-9e73-57cd092f7bde"/>
<textElement>
<font fontName="SansSerif&#xA;&#xA;" size="12" isBold="true" isItalic="false"/>
</textElement>
<text><![CDATA[C4PO]]></text>
</staticText>
<staticText>
<reportElement mode="Transparent" x="23" y="242" width="82" height="20" forecolor="#FEFEFF" backcolor="#151B2E" uuid="1e37e3b3-b3d2-4621-9928-08497bd4f667"/>
<textElement>
<font fontName="SansSerif&#xA;&#xA;" size="10" isItalic="true"/>
</textElement>
<text><![CDATA[v.0.0.1]]></text>
</staticText>
<rectangle>
<reportElement x="-20" y="350" width="595" height="30" uuid="e6a81d95-840a-42a8-860d-cb1957d1775c"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
</band>
</title>
<columnHeader>
<band height="190" splitType="Stretch">
<textField>
<reportElement x="107" y="20" width="340" height="40" forecolor="#232B44" uuid="0c2fdc55-5038-49f5-a972-3575837bb8a6"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="26" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{title.cover_one}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="107" y="61" width="340" height="40" forecolor="#232B44" uuid="edce29e2-8963-43bd-8361-69e579e4a1e1"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="26" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{title.cover_two}]]></textFieldExpression>
</textField>
</band>
</columnHeader>
<detail>
<band height="91" splitType="Stretch">
<textField>
<reportElement x="0" y="10" width="551" height="30" uuid="54c4a617-82ea-4ec4-aa3c-d52e8fd22406"/>
<textElement textAlignment="Right">
<font fontName="SansSerif" size="20" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{tester}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="80" y="50" width="471" height="30" uuid="f13c2ce6-8960-4ac8-ba3a-f79823f07025"/>
<textElement textAlignment="Right">
<font fontName="SansSerif" size="12" isBold="true" isItalic="true"/>
</textElement>
<textFieldExpression><![CDATA[(new SimpleDateFormat("dd/MM/yyyy").format($F{createdAt}))]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="76" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="30" width="595" height="30" forecolor="#232B44" backcolor="#232B44" uuid="1ed47e2d-9d46-44b9-bad7-8eeb1143c83c"/>
<graphicElement>
<pen lineWidth="1.0"/>
</graphicElement>
</rectangle>
<rectangle>
<reportElement x="-20" y="20" width="595" height="10" forecolor="#151B2E" backcolor="#151B2E" uuid="b9a5cd43-3460-4177-97f5-a46eac874e7d"/>
</rectangle>
<textField>
<reportElement x="380" y="35" width="174" height="20" forecolor="#FFFFFF" uuid="0aa9c401-c73c-4a7e-b5a2-b650d333093f"/>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font size="12" isItalic="true"/>
</textElement>
<textFieldExpression><![CDATA["Version " + $F{version}]]></textFieldExpression>
</textField>
</band>
</columnFooter>
<pageFooter>
<band height="10" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="-10" width="595" height="20" forecolor="#151B2E" backcolor="#151B2E" uuid="724a02c5-82c8-4a72-bf81-b77baa72c723"/>
</rectangle>
<textField>
<reportElement x="-14" y="-7" width="584" height="15" forecolor="#FFFFFF" uuid="32716a0d-4cec-4dc4-b766-f545dea11169"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="8" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$R{hint}]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>