Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[frontend/backend] add inject result inside report #1519

Merged
merged 12 commits into from
Oct 3, 2024
15 changes: 15 additions & 0 deletions openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,21 @@
));
}

@GetMapping(EXERCISE_URI + "/{exerciseId}/injects/resultdto")
@PreAuthorize("isExerciseObserver(#exerciseId)")
@Transactional(readOnly = true)
public List<InjectResultDTO> exerciseInjectsWithExpectations(@PathVariable final String exerciseId) {
return this.injectRepository.findAll(InjectSpecification.fromExercise(exerciseId)).stream()
.map(inject -> AtomicTestingMapper.toDto(
inject, getTargets(
inject.getTeams(),
inject.getAssets(),
inject.getAssetGroups()
)

Check warning on line 223 in openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java#L215-L223

Added lines #L215 - L223 were not covered by tests
))
.collect(Collectors.toList());

Check warning on line 225 in openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/rest/inject/InjectApi.java#L225

Added line #L225 was not covered by tests
}

@GetMapping(EXERCISE_URI + "/{exerciseId}/injects/{injectId}")
@PreAuthorize("isExerciseObserver(#exerciseId)")
public Inject exerciseInject(@PathVariable String exerciseId, @PathVariable String injectId) {
Expand Down
14 changes: 14 additions & 0 deletions openbas-api/src/main/java/io/openbas/rest/report/ReportApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import io.openbas.database.model.*;
import io.openbas.rest.exercise.ExerciseService;
import io.openbas.rest.helper.RestBehavior;
import io.openbas.rest.report.form.ReportInjectCommentInput;
import io.openbas.rest.report.form.ReportInput;
import io.openbas.service.InjectService;
import io.openbas.service.ReportService;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
Expand All @@ -23,6 +25,7 @@ public class ReportApi extends RestBehavior {

private final ExerciseService exerciseService;
private final ReportService reportService;
private final InjectService injectService;

@GetMapping("/api/reports/{reportId}")
savacano28 marked this conversation as resolved.
Show resolved Hide resolved
@PreAuthorize("isObserver()")
Expand All @@ -46,6 +49,17 @@ public Report createExerciseReport(@PathVariable String exerciseId, @Valid @Requ
return this.reportService.updateReport(report, input);
}

@PutMapping("/api/exercises/{exerciseId}/reports/{reportId}/inject-comments")
@PreAuthorize("isExercisePlanner(#exerciseId)")
@Transactional(rollbackOn = Exception.class)
public Iterable<ReportInjectComment> updateReportInjectComment(@PathVariable String exerciseId, @PathVariable String reportId, @Valid @RequestBody ReportInjectCommentInput input) {
Report report = this.reportService.report(UUID.fromString(reportId));
assert exerciseId.equals(report.getExercise().getId());
Inject inject = this.injectService.inject(input.getInjectId());
assert exerciseId.equals(inject.getExercise().getId());
return this.reportService.updateReportInjectComment(report, inject, input);
}

@PutMapping("/api/exercises/{exerciseId}/reports/{reportId}")
@PreAuthorize("isExercisePlanner(#exerciseId)")
@Transactional(rollbackOn = Exception.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.openbas.rest.report.form;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;

import static io.openbas.config.AppConfig.MANDATORY_MESSAGE;

@Data
public class ReportInjectCommentInput {
@NotBlank(message = MANDATORY_MESSAGE)
@JsonProperty("inject_id")
private String injectId;

@JsonProperty("report_inject_comment")
private String comment;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.*;
import jakarta.transaction.Transactional;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;
import org.apache.commons.io.FilenameUtils;
Expand Down Expand Up @@ -145,6 +146,11 @@
}
}

public Inject inject(@NotBlank final String injectId) {
return this.injectRepository.findById(injectId)
.orElseThrow(() -> new ElementNotFoundException("Inject not found"));

Check warning on line 151 in openbas-api/src/main/java/io/openbas/service/InjectService.java

View check run for this annotation

Codecov / codecov/patch

openbas-api/src/main/java/io/openbas/service/InjectService.java#L150-L151

Added lines #L150 - L151 were not covered by tests
}

@Tracing(name = "Fetch injects with criteria builder", layer = "service", operation = "GET")
public List<InjectOutput> injects(Specification<Inject> specification) {
CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
Expand Down
22 changes: 20 additions & 2 deletions openbas-api/src/main/java/io/openbas/service/ReportService.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package io.openbas.service;

import io.openbas.database.model.Report;
import io.openbas.database.model.ReportInformation;
import io.openbas.database.model.*;
import io.openbas.database.repository.ReportRepository;
import io.openbas.database.specification.ReportSpecification;
import io.openbas.rest.exception.ElementNotFoundException;
import io.openbas.rest.report.form.ReportInjectCommentInput;
import io.openbas.rest.report.form.ReportInput;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static java.time.Instant.now;
Expand Down Expand Up @@ -50,6 +51,23 @@ public Report updateReport(@NotNull final Report report, @NotNull final ReportIn
return this.reportRepository.save(report);
}

public List<ReportInjectComment> updateReportInjectComment(@NotNull final Report report, @NotNull final Inject inject, @NotNull final ReportInjectCommentInput input){
Optional<ReportInjectComment> reportInjectComment = this.reportRepository.findReportInjectComment(UUID.fromString(report.getId()), inject.getId());
ReportInjectComment injectComment;
if (reportInjectComment.isPresent()) {
injectComment = reportInjectComment.get();
injectComment.setComment(input.getComment());
} else {
injectComment = new ReportInjectComment();
injectComment.setInject(inject);
injectComment.setReport(report);
injectComment.setComment(input.getComment());
report.getReportInjectsComments().add(injectComment);
}
this.reportRepository.save(report);
return report.getReportInjectsComments();
}

public void deleteReport(@NotBlank final UUID reportId) {
this.reportRepository.deleteById(reportId);
}
Expand Down
43 changes: 42 additions & 1 deletion openbas-api/src/test/java/io/openbas/rest/ReportApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import io.openbas.rest.exercise.ExerciseService;
import io.openbas.rest.mapper.MapperApi;
import io.openbas.rest.report.ReportApi;
import io.openbas.rest.report.form.ReportInjectCommentInput;
import io.openbas.rest.report.form.ReportInput;
import io.openbas.service.InjectService;
import io.openbas.service.ReportService;
import io.openbas.utils.fixtures.PaginationFixture;
import io.openbas.utils.mockUser.WithMockPlannerUser;
Expand All @@ -21,6 +23,7 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

Expand All @@ -44,6 +47,8 @@ public class ReportApiTest {
private ReportService reportService;
@Mock
private ExerciseService exerciseService;
@Mock
private InjectService injectService;

@Autowired
private ObjectMapper objectMapper;
Expand All @@ -54,7 +59,7 @@ public class ReportApiTest {

@BeforeEach
void before() throws IllegalAccessException, NoSuchFieldException {
ReportApi reportApi = new ReportApi(exerciseService, reportService);
ReportApi reportApi = new ReportApi(exerciseService, reportService, injectService);
Field sessionContextField = MapperApi.class.getSuperclass().getDeclaredField("mapper");
sessionContextField.setAccessible(true);
sessionContextField.set(reportApi, objectMapper);
Expand Down Expand Up @@ -149,6 +154,42 @@ void updateReportForExercise() throws Exception {
assertEquals(JsonPath.read(response, "$.report_id"), report.getId());
}

@DisplayName("Update report inject comment")
@Test
void updateReportInjectCommentTest() throws Exception {
// -- PREPARE --
Inject inject = new Inject();
inject.setTitle("Test inject");
inject.setId(UUID.randomUUID().toString());
inject.setExercise(exercise);
report.setExercise(exercise);
ReportInjectCommentInput injectCommentInput = new ReportInjectCommentInput();
injectCommentInput.setInjectId(inject.getId());
injectCommentInput.setComment("Comment test");

when(reportService.report(any())).thenReturn(report);
when(injectService.inject(any())).thenReturn(inject);
when(reportService.updateReportInjectComment(any(Report.class), any(Inject.class), any(ReportInjectCommentInput.class)))
.thenReturn(null);

// -- EXECUTE --
String response = mvc
.perform(MockMvcRequestBuilders.put("/api/exercises/"+ exercise.getId() +"/reports/"+ report.getId()+"/inject-comments")
.content(asJsonString(injectCommentInput))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().is2xxSuccessful())
.andReturn()
.getResponse()
.getContentAsString();

// -- ASSERT --
verify(reportService).report(UUID.fromString(report.getId()));
verify(injectService).inject(inject.getId());
verify(reportService).updateReportInjectComment(report, inject, injectCommentInput);
assertNotNull(response);
}

@DisplayName("Delete Report")
@Test
void deleteReportForExercise() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package io.openbas.service;

import io.openbas.database.model.Report;
import io.openbas.database.model.ReportInformation;
import io.openbas.database.model.ReportInformationsType;
import io.openbas.database.model.*;
import io.openbas.database.repository.ReportRepository;
import io.openbas.rest.report.form.ReportInformationInput;
import io.openbas.rest.report.form.ReportInjectCommentInput;
import io.openbas.rest.report.form.ReportInput;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
Expand All @@ -16,9 +18,11 @@
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -99,7 +103,7 @@ void updateReport() throws Exception {
when(reportRepository.save(any(Report.class))).thenReturn(report);

// -- EXECUTE --
reportService.updateReport(report, reportInput);
reportService.updateReport(report, reportInput);

// -- ASSERT --
ArgumentCaptor<Report> reportCaptor = ArgumentCaptor.forClass(Report.class);
Expand All @@ -109,6 +113,73 @@ void updateReport() throws Exception {
assertEquals(1, capturedReport.getReportInformations().size());
assertEquals(true, capturedReport.getReportInformations().getFirst().getReportInformationsDisplay());
}

@Nested
@DisplayName("Reports inject comment")
class ReportInjectCommentTest {
@DisplayName("Test update existing report inject comment")
@Test
void updateExistingReportInjectComment() {
// -- PREPARE --
Report report = new Report();
report.setName("test");
report.setId(UUID.randomUUID().toString());
Inject inject = new Inject();
inject.setId("fakeID123");

// add report inject comment
ReportInjectComment existingReportInjectComment = new ReportInjectComment();
existingReportInjectComment.setReport(report);
existingReportInjectComment.setComment("comment");
existingReportInjectComment.setInject(inject);
report.setReportInjectsComments(List.of(existingReportInjectComment));

ReportInjectCommentInput commentInput = new ReportInjectCommentInput();
commentInput.setInjectId(inject.getId());
commentInput.setComment("New comment");

// Mock
when(reportRepository.findReportInjectComment(eq(UUID.fromString(report.getId())), eq(inject.getId()))).thenReturn(Optional.of(existingReportInjectComment));

// -- EXECUTE --
reportService.updateReportInjectComment(report, inject, commentInput);

// -- ASSERT --
ArgumentCaptor<Report> reportCaptor = ArgumentCaptor.forClass(Report.class);
verify(reportRepository).save(reportCaptor.capture());
Report capturedReport= reportCaptor.getValue();
assertEquals(1, capturedReport.getReportInjectsComments().size());
assertEquals(commentInput.getComment(), capturedReport.getReportInjectsComments().getFirst().getComment());
}

@DisplayName("Test add new report inject comment")
@Test
void addReportInjectComment() throws Exception {
// -- PREPARE --
Report report = new Report();
report.setName("test");
report.setId(UUID.randomUUID().toString());
Inject inject = new Inject();
inject.setId("fakeID123");

ReportInjectCommentInput commentInput = new ReportInjectCommentInput();
commentInput.setInjectId(inject.getId());
commentInput.setComment("New test comment");

// Mock
when(reportRepository.findReportInjectComment(eq(UUID.fromString(report.getId())), eq(inject.getId()))).thenReturn(Optional.empty());

// -- EXECUTE --
reportService.updateReportInjectComment(report, inject, commentInput);

// -- ASSERT --
ArgumentCaptor<Report> reportCaptor = ArgumentCaptor.forClass(Report.class);
verify(reportRepository).save(reportCaptor.capture());
Report capturedReport= reportCaptor.getValue();
assertEquals(1, capturedReport.getReportInjectsComments().size());
assertEquals(commentInput.getComment(), capturedReport.getReportInjectsComments().getFirst().getComment());
}
}
}


Expand Down
5 changes: 5 additions & 0 deletions openbas-front/src/actions/exercises/exercise-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export const searchExerciseInjects = (exerciseId: Exercise['exercise_id'], searc
return simplePostCall(uri, data);
};

export const exerciseInjectsResultDTO = (exerciseId: Exercise['exercise_id']) => {
const uri = `${EXERCISE_URI}${exerciseId}/injects/resultdto`;
return simpleCall(uri);
};

// -- IMPORT --

export const importXlsForExercise = (exerciseId: Exercise['exercise_id'], importId: string, input: InjectsImportInput) => {
Expand Down
13 changes: 11 additions & 2 deletions openbas-front/src/actions/reports/report-actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Dispatch } from 'redux';
import type { Exercise, Report, ReportInput } from '../../utils/api-types';
import { delReferential, getReferential, postReferential, putReferential } from '../../utils/Action';
import type { Exercise, Report, ReportInjectComment, ReportInput } from '../../utils/api-types';
import { delReferential, getReferential, postReferential, putReferential, simplePutCall } from '../../utils/Action';
import * as schema from '../Schema';

export const fetchReportsForExercise = (exerciseId: Exercise['exercise_id']) => (dispatch: Dispatch) => {
Expand All @@ -27,6 +27,15 @@ export const updateReportForExercise = (
return putReferential(schema.report, uri, data)(dispatch);
};

export const updateReportInjectCommentForExercise = (
exerciseId: Exercise['exercise_id'],
reportId: Report['report_id'],
data: ReportInjectComment,
) => {
const uri = `/api/exercises/${exerciseId}/reports/${reportId}/inject-comments`;
return simplePutCall(uri, data);
};

export const deleteReportForExercise = (exerciseId: Exercise['exercise_id'], reportId: Report['report_id']) => (dispatch: Dispatch) => {
const uri = `/api/exercises/${exerciseId}/reports/${reportId}`;
return delReferential(uri, 'reports', reportId)(dispatch);
Expand Down
Loading