diff --git a/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseApi.java b/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseApi.java index 7564d5b76c..f6b1e1060d 100644 --- a/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseApi.java +++ b/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseApi.java @@ -13,6 +13,7 @@ import io.openbas.rest.exercise.exports.VariableMixin; import io.openbas.rest.exercise.exports.VariableWithValueMixin; import io.openbas.rest.exercise.form.*; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.helper.RestBehavior; import io.openbas.rest.helper.TeamHelper; import io.openbas.rest.inject.form.InjectExpectationResultsByAttackPattern; @@ -231,14 +232,7 @@ public Iterable addExerciseTeams( @PreAuthorize("isExercisePlanner(#exerciseId)") public Iterable removeExerciseTeams(@PathVariable String exerciseId, @Valid @RequestBody ExerciseUpdateTeamsInput input) { - Exercise exercise = this.exerciseService.exercise(exerciseId); - // Remove teams from exercise - List teams = exercise.getTeams().stream().filter(team -> !input.getTeamIds().contains(team.getId())).toList(); - exercise.setTeams(new ArrayList<>(teams)); - this.exerciseService.updateExercise(exercise); - // Remove all association between users / exercises / teams - input.getTeamIds().forEach(exerciseTeamUserRepository::deleteTeamFromAllReferences); - return teamRepository.findAllById(input.getTeamIds()); + return this.exerciseService.removeTeams(exerciseId, input.getTeamIds()); } @Transactional(rollbackOn = Exception.class) diff --git a/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseImportApi.java b/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseImportApi.java index 8f2656618a..048f03d95b 100644 --- a/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseImportApi.java +++ b/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseImportApi.java @@ -4,6 +4,7 @@ import io.openbas.database.model.ImportMapper; import io.openbas.database.repository.ImportMapperRepository; import io.openbas.rest.exception.ElementNotFoundException; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.helper.RestBehavior; import io.openbas.rest.scenario.form.InjectsImportInput; import io.openbas.rest.scenario.response.ImportTestSummary; diff --git a/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseService.java b/openbas-api/src/main/java/io/openbas/rest/exercise/service/ExerciseService.java similarity index 90% rename from openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseService.java rename to openbas-api/src/main/java/io/openbas/rest/exercise/service/ExerciseService.java index 89082248b8..8423904b62 100644 --- a/openbas-api/src/main/java/io/openbas/rest/exercise/ExerciseService.java +++ b/openbas-api/src/main/java/io/openbas/rest/exercise/service/ExerciseService.java @@ -1,13 +1,11 @@ -package io.openbas.rest.exercise; +package io.openbas.rest.exercise.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import io.openbas.config.OpenBASConfig; import io.openbas.database.model.*; import io.openbas.database.raw.RawExerciseSimple; -import io.openbas.database.repository.ArticleRepository; -import io.openbas.database.repository.ExerciseRepository; -import io.openbas.database.repository.TeamRepository; +import io.openbas.database.repository.*; import io.openbas.rest.exception.ElementNotFoundException; import io.openbas.rest.exercise.form.ExerciseSimple; import io.openbas.rest.inject.service.InjectDuplicateService; @@ -23,7 +21,6 @@ import jakarta.persistence.Tuple; import jakarta.persistence.TypedQuery; import jakarta.persistence.criteria.*; -import jakarta.transaction.Transactional; import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; @@ -33,6 +30,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.Instant; @@ -67,6 +65,9 @@ public class ExerciseService { private final ArticleRepository articleRepository; private final ExerciseRepository exerciseRepository; private final TeamRepository teamRepository; + private final ExerciseTeamUserRepository exerciseTeamUserRepository; + private final InjectRepository injectRepository; + private final LessonsCategoryRepository lessonsCategoryRepository; // region properties @Value("${openbas.mail.imap.enabled}") @@ -79,18 +80,19 @@ public class ExerciseService { private OpenBASConfig openBASConfig; // endregion - public List exercises(){ + public List exercises() { // We get the exercises depending on whether or not we are granted List exercises = currentUser().isAdmin() ? exerciseRepository.rawAll() : exerciseRepository.rawAllGranted(currentUser().getId()); - return exercises.stream().map(exercise->exerciseMapper.fromRawExerciseSimple(exercise)).collect(Collectors.toList()); + return exercises.stream().map(exercise -> exerciseMapper.fromRawExerciseSimple(exercise)) + .collect(Collectors.toList()); } public Page exercises( - Specification specification, - Specification specificationCount, - Pageable pageable) { + Specification specification, + Specification specificationCount, + Pageable pageable) { CriteriaBuilder cb = this.entityManager.getCriteriaBuilder(); CriteriaQuery cq = cb.createTupleQuery(); @@ -120,9 +122,11 @@ public Page exercises( List exercises = execution(query); for (ExerciseSimple exercise : exercises) { - if (exercise.getInjectIds() != null) { - exercise.setExpectationResultByTypes(resultUtils.getResultsByTypes(new HashSet<>(Arrays.asList(exercise.getInjectIds())))); - exercise.setTargets(resultUtils.getInjectTargetWithResults(new HashSet<>(Arrays.asList(exercise.getInjectIds())))); + if (exercise.getInjectIds() != null) { + exercise.setExpectationResultByTypes( + resultUtils.getResultsByTypes(new HashSet<>(Arrays.asList(exercise.getInjectIds())))); + exercise.setTargets( + resultUtils.getInjectTargetWithResults(new HashSet<>(Arrays.asList(exercise.getInjectIds())))); } } @@ -189,7 +193,7 @@ private List execution(TypedQuery query) { // -- CREATION -- - @Transactional(rollbackOn = Exception.class) + @Transactional(rollbackFor = Exception.class) public Exercise createExercise(@NotNull final Exercise exercise) { if (imapEnabled) { exercise.setFrom(imapUsername); @@ -410,4 +414,20 @@ public Iterable scenarioExercises(@NotBlank String scenarioId) { public List getGlobalResults(@NotBlank String exerciseId) { return resultUtils.getResultsByTypes(exerciseRepository.findInjectsByExercise(exerciseId)); } + + // -- TEAMS -- + + @Transactional(rollbackFor = Exception.class) + public Iterable removeTeams(@NotBlank final String exerciseId, @NotNull final List teamIds) { + // Remove teams from exercise + this.exerciseRepository.removeTeams(exerciseId, teamIds); + // Remove all association between users / exercises / teams + this.exerciseTeamUserRepository.deleteTeamsFromAllReferences(teamIds); + // Remove all association between injects and teams + this.injectRepository.removeTeamsForExercise(exerciseId, teamIds); + // Remove all association between lessons learned and teams + this.lessonsCategoryRepository.removeTeamsForExercise(exerciseId, teamIds); + return teamRepository.findAllById(teamIds); + } + } diff --git a/openbas-api/src/main/java/io/openbas/rest/report/ReportApi.java b/openbas-api/src/main/java/io/openbas/rest/report/ReportApi.java index a1908cd4d0..21427d7245 100644 --- a/openbas-api/src/main/java/io/openbas/rest/report/ReportApi.java +++ b/openbas-api/src/main/java/io/openbas/rest/report/ReportApi.java @@ -1,7 +1,7 @@ package io.openbas.rest.report; import io.openbas.database.model.*; -import io.openbas.rest.exercise.ExerciseService; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.helper.RestBehavior; import io.openbas.rest.report.form.ReportInjectCommentInput; import io.openbas.rest.report.form.ReportInput; diff --git a/openbas-api/src/main/java/io/openbas/rest/scenario/ScenarioExerciseApi.java b/openbas-api/src/main/java/io/openbas/rest/scenario/ScenarioExerciseApi.java index ac1efe5fdc..a6d3e8f536 100644 --- a/openbas-api/src/main/java/io/openbas/rest/scenario/ScenarioExerciseApi.java +++ b/openbas-api/src/main/java/io/openbas/rest/scenario/ScenarioExerciseApi.java @@ -2,7 +2,7 @@ import io.openbas.aop.LogExecutionTime; import io.openbas.database.model.Exercise; -import io.openbas.rest.exercise.ExerciseService; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.exercise.form.ExerciseSimple; import io.openbas.utils.pagination.SearchPaginationInput; import jakarta.validation.Valid; diff --git a/openbas-api/src/main/java/io/openbas/service/ScenarioService.java b/openbas-api/src/main/java/io/openbas/service/ScenarioService.java index 59fef43e04..8e735582a9 100644 --- a/openbas-api/src/main/java/io/openbas/service/ScenarioService.java +++ b/openbas-api/src/main/java/io/openbas/service/ScenarioService.java @@ -103,7 +103,8 @@ public class ScenarioService { private final TeamService teamService; private final FileService fileService; private final InjectDuplicateService injectDuplicateService; - + private final InjectRepository injectRepository; + private final LessonsCategoryRepository lessonsCategoryRepository; @Transactional public Scenario createScenario(@NotNull final Scenario scenario) { @@ -460,13 +461,16 @@ public Iterable addTeams(@NotBlank final String scenarioId, @NotNull final return teamsToAdd; } + @Transactional(rollbackFor = Exception.class) public Iterable removeTeams(@NotBlank final String scenarioId, @NotNull final List teamIds) { - Scenario scenario = this.scenario(scenarioId); - List teams = scenario.getTeams().stream().filter(team -> !teamIds.contains(team.getId())).toList(); - scenario.setTeams(new ArrayList<>(teams)); - this.updateScenario(scenario); + // Remove teams from exercise + this.scenarioRepository.removeTeams(scenarioId, teamIds); // Remove all association between users / exercises / teams - teamIds.forEach(this.scenarioTeamUserRepository::deleteTeamFromAllReferences); + this.scenarioTeamUserRepository.deleteTeamFromAllReferences(teamIds); + // Remove all association between injects and teams + this.injectRepository.removeTeamsForScenario(scenarioId, teamIds); + // Remove all association between lessons learned and teams + this.lessonsCategoryRepository.removeTeamsForScenario(scenarioId, teamIds); return teamRepository.findAllById(teamIds); } diff --git a/openbas-api/src/test/java/io/openbas/rest/ExerciseLessonsApiTest.java b/openbas-api/src/test/java/io/openbas/rest/ExerciseLessonsApiTest.java index c7700fa257..386bbcb9b5 100644 --- a/openbas-api/src/test/java/io/openbas/rest/ExerciseLessonsApiTest.java +++ b/openbas-api/src/test/java/io/openbas/rest/ExerciseLessonsApiTest.java @@ -1,12 +1,15 @@ package io.openbas.rest; import io.openbas.IntegrationTest; -import io.openbas.database.model.*; +import io.openbas.database.model.Exercise; +import io.openbas.database.model.LessonsCategory; +import io.openbas.database.model.Team; +import io.openbas.database.model.User; import io.openbas.database.repository.ExerciseRepository; import io.openbas.database.repository.LessonsCategoryRepository; import io.openbas.database.repository.TeamRepository; import io.openbas.database.repository.UserRepository; -import io.openbas.rest.exercise.ExerciseService; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.lessons.form.LessonsSendInput; import io.openbas.service.MailingService; import io.openbas.utils.mockUser.WithMockPlannerUser; @@ -26,9 +29,9 @@ import static io.openbas.utils.fixtures.ExerciseLessonsCategoryFixture.getLessonsCategory; import static io.openbas.utils.fixtures.TeamFixture.getTeam; import static io.openbas.utils.fixtures.UserFixture.getUser; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.mockito.Mockito.*; @SpringBootTest diff --git a/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java b/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java index 03e5a3ddae..2a4f366166 100644 --- a/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java +++ b/openbas-api/src/test/java/io/openbas/rest/InjectApiTest.java @@ -5,7 +5,7 @@ import io.openbas.database.model.InjectorContract; import io.openbas.database.model.*; import io.openbas.database.repository.*; -import io.openbas.rest.exercise.ExerciseService; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.inject.form.InjectInput; import io.openbas.service.ScenarioService; import io.openbas.utils.fixtures.InjectExpectationFixture; diff --git a/openbas-api/src/test/java/io/openbas/rest/ReportApiTest.java b/openbas-api/src/test/java/io/openbas/rest/ReportApiTest.java index e78a9dd9fb..f02074ea10 100644 --- a/openbas-api/src/test/java/io/openbas/rest/ReportApiTest.java +++ b/openbas-api/src/test/java/io/openbas/rest/ReportApiTest.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; import io.openbas.database.model.*; -import io.openbas.rest.exercise.ExerciseService; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.mapper.MapperApi; import io.openbas.rest.report.ReportApi; import io.openbas.rest.report.form.ReportInjectCommentInput; diff --git a/openbas-api/src/test/java/io/openbas/service/ExerciseServiceTest.java b/openbas-api/src/test/java/io/openbas/service/ExerciseServiceTest.java index c4ff3c65a2..87591c7016 100644 --- a/openbas-api/src/test/java/io/openbas/service/ExerciseServiceTest.java +++ b/openbas-api/src/test/java/io/openbas/service/ExerciseServiceTest.java @@ -1,86 +1,146 @@ package io.openbas.service; import io.openbas.database.model.*; -import io.openbas.database.repository.ArticleRepository; -import io.openbas.database.repository.ExerciseRepository; -import io.openbas.database.repository.TeamRepository; -import io.openbas.rest.exercise.ExerciseService; +import io.openbas.database.repository.*; +import io.openbas.rest.exercise.service.ExerciseService; import io.openbas.rest.inject.service.InjectDuplicateService; import io.openbas.utils.ExerciseMapper; import io.openbas.utils.ResultUtils; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import io.openbas.utils.fixtures.ExerciseFixture; +import org.junit.jupiter.api.*; import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; -import static io.openbas.utils.fixtures.TeamFixture.getTeam; +import static io.openbas.database.specification.TeamSpecification.fromExercise; +import static io.openbas.injectors.email.EmailContract.EMAIL_DEFAULT; import static io.openbas.utils.fixtures.ExerciseFixture.getExercise; +import static io.openbas.utils.fixtures.InjectFixture.getInjectForEmailContract; +import static io.openbas.utils.fixtures.TeamFixture.getTeam; +import static io.openbas.utils.fixtures.UserFixture.getUser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @SpringBootTest -public class ExerciseServiceTest { - @Mock - GrantService grantService; - @Mock - InjectDuplicateService injectDuplicateService; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ExerciseServiceTest { + + @Mock + GrantService grantService; + @Mock + InjectDuplicateService injectDuplicateService; @Mock VariableService variableService; - @Autowired - private TeamService teamService; + @Autowired + private TeamService teamService; @Autowired ExerciseMapper exerciseMapper; @Autowired ResultUtils resultUtils; - @Autowired - private ArticleRepository articleRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired - private TeamRepository teamRepository; - - @InjectMocks - private ExerciseService exerciseService; - @BeforeEach - void setUp() { - exerciseService = new ExerciseService(grantService, injectDuplicateService, - teamService,variableService, exerciseMapper, resultUtils, articleRepository, - exerciseRepository, teamRepository); - } - - @DisplayName("Should create new contextual teams while exercise duplication") - @Test - @Transactional(rollbackOn = Exception.class) - void createNewContextualTeamsWhileExerciseDuplication(){ - // -- PREPARE -- - List exerciseTeams = new ArrayList<>();; - Team contextualTeam = this.teamRepository.save(getTeam(null, "fakeTeamName1", true)); - exerciseTeams.add(contextualTeam); - Team noContextualTeam = this.teamRepository.save(getTeam(null, "fakeTeamName2",false)); - exerciseTeams.add(noContextualTeam); - Exercise exercise = this.exerciseRepository.save(getExercise(exerciseTeams)); - - // -- EXECUTE -- - Exercise exerciseDuplicated = exerciseService.getDuplicateExercise(exercise.getId()); - - // -- ASSERT -- - assertNotEquals(exercise.getId(), exerciseDuplicated.getId()); - assertEquals(2, exerciseDuplicated.getTeams().size()); - exerciseDuplicated.getTeams().forEach(team -> { - if (team.getContextual()){ - assertNotEquals(contextualTeam.getId(), team.getId()); - assertEquals(contextualTeam.getName(), team.getName()); - } else { - assertEquals(noContextualTeam.getId(), team.getId()); - } - }); - } + @Autowired + private ArticleRepository articleRepository; + @Autowired + private ExerciseRepository exerciseRepository; + @Autowired + private TeamRepository teamRepository; + + @Autowired + private UserRepository userRepository; + @Autowired + private InjectRepository injectRepository; + @Autowired + private ExerciseTeamUserRepository exerciseTeamUserRepository; + @Autowired + private InjectorContractRepository injectorContractRepository; + @Autowired + private LessonsCategoryRepository lessonsCategoryRepository; + + private static String USER_ID; + private static String TEAM_ID; + private static String INJECT_ID; + + @InjectMocks + private ExerciseService exerciseService; + + @BeforeEach + void setUp() { + exerciseService = new ExerciseService( + grantService, injectDuplicateService, + teamService, variableService, exerciseMapper, resultUtils,articleRepository, exerciseRepository, teamRepository, + exerciseTeamUserRepository, injectRepository, lessonsCategoryRepository + ); + } + + @AfterAll + public void teardown() { + this.userRepository.deleteById(USER_ID); + this.teamRepository.deleteById(TEAM_ID); + this.injectRepository.deleteById(INJECT_ID); + } + + @DisplayName("Should create new contextual teams while exercise duplication") + @Test + @Transactional(rollbackFor = Exception.class) + void createNewContextualTeamsWhileExerciseDuplication() { + // -- PREPARE -- + List exerciseTeams = new ArrayList<>(); + Team contextualTeam = this.teamRepository.save(getTeam(null, "fakeTeamName1", true)); + exerciseTeams.add(contextualTeam); + Team noContextualTeam = this.teamRepository.save(getTeam(null, "fakeTeamName2", false)); + exerciseTeams.add(noContextualTeam); + Exercise exercise = this.exerciseRepository.save(getExercise(exerciseTeams)); + + // -- EXECUTE -- + Exercise exerciseDuplicated = exerciseService.getDuplicateExercise(exercise.getId()); + + // -- ASSERT -- + assertNotEquals(exercise.getId(), exerciseDuplicated.getId()); + assertEquals(2, exerciseDuplicated.getTeams().size()); + exerciseDuplicated.getTeams().forEach(team -> { + if (team.getContextual()) { + assertNotEquals(contextualTeam.getId(), team.getId()); + assertEquals(contextualTeam.getName(), team.getName()); + } else { + assertEquals(noContextualTeam.getId(), team.getId()); + } + }); + } + + @DisplayName("Should remove team from exercise") + @Test + void testRemoveTeams() { + // -- PREPARE -- + User user = getUser(); + User userSaved = this.userRepository.saveAndFlush(user); + USER_ID = userSaved.getId(); + Team team = getTeam(userSaved); + Team teamSaved = this.teamRepository.saveAndFlush(team); + TEAM_ID = teamSaved.getId(); + Exercise exercise = ExerciseFixture.getExercise(); + exercise.setTeams(List.of(teamSaved)); + exercise.setFrom(user.getEmail()); + Exercise exerciseSaved = this.exerciseRepository.saveAndFlush(exercise); + + InjectorContract injectorContract = this.injectorContractRepository.findById(EMAIL_DEFAULT).orElseThrow(); + Inject injectDefaultEmail = getInjectForEmailContract(injectorContract); + injectDefaultEmail.setExercise(exerciseSaved); + injectDefaultEmail.setTeams(List.of(teamSaved)); + Inject injectDefaultEmailSaved = this.injectRepository.saveAndFlush(injectDefaultEmail); + INJECT_ID = injectDefaultEmailSaved.getId(); + + // -- EXECUTE -- + this.exerciseService.removeTeams(exerciseSaved.getId(), List.of(teamSaved.getId())); + + // -- ASSERT -- + List teams = this.teamRepository.findAll(fromExercise(exerciseSaved.getId())); + assertEquals(0, teams.size()); + Inject injectAssert = this.injectRepository.findById(INJECT_ID).orElseThrow(); + assertEquals(0, injectAssert.getTeams().size()); + } } diff --git a/openbas-api/src/test/java/io/openbas/service/ScenarioServiceTest.java b/openbas-api/src/test/java/io/openbas/service/ScenarioServiceTest.java index 820c750486..bf3263ec6c 100644 --- a/openbas-api/src/test/java/io/openbas/service/ScenarioServiceTest.java +++ b/openbas-api/src/test/java/io/openbas/service/ScenarioServiceTest.java @@ -5,24 +5,29 @@ import io.openbas.rest.inject.service.InjectDuplicateService; import io.openbas.utils.ExerciseMapper; import io.openbas.utils.fixtures.ScenarioFixture; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import static io.openbas.utils.fixtures.TeamFixture.getTeam; -import static io.openbas.utils.fixtures.ScenarioFixture.getScenario; +import org.springframework.transaction.annotation.Transactional; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import static io.openbas.database.specification.TeamSpecification.fromScenario; +import static io.openbas.injectors.email.EmailContract.EMAIL_DEFAULT; +import static io.openbas.utils.fixtures.InjectFixture.getInjectForEmailContract; +import static io.openbas.utils.fixtures.TeamFixture.getTeam; +import static io.openbas.utils.fixtures.UserFixture.getUser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @SpringBootTest -public class ScenarioServiceTest { +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ScenarioServiceTest { @Autowired ScenarioRepository scenarioRepository; @@ -54,25 +59,39 @@ public class ScenarioServiceTest { private InjectDuplicateService injectDuplicateService; @Autowired private ExerciseMapper exerciseMapper; - + @Autowired + private InjectorContractRepository injectorContractRepository; + @Autowired + private LessonsCategoryRepository lessonsCategoryRepository; @InjectMocks private ScenarioService scenarioService; + private static String USER_ID; + private static String TEAM_ID; + private static String INJECT_ID; + @BeforeEach void setUp() { scenarioService = new ScenarioService(scenarioRepository, teamRepository, userRepository, documentRepository, scenarioTeamUserRepository, articleRepository, exerciseMapper, grantService, variableService, challengeService, - teamService, fileService, injectDuplicateService + teamService, fileService, injectDuplicateService, injectRepository, lessonsCategoryRepository ); } + @AfterAll + public void teardown() { + this.userRepository.deleteById(USER_ID); + this.teamRepository.deleteById(TEAM_ID); + this.injectRepository.deleteById(INJECT_ID); + } + @DisplayName("Should create new contextual teams during scenario duplication") @Test - @Transactional(rollbackOn = Exception.class) + @Transactional(rollbackFor = Exception.class) void createNewContextualTeamsDuringScenarioDuplication(){ // -- PREPARE -- - List scenarioTeams = new ArrayList<>();; + List scenarioTeams = new ArrayList<>(); Team contextualTeam = this.teamRepository.save(getTeam(null, "fakeTeamName1", true)); scenarioTeams.add(contextualTeam); Team noContextualTeam = this.teamRepository.save(getTeam(null, "fakeTeamName2",false)); @@ -100,8 +119,8 @@ void createNewContextualTeamsDuringScenarioDuplication(){ } }); assertEquals(1, scenarioDuplicated.getInjects().size()); - assertEquals(2, scenario.getInjects().get(0).getTeams().size()); - scenarioDuplicated.getInjects().get(0).getTeams().forEach(injectTeam -> { + assertEquals(2, scenario.getInjects().getFirst().getTeams().size()); + scenarioDuplicated.getInjects().getFirst().getTeams().forEach(injectTeam -> { if (injectTeam.getContextual()){ assertNotEquals(contextualTeam.getId(), injectTeam.getId()); assertEquals( @@ -113,4 +132,36 @@ void createNewContextualTeamsDuringScenarioDuplication(){ } }); } + + @DisplayName("Should remove team from scenario") + @Test + void testRemoveTeams() { + // -- PREPARE -- + User user = getUser(); + User userSaved = this.userRepository.saveAndFlush(user); + USER_ID = userSaved.getId(); + Team team = getTeam(userSaved); + Team teamSaved = this.teamRepository.saveAndFlush(team); + TEAM_ID = teamSaved.getId(); + Scenario scenario = ScenarioFixture.getScenario(); + scenario.setTeams(List.of(teamSaved)); + Scenario scenarioSaved = this.scenarioRepository.saveAndFlush(scenario); + + InjectorContract injectorContract = this.injectorContractRepository.findById(EMAIL_DEFAULT).orElseThrow(); + Inject injectDefaultEmail = getInjectForEmailContract(injectorContract); + injectDefaultEmail.setScenario(scenarioSaved); + injectDefaultEmail.setTeams(List.of(teamSaved)); + Inject injectDefaultEmailSaved = this.injectRepository.saveAndFlush(injectDefaultEmail); + INJECT_ID = injectDefaultEmailSaved.getId(); + + // -- EXECUTE -- + this.scenarioService.removeTeams(scenarioSaved.getId(), List.of(teamSaved.getId())); + + // -- ASSERT -- + List teams = this.teamRepository.findAll(fromScenario(scenarioSaved.getId())); + assertEquals(0, teams.size()); + Inject injectAssert = this.injectRepository.findById(INJECT_ID).orElseThrow(); + assertEquals(0, injectAssert.getTeams().size()); + } + } diff --git a/openbas-model/src/main/java/io/openbas/database/repository/ExerciseRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/ExerciseRepository.java index 6313d194a3..897099e21e 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/ExerciseRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/ExerciseRepository.java @@ -6,11 +6,13 @@ import io.openbas.database.raw.RawGlobalInjectExpectation; import io.openbas.database.raw.RawInjectExpectation; import jakarta.validation.constraints.NotNull; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; import java.time.Instant; import java.util.List; @@ -18,7 +20,7 @@ import java.util.Set; @Repository -public interface ExerciseRepository extends CrudRepository, +public interface ExerciseRepository extends JpaRepository, StatisticRepository, JpaSpecificationExecutor { @@ -260,4 +262,15 @@ Iterable rawGrantedInjectExpectationResultsFromDate( + "GROUP BY ex.exercise_id ;", nativeQuery = true) Set rawAllByScenarioId(@Param("scenarioIds") List scenarioIds); + + // -- TEAM -- + + @Modifying + @Query( + value = "DELETE FROM exercises_teams et WHERE et.exercise_id = :exerciseId AND et.team_id in :teamIds", + nativeQuery = true + ) + @Transactional + void removeTeams(@Param("exerciseId") final String exerciseId, @Param("teamIds") final List teamIds); + } diff --git a/openbas-model/src/main/java/io/openbas/database/repository/ExerciseTeamUserRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/ExerciseTeamUserRepository.java index 6982c84d7a..7bb96a51e0 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/ExerciseTeamUserRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/ExerciseTeamUserRepository.java @@ -10,6 +10,7 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @@ -25,8 +26,9 @@ public interface ExerciseTeamUserRepository extends CrudRepository teamIds); @Modifying @Query(value = "insert into exercises_teams_users (exercise_id, team_id, user_id) " + diff --git a/openbas-model/src/main/java/io/openbas/database/repository/InjectRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/InjectRepository.java index 3a0861e0be..ba9f7ccc84 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/InjectRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/InjectRepository.java @@ -6,19 +6,23 @@ import java.util.Set; import org.jetbrains.annotations.NotNull; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; import java.time.Instant; +import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.Set; @Repository -public interface InjectRepository extends CrudRepository, JpaSpecificationExecutor, +public interface InjectRepository extends + JpaRepository, JpaSpecificationExecutor, StatisticRepository { @NotNull @@ -149,4 +153,26 @@ void importSaveForScenario(@Param("id") String id, "GROUP BY org.organization_id", nativeQuery = true) List rawAll(); + + // -- TEAM -- + + @Modifying + @Query( + value = "DELETE FROM injects_teams it " + + "WHERE it.team_id IN :teamIds " + + "AND EXISTS (SELECT 1 FROM injects i WHERE it.inject_id = i.inject_id AND i.inject_exercise = :exerciseId)", + nativeQuery = true + ) + @Transactional + void removeTeamsForExercise(@Param("exerciseId") final String exerciseId, @Param("teamIds") final List teamIds); + + @Modifying + @Query( + value = "DELETE FROM injects_teams it " + + "WHERE it.team_id IN :teamIds " + + "AND EXISTS (SELECT 1 FROM injects i WHERE it.inject_id = i.inject_id AND i.inject_scenario = :scenarioId)", + nativeQuery = true + ) + @Transactional + void removeTeamsForScenario(@Param("scenarioId") final String scenarioId, @Param("teamIds") final List teamIds); } diff --git a/openbas-model/src/main/java/io/openbas/database/repository/LessonsCategoryRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/LessonsCategoryRepository.java index ede64bcfad..2e84329563 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/LessonsCategoryRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/LessonsCategoryRepository.java @@ -2,10 +2,16 @@ import io.openbas.database.model.LessonsCategory; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import jakarta.validation.constraints.NotNull; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; import java.util.Optional; @Repository @@ -13,4 +19,28 @@ public interface LessonsCategoryRepository extends CrudRepository findById(@NotNull String id); + + // -- TEAM - + + @Modifying + @Query( + value = "DELETE FROM lessons_categories_teams lct " + + "WHERE lct.team_id IN :teamIds " + + "AND EXISTS (SELECT 1 FROM lessons_categories lc WHERE lct.lessons_category_id = lc.lessons_category_id AND lc.lessons_category_exercise = :exerciseId)", + nativeQuery = true + ) + @Transactional + void removeTeamsForExercise(@Param("exerciseId") final String exerciseId, @Param("teamIds") final List teamIds); + + @Modifying + @Query( + value = "DELETE FROM lessons_categories_teams lct " + + "WHERE lct.team_id IN :teamIds " + + "AND EXISTS (SELECT 1 FROM lessons_categories lc WHERE lct.lessons_category_id = lc.lessons_category_id AND lc.lessons_category_scenario = :scenarioId)", + nativeQuery = true + ) + @Transactional + void removeTeamsForScenario(@Param("scenarioId") final String scenarioId, @Param("teamIds") final List teamIds); + + } diff --git a/openbas-model/src/main/java/io/openbas/database/repository/ScenarioRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/ScenarioRepository.java index b44e875e32..1571b0cb38 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/ScenarioRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/ScenarioRepository.java @@ -7,18 +7,17 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.jpa.repository.*; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; import java.time.Instant; import java.util.List; @Repository -public interface ScenarioRepository extends CrudRepository, +public interface ScenarioRepository extends + JpaRepository, StatisticRepository, JpaSpecificationExecutor { @@ -104,4 +103,14 @@ public interface ScenarioRepository extends CrudRepository, @EntityGraph(value = "Scenario.tags-injects", type = EntityGraph.EntityGraphType.LOAD) Page findAll(@NotNull Specification spec, @NotNull Pageable pageable); + // -- TEAM -- + + @Modifying + @Query( + value = "DELETE FROM scenarios_teams st WHERE st.scenario_id = :scenarioId AND st.team_id in :teamIds", + nativeQuery = true + ) + @Transactional + void removeTeams(@Param("scenarioId") final String scenarioId, @Param("teamIds") final List teamIds); + } diff --git a/openbas-model/src/main/java/io/openbas/database/repository/ScenarioTeamUserRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/ScenarioTeamUserRepository.java index 62244a3d54..14096b9360 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/ScenarioTeamUserRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/ScenarioTeamUserRepository.java @@ -9,7 +9,9 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; import java.util.Optional; @Repository @@ -19,17 +21,8 @@ public interface ScenarioTeamUserRepository extends CrudRepository findById(@NotNull final ScenarioTeamUserId id); @Modifying - @Query(value = "delete from scenarios_teams_users i where i.user_id = :userId", nativeQuery = true) - void deleteUserFromAllReferences(@Param("userId") final String userId); + @Query(value = "delete from scenarios_teams_users i where i.team_id in :teamIds", nativeQuery = true) + @Transactional + void deleteTeamFromAllReferences(@Param("teamIds") List teamIds); - @Modifying - @Query(value = "delete from scenarios_teams_users i where i.team_id = :teamId", nativeQuery = true) - void deleteTeamFromAllReferences(@Param("teamId") final String teamId); - - @Modifying - @Query(value = "insert into scenarios_teams_users (exercise_id, team_id, user_id) " + - "values (:exerciseId, :teamId, :userId)", nativeQuery = true) - void addExerciseTeamUser(@Param("exerciseId") final String exerciseId, - @Param("teamId") final String teamId, - @Param("userId") final String userId); } diff --git a/openbas-model/src/main/java/io/openbas/database/repository/TeamRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/TeamRepository.java index 516814220a..c8fc68871d 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/TeamRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/TeamRepository.java @@ -7,9 +7,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -19,7 +19,8 @@ import java.util.Set; @Repository -public interface TeamRepository extends CrudRepository, +public interface TeamRepository extends + JpaRepository, StatisticRepository, JpaSpecificationExecutor { diff --git a/openbas-model/src/main/java/io/openbas/database/repository/UserRepository.java b/openbas-model/src/main/java/io/openbas/database/repository/UserRepository.java index 256f590e70..3a5884875a 100644 --- a/openbas-model/src/main/java/io/openbas/database/repository/UserRepository.java +++ b/openbas-model/src/main/java/io/openbas/database/repository/UserRepository.java @@ -7,11 +7,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.jpa.repository.*; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -21,7 +17,8 @@ import java.util.Set; @Repository -public interface UserRepository extends CrudRepository, JpaSpecificationExecutor, +public interface UserRepository extends + JpaRepository, JpaSpecificationExecutor, StatisticRepository { @NotNull