1717package org .graylog .security .entities ;
1818
1919import com .google .common .collect .ImmutableSet ;
20+ import com .google .common .graph .GraphBuilder ;
2021import org .graylog .grn .GRN ;
2122import org .graylog .grn .GRNDescriptor ;
2223import org .graylog .grn .GRNDescriptorService ;
2324import org .graylog .grn .GRNRegistry ;
2425import org .graylog .grn .GRNType ;
26+ import org .graylog .grn .GRNTypes ;
2527import org .graylog .security .DBGrantService ;
2628import org .graylog .testing .GRNExtension ;
2729import org .graylog .testing .mongodb .MongoDBExtension ;
4648import static org .mockito .ArgumentMatchers .any ;
4749import static org .mockito .Mockito .when ;
4850
51+ @ SuppressWarnings ("UnstableApiUsage" )
4952@ ExtendWith (MongoDBExtension .class )
5053@ ExtendWith (MongoJackExtension .class )
5154@ ExtendWith (GRNExtension .class )
@@ -83,7 +86,9 @@ void resolve() {
8386 when (contentPackService .listAllEntityExcerpts ()).thenReturn (ImmutableSet .of (streamExcerpt ));
8487
8588 final EntityDescriptor streamDescriptor = EntityDescriptor .builder ().type (ModelTypes .STREAM_V1 ).id (ModelId .of ("54e3deadbeefdeadbeefaffe" )).build ();
86- when (contentPackService .resolveEntities (any ())).thenReturn (ImmutableSet .of (streamDescriptor ));
89+ final var dependencyGraph = GraphBuilder .directed ().<EntityDescriptor >build ();
90+ dependencyGraph .addNode (streamDescriptor );
91+ when (contentPackService .resolveEntityDependencyGraph (any ())).thenReturn (dependencyGraph );
8792
8893 when (grnDescriptorService .getDescriptor (any (GRN .class ))).thenAnswer (a -> {
8994 GRN grnArg = a .getArgument (0 );
@@ -108,7 +113,9 @@ void resolveWithInclompleteDependency() {
108113
109114 when (contentPackService .listAllEntityExcerpts ()).thenReturn (ImmutableSet .of ());
110115 final EntityDescriptor streamDescriptor = EntityDescriptor .builder ().type (ModelTypes .STREAM_V1 ).id (ModelId .of ("54e3deadbeefdeadbeefaffe" )).build ();
111- when (contentPackService .resolveEntities (any ())).thenReturn (ImmutableSet .of (streamDescriptor ));
116+ final var dependencyGraph = GraphBuilder .directed ().<EntityDescriptor >build ();
117+ dependencyGraph .addNode (streamDescriptor );
118+ when (contentPackService .resolveEntityDependencyGraph (any ())).thenReturn (dependencyGraph );
112119
113120 when (grnDescriptorService .getDescriptor (any (GRN .class ))).thenAnswer (a -> {
114121 GRN grnArg = a .getArgument (0 );
@@ -139,7 +146,9 @@ void resolveStreamReference() {
139146 when (contentPackService .listAllEntityExcerpts ()).thenReturn (ImmutableSet .of (streamExcerpt , streamRefExcerpt ));
140147
141148 final EntityDescriptor streamDescriptor = EntityDescriptor .builder ().type (ModelTypes .STREAM_REF_V1 ).id (ModelId .of ("54e3deadbeefdeadbeefaffe" )).build ();
142- when (contentPackService .resolveEntities (any ())).thenReturn (ImmutableSet .of (streamDescriptor ));
149+ final var dependencyGraph = GraphBuilder .directed ().<EntityDescriptor >build ();
150+ dependencyGraph .addNode (streamDescriptor );
151+ when (contentPackService .resolveEntityDependencyGraph (any ())).thenReturn (dependencyGraph );
143152
144153 when (grnDescriptorService .getDescriptor (any (GRN .class ))).thenAnswer (a -> {
145154 GRN grnArg = a .getArgument (0 );
@@ -163,11 +172,41 @@ void resolveStreamReference() {
163172 void resolveEventProcedureDependency () {
164173 final EntityDescriptor definitionDescriptor = EntityDescriptor .builder ().type (ModelTypes .EVENT_DEFINITION_V1 ).id (ModelId .of ("54e3deadbeefdeadbeefafff" )).build ();
165174 final EntityDescriptor procedureDescriptor = EntityDescriptor .builder ().type (ModelTypes .EVENT_PROCEDURE_V1 ).id (ModelId .of ("54e3deadbeefdeadbeefaffe" )).build ();
166- when (contentPackService .resolveEntities (any ())).thenReturn (ImmutableSet .of (definitionDescriptor , procedureDescriptor ));
175+ final var dependencyGraph = GraphBuilder .directed ().<EntityDescriptor >build ();
176+ dependencyGraph .addNode (definitionDescriptor );
177+ dependencyGraph .putEdge (definitionDescriptor , procedureDescriptor );
178+ when (contentPackService .resolveEntityDependencyGraph (any ())).thenReturn (dependencyGraph );
167179
168180 final GRN definitionGrn = grnRegistry .newGRN ("event_definition" , "54e3deadbeefdeadbeefafff" );
169181 grnRegistry .registerType (GRNType .create ("event_procedure" ));
170182 final ImmutableSet <org .graylog .security .entities .EntityDescriptor > missingDependencies = entityDependencyResolver .resolve (definitionGrn );
171183 assertThat (missingDependencies ).hasSize (1 );
172184 }
185+
186+ @ Test
187+ @ DisplayName ("Try to resolve with an output dependency" )
188+ void resolveWithOutputDependency () {
189+ final var output1 = EntityDescriptor .builder ().type (ModelTypes .OUTPUT_V1 ).id (ModelId .of ("output-1-id" )).build ();
190+ final var output2 = EntityDescriptor .builder ().type (ModelTypes .OUTPUT_V1 ).id (ModelId .of ("output-2-id" )).build ();
191+ final var stream = EntityDescriptor .builder ().type (ModelTypes .STREAM_V1 ).id (ModelId .of ("stream-id" )).build ();
192+ // just for testing purposes, let's assume we'd allow event definitions to depend directly on outputs
193+ final var dashboard = EntityDescriptor .builder ().type (ModelTypes .EVENT_DEFINITION_V1 ).id (ModelId .of ("event-definition-id" )).build ();
194+
195+ // we'll resolve this dependency graph for whatever entity we pass in
196+ final var dependencyGraph = GraphBuilder .directed ().<EntityDescriptor >build ();
197+ dependencyGraph .addNode (stream );
198+ dependencyGraph .addNode (dashboard );
199+ dependencyGraph .putEdge (stream , output1 );
200+ dependencyGraph .putEdge (dashboard , output2 );
201+ when (contentPackService .resolveEntityDependencyGraph (any ())).thenReturn (dependencyGraph );
202+
203+ // output1 should be ignored because it is only a dependency of the stream
204+ final var dependencies = entityDependencyResolver .resolve (grnRegistry .newGRN (GRNTypes .DASHBOARD , "dashboard-id" ));
205+ assertThat (dependencies )
206+ .extracting (org .graylog .security .entities .EntityDescriptor ::id )
207+ .containsExactlyInAnyOrder (grnRegistry .newGRN (GRNTypes .EVENT_DEFINITION , "event-definition-id" ),
208+ grnRegistry .newGRN (GRNTypes .STREAM , "stream-id" ),
209+ grnRegistry .newGRN (GRNTypes .OUTPUT , "output-2-id" )
210+ );
211+ }
173212}
0 commit comments