fix: design pattern and QoL Improvements
This commit is contained in:
parent
46f79dcf89
commit
2ab6940673
|
@ -2997,6 +2997,21 @@
|
|||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ngxs/storage-plugin": {
|
||||
"version": "3.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ngxs/storage-plugin/-/storage-plugin-3.7.6.tgz",
|
||||
"integrity": "sha512-jeeoUgsMdb4M8kIHdnO0X6I73okmRJhMW9znaqhYF/aZ+PiQrogdJ5xvSXmoQ7Gg57YfQEhVErM+zf/HD7fnMA==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@ngxs/store": {
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@ngxs/store/-/store-3.7.4.tgz",
|
||||
|
@ -11338,9 +11353,9 @@
|
|||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.38",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.38.tgz",
|
||||
"integrity": "sha512-nMIrzGah4+oYZPflDvLZUgoVUO4fvAqHstvG3xAUnMolWncuAiLDWNnJZj6EwJGMGfb1ZcuTFE6GI3hNOVWI/Q==",
|
||||
"version": "0.5.40",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz",
|
||||
"integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"@ngneat/until-destroy": "~8.0.4",
|
||||
"@ngx-translate/core": "^13.0.0",
|
||||
"@ngx-translate/http-loader": "^6.0.0",
|
||||
"@ngxs/storage-plugin": "^3.7.3",
|
||||
"@ngxs/store": "^3.7.3",
|
||||
"eva-icons": "^1.1.3",
|
||||
"i18n-iso-countries": "^6.8.0",
|
||||
|
|
|
@ -38,7 +38,12 @@
|
|||
{{ 'comment.relatedFindings' | translate }}
|
||||
</th>
|
||||
<td nbTreeGridCell *nbTreeGridCellDef="let comment" class="related-finding-cell">
|
||||
{{ comment.data['relatedFindings'].length ? comment.data['relatedFindings'] : 'comment.no.relatedFindings' | translate }}
|
||||
<ng-container *ngIf="comment.data['relatedFindings'].length > 0; else NoRelatedFindings">
|
||||
<app-findig-widget [numberOfFindigs]="comment.data['relatedFindings'].length"></app-findig-widget>
|
||||
</ng-container>
|
||||
<ng-template #NoRelatedFindings>
|
||||
{{ 'comment.no.relatedFindings' | translate }}
|
||||
</ng-template>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Actions -->
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
.comment-cell {
|
||||
// Add style here
|
||||
height: 4.5rem !important;
|
||||
max-height: 4.5rem !important;
|
||||
// max-height: 4.5rem !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.comment-cell:hover {
|
||||
|
@ -15,10 +16,17 @@
|
|||
background-color: nb-theme(color-basic-transparent-focus);
|
||||
}
|
||||
|
||||
.cell {
|
||||
height: 4.5rem !important;
|
||||
max-height: 4.5rem !important;
|
||||
}
|
||||
|
||||
.related-finding-cell {
|
||||
height: 4.5rem !important;
|
||||
max-height: 4.5rem !important;
|
||||
// cursor: pointer;
|
||||
font-family: Courier, serif;
|
||||
color: nb-theme(color-info-default);
|
||||
color: nb-theme(color-danger-default);
|
||||
}
|
||||
|
||||
.cell-actions {
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
{{ 'finding.severity' | translate }}
|
||||
</th>
|
||||
<td nbTreeGridCell *nbTreeGridCellDef="let finding" class="cell-severity border-style" fxLayoutAlign="center center">
|
||||
<ng-container>
|
||||
<app-severity-tag [currentSeverity]="finding.data['severity']"></app-severity-tag>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Title -->
|
||||
|
|
|
@ -22,6 +22,7 @@ import {Store} from '@ngxs/store';
|
|||
import {UpdatePentestFindings} from '@shared/stores/project-state/project-state.actions';
|
||||
import {ProjectState} from '@shared/stores/project-state/project-state';
|
||||
import {DialogService} from '@shared/services/dialog-service/dialog.service';
|
||||
import {FindingService} from '@shared/services/finding.service';
|
||||
|
||||
@UntilDestroy()
|
||||
@Component({
|
||||
|
@ -31,7 +32,7 @@ import {DialogService} from '@shared/services/dialog-service/dialog.service';
|
|||
})
|
||||
export class PentestFindingsComponent implements OnInit {
|
||||
|
||||
constructor(private readonly pentestService: PentestService,
|
||||
constructor(private readonly findingService: FindingService,
|
||||
private dataSourceBuilder: NbTreeGridDataSourceBuilder<FindingEntry>,
|
||||
private notificationService: NotificationService,
|
||||
private dialogService: DialogService,
|
||||
|
@ -75,7 +76,7 @@ export class PentestFindingsComponent implements OnInit {
|
|||
}
|
||||
|
||||
loadFindingsData(): void {
|
||||
this.pentestService.getFindingsByPentestId(this.pentestInfo$.getValue() ? this.pentestInfo$.getValue().id : '')
|
||||
this.findingService.getFindingsByPentestId(this.pentestInfo$.getValue() ? this.pentestInfo$.getValue().id : '')
|
||||
.pipe(
|
||||
untilDestroyed(this),
|
||||
/*filter(isNotNullOrUndefined),*/
|
||||
|
@ -115,7 +116,7 @@ export class PentestFindingsComponent implements OnInit {
|
|||
filter(value => !!value),
|
||||
/*tap((value) => console.warn('FindingDialogBody: ', value)),*/
|
||||
mergeMap((value: FindingDialogBody) =>
|
||||
this.pentestService.saveFinding(
|
||||
this.findingService.saveFinding(
|
||||
this.pentestInfo$.getValue() ? this.pentestInfo$.getValue().id : '',
|
||||
transformFindingToRequestBody(value)
|
||||
)
|
||||
|
@ -135,7 +136,7 @@ export class PentestFindingsComponent implements OnInit {
|
|||
}
|
||||
|
||||
onClickEditFinding(findingEntry): void {
|
||||
this.pentestService.getFindingById(findingEntry.data.findingId).pipe(
|
||||
this.findingService.getFindingById(findingEntry.data.findingId).pipe(
|
||||
filter(isNotNullOrUndefined),
|
||||
untilDestroyed(this)
|
||||
).subscribe({
|
||||
|
@ -154,7 +155,7 @@ export class PentestFindingsComponent implements OnInit {
|
|||
filter(value => !!value),
|
||||
/*tap((value) => console.warn('FindingDialogBody: ', value)),*/
|
||||
mergeMap((value: FindingDialogBody) =>
|
||||
this.pentestService.updateFinding(
|
||||
this.findingService.updateFinding(
|
||||
findingEntry.data.findingId,
|
||||
transformFindingToRequestBody(value)
|
||||
)
|
||||
|
@ -191,7 +192,7 @@ export class PentestFindingsComponent implements OnInit {
|
|||
message
|
||||
).onClose.pipe(
|
||||
filter((confirm) => !!confirm),
|
||||
switchMap(() => this.pentestService.deleteFindingByPentestAndFindingId(
|
||||
switchMap(() => this.findingService.deleteFindingByPentestAndFindingId(
|
||||
this.pentestInfo$.getValue() ? this.pentestInfo$.getValue().id : '',
|
||||
findingEntry.data.findingId)
|
||||
),
|
||||
|
@ -201,7 +202,8 @@ export class PentestFindingsComponent implements OnInit {
|
|||
}),
|
||||
untilDestroyed(this)
|
||||
).subscribe({
|
||||
next: () => {
|
||||
next: (deletedFinding: any) => {
|
||||
this.store.dispatch(new UpdatePentestFindings(deletedFinding.id));
|
||||
this.loadFindingsData();
|
||||
this.notificationService.showPopup('finding.popup.delete.success', PopupType.SUCCESS);
|
||||
}, error: error => {
|
||||
|
|
|
@ -16,6 +16,7 @@ import {CommonAppModule} from '../common-app.module';
|
|||
import {SeverityTagModule} from '@shared/widgets/severity-tag/severity-tag.module';
|
||||
import {FindingDialogModule} from '@shared/modules/finding-dialog/finding-dialog.module';
|
||||
import {CommentDialogModule} from '@shared/modules/comment-dialog/comment-dialog.module';
|
||||
import {FindigWidgetModule} from '@shared/widgets/findig-widget/findig-widget.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -47,6 +48,7 @@ import {CommentDialogModule} from '@shared/modules/comment-dialog/comment-dialog
|
|||
// Dialog Modules
|
||||
FindingDialogModule,
|
||||
CommentDialogModule,
|
||||
FindigWidgetModule,
|
||||
]
|
||||
})
|
||||
export class PentestModule {
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
"add": "Kommentar hinzufügen",
|
||||
"add.finding": "Fund hinzufügen",
|
||||
"no.comments": "Keine Kommentare verfügbar",
|
||||
"no.relatedFindings": "Nicht verbunden mit Fund",
|
||||
"no.relatedFindings": "Nicht verbunden mit einem Fund",
|
||||
"relatedFindingsPlaceholder": "Fund auswählen",
|
||||
"noFindingsInObjectivePlaceholder": "Objective hat keine Befunde, auf die es sich beziehen könnte.",
|
||||
"create": {
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
"add": "Add Comment",
|
||||
"add.finding": "Add related finding",
|
||||
"no.comments": "No comments available",
|
||||
"no.relatedFindings": "Not related to finding",
|
||||
"no.relatedFindings": "Not related to any finding",
|
||||
"relatedFindingsPlaceholder": "Select a related finding",
|
||||
"noFindingsInObjectivePlaceholder": "Objective doesn't have any findings to relate to.",
|
||||
"create": {
|
||||
|
|
|
@ -12,6 +12,7 @@ import {Store} from '@ngxs/store';
|
|||
import {Finding} from '@shared/models/finding.model';
|
||||
import {RelatedFindingOption} from '@shared/models/comment.model';
|
||||
import {BehaviorSubject} from 'rxjs';
|
||||
import {FindingService} from '@shared/services/finding.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-comment-dialog',
|
||||
|
@ -39,7 +40,7 @@ export class CommentDialogComponent implements OnInit {
|
|||
@Inject(NB_DIALOG_CONFIG) private data: GenericDialogData,
|
||||
private fb: FormBuilder,
|
||||
protected dialogRef: NbDialogRef<CommentDialogComponent>,
|
||||
private readonly pentestService: PentestService,
|
||||
private readonly findingService: FindingService,
|
||||
private store: Store
|
||||
) {
|
||||
}
|
||||
|
@ -95,7 +96,7 @@ export class CommentDialogComponent implements OnInit {
|
|||
}
|
||||
|
||||
requestRelatedFindingsData(pentestId: string, relatedFindings: any): void {
|
||||
this.pentestService.getFindingsByPentestId(pentestId).pipe(
|
||||
this.findingService.getFindingsByPentestId(pentestId).pipe(
|
||||
untilDestroyed(this)
|
||||
).subscribe({
|
||||
next: (findings: Finding[]) => {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { FindingService } from './finding.service';
|
||||
import {HttpClientTestingModule} from '@angular/common/http/testing';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {NgxsModule} from '@ngxs/store';
|
||||
import {ProjectState} from '@shared/stores/project-state/project-state';
|
||||
|
||||
describe('FindingService', () => {
|
||||
let service: FindingService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientTestingModule,
|
||||
BrowserAnimationsModule,
|
||||
NgxsModule.forRoot([ProjectState])
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(FindingService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,62 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {environment} from '../../environments/environment';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {Store} from '@ngxs/store';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Finding} from '@shared/models/finding.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FindingService {
|
||||
|
||||
private apiBaseURL = `${environment.apiEndpoint}/pentests`;
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private readonly store: Store) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Findings for Pentest Id
|
||||
* @param pentestId the id of the project
|
||||
*/
|
||||
public getFindingsByPentestId(pentestId: string): Observable<Finding[]> {
|
||||
return this.http.get<Finding[]>(`${this.apiBaseURL}/${pentestId}/findings`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Finding by Id
|
||||
* @param findingId the id of the finding
|
||||
*/
|
||||
public getFindingById(findingId: string): Observable<Finding> {
|
||||
return this.http.get<Finding>(`${this.apiBaseURL}/${findingId}/finding`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Finding
|
||||
* @param pentestId the id of the pentest
|
||||
* @param finding the information of the finding
|
||||
*/
|
||||
public saveFinding(pentestId: string, finding: Finding): Observable<Finding> {
|
||||
return this.http.post<Finding>(`${this.apiBaseURL}/${pentestId}/finding`, finding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Finding
|
||||
* @param findingId the id of the finding
|
||||
* @param finding the information of the finding
|
||||
*/
|
||||
public updateFinding(findingId: string, finding: Finding): Observable<Finding> {
|
||||
return this.http.patch<Finding>(`${this.apiBaseURL}/${findingId}/finding`, finding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Finding
|
||||
* @param pentestId the id of the pentest
|
||||
* @param findingId the id of the finding
|
||||
*/
|
||||
public deleteFindingByPentestAndFindingId(pentestId: string, findingId: string): Observable<string> {
|
||||
return this.http.delete<string>(`${this.apiBaseURL}/${pentestId}/finding/${findingId}`);
|
||||
}
|
||||
}
|
|
@ -9,8 +9,6 @@ import {ProjectState} from '@shared/stores/project-state/project-state';
|
|||
import {catchError, map, switchMap} from 'rxjs/operators';
|
||||
import {getTempPentestsForCategory} from '@shared/functions/categories/get-temp-pentests-for-category.function';
|
||||
import {Finding} from '@shared/models/finding.model';
|
||||
import {Comment} from '@shared/models/comment.model';
|
||||
import {v4 as UUID} from 'uuid';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -78,47 +76,4 @@ export class PentestService {
|
|||
public updatePentest(pentest: Pentest): Observable<Pentest> {
|
||||
return this.http.patch<Pentest>(`${this.apiBaseURL}/${pentest.id}`, pentest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Findings for Pentest Id
|
||||
* @param pentestId the id of the project
|
||||
*/
|
||||
public getFindingsByPentestId(pentestId: string): Observable<Finding[]> {
|
||||
return this.http.get<Finding[]>(`${this.apiBaseURL}/${pentestId}/findings`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Finding by Id
|
||||
* @param findingId the id of the finding
|
||||
*/
|
||||
public getFindingById(findingId: string): Observable<Finding> {
|
||||
return this.http.get<Finding>(`${this.apiBaseURL}/${findingId}/finding`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Finding
|
||||
* @param pentestId the id of the pentest
|
||||
* @param finding the information of the finding
|
||||
*/
|
||||
public saveFinding(pentestId: string, finding: Finding): Observable<Finding> {
|
||||
return this.http.post<Finding>(`${this.apiBaseURL}/${pentestId}/finding`, finding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Finding
|
||||
* @param findingId the id of the finding
|
||||
* @param finding the information of the finding
|
||||
*/
|
||||
public updateFinding(findingId: string, finding: Finding): Observable<Finding> {
|
||||
return this.http.patch<Finding>(`${this.apiBaseURL}/${findingId}/finding`, finding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Finding
|
||||
* @param pentestId the id of the pentest
|
||||
* @param findingId the id of the finding
|
||||
*/
|
||||
public deleteFindingByPentestAndFindingId(pentestId: string, findingId: string): Observable<string> {
|
||||
return this.http.delete<string>(`${this.apiBaseURL}/${pentestId}/finding/${findingId}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@ export interface ProjectStateModel {
|
|||
selectedPentest: Pentest;
|
||||
}
|
||||
|
||||
export interface FindingMap {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
@State<ProjectStateModel>({
|
||||
name: PROJECT_STATE_NAME,
|
||||
defaults: {
|
||||
|
@ -91,12 +95,14 @@ export class ProjectState {
|
|||
updatePentestFindings(ctx: StateContext<ProjectStateModel>, {findingId}: UpdatePentestFindings): void {
|
||||
const state = ctx.getState();
|
||||
let stateSelectedPentest: Pentest = state.selectedPentest;
|
||||
// State objects
|
||||
const stateFindingIds: Array<string> = stateSelectedPentest.findingIds || [];
|
||||
let updatedFindingIds: Array<string> = [];
|
||||
if (!stateFindingIds.includes(findingId)) {
|
||||
updatedFindingIds = [...stateFindingIds, findingId];
|
||||
} else {
|
||||
// ToDo: Add logic to remove findingId from array
|
||||
const findingIndex = stateFindingIds.indexOf(findingId);
|
||||
updatedFindingIds = [...stateFindingIds.slice(0, findingIndex)];
|
||||
}
|
||||
// overwrites only findingIds
|
||||
stateSelectedPentest = {
|
||||
|
@ -113,12 +119,14 @@ export class ProjectState {
|
|||
updatePentestComments(ctx: StateContext<ProjectStateModel>, {commentId}: UpdatePentestComments): void {
|
||||
const state = ctx.getState();
|
||||
let stateSelectedPentest: Pentest = state.selectedPentest;
|
||||
// State objects
|
||||
const stateCommentIds: Array<string> = stateSelectedPentest.commentIds || [];
|
||||
let updatedCommentIds: Array<string> = [];
|
||||
if (!stateCommentIds.includes(commentId)) {
|
||||
updatedCommentIds = [...stateCommentIds, commentId];
|
||||
} else {
|
||||
// ToDo: Add logic to remove commentId from array
|
||||
const commentIndex = stateCommentIds.indexOf(commentId);
|
||||
updatedCommentIds = [...stateCommentIds.slice(0, commentIndex)];
|
||||
}
|
||||
// overwrites only findingIds
|
||||
stateSelectedPentest = {
|
||||
|
|
|
@ -13,11 +13,8 @@
|
|||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "es2020",
|
||||
"lib": [
|
||||
"es2018",
|
||||
"dom"
|
||||
],
|
||||
"module": "esNext",
|
||||
"lib": ["es2019", "es2018", "dom"],
|
||||
"paths": {
|
||||
"@shared/*": ["./src/shared/*"],
|
||||
"@assets/*": ["./src/assets/*"]
|
||||
|
|
|
@ -4,15 +4,10 @@ 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.finding.FindingRequestBody
|
||||
import com.securityc4po.api.finding.FindingService
|
||||
import com.securityc4po.api.finding.toFindingDeleteResponseBody
|
||||
import com.securityc4po.api.finding.toFindingResponseBody
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.http.ResponseEntity.noContent
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.kotlin.core.publisher.switchIfEmpty
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/pentests")
|
||||
|
@ -23,7 +18,7 @@ import reactor.kotlin.core.publisher.switchIfEmpty
|
|||
methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH]
|
||||
)
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
class PentestController(private val pentestService: PentestService, private val findingService: FindingService) {
|
||||
class PentestController(private val pentestService: PentestService) {
|
||||
|
||||
var logger = getLoggerFor<PentestController>()
|
||||
|
||||
|
@ -71,55 +66,4 @@ class PentestController(private val pentestService: PentestService, private val
|
|||
ResponseEntity.accepted().body(it.toPentestResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{pentestId}/findings")
|
||||
fun getFindings(@PathVariable(value = "pentestId") pentestId: String): Mono<ResponseEntity<List<ResponseBody>>> {
|
||||
return this.pentestService.getFindingIdsByPentestId(pentestId).flatMap { findingIds: List<String> ->
|
||||
this.findingService.getFindingsByIds(findingIds).map { findingList ->
|
||||
findingList.map { it.toFindingResponseBody() }
|
||||
}
|
||||
}.map {
|
||||
if (it.isEmpty()) noContent().build()
|
||||
else ResponseEntity.ok(it)
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{findingId}/finding")
|
||||
fun getFinding(@PathVariable(value = "findingId") findingId: String):Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.getFindingById(findingId).map {
|
||||
ResponseEntity.ok().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/{pentestId}/finding")
|
||||
fun saveFinding(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
@RequestBody body: FindingRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.saveFinding(pentestId, body).map {
|
||||
ResponseEntity.accepted().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@PatchMapping("/{findingId}/finding")
|
||||
fun updateFinding(
|
||||
@PathVariable(value = "findingId") findingId: String,
|
||||
@RequestBody body: FindingRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.updateFinding(findingId, body).map {
|
||||
ResponseEntity.accepted().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{pentestId}/finding/{findingId}")
|
||||
fun deleteFinding(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
@PathVariable(value = "findingId") findingId: String
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.deleteFindingByPentestAndFindingId(pentestId, findingId).map {
|
||||
ResponseEntity.ok().body(it.toFindingDeleteResponseBody())
|
||||
}.switchIfEmpty {
|
||||
Mono.just(noContent().build<ResponseBody>())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,16 +53,16 @@ class PentestService(private val pentestRepository: PentestRepository, private v
|
|||
val pentest = body.toPentest()
|
||||
val pentestEntity = PentestEntity(pentest)
|
||||
return pentestRepository.insert(pentestEntity).flatMap { newPentestEntity: PentestEntity ->
|
||||
val pentest = newPentestEntity.toPentest()
|
||||
val newPentest = newPentestEntity.toPentest()
|
||||
// After successfully saving pentest add id and status to project
|
||||
val projectPentest = ProjectPentest(pentestId = pentest.id, status = pentest.status)
|
||||
val projectPentest = ProjectPentest(pentestId = newPentest.id, status = newPentest.status)
|
||||
projectService.updateProjectTestingProgress(projectId, projectPentest).onErrorMap {
|
||||
TransactionInterruptedException(
|
||||
"Project Pentests could not be updated in Database.",
|
||||
Errorcode.ProjectPentestInsertionFailed
|
||||
)
|
||||
}.map {
|
||||
pentest
|
||||
newPentest
|
||||
}
|
||||
}.doOnError {
|
||||
throw wrappedException(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import com.securityc4po.api.ResponseBody
|
||||
import com.securityc4po.api.finding.FindingRequestBody
|
||||
import com.securityc4po.api.pentest.finding.FindingRequestBody
|
||||
import org.springframework.data.mongodb.core.index.Indexed
|
||||
import java.util.*
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.extensions.getLoggerFor
|
||||
|
@ -6,7 +6,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
|||
import com.securityc4po.api.ResponseBody
|
||||
import com.securityc4po.api.configuration.error.handler.EntityNotFoundException
|
||||
import com.securityc4po.api.configuration.error.handler.Errorcode
|
||||
import com.securityc4po.api.finding.toFindingResponseBody
|
||||
import com.securityc4po.api.pentest.finding.toFindingResponseBody
|
||||
import com.securityc4po.api.pentest.PentestService
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.http.ResponseEntity.noContent
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import com.securityc4po.api.BaseEntity
|
||||
import org.springframework.data.mongodb.core.mapping.Document
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import org.springframework.data.mongodb.repository.DeleteQuery
|
||||
import org.springframework.data.mongodb.repository.Query
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
|
@ -7,7 +7,6 @@ import com.securityc4po.api.configuration.error.handler.EntityNotFoundException
|
|||
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.finding.*
|
||||
import com.securityc4po.api.pentest.PentestService
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.springframework.stereotype.Service
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.finding
|
||||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import com.securityc4po.api.ResponseBody
|
||||
import org.springframework.data.mongodb.core.index.Indexed
|
|
@ -0,0 +1,85 @@
|
|||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import com.securityc4po.api.pentest.PentestCategory
|
||||
import com.securityc4po.api.pentest.PentestRequestBody
|
||||
import com.securityc4po.api.pentest.PentestService
|
||||
import com.securityc4po.api.pentest.toPentestResponseBody
|
||||
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.finding.FindingRequestBody
|
||||
import com.securityc4po.api.pentest.finding.FindingService
|
||||
import com.securityc4po.api.pentest.finding.toFindingDeleteResponseBody
|
||||
import com.securityc4po.api.pentest.finding.toFindingResponseBody
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.http.ResponseEntity.noContent
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.kotlin.core.publisher.switchIfEmpty
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/pentests")
|
||||
@CrossOrigin(
|
||||
origins = [],
|
||||
allowCredentials = "false",
|
||||
allowedHeaders = ["*"],
|
||||
methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH]
|
||||
)
|
||||
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||
class FindingController(private val pentestService: PentestService, private val findingService: FindingService) {
|
||||
|
||||
var logger = getLoggerFor<FindingController>()
|
||||
|
||||
@GetMapping("/{pentestId}/findings")
|
||||
fun getFindings(@PathVariable(value = "pentestId") pentestId: String): Mono<ResponseEntity<List<ResponseBody>>> {
|
||||
return this.pentestService.getFindingIdsByPentestId(pentestId).flatMap { findingIds: List<String> ->
|
||||
this.findingService.getFindingsByIds(findingIds).map { findingList ->
|
||||
findingList.map { it.toFindingResponseBody() }
|
||||
}
|
||||
}.map {
|
||||
if (it.isEmpty()) noContent().build()
|
||||
else ResponseEntity.ok(it)
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{findingId}/finding")
|
||||
fun getFinding(@PathVariable(value = "findingId") findingId: String):Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.getFindingById(findingId).map {
|
||||
ResponseEntity.ok().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/{pentestId}/finding")
|
||||
fun saveFinding(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
@RequestBody body: FindingRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.saveFinding(pentestId, body).map {
|
||||
ResponseEntity.accepted().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@PatchMapping("/{findingId}/finding")
|
||||
fun updateFinding(
|
||||
@PathVariable(value = "findingId") findingId: String,
|
||||
@RequestBody body: FindingRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.updateFinding(findingId, body).map {
|
||||
ResponseEntity.accepted().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{pentestId}/finding/{findingId}")
|
||||
fun deleteFinding(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
@PathVariable(value = "findingId") findingId: String
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
// ToDo: Add remove finding from comment as well
|
||||
return this.findingService.deleteFindingByPentestAndFindingId(pentestId, findingId).map {
|
||||
ResponseEntity.ok().body(it.toFindingDeleteResponseBody())
|
||||
}.switchIfEmpty {
|
||||
Mono.just(noContent().build<ResponseBody>())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.finding
|
||||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import com.securityc4po.api.BaseEntity
|
||||
import org.springframework.data.mongodb.core.mapping.Document
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.finding
|
||||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import org.springframework.data.mongodb.repository.DeleteQuery
|
||||
import org.springframework.data.mongodb.repository.Query
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.finding
|
||||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||
|
@ -37,15 +37,15 @@ class FindingService(private val findingRepository: FindingRepository, private v
|
|||
val finding = body.toFinding()
|
||||
val findingEntity = FindingEntity(finding)
|
||||
return findingRepository.insert(findingEntity).flatMap { newFindingEntity: FindingEntity ->
|
||||
val finding = newFindingEntity.toFinding()
|
||||
val newFinding = newFindingEntity.toFinding()
|
||||
// After successfully saving finding add id to pentest
|
||||
pentestService.updatePentestFinding(pentestId, finding.id).onErrorMap {
|
||||
pentestService.updatePentestFinding(pentestId, newFinding.id).onErrorMap {
|
||||
TransactionInterruptedException(
|
||||
"Pentest could not be updated in Database.",
|
||||
Errorcode.PentestInsertionFailed
|
||||
)
|
||||
}.map {
|
||||
finding
|
||||
newFinding
|
||||
}
|
||||
}.doOnError {
|
||||
throw wrappedException(
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.finding
|
||||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
enum class Severity {
|
||||
LOW,
|
|
@ -6,7 +6,6 @@ import com.securityc4po.api.BaseDocumentationIntTest
|
|||
import com.securityc4po.api.configuration.NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
|
||||
import com.securityc4po.api.configuration.RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
import com.securityc4po.api.configuration.SIC_INNER_SHOULD_BE_STATIC
|
||||
import com.securityc4po.api.finding.*
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
|
@ -109,7 +108,7 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
|
||||
|
@ -233,287 +232,6 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFindings {
|
||||
@Test
|
||||
fun getFindingsByPentestId() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{pentestId}/findings", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(getFindingsResponse()))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to get the findings for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("[].id").type(JsonFieldType.STRING)
|
||||
.description("The id of the requested findings"),
|
||||
PayloadDocumentation.fieldWithPath("[].severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
|
||||
private fun getFindingsResponse() = listOf(
|
||||
findingOne.toFindingResponseBody()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFinding {
|
||||
@Test
|
||||
fun getFindingById() {
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingOne.toFindingResponseBody()))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("findingId").description("The id of the feinidng you want to get")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveFinding {
|
||||
@Test
|
||||
fun saveFindingByPentestId() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{pentestId}/finding", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to save the finding for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the saved finding"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "MEDIUM",
|
||||
title = "Found another Bug",
|
||||
description = "Another OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack more",
|
||||
mitigation = "Another None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdateFinding {
|
||||
@Test
|
||||
fun updateFindingById() {
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.patch()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("findingId").description("The id of the finding you want to update")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the updated finding"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "HIGH",
|
||||
title = "Updated Bug",
|
||||
description = "Updated OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "Still None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class DeleteFinding {
|
||||
@Test
|
||||
fun deleteFindingByPentestAndFindingId() {
|
||||
val pentestId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.delete()
|
||||
.uri("/pentests/{pentestId}/finding/{findingId}", pentestId, findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody()
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to remove the finidng from"),
|
||||
RequestDocumentation.parameterWithName("findingId").description("The id of the finding you want to delete")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the finding you deleted")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
// Project
|
||||
|
@ -542,7 +260,7 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestThree = Pentest(
|
||||
|
@ -554,23 +272,11 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
// Finding
|
||||
val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
// persist test data in database
|
||||
mongoTemplate.save(ProjectEntity(projectOne))
|
||||
mongoTemplate.save(PentestEntity(pentestOne))
|
||||
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||
mongoTemplate.save(PentestEntity(pentestThree))
|
||||
mongoTemplate.save(FindingEntity(findingOne))
|
||||
}
|
||||
|
||||
private fun configureAdminToken() {
|
||||
|
@ -580,7 +286,6 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
private fun cleanUp() {
|
||||
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), FindingEntity::class.java)
|
||||
|
||||
tokenAdmin = "n/a"
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import com.securityc4po.api.BaseIntTest
|
|||
import com.securityc4po.api.configuration.NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
|
||||
import com.securityc4po.api.configuration.RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
import com.securityc4po.api.configuration.SIC_INNER_SHOULD_BE_STATIC
|
||||
import com.securityc4po.api.finding.*
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
|
@ -86,7 +85,7 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
|
||||
|
@ -159,145 +158,6 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFindings {
|
||||
@Test
|
||||
fun `requesting findings by pentestId successfully`() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{pentestId}/findings", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(getFindings()))
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
|
||||
private fun getFindings() = listOf(
|
||||
findingOne.toFindingResponseBody()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFinding {
|
||||
@Test
|
||||
fun `requesting finding by findingId successfully`() {
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(findingOne.toFindingResponseBody()))
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveFinding {
|
||||
@Test
|
||||
fun `save finding successfully`() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{pentestId}/finding", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.severity").isEqualTo("MEDIUM")
|
||||
.jsonPath("$.title").isEqualTo("Found another Bug")
|
||||
.jsonPath("$.description").isEqualTo("Another OTG-INFO-002 Bug")
|
||||
.jsonPath("$.impact").isEqualTo("Service")
|
||||
.jsonPath("$.affectedUrls").isEmpty
|
||||
.jsonPath("$.reproduction").isEqualTo("Step 1: Hack more")
|
||||
.jsonPath("$.mitigation").isEqualTo("Another None")
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "MEDIUM",
|
||||
title = "Found another Bug",
|
||||
description = "Another OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack more",
|
||||
mitigation = "Another None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdateFinding {
|
||||
@Test
|
||||
fun `update finding successfully`() {
|
||||
val findingId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.severity").isEqualTo("HIGH")
|
||||
.jsonPath("$.title").isEqualTo("Updated Bug")
|
||||
.jsonPath("$.description").isEqualTo("Updated OTG-INFO-002 Bug")
|
||||
.jsonPath("$.impact").isEqualTo("Service")
|
||||
.jsonPath("$.affectedUrls").isEmpty
|
||||
.jsonPath("$.reproduction").isEqualTo("Step 1: Hack")
|
||||
.jsonPath("$.mitigation").isEqualTo("Still None")
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "HIGH",
|
||||
title = "Updated Bug",
|
||||
description = "Updated OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "Still None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class DeleteFinding {
|
||||
@Test
|
||||
fun `delete finding successfully`() {
|
||||
val pentestId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.delete()
|
||||
.uri("/pentests/{pentestId}/finding/{findingId}", pentestId, findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.id").isEqualTo("ab62d365-1b1d-4da1-89bc-5496616e220f")
|
||||
}
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
// project
|
||||
|
@ -325,7 +185,7 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestThree = Pentest(
|
||||
|
@ -337,23 +197,11 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
// Finding
|
||||
val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
// persist test data in database
|
||||
mongoTemplate.save(ProjectEntity(projectOne))
|
||||
mongoTemplate.save(PentestEntity(pentestOne))
|
||||
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||
mongoTemplate.save(PentestEntity(pentestThree))
|
||||
mongoTemplate.save(FindingEntity(findingOne))
|
||||
}
|
||||
|
||||
private fun configureAdminToken() {
|
||||
|
@ -363,7 +211,6 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
private fun cleanUp() {
|
||||
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), FindingEntity::class.java)
|
||||
|
||||
tokenAdmin = "n/a"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.github.tomakehurst.wiremock.common.Json
|
||||
|
@ -10,6 +10,10 @@ import com.securityc4po.api.pentest.Pentest
|
|||
import com.securityc4po.api.pentest.PentestCategory
|
||||
import com.securityc4po.api.pentest.PentestEntity
|
||||
import com.securityc4po.api.pentest.PentestStatus
|
||||
import com.securityc4po.api.pentest.comment.Comment
|
||||
import com.securityc4po.api.pentest.comment.CommentEntity
|
||||
import com.securityc4po.api.pentest.comment.CommentRequestBody
|
||||
import com.securityc4po.api.pentest.comment.toCommentResponseBody
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
|
@ -1,4 +1,4 @@
|
|||
package com.securityc4po.api.comment
|
||||
package com.securityc4po.api.pentest.comment
|
||||
|
||||
import com.github.tomakehurst.wiremock.common.Json
|
||||
import com.securityc4po.api.BaseIntTest
|
||||
|
@ -9,6 +9,10 @@ import com.securityc4po.api.pentest.Pentest
|
|||
import com.securityc4po.api.pentest.PentestCategory
|
||||
import com.securityc4po.api.pentest.PentestEntity
|
||||
import com.securityc4po.api.pentest.PentestStatus
|
||||
import com.securityc4po.api.pentest.comment.Comment
|
||||
import com.securityc4po.api.pentest.comment.CommentEntity
|
||||
import com.securityc4po.api.pentest.comment.CommentRequestBody
|
||||
import com.securityc4po.api.pentest.comment.toCommentResponseBody
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
|
@ -0,0 +1,403 @@
|
|||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.github.tomakehurst.wiremock.common.Json
|
||||
import com.securityc4po.api.BaseDocumentationIntTest
|
||||
import com.securityc4po.api.configuration.NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
|
||||
import com.securityc4po.api.configuration.RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
import com.securityc4po.api.configuration.SIC_INNER_SHOULD_BE_STATIC
|
||||
import com.securityc4po.api.pentest.Pentest
|
||||
import com.securityc4po.api.pentest.PentestCategory
|
||||
import com.securityc4po.api.pentest.PentestEntity
|
||||
import com.securityc4po.api.pentest.PentestStatus
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.data.mongodb.core.query.Query
|
||||
import org.springframework.restdocs.operation.preprocess.Preprocessors
|
||||
import org.springframework.restdocs.payload.JsonFieldType
|
||||
import org.springframework.restdocs.payload.PayloadDocumentation
|
||||
import org.springframework.restdocs.request.RequestDocumentation
|
||||
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
|
||||
import reactor.core.publisher.Mono
|
||||
|
||||
@SuppressFBWarnings(
|
||||
SIC_INNER_SHOULD_BE_STATIC,
|
||||
NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR,
|
||||
RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
)
|
||||
class FindingControllerDocumentationTest: BaseDocumentationIntTest() {
|
||||
|
||||
@Autowired
|
||||
lateinit var mongoTemplate: MongoTemplate
|
||||
var mapper = ObjectMapper()
|
||||
|
||||
@BeforeEach
|
||||
fun init() {
|
||||
configureAdminToken()
|
||||
persistBasicTestScenario()
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun destroy() {
|
||||
cleanUp()
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFindings {
|
||||
@Test
|
||||
fun getFindingsByPentestId() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{pentestId}/findings", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(getFindingsResponse()))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to get the findings for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("[].id").type(JsonFieldType.STRING)
|
||||
.description("The id of the requested findings"),
|
||||
PayloadDocumentation.fieldWithPath("[].severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
|
||||
private fun getFindingsResponse() = listOf(
|
||||
findingOne.toFindingResponseBody()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFinding {
|
||||
@Test
|
||||
fun getFindingById() {
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingOne.toFindingResponseBody()))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("findingId").description("The id of the feinidng you want to get")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveFinding {
|
||||
@Test
|
||||
fun saveFindingByPentestId() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{pentestId}/finding", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to save the finding for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the saved finding"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "MEDIUM",
|
||||
title = "Found another Bug",
|
||||
description = "Another OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack more",
|
||||
mitigation = "Another None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdateFinding {
|
||||
@Test
|
||||
fun updateFindingById() {
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.patch()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("findingId").description("The id of the finding you want to update")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the updated finding"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "HIGH",
|
||||
title = "Updated Bug",
|
||||
description = "Updated OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "Still None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class DeleteFinding {
|
||||
@Test
|
||||
fun deleteFindingByPentestAndFindingId() {
|
||||
val pentestId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.delete()
|
||||
.uri("/pentests/{pentestId}/finding/{findingId}", pentestId, findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody()
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to remove the finidng from"),
|
||||
RequestDocumentation.parameterWithName("findingId").description("The id of the finding you want to delete")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the finding you deleted")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
// Project
|
||||
val projectOne = Project(
|
||||
id = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
client = "E Corp",
|
||||
title = "Some Mock API (v1.0) Scanning",
|
||||
createdAt = "2021-01-10T18:05:00Z",
|
||||
tester = "Novatester",
|
||||
projectPentests = emptyList(),
|
||||
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
|
||||
)
|
||||
// Pentests
|
||||
val pentestOne = Pentest(
|
||||
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = PentestStatus.NOT_STARTED,
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestTwo = Pentest(
|
||||
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestThree = Pentest(
|
||||
id = "74eae112-f62c-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.AUTHENTICATION_TESTING,
|
||||
refNumber = "OTG-AUTHN-001",
|
||||
status = PentestStatus.COMPLETED,
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
// Finding
|
||||
val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
// persist test data in database
|
||||
mongoTemplate.save(ProjectEntity(projectOne))
|
||||
mongoTemplate.save(PentestEntity(pentestOne))
|
||||
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||
mongoTemplate.save(PentestEntity(pentestThree))
|
||||
mongoTemplate.save(FindingEntity(findingOne))
|
||||
}
|
||||
|
||||
private fun configureAdminToken() {
|
||||
tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local")
|
||||
}
|
||||
|
||||
private fun cleanUp() {
|
||||
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), FindingEntity::class.java)
|
||||
|
||||
tokenAdmin = "n/a"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,270 @@
|
|||
package com.securityc4po.api.pentest.finding
|
||||
|
||||
import com.github.tomakehurst.wiremock.common.Json
|
||||
import com.securityc4po.api.BaseIntTest
|
||||
import com.securityc4po.api.configuration.NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
|
||||
import com.securityc4po.api.configuration.RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
import com.securityc4po.api.configuration.SIC_INNER_SHOULD_BE_STATIC
|
||||
import com.securityc4po.api.pentest.Pentest
|
||||
import com.securityc4po.api.pentest.PentestCategory
|
||||
import com.securityc4po.api.pentest.PentestEntity
|
||||
import com.securityc4po.api.pentest.PentestStatus
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.web.server.LocalServerPort
|
||||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.data.mongodb.core.query.Query
|
||||
import org.springframework.test.web.reactive.server.WebTestClient
|
||||
import reactor.core.publisher.Mono
|
||||
import java.time.Duration
|
||||
|
||||
@SuppressFBWarnings(
|
||||
SIC_INNER_SHOULD_BE_STATIC,
|
||||
NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR,
|
||||
RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
)
|
||||
class FindingControllerIntTest: BaseIntTest() {
|
||||
|
||||
@LocalServerPort
|
||||
private var port = 0
|
||||
|
||||
@Autowired
|
||||
lateinit var mongoTemplate: MongoTemplate
|
||||
|
||||
@Autowired
|
||||
private lateinit var webTestClient: WebTestClient
|
||||
|
||||
@BeforeEach
|
||||
fun setupWebClient() {
|
||||
webTestClient = WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:$port")
|
||||
.responseTimeout(Duration.ofMillis(10000))
|
||||
.build()
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun init() {
|
||||
configureAdminToken()
|
||||
persistBasicTestScenario()
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun destroy() {
|
||||
cleanUp()
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFindings {
|
||||
@Test
|
||||
fun `requesting findings by pentestId successfully`() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{pentestId}/findings", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(getFindings()))
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
|
||||
private fun getFindings() = listOf(
|
||||
findingOne.toFindingResponseBody()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFinding {
|
||||
@Test
|
||||
fun `requesting finding by findingId successfully`() {
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(findingOne.toFindingResponseBody()))
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveFinding {
|
||||
@Test
|
||||
fun `save finding successfully`() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{pentestId}/finding", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.severity").isEqualTo("MEDIUM")
|
||||
.jsonPath("$.title").isEqualTo("Found another Bug")
|
||||
.jsonPath("$.description").isEqualTo("Another OTG-INFO-002 Bug")
|
||||
.jsonPath("$.impact").isEqualTo("Service")
|
||||
.jsonPath("$.affectedUrls").isEmpty
|
||||
.jsonPath("$.reproduction").isEqualTo("Step 1: Hack more")
|
||||
.jsonPath("$.mitigation").isEqualTo("Another None")
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "MEDIUM",
|
||||
title = "Found another Bug",
|
||||
description = "Another OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack more",
|
||||
mitigation = "Another None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdateFinding {
|
||||
@Test
|
||||
fun `update finding successfully`() {
|
||||
val findingId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{findingId}/finding", findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.severity").isEqualTo("HIGH")
|
||||
.jsonPath("$.title").isEqualTo("Updated Bug")
|
||||
.jsonPath("$.description").isEqualTo("Updated OTG-INFO-002 Bug")
|
||||
.jsonPath("$.impact").isEqualTo("Service")
|
||||
.jsonPath("$.affectedUrls").isEmpty
|
||||
.jsonPath("$.reproduction").isEqualTo("Step 1: Hack")
|
||||
.jsonPath("$.mitigation").isEqualTo("Still None")
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "HIGH",
|
||||
title = "Updated Bug",
|
||||
description = "Updated OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "Still None"
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class DeleteFinding {
|
||||
@Test
|
||||
fun `delete finding successfully`() {
|
||||
val pentestId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
val findingId = "ab62d365-1b1d-4da1-89bc-5496616e220f"
|
||||
webTestClient.delete()
|
||||
.uri("/pentests/{pentestId}/finding/{findingId}", pentestId, findingId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.id").isEqualTo("ab62d365-1b1d-4da1-89bc-5496616e220f")
|
||||
}
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
// project
|
||||
val projectOne = Project(
|
||||
id = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
client = "E Corp",
|
||||
title = "Some Mock API (v1.0) Scanning",
|
||||
createdAt = "2021-01-10T18:05:00Z",
|
||||
tester = "Novatester",
|
||||
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
|
||||
)
|
||||
// pentests
|
||||
val pentestOne = Pentest(
|
||||
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = PentestStatus.NOT_STARTED,
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestTwo = Pentest(
|
||||
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestThree = Pentest(
|
||||
id = "16vbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.AUTHENTICATION_TESTING,
|
||||
refNumber = "OTG-AUTHN-001",
|
||||
status = PentestStatus.COMPLETED,
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
// Finding
|
||||
val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
// persist test data in database
|
||||
mongoTemplate.save(ProjectEntity(projectOne))
|
||||
mongoTemplate.save(PentestEntity(pentestOne))
|
||||
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||
mongoTemplate.save(PentestEntity(pentestThree))
|
||||
mongoTemplate.save(FindingEntity(findingOne))
|
||||
}
|
||||
|
||||
private fun configureAdminToken() {
|
||||
tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local")
|
||||
}
|
||||
|
||||
private fun cleanUp() {
|
||||
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), FindingEntity::class.java)
|
||||
|
||||
tokenAdmin = "n/a"
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
"data": {
|
||||
"_id": "89703b19-16c7-49e5-8e33-0c706313e5fe",
|
||||
"title": "Test Comment",
|
||||
"description": "Test Comment Description",
|
||||
"description": "No related findings",
|
||||
"relatedFindings": []
|
||||
},
|
||||
"_class": "com.securityc4po.api.comment.CommentEntity"
|
||||
|
@ -25,8 +25,8 @@
|
|||
},
|
||||
"data": {
|
||||
"_id": "df516de6-ca5e-44a6-ac50-db89bb17aac3",
|
||||
"title": "New Test",
|
||||
"description": "New Test",
|
||||
"title": "New Test Comment",
|
||||
"description": "Two related findings",
|
||||
"relatedFindings": [
|
||||
"0bda8950-94fa-4ec6-8fa7-e09f5a8cd3e8",
|
||||
"4ddb84f6-068c-4319-a8ee-1000008bb75a"
|
||||
|
@ -44,8 +44,8 @@
|
|||
},
|
||||
"data": {
|
||||
"_id": "e55e943b-6a48-4d84-8d72-b48d7d9de5b7",
|
||||
"title": "Wow another one?",
|
||||
"description": "Epic!",
|
||||
"title": "Another Test Comment",
|
||||
"description": "One related findings",
|
||||
"relatedFindings": [
|
||||
"5e22d38f-a4f6-4809-84ea-a803b5f1f9fc"
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue