Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ public class ScenarioInjectApi extends RestBehavior {
resourceType = ResourceType.SCENARIO)
@Transactional(readOnly = true)
public Iterable<InjectOutput> scenarioInjectsSimple(
@PathVariable @NotBlank final String scenarioId) {
// The TxCtx parameter is not used directly; it signals the transaction aspect to set the
// tenant scope in the DB session. Every inject read resolves its injector on the v2-scoped
// injectors table: without the scope the join fails closed and inject_type comes back null,
// which the frontend renders as the generic "unknown" icon (#7605, #7621).
TxCtx ctx, @PathVariable @NotBlank final String scenarioId) {
return injectSearchService.injects(fromScenario(scenarioId));
}

Expand All @@ -75,6 +79,7 @@ public Iterable<InjectOutput> scenarioInjectsSimple(
resourceType = ResourceType.SCENARIO)
@Transactional(readOnly = true)
public Iterable<InjectOutput> scenarioInjectsSimple(
TxCtx ctx,
@PathVariable @NotBlank final String scenarioId,
@RequestBody @Valid final SearchPaginationInput searchPaginationInput) {
Map<String, Join<Base, Base>> joinMap = new HashMap<>();
Expand All @@ -101,7 +106,8 @@ public Iterable<InjectOutput> scenarioInjectsSimple(
resourceId = "#scenarioId",
actionPerformed = Action.READ,
resourceType = ResourceType.SCENARIO)
public Iterable<Inject> scenarioInjects(@PathVariable @NotBlank final String scenarioId) {
public Iterable<Inject> scenarioInjects(
TxCtx ctx, @PathVariable @NotBlank final String scenarioId) {
Comment on lines +105 to +106
return this.injectRepository.findByScenarioId(scenarioId).stream()
.sorted(Inject.executionComparator)
.toList();
Expand All @@ -117,6 +123,7 @@ public Iterable<Inject> scenarioInjects(@PathVariable @NotBlank final String sce
actionPerformed = Action.READ,
resourceType = ResourceType.SCENARIO)
public Inject scenarioInject(
TxCtx ctx,
@PathVariable @NotBlank final String scenarioId,
@PathVariable @NotBlank final String injectId) {
Scenario scenario = this.scenarioService.scenario(scenarioId);
Expand Down Expand Up @@ -242,6 +249,9 @@ public InjectOutput updateInjectForScenario(
actionPerformed = Action.WRITE,
resourceType = ResourceType.INJECT)
public Inject updateInjectActivationForScenario(
// Same as the reads above: the returned Inject serializes inject_type, so the response
// needs the tenant scope too or it blanks the field in the frontend store.
TxCtx ctx,
@PathVariable @NotBlank final String scenarioId,
@PathVariable @NotBlank final String injectId,
@Valid @RequestBody InjectUpdateActivationInput input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ public class SimulationInjectApi extends RestBehavior {
resourceType = ResourceType.SIMULATION)
@Transactional(readOnly = true)
public Iterable<InjectOutput> exerciseInjectsSimple(
@PathVariable @NotBlank final String exerciseId) {
// The TxCtx parameter is not used directly; it signals the transaction aspect to set the
// tenant scope in the DB session. Every inject read resolves its injector on the v2-scoped
// injectors table: without the scope the join fails closed and inject_type comes back null,
// which the frontend renders as the generic "unknown" icon (#7605, #7621).
TxCtx ctx, @PathVariable @NotBlank final String exerciseId) {
return injectSearchService.injects(fromSimulation(exerciseId));
}

Expand All @@ -112,6 +116,7 @@ public Iterable<InjectOutput> exerciseInjectsSimple(
resourceType = ResourceType.SIMULATION)
@Transactional(readOnly = true)
public Iterable<InjectOutput> exerciseInjectsSimple(
TxCtx ctx,
@PathVariable @NotBlank final String exerciseId,
@RequestBody @Valid final SearchPaginationInput searchPaginationInput) {
Map<String, Join<Base, Base>> joinMap = new HashMap<>();
Expand Down Expand Up @@ -139,7 +144,8 @@ public Iterable<InjectOutput> exerciseInjectsSimple(
resourceId = "#exerciseId",
actionPerformed = Action.READ,
resourceType = ResourceType.SIMULATION)
public Iterable<Inject> exerciseInjects(@PathVariable @NotBlank final String exerciseId) {
public Iterable<Inject> exerciseInjects(
TxCtx ctx, @PathVariable @NotBlank final String exerciseId) {
Comment on lines +143 to +144
return injectRepository.findByExerciseId(exerciseId).stream()
.sorted(Inject.executionComparator)
.toList();
Expand All @@ -156,6 +162,7 @@ public Iterable<Inject> exerciseInjects(@PathVariable @NotBlank final String exe
resourceType = ResourceType.SIMULATION)
@Transactional(readOnly = true)
public Page<InjectResultOutput> searchExerciseInjects(
TxCtx ctx,
@PathVariable final String exerciseId,
@RequestBody @Valid SearchPaginationInput searchPaginationInput) {
return injectSearchService.getPageOfInjectResults(exerciseId, searchPaginationInput);
Expand All @@ -171,7 +178,8 @@ public Page<InjectResultOutput> searchExerciseInjects(
actionPerformed = Action.READ,
resourceType = ResourceType.SIMULATION)
@Transactional(readOnly = true)
public List<InjectResultOutput> exerciseInjectsResults(@PathVariable final String exerciseId) {
public List<InjectResultOutput> exerciseInjectsResults(
TxCtx ctx, @PathVariable final String exerciseId) {
return injectSearchService.getListOfInjectResults(exerciseId);
}

Expand Down Expand Up @@ -354,6 +362,9 @@ public InjectStatus executeInject(
actionPerformed = Action.WRITE,
resourceType = ResourceType.INJECT)
public Inject updateInjectActivationForExercise(
// Same as the reads above: the returned Inject serializes inject_type, so the response
// needs the tenant scope too or it blanks the field in the frontend store.
TxCtx ctx,
@PathVariable String exerciseId,
@PathVariable String injectId,
@Valid @RequestBody InjectUpdateActivationInput input) {
Expand All @@ -370,7 +381,7 @@ public Inject updateInjectActivationForExercise(
actionPerformed = Action.WRITE,
resourceType = ResourceType.INJECT)
public Inject updateInjectTrigger(
@PathVariable String exerciseId, @PathVariable String injectId) {
TxCtx ctx, @PathVariable String exerciseId, @PathVariable String injectId) {
return simulationInjectService.triggerInjectForSimulation(exerciseId, injectId);
}

Expand All @@ -384,6 +395,7 @@ public Inject updateInjectTrigger(
actionPerformed = Action.WRITE,
resourceType = ResourceType.INJECT)
public Inject setInjectStatus(
TxCtx ctx,
@PathVariable String exerciseId,
@PathVariable String injectId,
@Valid @RequestBody InjectUpdateStatusInput input) {
Expand All @@ -400,6 +412,7 @@ public Inject setInjectStatus(
actionPerformed = Action.WRITE,
resourceType = ResourceType.INJECT)
public Inject updateInjectTeams(
TxCtx ctx,
@PathVariable String exerciseId,
@PathVariable String injectId,
@Valid @RequestBody InjectTeamsInput input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,22 @@ class TenantScopedEntrypointsTxCtxArchTest {
"io.openaev.rest.atomic_testing.AtomicTestingApi#collectorsFromAtomicTesting",
// inject: updateInject calls injectService.runChecks -> securityPlatformCollectors
"io.openaev.rest.inject.InjectApi#updateInject",
// inject listings and single-inject mutations: every one of them serializes inject_type,
// resolved through the contract's injector link on the v2-scoped injectors table. Losing
// the scope does not fail loudly - inject_type just comes back null and the frontend
// draws the generic "unknown" icon on the execution screens (#7605, #7621).
"io.openaev.rest.inject.SimulationInjectApi#exerciseInjects",
"io.openaev.rest.inject.SimulationInjectApi#exerciseInjectsSimple",
"io.openaev.rest.inject.SimulationInjectApi#searchExerciseInjects",
"io.openaev.rest.inject.SimulationInjectApi#exerciseInjectsResults",
"io.openaev.rest.inject.SimulationInjectApi#updateInjectActivationForExercise",
"io.openaev.rest.inject.SimulationInjectApi#updateInjectTrigger",
"io.openaev.rest.inject.SimulationInjectApi#setInjectStatus",
"io.openaev.rest.inject.SimulationInjectApi#updateInjectTeams",
"io.openaev.rest.inject.ScenarioInjectApi#scenarioInjects",
"io.openaev.rest.inject.ScenarioInjectApi#scenarioInjectsSimple",
"io.openaev.rest.inject.ScenarioInjectApi#scenarioInject",
"io.openaev.rest.inject.ScenarioInjectApi#updateInjectActivationForScenario",
// simulation injects: runChecks path
"io.openaev.rest.inject.SimulationInjectApi#exerciseInject",
"io.openaev.rest.inject.SimulationInjectApi#createInjectForExercise",
Expand Down
Loading