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

[backend/frontend] fix bulk update injects #1628

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 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 @@ -177,6 +177,17 @@
return injectRepository.save(inject);
}

@Transactional(rollbackFor = Exception.class)
@PutMapping(INJECT_URI + "/{exerciseId}/{injectId}/bulk")
@PreAuthorize("isExercisePlanner(#exerciseId)")
public Inject bulkUpdateInject(
@PathVariable String exerciseId,
@PathVariable String injectId,
@Valid @RequestBody InjectInput input) {
Inject inject = bulkUpdateInject(injectId, input);
return injectRepository.save(inject);

Check warning on line 188 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#L187-L188

Added lines #L187 - L188 were not covered by tests
}

// -- EXERCISES --

@GetMapping(EXERCISE_URI + "/{exerciseId}/injects")
Expand Down Expand Up @@ -505,6 +516,17 @@
return injectRepository.findById(injectId).orElseThrow(ElementNotFoundException::new);
}

@Transactional(rollbackFor = Exception.class)
@PutMapping(SCENARIO_URI + "/{scenarioId}/injects/{injectId}/bulk")
@PreAuthorize("isScenarioPlanner(#scenarioId)")
public Inject bulkUpdateInjectForScenario(
@PathVariable String scenarioId,
@PathVariable String injectId,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna be super annoying but in a bulk update endpoint, shouldn't we send the list of injects to update in one call instead of having many calls viewed as bulk ? Since this endpoint is dedicated to those kind of calls, that would make sense and prevent us from calling a lot of times the API for almost the same call with just the inject id changing ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! I'll modify it, thank you!

@Valid @RequestBody InjectInput input) {
Inject inject = bulkUpdateInject(injectId, input);
return injectRepository.save(inject);

Check warning on line 527 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#L526-L527

Added lines #L526 - L527 were not covered by tests
}

@Transactional(rollbackFor = Exception.class)
@PutMapping(SCENARIO_URI + "/{scenarioId}/injects/{injectId}")
@PreAuthorize("isScenarioPlanner(#scenarioId)")
Expand Down Expand Up @@ -596,6 +618,17 @@
return inject;
}

private Inject bulkUpdateInject(@NotBlank final String injectId, @NotNull InjectInput input) {
Inject inject = this.injectRepository.findById(injectId).orElseThrow(ElementNotFoundException::new);

Check warning on line 622 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#L622

Added line #L622 was not covered by tests

// Set dependencies
inject.setTeams(fromIterable(this.teamRepository.findAllById(input.getTeams())));
inject.setAssets(fromIterable(this.assetService.assets(input.getAssets())));
inject.setAssetGroups(fromIterable(this.assetGroupService.assetGroups(input.getAssetGroups())));

Check warning on line 627 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#L625-L627

Added lines #L625 - L627 were not covered by tests

return inject;

Check warning on line 629 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#L629

Added line #L629 was not covered by tests
}

private Inject updateInjectActivation(@NotBlank final String injectId,
@NotNull final InjectUpdateActivationInput input) {
Inject inject = this.injectRepository.findById(injectId).orElseThrow(ElementNotFoundException::new);
Expand Down
10 changes: 10 additions & 0 deletions openbas-front/src/actions/Inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export const updateInjectForExercise = (exerciseId, injectId, data) => (dispatch
return putReferential(schema.inject, uri, data)(dispatch);
};

export const bulkUpdateInjectForExercise = (exerciseId, injectId, data) => (dispatch) => {
const uri = `/api/injects/${exerciseId}/${injectId}/bulk`;
return putReferential(schema.inject, uri, data)(dispatch);
};

export const updateInjectTriggerForExercise = (exerciseId, injectId) => (dispatch) => {
const uri = `/api/exercises/${exerciseId}/injects/${injectId}/trigger`;
return putReferential(schema.inject, uri)(dispatch);
Expand Down Expand Up @@ -87,6 +92,11 @@ export const fetchScenarioInjects = (scenarioId) => (dispatch) => {
return getReferential(schema.arrayOfInjects, uri)(dispatch);
};

export const bulkUpdateInjectForScenario = (scenarioId, injectId, data) => (dispatch) => {
const uri = `/api/scenarios/${scenarioId}/injects/${injectId}/bulk`;
return putReferential(schema.inject, uri, data)(dispatch);
};

export const updateInjectForScenario = (scenarioId, injectId, data) => (dispatch) => {
const uri = `/api/scenarios/${scenarioId}/injects/${injectId}`;
return putReferential(schema.inject, uri, data)(dispatch);
Expand Down
4 changes: 4 additions & 0 deletions openbas-front/src/admin/components/common/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export type TeamContextType = {
export type InjectContextType = {
searchInjects: (input: SearchPaginationInput) => Promise<{ data: Page<InjectOutputType> }>,
onAddInject: (inject: Inject) => Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }>,
onBulkUpdateInject: (injectId: Inject['inject_id'], inject: Inject) => Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }>,
onUpdateInject: (injectId: Inject['inject_id'], inject: Inject) => Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }>,
onUpdateInjectTrigger?: (injectId: Inject['inject_id']) => Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }>,
onUpdateInjectActivation: (injectId: Inject['inject_id'], injectEnabled: { inject_enabled: boolean }) => Promise<{
Expand Down Expand Up @@ -193,6 +194,9 @@ export const InjectContext = createContext<InjectContextType>({
onAddInject(_inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return Promise.resolve({ result: '', entities: { injects: {} } });
},
onBulkUpdateInject(_injectId: Inject['inject_id'], _inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return Promise.resolve({ result: '', entities: { injects: {} } });
},
onUpdateInject(_injectId: Inject['inject_id'], _inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return Promise.resolve({ result: '', entities: { injects: {} } });
},
Expand Down
9 changes: 3 additions & 6 deletions openbas-front/src/admin/components/common/injects/Injects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,8 @@ const inlineStyles: Record<string, CSSProperties> = {

interface Props {
exerciseOrScenarioId: string

setViewMode?: (mode: string) => void

availableButtons: string[]

teams: TeamStore[]
articles: ArticleStore[]
variables: Variable[]
Expand Down Expand Up @@ -411,7 +408,7 @@ const Injects: FunctionComponent<Props> = ({
injectToUpdate[`inject_${action.field}`] = R.uniq(action.values.map((n) => n.value));
}
// eslint-disable-next-line no-await-in-loop
await injectContext.onUpdateInject(injectToUpdate.inject_id, R.pick(updateFields, injectToUpdate))
await injectContext.onBulkUpdateInject(injectToUpdate.inject_id, R.pick(updateFields, injectToUpdate))
.then((result: { result: string, entities: { injects: Record<string, InjectStore> } }) => {
onUpdate(result);
});
Expand All @@ -420,7 +417,7 @@ const Injects: FunctionComponent<Props> = ({
// @ts-expect-error define type
injectToUpdate[`inject_${action.field}`] = R.uniq(action.values.map((n) => n.value));
// eslint-disable-next-line no-await-in-loop
await injectContext.onUpdateInject(injectToUpdate.inject_id, R.pick(updateFields, injectToUpdate))
await injectContext.onBulkUpdateInject(injectToUpdate.inject_id, R.pick(updateFields, injectToUpdate))
.then((result: { result: string, entities: { injects: Record<string, InjectStore> } }) => {
onUpdate(result);
});
Expand All @@ -435,7 +432,7 @@ const Injects: FunctionComponent<Props> = ({
injectToUpdate[`inject_${action.field}`] = [];
}
// eslint-disable-next-line no-await-in-loop
await injectContext.onUpdateInject(injectToUpdate.inject_id, R.pick(updateFields, injectToUpdate))
await injectContext.onBulkUpdateInject(injectToUpdate.inject_id, R.pick(updateFields, injectToUpdate))
.then((result: { result: string, entities: { injects: Record<string, InjectStore> } }) => {
onUpdate(result);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ImportTestSummary, Inject, InjectsImportInput, InjectTestStatus, S
import {
addInjectForScenario,
bulkDeleteInjectsForScenario,
bulkUpdateInjectForScenario,
deleteInjectScenario,
fetchScenarioInjects,
updateInjectActivationForScenario,
Expand All @@ -24,6 +25,9 @@ const injectContextForScenario = (scenario: ScenarioStore) => {
onAddInject(inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return dispatch(addInjectForScenario(scenario.scenario_id, inject));
},
onBulkUpdateInject(injectId: Inject['inject_id'], inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return dispatch(bulkUpdateInjectForScenario(scenario.scenario_id, injectId, inject));
},
onUpdateInject(injectId: Inject['inject_id'], inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return dispatch(updateInjectForScenario(scenario.scenario_id, injectId, inject));
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
fetchExerciseInjects,
injectDone,
updateInjectActivationForExercise,
bulkUpdateInjectForExercise,
updateInjectForExercise,
updateInjectTriggerForExercise,
} from '../../../../actions/Inject';
Expand All @@ -27,6 +28,9 @@ const injectContextForExercise = (exercise: ExerciseStore) => {
onAddInject(inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return dispatch(addInjectForExercise(exercise.exercise_id, inject));
},
onBulkUpdateInject(injectId: Inject['inject_id'], inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return dispatch(bulkUpdateInjectForExercise(exercise.exercise_id, injectId, inject));
},
onUpdateInject(injectId: Inject['inject_id'], inject: Inject): Promise<{ result: string, entities: { injects: Record<string, InjectStore> } }> {
return dispatch(updateInjectForExercise(exercise.exercise_id, injectId, inject));
},
Expand Down