Skip to content

Commit

Permalink
[frontend/backend] retrieve only usefull teams informations (#1626)
Browse files Browse the repository at this point in the history
Signed-off-by: Marine LM <[email protected]>
  • Loading branch information
MarineLeM authored and savacano28 committed Jan 30, 2025
1 parent 4f1a886 commit 1007358
Show file tree
Hide file tree
Showing 20 changed files with 146 additions and 363 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static io.openbas.database.model.User.ROLE_ADMIN;
import static io.openbas.database.model.User.ROLE_USER;
import static io.openbas.database.specification.ExerciseSpecification.findGrantedFor;
import static io.openbas.database.specification.TeamSpecification.fromExercise;
import static io.openbas.helper.StreamHelper.fromIterable;
import static io.openbas.helper.StreamHelper.iterableToSet;
import static io.openbas.service.ImportService.EXPORT_ENTRY_ATTACHMENT;
Expand All @@ -29,9 +30,9 @@
import io.openbas.rest.exercise.response.ExercisesGlobalScoresOutput;
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;
import io.openbas.rest.inject.service.InjectService;
import io.openbas.rest.team.output.TeamOutput;
import io.openbas.service.*;
import io.openbas.telemetry.Tracing;
import io.openbas.utils.AtomicTestingUtils.ExpectationResultsByType;
Expand Down Expand Up @@ -90,9 +91,6 @@ public class ExerciseApi extends RestBehavior {
private final LessonsAnswerRepository lessonsAnswerRepository;
private final InjectStatusRepository injectStatusRepository;
private final InjectRepository injectRepository;
private final InjectExpectationRepository injectExpectationRepository;
private final ScenarioRepository scenarioRepository;
private final CommunicationRepository communicationRepository;
private final ObjectiveRepository objectiveRepository;
private final EvaluationRepository evaluationRepository;
private final KillChainPhaseRepository killChainPhaseRepository;
Expand All @@ -105,6 +103,7 @@ public class ExerciseApi extends RestBehavior {
private final ChallengeService challengeService;
private final VariableService variableService;
private final ExerciseService exerciseService;
private final TeamService teamService;

// endregion

Expand Down Expand Up @@ -178,51 +177,24 @@ public List<ComcheckStatus> comcheckStatuses(
@GetMapping(EXERCISE_URI + "/{exerciseId}/teams")
@PreAuthorize("isExerciseObserver(#exerciseId)")
@Tracing(name = "Get teams of the exercise", layer = "api", operation = "GET")
public Iterable<TeamSimple> getExerciseTeams(@PathVariable String exerciseId) {
return TeamHelper.rawTeamToSimplerTeam(
teamRepository.rawTeamByExerciseId(exerciseId),
injectExpectationRepository,
injectRepository,
communicationRepository,
exerciseTeamUserRepository,
scenarioRepository);
}

@Transactional(rollbackOn = Exception.class)
@PutMapping(EXERCISE_URI + "/{exerciseId}/teams/add")
@PreAuthorize("isExercisePlanner(#exerciseId)")
public Iterable<Team> addExerciseTeams(
@PathVariable String exerciseId, @Valid @RequestBody ExerciseUpdateTeamsInput input) {
Exercise exercise = this.exerciseService.exercise(exerciseId);
// Add teams to exercise
List<Team> teams = exercise.getTeams();
List<Team> teamsToAdd = fromIterable(this.teamRepository.findAllById(input.getTeamIds()));
List<String> existingTeamIds = teams.stream().map(Team::getId).toList();
teams.addAll(teamsToAdd.stream().filter(t -> !existingTeamIds.contains(t.getId())).toList());
exercise.setTeams(teams);
this.exerciseService.updateExercise(exercise);
return teamsToAdd;
public List<TeamOutput> getExerciseTeams(@PathVariable String exerciseId) {
return this.teamService.find(fromExercise(exerciseId));
}

@Transactional(rollbackOn = Exception.class)
@PutMapping(EXERCISE_URI + "/{exerciseId}/teams/remove")
@PreAuthorize("isExercisePlanner(#exerciseId)")
public Iterable<Team> removeExerciseTeams(
public Iterable<TeamOutput> removeExerciseTeams(
@PathVariable String exerciseId, @Valid @RequestBody ExerciseUpdateTeamsInput input) {
return this.exerciseService.removeTeams(exerciseId, input.getTeamIds());
}

@Transactional(rollbackOn = Exception.class)
@PutMapping(EXERCISE_URI + "/{exerciseId}/teams/replace")
@PreAuthorize("isExercisePlanner(#exerciseId)")
public Iterable<Team> replaceExerciseTeams(
public Iterable<TeamOutput> replaceExerciseTeams(
@PathVariable String exerciseId, @Valid @RequestBody ExerciseUpdateTeamsInput input) {
Exercise exercise = this.exerciseService.exercise(exerciseId);
// Replace teams from exercise
List<Team> teams = fromIterable(this.teamRepository.findAllById(input.getTeamIds()));
exercise.setTeams(teams);
this.exerciseService.updateExercise(exercise);
return teams;
return this.exerciseService.replaceTeams(exerciseId, input.getTeamIds());
}

@GetMapping(EXERCISE_URI + "/{exerciseId}/players")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static io.openbas.config.SessionHelper.currentUser;
import static io.openbas.database.criteria.GenericCriteria.countQuery;
import static io.openbas.database.specification.TeamSpecification.fromIds;
import static io.openbas.helper.StreamHelper.fromIterable;
import static io.openbas.utils.Constants.ARTICLES;
import static io.openbas.utils.JpaUtils.arrayAggOnId;
import static io.openbas.utils.StringUtils.duplicateString;
Expand All @@ -25,6 +27,7 @@
import io.openbas.rest.exercise.response.ExercisesGlobalScoresOutput;
import io.openbas.rest.inject.service.InjectDuplicateService;
import io.openbas.rest.inject.service.InjectService;
import io.openbas.rest.team.output.TeamOutput;
import io.openbas.service.GrantService;
import io.openbas.service.TagRuleService;
import io.openbas.service.TeamService;
Expand Down Expand Up @@ -606,7 +609,7 @@ public ExercisesGlobalScoresOutput getExercisesGlobalScores(ExercisesGlobalScore

// -- TEAMS --
@Transactional(rollbackFor = Exception.class)
public Iterable<Team> removeTeams(
public Iterable<TeamOutput> removeTeams(
@NotBlank final String exerciseId, @NotNull final List<String> teamIds) {
// Remove teams from exercise
this.exerciseRepository.removeTeams(exerciseId, teamIds);
Expand All @@ -616,7 +619,24 @@ public Iterable<Team> removeTeams(
this.injectRepository.removeTeamsForExercise(exerciseId, teamIds);
// Remove all association between lessons learned and teams
this.lessonsCategoryRepository.removeTeamsForExercise(exerciseId, teamIds);
return teamRepository.findAllById(teamIds);
return teamService.find(fromIds(teamIds));
}

public List<TeamOutput> replaceTeams(
@NotBlank final String exerciseId, @NotNull final List<String> teamIds) {
Exercise exercise = this.exercise(exerciseId);
List<String> previousTeamIds = exercise.getTeams().stream().map(Team::getId).toList();

// Replace teams from exercise
List<Team> teams = fromIterable(this.teamRepository.findAllById(teamIds));
exercise.setTeams(teams);

// You must return all the modified teams to ensure the frontend store updates correctly
List<String> modifiedTeamIds =
Stream.concat(previousTeamIds.stream(), teams.stream().map(Team::getId))
.distinct()
.toList();
return teamService.find(fromIds(modifiedTeamIds));
}

/**
Expand Down
158 changes: 0 additions & 158 deletions openbas-api/src/main/java/io/openbas/rest/helper/TeamHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,170 +2,12 @@

import io.openbas.database.model.*;
import io.openbas.database.raw.*;
import io.openbas.database.repository.CommunicationRepository;
import io.openbas.database.repository.ExerciseTeamUserRepository;
import io.openbas.database.repository.InjectExpectationRepository;
import io.openbas.database.repository.InjectRepository;
import io.openbas.database.repository.ScenarioRepository;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public class TeamHelper {

public static List<TeamSimple> rawTeamToSimplerTeam(
List<RawTeam> teams,
InjectExpectationRepository injectExpectationRepository,
InjectRepository injectRepository,
CommunicationRepository communicationRepository,
ExerciseTeamUserRepository exerciseTeamUserRepository,
ScenarioRepository scenarioRepository) {
// Getting a map of inject expectations
Map<String, RawInjectExpectation> mapInjectExpectation =
injectExpectationRepository
.rawByIds(
teams.stream().flatMap(rawTeam -> rawTeam.getTeam_expectations().stream()).toList())
.stream()
.collect(
Collectors.toMap(
RawInjectExpectation::getInject_expectation_id, Function.identity()));

// Getting a map of communications
Map<String, RawCommunication> mapCommunication =
communicationRepository
.rawByIds(
teams.stream()
.flatMap(rawTeam -> rawTeam.getTeam_communications().stream())
.toList())
.stream()
.collect(Collectors.toMap(RawCommunication::getCommunication_id, Function.identity()));

// Getting a map of exercises team users by team id
Map<String, List<RawExerciseTeamUser>> mapExerciseTeamUser =
exerciseTeamUserRepository
.rawByTeamIds(teams.stream().map(RawTeam::getTeam_id).toList())
.stream()
.collect(Collectors.groupingBy(RawExerciseTeamUser::getTeam_id));

// Getting a map of Injects by scenarios ids
Map<String, Set<String>> mapInjectsByScenarioIds =
scenarioRepository
.rawInjectsFromScenarios(
teams.stream().flatMap(rawTeam -> rawTeam.getTeam_scenarios().stream()).toList())
.stream()
.collect(
Collectors.toMap(RawScenario::getScenario_id, RawScenario::getScenario_injects));

// Then, for all the raw teams, we will create a simpler team object and then send it back to
// the front
return teams.stream()
.map(
rawTeam -> {
// We create the simpler team object using the raw one
TeamSimple teamSimple = new TeamSimple(rawTeam);

// We set the inject expectations
teamSimple.setInjectExpectations(
rawTeam.getTeam_expectations().stream()
.map(
expectation -> {
// We set the inject expectation using the map we generated earlier
InjectExpectation injectExpectation = new InjectExpectation();
Optional<RawInjectExpectation> raw =
Optional.ofNullable(mapInjectExpectation.get(expectation));
raw.ifPresent(
toProcess -> {
injectExpectation.setScore(
toProcess.getInject_expectation_score());
injectExpectation.setExpectedScore(
toProcess.getInject_expectation_expected_score());
injectExpectation.setId(toProcess.getInject_expectation_id());
injectExpectation.setExpectedScore(
toProcess.getInject_expectation_expected_score());
if (toProcess.getExercise_id() != null) {
injectExpectation.setExercise(new Exercise());
injectExpectation
.getExercise()
.setId(toProcess.getExercise_id());
}
injectExpectation.setTeam(new Team());
injectExpectation.getTeam().setId(rawTeam.getTeam_id());
injectExpectation.setType(
InjectExpectation.EXPECTATION_TYPE.valueOf(
toProcess.getInject_expectation_type()));
});
return injectExpectation;
})
.toList());

// We set the communications using the map we generated earlier
// This object has content, content_html and attachments ignored because WE DON'T WANT
// THE FULL EXTENT
teamSimple.setCommunications(
rawTeam.getTeam_communications().stream()
.map(
communicationId -> {
RawCommunication raw = mapCommunication.get(communicationId);
Communication communication = new Communication();
communication.setAck(raw.getCommunication_ack());
communication.setId(raw.getCommunication_id());
communication.setIdentifier(raw.getCommunication_message_id());
communication.setReceivedAt(raw.getCommunication_received_at());
communication.setSentAt(raw.getCommunication_sent_at());
communication.setSubject(raw.getCommunication_subject());
Inject inject = new Inject();
inject.setId(raw.getCommunication_inject());
Exercise exercise = new Exercise();
exercise.setId(raw.getCommunication_exercise());
inject.setExercise(exercise);
communication.setInject(inject);
communication.setUsers(
raw.getCommunication_users().stream()
.map(
id -> {
User user = new User();
user.setId(id);
return user;
})
.toList());
communication.setAnimation(raw.getCommunication_animation());
communication.setFrom(raw.getCommunication_from());
communication.setTo(raw.getCommunication_to());
return communication;
})
.toList());

// We set the tuple of exercise/user/team
List<RawExerciseTeamUser> exerciseTeamUsers = mapExerciseTeamUser.get(rawTeam);
if (exerciseTeamUsers != null) {
teamSimple.setExerciseTeamUsers(
exerciseTeamUsers.stream()
.map(ExerciseTeamUser::fromRawExerciseTeamUser)
.collect(Collectors.toSet()));
}

// We set the injects linked to the scenarios
teamSimple.setScenariosInjects(
getInjectTeamsIds(
teamSimple.getId(),
rawTeam.getTeam_scenarios().stream()
.flatMap(scenario -> mapInjectsByScenarioIds.get(scenario).stream())
.collect(Collectors.toSet()),
injectRepository));

// We set the injects linked to the exercises
teamSimple.setExercisesInjects(
getInjectTeamsIds(
teamSimple.getId(), rawTeam.getTeam_exercise_injects(), injectRepository));

return teamSimple;
})
.collect(Collectors.toList());
}

public static List<TeamSimple> rawAllTeamToSimplerAllTeam(List<RawTeam> teams) {
// Then, for all the raw teams, we will create a simpler team object and then send it back to
// the front
Expand Down
Loading

0 comments on commit 1007358

Please sign in to comment.