From beeb2d56f1f288ef2527cb5fbcb7da6ede3c37dd Mon Sep 17 00:00:00 2001 From: Zack King <91903901+kingzacko1@users.noreply.github.com> Date: Fri, 1 May 2026 15:59:58 -0500 Subject: [PATCH] Improve query parameter in event definition filter query workflow (#25755) * Improve query parameter in event definition filter query workflow * Remove unused mock (cherry picked from commit c614a7582679be2cfc4ee24959970e1fd76bd714) --- .../DefaultEntityDependencyResolver.java | 5 ++++ .../DefaultEntityDependencyResolverTest.java | 28 +++++++++++++++++-- .../EditQueryParameterModal.tsx | 4 ++- .../event-definition-types/FilterPreview.tsx | 8 ++++-- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/graylog2-server/src/main/java/org/graylog/security/entities/DefaultEntityDependencyResolver.java b/graylog2-server/src/main/java/org/graylog/security/entities/DefaultEntityDependencyResolver.java index de385a3231df..5579d6822dd0 100644 --- a/graylog2-server/src/main/java/org/graylog/security/entities/DefaultEntityDependencyResolver.java +++ b/graylog2-server/src/main/java/org/graylog/security/entities/DefaultEntityDependencyResolver.java @@ -77,6 +77,11 @@ protected ImmutableSet resolve(Collection entities) { dependencyGraph.predecessors(dependency).stream().anyMatch( predecessor -> !ModelTypes.STREAM_V1.equals(predecessor.type())) ) + // Ignore lookup tables, adapters, and caches as dependencies. Lookup tables don't have a corresponding + // GRN type registered and cannot be resolved for permission checks. + .filter(dependency -> !ModelTypes.LOOKUP_TABLE_V1.equals(dependency.type()) && + !ModelTypes.LOOKUP_ADAPTER_V1.equals(dependency.type()) && + !ModelTypes.LOOKUP_CACHE_V1.equals(dependency.type())) // TODO: Work around from using the content pack dependency resolver: // We've added stream_title content pack entities in https://github.com/Graylog2/graylog2-server/pull/17089, // but in this context we want to return the actual dependent Stream to add additional permissions to. diff --git a/graylog2-server/src/test/java/org/graylog/security/entities/DefaultEntityDependencyResolverTest.java b/graylog2-server/src/test/java/org/graylog/security/entities/DefaultEntityDependencyResolverTest.java index 55c20c07156e..5c0ba29d2d12 100644 --- a/graylog2-server/src/test/java/org/graylog/security/entities/DefaultEntityDependencyResolverTest.java +++ b/graylog2-server/src/test/java/org/graylog/security/entities/DefaultEntityDependencyResolverTest.java @@ -28,7 +28,6 @@ import org.graylog.testing.GRNExtension; import org.graylog.testing.mongodb.MongoDBExtension; import org.graylog.testing.mongodb.MongoDBFixtures; -import org.graylog.testing.mongodb.MongoDBTestService; import org.graylog.testing.mongodb.MongoJackExtension; import org.graylog2.bindings.providers.MongoJackObjectMapperProvider; import org.graylog2.contentpacks.ContentPackEntityResolver; @@ -76,7 +75,7 @@ void setUp(@Mock ContentPackEntityResolver contentPackEntityResolver, } @Test - @DisplayName("Try a regular depency resolve") + @DisplayName("Try a regular dependency resolve") void resolve() { final String TEST_TITLE = "Test Stream Title"; final EntityExcerpt streamExcerpt = EntityExcerpt.builder() @@ -183,6 +182,31 @@ void resolveEventProcedureDependency() { assertThat(missingDependencies).hasSize(1); } + @Test + @DisplayName("Lookup table dependencies are ignored during resolve") + void resolveWithLookupTableDependency() { + final EntityDescriptor eventDefDescriptor = EntityDescriptor.builder() + .type(ModelTypes.EVENT_DEFINITION_V1).id(ModelId.of("54e3deadbeefdeadbeefafff")).build(); + final EntityDescriptor lookupTableDescriptor = EntityDescriptor.builder() + .type(ModelTypes.LOOKUP_TABLE_V1).id(ModelId.of("54e3deadbeefdeadbeefaffe")).build(); + final EntityDescriptor streamDescriptor = EntityDescriptor.builder() + .type(ModelTypes.STREAM_V1).id(ModelId.of("54e3deadbeefdeadbeefaffd")).build(); + + final var dependencyGraph = GraphBuilder.directed().build(); + dependencyGraph.addNode(eventDefDescriptor); + dependencyGraph.putEdge(eventDefDescriptor, lookupTableDescriptor); + dependencyGraph.putEdge(eventDefDescriptor, streamDescriptor); + when(contentPackEntityResolver.resolveEntityDependencyGraph(any())).thenReturn(dependencyGraph); + when(contentPackEntityResolver.listAllEntityExcerpts()).thenReturn(ImmutableSet.of()); + + final GRN eventDefGrn = grnRegistry.newGRN("event_definition", "54e3deadbeefdeadbeefafff"); + final ImmutableSet dependencies = entityDependencyResolver.resolve(eventDefGrn); + + // The lookup_table dependency should be skipped, only the stream should remain + assertThat(dependencies).hasSize(1); + assertThat(dependencies.asList().get(0).id().toString()).isEqualTo("grn::::stream:54e3deadbeefdeadbeefaffd"); + } + @Test @DisplayName("Try to resolve with an output dependency") void resolveWithOutputDependency() { diff --git a/graylog2-web-interface/src/components/event-definitions/event-definition-form/EditQueryParameterModal.tsx b/graylog2-web-interface/src/components/event-definitions/event-definition-form/EditQueryParameterModal.tsx index d5b14ab90f26..49f0706e1e47 100644 --- a/graylog2-web-interface/src/components/event-definitions/event-definition-form/EditQueryParameterModal.tsx +++ b/graylog2-web-interface/src/components/event-definitions/event-definition-form/EditQueryParameterModal.tsx @@ -55,7 +55,9 @@ class EditQueryParameterModal extends React.Component { } openModal = () => { - this.setState({ showModal: true }); + const { queryParameter } = this.props; + + this.setState({ showModal: true, queryParameter }); }; _cleanState = () => { diff --git a/graylog2-web-interface/src/components/event-definitions/event-definition-types/FilterPreview.tsx b/graylog2-web-interface/src/components/event-definitions/event-definition-types/FilterPreview.tsx index efebbfcaffef..5298145752f1 100644 --- a/graylog2-web-interface/src/components/event-definitions/event-definition-types/FilterPreview.tsx +++ b/graylog2-web-interface/src/components/event-definitions/event-definition-types/FilterPreview.tsx @@ -153,12 +153,16 @@ const useExecutePreview = (config: EventDefinition['config']) => { [executeJobResult, searchTypeId, startJob], ); + const hasEmbryonicParams = config?.query_parameters?.some( + (param: LookupTableParameterJsonEmbryonic) => param.embryonic, + ); + useEffect(() => { - if (isPermittedToSeePreview(currentUser, config)) { + if (isPermittedToSeePreview(currentUser, config) && !hasEmbryonicParams) { const search = constructSearch(config, searchTypeId, queryId); executeSearch(search); } - }, [config, currentUser, executeSearch, queryId, searchTypeId]); + }, [config, currentUser, executeSearch, hasEmbryonicParams, queryId, searchTypeId]); return { errors: results?.result?.errors,