feat: added pentest status selection

This commit is contained in:
Marcel Haag 2022-11-04 12:49:38 +01:00
parent c1293b4da1
commit de659e3293
8 changed files with 168 additions and 30 deletions

View File

@ -4,20 +4,33 @@
<nb-tab class="pentest-tabset" tabTitle="{{ 'global.action.info' | translate }}">
<app-pentest-info [pentestInfo$]=pentest$></app-pentest-info>
</nb-tab>
<nb-tab class="pentest-tabset" tabTitle="{{ 'pentest.findings' | translate }}" badgeText="{{currentNumberOfFindings$.getValue()}}" badgeStatus="danger">
<nb-tab class="pentest-tabset" tabTitle="{{ 'pentest.findings' | translate }}"
badgeText="{{currentNumberOfFindings$.getValue()}}" badgeStatus="danger">
<app-pentest-findings [pentestInfo$]=pentest$></app-pentest-findings>
</nb-tab>
<nb-tab class="pentest-tabset" tabTitle="{{ 'pentest.comments' | translate }}" badgeText="{{currentNumberOfComments$.getValue()}}" badgeStatus="info">
<nb-tab class="pentest-tabset" tabTitle="{{ 'pentest.comments' | translate }}"
badgeText="{{currentNumberOfComments$.getValue()}}" badgeStatus="info">
<app-pentest-comments [pentestInfo$]=pentest$></app-pentest-comments>
</nb-tab>
</nb-tabset>
</div>
<div fxLayoutAlign="end end" class="content-footer">
<!-- Pentest Status Selection -->
<div class="pentest-status-dialog">
<nb-select class="status"
[(selected)]="currentStatus"
shape="round" filled
status="{{getPentestFillStatus(currentStatus)}}">
<nb-option *ngFor="let status of statusTexts" [value]="status.value">
{{ status.translationText | translate }}
</nb-option>
</nb-select>
</div>
<button nbButton
class="save-pentest-button"
status="primary"
[disabled]="!pentestChanged$.getValue()"
[disabled]="!pentestStatusChanged()"
title="{{ 'global.action.save' | translate }}"
(click)="onClickSavePentest()">
<span class="exit-element-text"> {{ 'global.action.save' | translate }} </span>

View File

@ -14,6 +14,28 @@
.content-footer {
height: 5%;
.pentest-status-dialog {
margin: 1rem 2.25rem 1rem 0;
.status {
width: 12rem;
}
.basic {
background-color: nb-theme(color-basic-default);
}
.info {
background-color: nb-theme(color-info-default);
}
.warning {
background-color: nb-theme(color-warning-default);
}
.success {
background-color: nb-theme(color-success-default);
}
}
.save-pentest-button {
margin: 1rem 6rem 1rem 0;
}

View File

@ -5,6 +5,10 @@ import {Store} from '@ngxs/store';
import {ProjectState} from '@shared/stores/project-state/project-state';
import {UntilDestroy, untilDestroyed} from '@ngneat/until-destroy';
import {Pentest} from '@shared/models/pentest.model';
import {PentestStatus} from '@shared/models/pentest-status.model';
import {StatusText} from '@shared/widgets/status-tag/status-tag.component';
import {PentestService} from '@shared/services/pentest.service';
import {NotificationService, PopupType} from '@shared/services/notification.service';
@UntilDestroy()
@Component({
@ -21,7 +25,24 @@ export class PentestContentComponent implements OnInit {
currentNumberOfFindings$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
currentNumberOfComments$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
constructor(private store: Store) { }
// Pentest Status Handler
currentStatus: PentestStatus = PentestStatus.NOT_STARTED;
private initialPentestStatus: PentestStatus;
status = PentestStatus;
readonly statusTexts: Array<StatusText> = [
{value: PentestStatus.NOT_STARTED, translationText: 'pentest.statusText.not_started'},
/* ToDo: Disabled not needed inside pentest */
/*{value: PentestStatus.DISABLED, translationText: 'pentest.statusText.disabled'},*/
{value: PentestStatus.OPEN, translationText: 'pentest.statusText.open'},
{value: PentestStatus.IN_PROGRESS, translationText: 'pentest.statusText.in_progress'},
{value: PentestStatus.COMPLETED, translationText: 'pentest.statusText.completed'}
];
constructor(
private readonly pentestService: PentestService,
private notificationService: NotificationService,
private store: Store) {
}
ngOnInit(): void {
this.store.selectOnce(ProjectState.pentest).pipe(
@ -29,6 +50,8 @@ export class PentestContentComponent implements OnInit {
).subscribe({
next: (selectedPentest: Pentest) => {
this.pentest$.next(selectedPentest);
this.currentStatus = selectedPentest.status;
this.initialPentestStatus = selectedPentest.status;
const findings = selectedPentest.findingsIds ? selectedPentest.findingsIds.length : 0;
this.currentNumberOfFindings$.next(findings);
const comments = selectedPentest.commentsIds ? selectedPentest.commentsIds.length : 0;
@ -41,6 +64,59 @@ export class PentestContentComponent implements OnInit {
}
onClickSavePentest(): void {
console.info('to be implemented..');
this.pentest$.next({...this.pentest$.getValue(), status: this.currentStatus});
console.warn('Updated Pentest: ', this.pentest$.getValue());
this.pentestService.savePentest(this.pentest$.getValue())
.subscribe({
next: (pentest: Pentest) => {
this.notificationService.showPopup('pentest.popup.save.success', PopupType.SUCCESS);
},
error: err => {
console.log(err);
this.notificationService.showPopup('pentest.popup.save.failed', PopupType.FAILURE);
}
});
}
/**
* @return true if initial pentest Status is different from current pentest status
*/
pentestStatusChanged(): boolean {
if (this.initialPentestStatus !== this.currentStatus) {
this.pentestChanged$.next(true);
} else {
this.pentestChanged$.next(false);
}
return this.pentestChanged$.getValue();
}
/**
* @return the correct nb-status for current pentest-status
*/
getPentestFillStatus(value: PentestStatus): string {
let pentestFillStatus;
switch (value) {
case PentestStatus.NOT_STARTED: {
pentestFillStatus = 'basic';
break;
}
case PentestStatus.OPEN: {
pentestFillStatus = 'info';
break;
}
case PentestStatus.IN_PROGRESS: {
pentestFillStatus = 'warning';
break;
}
case PentestStatus.COMPLETED: {
pentestFillStatus = 'success';
break;
}
default: {
pentestFillStatus = 'basic';
break;
}
}
return pentestFillStatus;
}
}

View File

@ -2,7 +2,7 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule} from '@angular/router';
import {PentestComponent} from './pentest.component';
import {NbButtonModule, NbCardModule, NbLayoutModule, NbTabsetModule, NbTreeGridModule} from '@nebular/theme';
import {NbButtonModule, NbCardModule, NbLayoutModule, NbSelectModule, NbTabsetModule, NbTreeGridModule} from '@nebular/theme';
import { PentestHeaderComponent } from './pentest-header/pentest-header.component';
import { PentestContentComponent } from './pentest-content/pentest-content.component';
import {FlexLayoutModule} from '@angular/flex-layout';
@ -42,7 +42,8 @@ import {FindingDialogModule} from '@shared/modules/finding-dialog/finding-dialog
NbTabsetModule,
NbTreeGridModule,
SeverityTagModule,
FindingDialogModule
FindingDialogModule,
NbSelectModule
]
})
export class PentestModule {

View File

@ -174,6 +174,15 @@
"in_progress": "In Bearbeitung",
"completed": "Fertig"
},
"popup": {
"not.found": "Keine pentests gefunden",
"save.success": "Pentest erfolgreich gespeichert",
"save.failed": "Pentest konnte nicht gespeichert werden",
"update.success": "Pentest erfolgreich aktualisiert",
"update.failed": "Pentest konnte nicht aktualisiert werden",
"delete.success": "Pentest erfolgreich gelöscht",
"delete.failed": "Pentest konnte nicht gelöscht werden"
},
"info": {
"001": "Nutze Suchmaschinenerkennung und -aufklärung für Informationslecks",
"002": "Fingerabdruck-Webserver",

View File

@ -174,6 +174,15 @@
"in_progress": "In progress",
"completed": "Completed"
},
"popup": {
"not.found": "No pentest found",
"save.success": "Pentest saved successfully",
"save.failed": "Pentest could not be saved",
"update.success": "Pentest updated successfully",
"update.failed": "Pentest could not be updated",
"delete.success": "Pentest deleted successfully",
"delete.failed": "Pentest could not be deleted"
},
"info": {
"001": "Conduct Search Engine Discovery and Reconnaissance for Information Leakage",
"002": "Fingerprint Web Server",

View File

@ -54,6 +54,14 @@ export class PentestService {
return this.http.get<Pentest[]>(`${this.apiBaseURL}`, {params: queryParams});
}
/**
* Save Pentest
* @param pentest the information of the Pentest
*/
public savePentest(pentest: Pentest): Observable<Pentest> {
return this.http.post<Pentest>(`${this.apiBaseURL}/${pentest.id}`, pentest);
}
/**
* Get Findings for Pentest Id
* @param pentestId the id of the project

View File

@ -30,7 +30,7 @@ export class StatusTagComponent implements OnInit {
}
}
interface StatusText {
export interface StatusText {
value: string;
translationText: string;
}