From f2e533089ba4bf5e0ae4c824f283dadb58eecc77 Mon Sep 17 00:00:00 2001 From: Eric Secules Date: Mon, 10 Aug 2026 17:48:13 -0700 Subject: [PATCH] NIFI-16179 add optional query parameter to parameter context endpoints to exclude referencing components from the response. Updated the UI callers so they correctly include or omit parameter referencing components if they don't use them --- .../endpoints/ParameterContextMerger.java | 26 +++-- .../endpoints/ParameterContextMergerTest.java | 93 ++++++++++++++++ .../apache/nifi/web/NiFiServiceFacade.java | 38 ++++--- .../nifi/web/StandardNiFiServiceFacade.java | 34 +++--- .../nifi/web/api/ApplicationResource.java | 1 + .../nifi/web/api/ConnectorResource.java | 8 +- .../org/apache/nifi/web/api/FlowResource.java | 10 +- .../web/api/ParameterContextResource.java | 67 +++++++----- .../web/api/ParameterProviderResource.java | 72 ++++++++----- .../nifi/web/api/ProcessGroupResource.java | 2 +- .../apache/nifi/web/api/dto/DtoFactory.java | 51 +++++---- .../nifi/web/util/ParameterUpdateManager.java | 4 +- .../web/StandardNiFiServiceFacadeTest.java | 10 +- .../nifi/web/api/TestConnectorResource.java | 16 +-- .../nifi/web/api/dto/DtoFactoryTest.java | 101 ++++++++++++++++-- .../connectors/service/connector.service.ts | 5 +- .../connector-canvas.effects.spec.ts | 6 +- .../connector-canvas.effects.ts | 28 ++--- .../service/parameter-helper.service.ts | 2 +- .../service/parameter.service.ts | 35 ++++-- .../controller-services.effects.ts | 2 +- .../flow-designer/state/flow/flow.effects.ts | 10 +- .../state/parameter/parameter.effects.ts | 10 +- .../service/parameter-contexts.service.ts | 53 ++++++--- .../parameter-context-listing.effects.spec.ts | 6 +- .../parameter-context-listing.effects.ts | 15 +-- .../service/parameter-provider.service.ts | 32 ++++-- .../parameter-providers.effects.spec.ts | 2 +- .../parameter-providers.effects.ts | 11 +- 29 files changed, 537 insertions(+), 213 deletions(-) create mode 100644 nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMergerTest.java diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMerger.java b/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMerger.java index a56c89989b4e..bbc7a248f128 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMerger.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMerger.java @@ -62,6 +62,7 @@ public static void merge(final ParameterContextEntity target, final Map entityMap) { final Map mergedBoundGroups = new HashMap<>(); final Map> affectedComponentsByParameterName = new HashMap<>(); + final Set parameterNamesWithReferencingComponents = new HashSet<>(); final Set unwritableParameters = new HashSet<>(); for (final Map.Entry entry : entityMap.entrySet()) { @@ -94,14 +95,17 @@ public static void merge(final ParameterContextDTO target, final Map affectedComponentsById = affectedComponentsByParameterName.computeIfAbsent(parameterDto.getName(), key -> new HashMap<>()); - for (final AffectedComponentEntity referencingComponent : parameterDto.getReferencingComponents()) { - AffectedComponentEntity mergedAffectedComponent = affectedComponentsById.get(referencingComponent.getId()); - if (mergedAffectedComponent == null) { - affectedComponentsById.put(referencingComponent.getId(), referencingComponent); - continue; - } + if (parameterDto.getReferencingComponents() != null) { + parameterNamesWithReferencingComponents.add(parameterDto.getName()); + for (final AffectedComponentEntity referencingComponent : parameterDto.getReferencingComponents()) { + AffectedComponentEntity mergedAffectedComponent = affectedComponentsById.get(referencingComponent.getId()); + if (mergedAffectedComponent == null) { + affectedComponentsById.put(referencingComponent.getId(), referencingComponent); + continue; + } - merge(mergedAffectedComponent, referencingComponent); + merge(mergedAffectedComponent, referencingComponent); + } } } } @@ -117,8 +121,12 @@ public static void merge(final ParameterContextDTO target, final Map componentMap = affectedComponentsByParameterName.get(parameterDto.getName()); - parameterDto.setReferencingComponents(new HashSet<>(componentMap.values())); + // Only overwrite referencing components if at least one node actually reported them; otherwise leave the DTO's + // existing value (null) as-is, since null indicates the caller asked to exclude referencing components. + if (parameterNamesWithReferencingComponents.contains(parameterDto.getName())) { + final Map componentMap = affectedComponentsByParameterName.get(parameterDto.getName()); + parameterDto.setReferencingComponents(new HashSet<>(componentMap.values())); + } } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMergerTest.java b/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMergerTest.java new file mode 100644 index 000000000000..115a498f85e4 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/ParameterContextMergerTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.cluster.coordination.http.endpoints; + +import org.apache.nifi.cluster.protocol.NodeIdentifier; +import org.apache.nifi.web.api.dto.ParameterContextDTO; +import org.apache.nifi.web.api.dto.ParameterDTO; +import org.apache.nifi.web.api.entity.AffectedComponentEntity; +import org.apache.nifi.web.api.entity.ParameterEntity; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +class ParameterContextMergerTest { + + @Test + void testMergePreservesNullReferencingComponentsWhenExcludedByEveryNode() { + final Map entityMap = new HashMap<>(); + entityMap.put(getNodeIdentifier("node1", 8000), createParameterContextDto("param1", null)); + entityMap.put(getNodeIdentifier("node2", 8010), createParameterContextDto("param1", null)); + + final ParameterContextDTO target = createParameterContextDto("param1", null); + + ParameterContextMerger.merge(target, entityMap); + + final ParameterDTO mergedParameter = target.getParameters().iterator().next().getParameter(); + assertNull(mergedParameter.getReferencingComponents(), + "Referencing components should remain null when every node excluded them from its response, rather than being coerced into an empty collection"); + } + + @Test + void testMergeCombinesReferencingComponentsAcrossNodesWhenIncluded() { + final Map entityMap = new HashMap<>(); + entityMap.put(getNodeIdentifier("node1", 8000), createParameterContextDto("param1", Set.of(createAffectedComponent("component1")))); + entityMap.put(getNodeIdentifier("node2", 8010), createParameterContextDto("param1", Set.of(createAffectedComponent("component2")))); + + final ParameterContextDTO target = createParameterContextDto("param1", Set.of()); + + ParameterContextMerger.merge(target, entityMap); + + final ParameterDTO mergedParameter = target.getParameters().iterator().next().getParameter(); + assertNotNull(mergedParameter.getReferencingComponents()); + assertEquals(2, mergedParameter.getReferencingComponents().size()); + } + + private ParameterContextDTO createParameterContextDto(final String parameterName, final Set referencingComponents) { + final ParameterDTO parameterDto = new ParameterDTO(); + parameterDto.setName(parameterName); + parameterDto.setReferencingComponents(referencingComponents); + + final ParameterEntity parameterEntity = new ParameterEntity(); + parameterEntity.setParameter(parameterDto); + parameterEntity.setCanWrite(true); + + final ParameterContextDTO contextDto = new ParameterContextDTO(); + contextDto.setId("context1"); + contextDto.setParameters(new HashSet<>(Set.of(parameterEntity))); + contextDto.setBoundProcessGroups(new HashSet<>()); + + return contextDto; + } + + private AffectedComponentEntity createAffectedComponent(final String id) { + final AffectedComponentEntity entity = new AffectedComponentEntity(); + entity.setId(id); + return entity; + } + + private NodeIdentifier getNodeIdentifier(final String id, final int port) { + return new NodeIdentifier(id, "localhost", port, "localhost", port + 1, "localhost", port + 2, port + 3, true); + } +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java index 2313b34f977c..ecbfcf3d9726 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java @@ -294,11 +294,12 @@ Set getConnectorControllerServices(String connectorId, * Returns the parameter context bound to the specified process group within the connector's hierarchy. Sensitive parameter values are masked * by the underlying DTO factory. * - * @param connectorId the connector id - * @param processGroupId the process group id within the connector's hierarchy + * @param connectorId the connector id + * @param processGroupId the process group id within the connector's hierarchy + * @param includeReferences whether to include parameters' referencing components * @return the parameter context entity with effective parameters (inherited included), or {@code null} if the process group has no bound parameter context */ - ParameterContextEntity getConnectorParameterContext(String connectorId, String processGroupId); + ParameterContextEntity getConnectorParameterContext(String connectorId, String processGroupId, boolean includeReferences); void verifyCanVerifyConnectorConfigurationStep(String connectorId, String configurationStepName); @@ -1407,9 +1408,10 @@ Set getControllerServiceTypes(final String serviceType, final /** * Returns the Set of all Parameter Context Entities for the current user + * @param includeReferences whether to include parameters' referencing components * @return the Set of all Parameter Context Entities for the current user */ - Set getParameterContexts(); + Set getParameterContexts(boolean includeReferences); /** * Returns the Parameter Context with the given name @@ -1425,33 +1427,39 @@ Set getControllerServiceTypes(final String serviceType, final * @param parameterContextId the ID of the Parameter Context * @param includeInheritedParameters Whether to include inherited parameters (and thus overridden values) * @param user the user on whose behalf the Parameter Context is being retrieved + * @param includeReferences whether to include parameters' referencing components * @return the ParameterContextEntity */ - ParameterContextEntity getParameterContext(String parameterContextId, boolean includeInheritedParameters, NiFiUser user); + ParameterContextEntity getParameterContext(String parameterContextId, boolean includeInheritedParameters, NiFiUser user, boolean includeReferences); /** * Creates a new Parameter Context - * @param revision the revision for the newly created Parameter Context - * @param parameterContext the Parameter Context + * + * @param revision the revision for the newly created Parameter Context + * @param parameterContext the Parameter Context + * @param includeReferences whether to include parameters' referencing components * @return a ParameterContextEntity representing the newly created ParameterContext */ - ParameterContextEntity createParameterContext(Revision revision, ParameterContextDTO parameterContext); + ParameterContextEntity createParameterContext(Revision revision, ParameterContextDTO parameterContext, boolean includeReferences); /** * Updates the Parameter Context * @param revision the current revision of the Parameter Context * @param parameterContext the updated version of the ParameterContext + * @param includeReferences whether to include parameters' referencing components * @return the updated Parameter Context Entity */ - ParameterContextEntity updateParameterContext(Revision revision, ParameterContextDTO parameterContext); + ParameterContextEntity updateParameterContext(Revision revision, ParameterContextDTO parameterContext, boolean includeReferences); /** * Deletes the Parameter Context - * @param revision the revision of the Parameter Context + * + * @param revision the revision of the Parameter Context * @param parameterContextId the ID of the Parameter Context + * @param includeReferences whether to include parameters' referencing components * @return a Parameter Context Entity that represents the Parameter Context that was deleted */ - ParameterContextEntity deleteParameterContext(Revision revision, String parameterContextId); + ParameterContextEntity deleteParameterContext(Revision revision, String parameterContextId, boolean includeReferences); /** * Performs validation of all components that make use of the Parameter Context with the same ID as the given DTO, but validating against the Parameters @@ -2736,12 +2744,16 @@ ControllerServiceReferencingComponentsEntity updateControllerServiceReferencingC /** * Returns a list of ParameterContext entities representing updates needed in order to apply the fetched * parameters from the parameter provider to the referencing parameter contexts - * @param parameterProviderId parameter provider id + * + * @param parameterProviderId parameter provider id * @param parameterGroupConfigurations Configuration for each fetched Parameter Group. Any parameters not found in this set will not be included in the update. + * @param includeReferences whether to include parameters' referencing components * @return The list of ParameterContextEntity objects representing required updates to referencing * parameter contexts */ - List getParameterContextUpdatesForAppliedParameters(String parameterProviderId, Collection parameterGroupConfigurations); + List getParameterContextUpdatesForAppliedParameters(String parameterProviderId, + Collection parameterGroupConfigurations, + boolean includeReferences); /** * Gets the references for specified parameter provider. diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index 6688dd48152a..74aa6f54986f 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -1382,13 +1382,13 @@ public void verifyUpdateParameterContext(final ParameterContextDTO parameterCont } @Override - public ParameterContextEntity updateParameterContext(final Revision revision, final ParameterContextDTO parameterContextDto) { + public ParameterContextEntity updateParameterContext(final Revision revision, final ParameterContextDTO parameterContextDto, final boolean includeReferences) { // get the component, ensure we have access to it, and perform the update request final ParameterContext parameterContext = parameterContextDAO.getParameterContext(parameterContextDto.getId()); final RevisionUpdate snapshot = updateComponent(revision, parameterContext, () -> parameterContextDAO.updateParameterContext(parameterContextDto), - context -> dtoFactory.createParameterContextDto(context, revisionManager, false, parameterContextDAO)); + context -> dtoFactory.createParameterContextDto(context, revisionManager, false, parameterContextDAO, includeReferences)); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(parameterContext); final RevisionDTO revisionDto = dtoFactory.createRevisionDTO(snapshot.getLastModification()); @@ -1397,17 +1397,17 @@ public ParameterContextEntity updateParameterContext(final Revision revision, fi } @Override - public ParameterContextEntity getParameterContext(final String parameterContextId, final boolean includeInheritedParameters, final NiFiUser user) { + public ParameterContextEntity getParameterContext(final String parameterContextId, final boolean includeInheritedParameters, final NiFiUser user, final boolean includeReferences) { final ParameterContext parameterContext = parameterContextDAO.getParameterContext(parameterContextId); - return createParameterContextEntity(parameterContext, includeInheritedParameters, user, parameterContextDAO); + return createParameterContextEntity(parameterContext, includeInheritedParameters, user, parameterContextDAO, includeReferences); } @Override - public Set getParameterContexts() { + public Set getParameterContexts(final boolean includeReferences) { final NiFiUser user = NiFiUserUtils.getNiFiUser(); final Set entities = parameterContextDAO.getParameterContexts().stream() - .map(context -> createParameterContextEntity(context, false, user, parameterContextDAO)) + .map(context -> createParameterContextEntity(context, false, user, parameterContextDAO, includeReferences)) .collect(Collectors.toSet()); return entities; @@ -1436,11 +1436,11 @@ public ParameterContext getParameterContextByName(final String parameterContextN } private ParameterContextEntity createParameterContextEntity(final ParameterContext parameterContext, final boolean includeInheritedParameters, final NiFiUser user, - final ParameterContextLookup parameterContextLookup) { + final ParameterContextLookup parameterContextLookup, final boolean includeReferences) { final PermissionsDTO permissions = dtoFactory.createPermissionsDto(parameterContext, user); final RevisionDTO revisionDto = dtoFactory.createRevisionDTO(revisionManager.getRevision(parameterContext.getIdentifier())); final ParameterContextDTO parameterContextDto = dtoFactory.createParameterContextDto(parameterContext, revisionManager, includeInheritedParameters, - parameterContextLookup); + parameterContextLookup, includeReferences); final ParameterContextEntity entity = entityFactory.createParameterContextEntity(parameterContextDto, revisionDto, permissions); return entity; } @@ -1542,7 +1542,7 @@ private Asset getAsset(final String assetId) { } @Override - public ParameterContextEntity createParameterContext(final Revision revision, final ParameterContextDTO parameterContextDto) { + public ParameterContextEntity createParameterContext(final Revision revision, final ParameterContextDTO parameterContextDto, final boolean includeReferences) { final NiFiUser user = NiFiUserUtils.getNiFiUser(); // request claim for component to be created... revision already verified (version == 0) @@ -1557,7 +1557,7 @@ public ParameterContextEntity createParameterContext(final Revision revision, fi controllerFacade.save(); final ParameterContextDTO dto = dtoFactory.createParameterContextDto(parameterContext, revisionManager, false, - parameterContextDAO); + parameterContextDAO, includeReferences); final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getIdentity()); return new StandardRevisionUpdate<>(dto, lastMod); }); @@ -1574,7 +1574,7 @@ public void verifyDeleteParameterContext(final String parameterContextId) { } @Override - public ParameterContextEntity deleteParameterContext(final Revision revision, final String parameterContextId) { + public ParameterContextEntity deleteParameterContext(final Revision revision, final String parameterContextId, final boolean includeReferences) { final ParameterContext parameterContext = parameterContextDAO.getParameterContext(parameterContextId); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(parameterContext); final ParameterContextDTO snapshot = deleteComponent( @@ -1582,7 +1582,7 @@ public ParameterContextEntity deleteParameterContext(final Revision revision, fi parameterContext.getResource(), () -> parameterContextDAO.deleteParameterContext(parameterContextId), true, - dtoFactory.createParameterContextDto(parameterContext, revisionManager, false, parameterContextDAO)); + dtoFactory.createParameterContextDto(parameterContext, revisionManager, false, parameterContextDAO, includeReferences)); return entityFactory.createParameterContextEntity(snapshot, null, permissions); @@ -4138,7 +4138,7 @@ public Set getConnectorControllerServices(final String } @Override - public ParameterContextEntity getConnectorParameterContext(final String connectorId, final String processGroupId) { + public ParameterContextEntity getConnectorParameterContext(final String connectorId, final String processGroupId, final boolean includeReferences) { final ConnectorNode connectorNode = connectorDAO.getConnector(connectorId, ConnectorSyncMode.LOCAL_ONLY); final ProcessGroup managedProcessGroup = connectorNode.getActiveFlowContext().getManagedProcessGroup(); final ProcessGroup targetProcessGroup = managedProcessGroup.findProcessGroup(processGroupId); @@ -4155,7 +4155,7 @@ public ParameterContextEntity getConnectorParameterContext(final String connecto // global flow's ParameterContextManager, so a DAO-backed lookup would fail to resolve inherited parameters. // The DTO factory walks the in-memory inheritance graph reachable from the supplied context to resolve // parameter source contexts for connector-managed flows, making an empty lookup safe here. - return createParameterContextEntity(parameterContext, true, NiFiUserUtils.getNiFiUser(), ParameterContextLookup.EMPTY); + return createParameterContextEntity(parameterContext, true, NiFiUserUtils.getNiFiUser(), ParameterContextLookup.EMPTY, includeReferences); } @Override @@ -4431,7 +4431,9 @@ public ParameterProviderEntity fetchParameters(final String parameterProviderId) } @Override - public List getParameterContextUpdatesForAppliedParameters(final String parameterProviderId, final Collection parameterGroupConfigurations) { + public List getParameterContextUpdatesForAppliedParameters(final String parameterProviderId, + final Collection parameterGroupConfigurations, + final boolean includeReferences) { final NiFiUser user = NiFiUserUtils.getNiFiUser(); final Map parameterGroupConfigurationMap = parameterGroupConfigurations.stream() .collect(Collectors.toMap(ParameterGroupConfiguration::getParameterContextName, Function.identity())); @@ -4442,7 +4444,7 @@ public List getParameterContextUpdatesForAppliedParamete .map(parametersApplication -> { final ParameterContext parameterContext = parametersApplication.getParameterContext(); final ParameterGroupConfiguration parameterGroupConfiguration = parameterGroupConfigurationMap.get(parameterContext.getName()); - final ParameterContextEntity entity = createParameterContextEntity(parameterContext, false, user, parameterContextDAO); + final ParameterContextEntity entity = createParameterContextEntity(parameterContext, false, user, parameterContextDAO, includeReferences); final ParameterProviderConfigurationDTO parameterProviderConfiguration = entity.getComponent().getParameterProviderConfiguration().getComponent(); parameterProviderConfiguration.setSynchronized(parameterGroupConfiguration.isSynchronized()); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java index 81f16ad70578..95b894fd357b 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java @@ -121,6 +121,7 @@ public abstract class ApplicationResource { public static final String VERSION = "version"; public static final String CLIENT_ID = "clientId"; public static final String DISCONNECTED_NODE_ACKNOWLEDGED = "disconnectedNodeAcknowledged"; + public static final String INCLUDE_REFERENCING_COMPONENTS = "includeReferencingComponents"; protected static final String NON_GUARANTEED_ENDPOINT = "Note: This endpoint is subject to change as NiFi and it's REST API evolve."; diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java index 7836582db82a..2523590c7d7d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java @@ -2061,7 +2061,7 @@ public Response getControllerServicesFromConnectorProcessGroup( @QueryParam("includeDescendantGroups") @DefaultValue("false") final boolean includeDescendantGroups, @Parameter(description = "Whether or not to include services' referencing components in the response") - @QueryParam("includeReferencingComponents") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (isReplicateRequest()) { @@ -2123,7 +2123,9 @@ public Response getParameterContextForConnectorProcessGroup( @Parameter(description = "The connector id.", required = true) @PathParam("connectorId") final String connectorId, @Parameter(description = "The process group id.", required = true) - @PathParam("processGroupId") final String processGroupId) { + @PathParam("processGroupId") final String processGroupId, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (isReplicateRequest()) { return replicate(HttpMethod.GET); @@ -2135,7 +2137,7 @@ public Response getParameterContextForConnectorProcessGroup( connector.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser()); }); - final ParameterContextEntity entity = serviceFacade.getConnectorParameterContext(connectorId, processGroupId); + final ParameterContextEntity entity = serviceFacade.getConnectorParameterContext(connectorId, processGroupId, includeReferences); if (entity == null) { return Response.noContent().build(); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java index 753c6c66a97d..dea734dc0236 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java @@ -648,7 +648,7 @@ public Response getFlowMetrics( ) public Response getControllerServicesFromController( @Parameter(description = "Whether or not to include services' referencing components in the response") - @QueryParam("includeReferencingComponents") @DefaultValue("true") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") boolean includeReferences, @QueryParam("uiOnly") @DefaultValue("false") final boolean uiOnly) { @@ -711,7 +711,7 @@ public Response getControllerServicesFromGroup( @QueryParam("includeDescendantGroups") @DefaultValue("false") final boolean includeDescendantGroups, @Parameter(description = "Whether or not to include services' referencing components in the response") - @QueryParam("includeReferencingComponents") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences, @QueryParam("uiOnly") @DefaultValue("false") final boolean uiOnly) { @@ -3839,14 +3839,16 @@ public Response getConnectionStatusHistory( @SecurityRequirement(name = "Read - /parameter-contexts/{id} for each Parameter Context") } ) - public Response getParameterContexts() { + public Response getParameterContexts( + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { authorizeFlow(); if (isReplicateRequest()) { return replicate(HttpMethod.GET); } - final Set parameterContexts = serviceFacade.getParameterContexts(); + final Set parameterContexts = serviceFacade.getParameterContexts(includeReferences); parameterContexts.forEach(entity -> entity.setUri(generateResourceUri("parameter-contexts", entity.getId()))); final ParameterContextsEntity entity = new ParameterContextsEntity(); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java index 87e5ac45384b..e871709493ef 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterContextResource.java @@ -247,7 +247,9 @@ public Response getParameterContext( description = "Whether or not to include inherited parameters from other parameter contexts, and therefore also overridden values. " + "If true, the result will be the 'effective' parameter context." ) @QueryParam("includeInheritedParameters") - @DefaultValue("false") final boolean includeInheritedParameters) { + @DefaultValue("false") final boolean includeInheritedParameters, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { // authorize access authorizeReadParameterContext(parameterContextId); @@ -256,7 +258,7 @@ public Response getParameterContext( } // get the specified parameter context - final ParameterContextEntity entity = serviceFacade.getParameterContext(parameterContextId, includeInheritedParameters, NiFiUserUtils.getNiFiUser()); + final ParameterContextEntity entity = serviceFacade.getParameterContext(parameterContextId, includeInheritedParameters, NiFiUserUtils.getNiFiUser(), includeReferences); entity.setUri(generateResourceUri("parameter-contexts", entity.getId())); // generate the response @@ -282,7 +284,9 @@ public Response getParameterContext( } ) public Response createParameterContext( - @Parameter(description = "The Parameter Context.", required = true) final ParameterContextEntity requestEntity) { + @Parameter(description = "The Parameter Context.", required = true) final ParameterContextEntity requestEntity, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (requestEntity == null || requestEntity.getComponent() == null) { throw new IllegalArgumentException("Parameter Context must be specified"); @@ -318,7 +322,7 @@ public Response createParameterContext( entity.getComponent().setId(contextId); final Revision revision = getRevision(entity.getRevision(), contextId); - final ParameterContextEntity contextEntity = serviceFacade.createParameterContext(revision, entity.getComponent()); + final ParameterContextEntity contextEntity = serviceFacade.createParameterContext(revision, entity.getComponent(), includeReferences); // generate a 201 created response final String uri = generateResourceUri("parameter-contexts", contextEntity.getId()); @@ -355,7 +359,9 @@ public Response createParameterContext( ) public Response updateParameterContext( @PathParam("id") String contextId, - @Parameter(description = "The updated Parameter Context", required = true) final ParameterContextEntity requestEntity) { + @Parameter(description = "The updated Parameter Context", required = true) final ParameterContextEntity requestEntity, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { // Validate request if (requestEntity.getId() == null) { @@ -396,7 +402,7 @@ public Response updateParameterContext( lookup -> authorizeReadWriteParameterContextWithComponents(lookup, contextId, requestEntity, affectedComponents, user), () -> serviceFacade.verifyUpdateParameterContext(updateDto, true), (rev, entity) -> { - final ParameterContextEntity updatedEntity = serviceFacade.updateParameterContext(rev, entity.getComponent()); + final ParameterContextEntity updatedEntity = serviceFacade.updateParameterContext(rev, entity.getComponent(), includeReferences); updatedEntity.setUri(generateResourceUri("parameter-contexts", entity.getId())); return generateOkResponse(updatedEntity).build(); @@ -459,7 +465,7 @@ public Response createAsset( // Get the context or throw ResourceNotFoundException final NiFiUser user = NiFiUserUtils.getNiFiUser(); - final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(contextId, false, user); + final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(contextId, false, user, false); final Set affectedComponents = serviceFacade.getComponentsAffectedByParameterContextUpdate(Collections.singletonList(contextEntity.getComponent())); final Optional previousAsset = assetManager.getAssets(contextId).stream().filter(asset -> asset.getName().equals(sanitizedAssetName)).findAny(); @@ -654,7 +660,7 @@ public Response deleteAsset( // Get the context or throw ResourceNotFoundException final NiFiUser user = NiFiUserUtils.getNiFiUser(); - final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(parameterContextId, false, user); + final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(parameterContextId, false, user, false); final AssetDTO assetDTO = new AssetDTO(); assetDTO.setId(assetId); @@ -712,7 +718,9 @@ public Response deleteAsset( ) public Response submitParameterContextUpdate( @PathParam("contextId") final String contextId, - @Parameter(description = "The updated version of the parameter context.", required = true) final ParameterContextEntity requestEntity) { + @Parameter(description = "The updated version of the parameter context.", required = true) final ParameterContextEntity requestEntity, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (requestEntity == null) { throw new IllegalArgumentException("Parameter Context must be specified."); @@ -774,7 +782,7 @@ public Response submitParameterContextUpdate( // Verify Request serviceFacade.verifyUpdateParameterContext(contextDto, false); }, - this::submitUpdateRequest + (rev, wrapper) -> submitUpdateRequest(rev, wrapper, includeReferences) ); } @@ -913,11 +921,13 @@ public Response getParameterContextUpdate( @Parameter(description = "The ID of the Parameter Context") @PathParam("contextId") final String contextId, @Parameter(description = "The ID of the Update Request") - @PathParam("requestId") final String updateRequestId) { + @PathParam("requestId") final String updateRequestId, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { authorizeReadParameterContext(contextId); - return retrieveUpdateRequest("update-requests", contextId, updateRequestId); + return retrieveUpdateRequest("update-requests", contextId, updateRequestId, includeReferences); } @DELETE @@ -949,10 +959,12 @@ public Response deleteUpdateRequest( @Parameter(description = "The ID of the ParameterContext") @PathParam("contextId") final String contextId, @Parameter(description = "The ID of the Update Request") - @PathParam("requestId") final String updateRequestId) { + @PathParam("requestId") final String updateRequestId, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { authorizeReadParameterContext(contextId); - return deleteUpdateRequest("update-requests", contextId, updateRequestId, disconnectedNodeAcknowledged.booleanValue()); + return deleteUpdateRequest("update-requests", contextId, updateRequestId, disconnectedNodeAcknowledged.booleanValue(), includeReferences); } @DELETE @@ -992,7 +1004,9 @@ public Response deleteParameterContext( @QueryParam(DISCONNECTED_NODE_ACKNOWLEDGED) @DefaultValue("false") final Boolean disconnectedNodeAcknowledged, @Parameter(description = "The Parameter Context ID.") - @PathParam("id") final String parameterContextId) { + @PathParam("id") final String parameterContextId, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (isReplicateRequest()) { return replicate(HttpMethod.DELETE); @@ -1009,7 +1023,7 @@ public Response deleteParameterContext( authorizeReadWriteParameterContext(parameterContextId); final NiFiUser user = NiFiUserUtils.getNiFiUser(); - final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(parameterContextId, false, user); + final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(parameterContextId, false, user, false); for (final ProcessGroupEntity boundGroupEntity : contextEntity.getComponent().getBoundProcessGroups()) { final String groupId = boundGroupEntity.getId(); final Authorizable groupAuthorizable = lookup.getProcessGroup(groupId).getAuthorizable(); @@ -1020,7 +1034,7 @@ public Response deleteParameterContext( () -> serviceFacade.verifyDeleteParameterContext(parameterContextId), (revision, groupEntity) -> { // disconnect from version control - final ParameterContextEntity entity = serviceFacade.deleteParameterContext(revision, parameterContextId); + final ParameterContextEntity entity = serviceFacade.deleteParameterContext(revision, parameterContextId, includeReferences); // generate the response return generateOkResponse(entity).build(); @@ -1094,7 +1108,7 @@ public Response submitValidationRequest( } private void authorizeReferencingComponents(final String parameterContextId, final AuthorizableLookup lookup, final NiFiUser user) { - final ParameterContextEntity context = serviceFacade.getParameterContext(parameterContextId, false, NiFiUserUtils.getNiFiUser()); + final ParameterContextEntity context = serviceFacade.getParameterContext(parameterContextId, false, NiFiUserUtils.getNiFiUser(), true); for (final ParameterEntity parameterEntity : context.getComponent().getParameters()) { final ParameterDTO dto = parameterEntity.getParameter(); @@ -1234,7 +1248,7 @@ private ComponentValidationResultsEntity validateComponents(final ParameterConte return resultsEntity; } - private Response submitUpdateRequest(final Revision requestRevision, final InitiateChangeParameterContextRequestWrapper requestWrapper) { + private Response submitUpdateRequest(final Revision requestRevision, final InitiateChangeParameterContextRequestWrapper requestWrapper, final boolean includeReferences) { // Create an asynchronous request that will occur in the background, because this request may // result in stopping components, which can take an indeterminate amount of time. final String requestId = UUID.randomUUID().toString(); @@ -1265,7 +1279,7 @@ private Response submitUpdateRequest(final Revision requestRevision, final Initi updateRequestManager.submitRequest("update-requests", requestId, request, updateTask); // Generate the response. - final ParameterContextUpdateRequestEntity updateRequestEntity = createUpdateRequestEntity(request, "update-requests", contextId, requestId); + final ParameterContextUpdateRequestEntity updateRequestEntity = createUpdateRequestEntity(request, "update-requests", contextId, requestId, includeReferences); return generateOkResponse(updateRequestEntity).build(); } @@ -1332,7 +1346,7 @@ private ParameterContextValidationRequestEntity createValidationRequestEntity(fi return entity; } - private Response retrieveUpdateRequest(final String requestType, final String contextId, final String requestId) { + private Response retrieveUpdateRequest(final String requestType, final String contextId, final String requestId, final boolean includeReferences) { if (requestId == null) { throw new IllegalArgumentException("Request ID must be specified."); } @@ -1341,11 +1355,12 @@ private Response retrieveUpdateRequest(final String requestType, final String co // request manager will ensure that the current is the user that submitted this request final AsynchronousWebRequest, List> asyncRequest = updateRequestManager.getRequest(requestType, requestId, user); - final ParameterContextUpdateRequestEntity updateRequestEntity = createUpdateRequestEntity(asyncRequest, requestType, contextId, requestId); + final ParameterContextUpdateRequestEntity updateRequestEntity = createUpdateRequestEntity(asyncRequest, requestType, contextId, requestId, includeReferences); return generateOkResponse(updateRequestEntity).build(); } - private Response deleteUpdateRequest(final String requestType, final String contextId, final String requestId, final boolean disconnectedNodeAcknowledged) { + private Response deleteUpdateRequest(final String requestType, final String contextId, final String requestId, final boolean disconnectedNodeAcknowledged, + final boolean includeReferences) { if (requestId == null) { throw new IllegalArgumentException("Request ID must be specified."); } @@ -1366,12 +1381,12 @@ private Response deleteUpdateRequest(final String requestType, final String cont asyncRequest.cancel(); } - final ParameterContextUpdateRequestEntity updateRequestEntity = createUpdateRequestEntity(asyncRequest, requestType, contextId, requestId); + final ParameterContextUpdateRequestEntity updateRequestEntity = createUpdateRequestEntity(asyncRequest, requestType, contextId, requestId, includeReferences); return generateOkResponse(updateRequestEntity).build(); } private ParameterContextUpdateRequestEntity createUpdateRequestEntity(final AsynchronousWebRequest, List> asyncRequest, - final String requestType, final String contextId, final String requestId) { + final String requestType, final String contextId, final String requestId, final boolean includeReferences) { final List initialRequestList = asyncRequest.getRequest(); // Safe because this is from the request, not the response final ParameterContextEntity initialEntity = initialRequestList.get(0); @@ -1404,7 +1419,7 @@ private ParameterContextUpdateRequestEntity createUpdateRequestEntity(final Asyn updateRequestDto.setReferencingComponents(new HashSet<>(affectedComponents.values())); // Populate the Affected Components - final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(asyncRequest.getComponentId(), false, NiFiUserUtils.getNiFiUser()); + final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(asyncRequest.getComponentId(), false, NiFiUserUtils.getNiFiUser(), includeReferences); final ParameterContextUpdateRequestEntity updateRequestEntity = new ParameterContextUpdateRequestEntity(); // If the request is complete, include the new representation of the Parameter Context along with its new Revision. Otherwise, do not include the information, since it is 'stale' diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java index 418ab7325bc0..0e471ad9d9d0 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ParameterProviderResource.java @@ -785,7 +785,9 @@ public Response fetchParameters( @Parameter( description = "The parameter fetch request.", required = true - ) final ParameterProviderParameterFetchEntity fetchParametersEntity) { + ) final ParameterProviderParameterFetchEntity fetchParametersEntity, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (fetchParametersEntity.getId() == null) { throw new IllegalArgumentException("The ID of the Parameter Provider must be specified"); @@ -815,7 +817,7 @@ public Response fetchParameters( final Collection referencingParameterContextDtos = new HashSet<>(); references.forEach(referencingEntity -> { final String parameterContextId = referencingEntity.getComponent().getId(); - final ParameterContextEntity parameterContextEntity = serviceFacade.getParameterContext(parameterContextId, true, user); + final ParameterContextEntity parameterContextEntity = serviceFacade.getParameterContext(parameterContextId, true, user, true); parameterContextEntity.getComponent().getParameters().stream() .filter(dto -> Boolean.TRUE.equals(dto.getParameter().getProvided())) .forEach(p -> referencingComponents.addAll(p.getParameter().getReferencingComponents())); @@ -854,7 +856,8 @@ public Response fetchParameters( parameterGroupConfigurations.add(new ParameterGroupConfiguration(group.getGroupName(), group.getParameterContextName(), updatedSensitivities, group.isSynchronized())); }); - final List parameterContextUpdates = serviceFacade.getParameterContextUpdatesForAppliedParameters(parameterProviderId, parameterGroupConfigurations); + final List parameterContextUpdates = + serviceFacade.getParameterContextUpdatesForAppliedParameters(parameterProviderId, parameterGroupConfigurations, includeReferences); final Set removedParameters = parameterContextUpdates.stream() .flatMap(context -> context.getComponent().getParameters().stream()) @@ -867,7 +870,7 @@ public Response fetchParameters( if (!affectedComponents.isEmpty()) { entity.getComponent().setAffectedComponents(affectedComponents); } - final Set parameterStatus = getParameterStatus(entity, parameterContextUpdates, removedParameters, user); + final Set parameterStatus = getParameterStatus(entity, parameterContextUpdates, removedParameters, user, includeReferences); if (!parameterStatus.isEmpty()) { entity.getComponent().setParameterStatus(parameterStatus); } @@ -879,7 +882,7 @@ public Response fetchParameters( } private void authorizeReferencingComponents(final String parameterContextId, final AuthorizableLookup lookup, final NiFiUser user) { - final ParameterContextEntity context = serviceFacade.getParameterContext(parameterContextId, false, NiFiUserUtils.getNiFiUser()); + final ParameterContextEntity context = serviceFacade.getParameterContext(parameterContextId, false, NiFiUserUtils.getNiFiUser(), true); for (final ParameterEntity parameterEntity : context.getComponent().getParameters()) { final ParameterDTO dto = parameterEntity.getParameter(); @@ -922,7 +925,9 @@ private void authorizeReferencingComponents(final String parameterContextId, fin public Response submitApplyParameters( @Parameter(description = "The ID of the Parameter Provider") @PathParam("providerId") final String parameterProviderId, - @Parameter(description = "The apply parameters request.", required = true) final ParameterProviderParameterApplicationEntity requestEntity) { + @Parameter(description = "The apply parameters request.", required = true) final ParameterProviderParameterApplicationEntity requestEntity, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { if (requestEntity == null) { throw new IllegalArgumentException("Apply Parameters Request must be specified."); @@ -967,14 +972,14 @@ public Response submitApplyParameters( .forEach(parameterGroupConfiguration -> { final ParameterContextEntity newParameterContext = getNewParameterContextEntity(parameterProviderId, parameterGroupConfiguration); try { - performParameterContextCreate(user, getAbsolutePath(), replicateRequest, newParameterContext); + performParameterContextCreate(user, getAbsolutePath(), replicateRequest, newParameterContext, includeReferences); } catch (final LifecycleManagementException e) { throw new RuntimeException("Failed to create Parameter Context " + parameterGroupConfiguration.getGroupName(), e); } }); // Get a list of parameter context entities representing changes needed in order to apply the fetched parameters - final List parameterContextUpdates = serviceFacade.getParameterContextUpdatesForAppliedParameters(parameterProviderId, parameterGroupConfigurations); + final List parameterContextUpdates = serviceFacade.getParameterContextUpdatesForAppliedParameters(parameterProviderId, parameterGroupConfigurations, includeReferences); final Set affectedComponents = getAffectedComponentEntities(parameterContextUpdates); logger.debug("Received Apply Request for Parameter Provider: {}; the following {} components will be affected: {}", requestEntity, affectedComponents.size(), affectedComponents); @@ -1005,7 +1010,7 @@ public Response submitApplyParameters( // Verify Request serviceFacade.verifyCanApplyParameters(parameterProviderId, parameterGroupConfigurations); }, - this::submitApplyRequest + (rev, wrapper) -> submitApplyRequest(rev, wrapper, includeReferences) ); } @@ -1017,7 +1022,7 @@ private Set getAffectedComponentEntities(final List getParameterStatus(final ParameterProviderEntity parameterProvider, final List parameterContextUpdates, - final Set removedParameters, final NiFiUser niFiUser) { + final Set removedParameters, final NiFiUser niFiUser, final boolean includeReferences) { final Set parameterStatus = new HashSet<>(); if (parameterProvider.getComponent() == null || parameterProvider.getComponent().getReferencingParameterContexts() == null) { return parameterStatus; @@ -1034,7 +1039,7 @@ private Set getParameterStatus(final ParameterProviderEntity for (final ParameterProviderReferencingComponentEntity reference : parameterProvider.getComponent().getReferencingParameterContexts()) { final String parameterContextId = reference.getComponent().getId(); - final ParameterContextEntity parameterContext = serviceFacade.getParameterContext(parameterContextId, false, niFiUser); + final ParameterContextEntity parameterContext = serviceFacade.getParameterContext(parameterContextId, false, niFiUser, includeReferences); if (parameterContext.getComponent() == null) { continue; } @@ -1108,11 +1113,13 @@ private Set getParameterStatus(final ParameterProviderEntity ) public Response getParameterProviderApplyParametersRequest( @Parameter(description = "The ID of the Parameter Provider") @PathParam("providerId") final String parameterProviderId, - @Parameter(description = "The ID of the Apply Parameters Request") @PathParam("requestId") final String applyParametersRequestId) { + @Parameter(description = "The ID of the Apply Parameters Request") @PathParam("requestId") final String applyParametersRequestId, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { authorizeReadParameterProvider(parameterProviderId); - return retrieveApplyParametersRequest("apply-parameters-requests", parameterProviderId, applyParametersRequestId); + return retrieveApplyParametersRequest("apply-parameters-requests", parameterProviderId, applyParametersRequestId, includeReferences); } @DELETE @@ -1142,10 +1149,12 @@ public Response deleteApplyParametersRequest( ) @QueryParam(DISCONNECTED_NODE_ACKNOWLEDGED) @DefaultValue("false") final Boolean disconnectedNodeAcknowledged, @Parameter(description = "The ID of the Parameter Provider") @PathParam("providerId") final String parameterProviderId, - @Parameter(description = "The ID of the Apply Parameters Request") @PathParam("requestId") final String applyParametersRequestId) { + @Parameter(description = "The ID of the Apply Parameters Request") @PathParam("requestId") final String applyParametersRequestId, + @Parameter(description = "Whether or not to include parameters' referencing components in the response") + @QueryParam(INCLUDE_REFERENCING_COMPONENTS) @DefaultValue("true") final boolean includeReferences) { authorizeReadParameterProvider(parameterProviderId); - return deleteApplyParametersRequest("apply-parameters-requests", parameterProviderId, applyParametersRequestId, disconnectedNodeAcknowledged.booleanValue()); + return deleteApplyParametersRequest("apply-parameters-requests", parameterProviderId, applyParametersRequestId, disconnectedNodeAcknowledged.booleanValue(), includeReferences); } @POST @@ -1424,7 +1433,7 @@ private VerifyConfigRequestEntity createVerifyParameterProviderConfigRequestEnti return entity; } - private Response retrieveApplyParametersRequest(final String requestType, final String parameterProviderId, final String requestId) { + private Response retrieveApplyParametersRequest(final String requestType, final String parameterProviderId, final String requestId, final boolean includeReferences) { if (requestId == null) { throw new IllegalArgumentException("Request ID must be specified."); } @@ -1433,11 +1442,13 @@ private Response retrieveApplyParametersRequest(final String requestType, final // request manager will ensure that the current is the user that submitted this request final AsynchronousWebRequest, List> asyncRequest = updateRequestManager.getRequest(requestType, requestId, user); - final ParameterProviderApplyParametersRequestEntity applyParametersRequestEntity = createApplyParametersRequestEntity(asyncRequest, requestType, parameterProviderId, requestId); + final ParameterProviderApplyParametersRequestEntity applyParametersRequestEntity = + createApplyParametersRequestEntity(asyncRequest, requestType, parameterProviderId, requestId, includeReferences); return generateOkResponse(applyParametersRequestEntity).build(); } - private Response deleteApplyParametersRequest(final String requestType, final String parameterProviderId, final String requestId, final boolean disconnectedNodeAcknowledged) { + private Response deleteApplyParametersRequest(final String requestType, final String parameterProviderId, final String requestId, final boolean disconnectedNodeAcknowledged, + final boolean includeReferences) { if (requestId == null) { throw new IllegalArgumentException("Request ID must be specified."); } @@ -1458,12 +1469,14 @@ private Response deleteApplyParametersRequest(final String requestType, final St asyncRequest.cancel(); } - final ParameterProviderApplyParametersRequestEntity applyParametersRequestEntity = createApplyParametersRequestEntity(asyncRequest, requestType, parameterProviderId, requestId); + final ParameterProviderApplyParametersRequestEntity applyParametersRequestEntity = + createApplyParametersRequestEntity(asyncRequest, requestType, parameterProviderId, requestId, includeReferences); return generateOkResponse(applyParametersRequestEntity).build(); } private ParameterProviderApplyParametersRequestEntity createApplyParametersRequestEntity(final AsynchronousWebRequest, List> asyncRequest, - final String requestType, final String parameterProviderId, final String requestId) { + final String requestType, final String parameterProviderId, final String requestId, + final boolean includeReferences) { final ParameterProviderApplyParametersRequestEntity applyParametersRequestEntity = new ParameterProviderApplyParametersRequestEntity(); final ParameterProviderApplyParametersRequestDTO applyParametersRequestDTO = new ParameterProviderApplyParametersRequestDTO(); applyParametersRequestDTO.setComplete(asyncRequest.isComplete()); @@ -1495,7 +1508,12 @@ private ParameterProviderApplyParametersRequestEntity createApplyParametersReque // The AffectedComponentEntity itself does not evaluate equality based on component information. As a result, we want to de-dupe the entities based on their identifiers. final Map affectedComponents = new HashMap<>(); for (final ParameterEntity entity : parameterContextEntity.getComponent().getParameters()) { - for (final AffectedComponentEntity affectedComponentEntity : entity.getParameter().getReferencingComponents()) { + final Set referencingComponents = entity.getParameter().getReferencingComponents(); + if (referencingComponents == null) { + continue; + } + + for (final AffectedComponentEntity affectedComponentEntity : referencingComponents) { final AffectedComponentEntity updatedAffectedComponentEntity = serviceFacade.getUpdatedAffectedComponentEntity(affectedComponentEntity); final String affectedComponentEntityId = affectedComponentEntity.getId(); @@ -1505,7 +1523,7 @@ private ParameterProviderApplyParametersRequestEntity createApplyParametersReque } // Populate the Affected Components - final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(parameterContextEntity.getId(), false, NiFiUserUtils.getNiFiUser()); + final ParameterContextEntity contextEntity = serviceFacade.getParameterContext(parameterContextEntity.getId(), false, NiFiUserUtils.getNiFiUser(), includeReferences); final ParameterContextUpdateEntity parameterContextUpdate = new ParameterContextUpdateEntity(); parameterContextUpdate.setReferencingComponents(new HashSet<>(affectedComponents.values())); @@ -1583,7 +1601,7 @@ private ParameterContextEntity getNewParameterContextEntity(final String paramet return parameterContextEntity; } - private Response submitApplyRequest(final Revision requestRevision, final InitiateParameterProviderApplyParametersRequestWrapper requestWrapper) { + private Response submitApplyRequest(final Revision requestRevision, final InitiateParameterProviderApplyParametersRequestWrapper requestWrapper, final boolean includeReferences) { // Create an asynchronous request that will occur in the background, because this request may // result in stopping components, which can take an indeterminate amount of time. final String requestId = UUID.randomUUID().toString(); @@ -1614,12 +1632,12 @@ private Response submitApplyRequest(final Revision requestRevision, final Initia // Generate the response. final ParameterProviderApplyParametersRequestEntity applicationRequestEntity = createApplyParametersRequestEntity( - request, "apply-parameters-requests", parameterProviderId, requestId); + request, "apply-parameters-requests", parameterProviderId, requestId, includeReferences); return generateOkResponse(applicationRequestEntity).build(); } private ParameterContextEntity performParameterContextCreate(final NiFiUser user, final URI exampleUri, final boolean replicateRequest, - final ParameterContextEntity parameterContext) throws LifecycleManagementException { + final ParameterContextEntity parameterContext, final boolean includeReferences) throws LifecycleManagementException { if (replicateRequest) { final URI updateUri; @@ -1644,14 +1662,14 @@ private ParameterContextEntity performParameterContextCreate(final NiFiUser user } final String parameterContextId = ParameterUpdateManager.getResponseEntity(clusterResponse, ParameterContextEntity.class).getId(); - return serviceFacade.getParameterContext(parameterContextId, false, user); + return serviceFacade.getParameterContext(parameterContextId, false, user, includeReferences); } else { serviceFacade.verifyCreateParameterContext(parameterContext.getComponent()); final String contextId = generateUuid(); parameterContext.getComponent().setId(contextId); final Revision revision = getRevision(parameterContext.getRevision(), contextId); - return serviceFacade.createParameterContext(revision, parameterContext.getComponent()); + return serviceFacade.createParameterContext(revision, parameterContext.getComponent(), includeReferences); } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java index 77c43f836d32..587c75041788 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java @@ -1086,7 +1086,7 @@ public Response createProcessGroup( // Step 4: Replace parameter contexts if necessary if (ParameterContextHandlingStrategy.REPLACE.equals(parameterContextHandlingStrategy)) { - parameterContextReplacer.replaceParameterContexts(flowSnapshot, serviceFacade.getParameterContexts()); + parameterContextReplacer.replaceParameterContexts(flowSnapshot, serviceFacade.getParameterContexts(false)); } // Step 5: Resolve Bundle info diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index 9fe3af8f41ee..b97396aec017 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@ -1504,7 +1504,7 @@ public PortDTO createPortDto(final Port port) { } public ParameterContextDTO createParameterContextDto(final ParameterContext parameterContext, final RevisionManager revisionManager, - final boolean includeInheritedParameters, final ParameterContextLookup parameterContextLookup) { + final boolean includeInheritedParameters, final ParameterContextLookup parameterContextLookup, final boolean includeReferences) { final ParameterContextDTO dto = new ParameterContextDTO(); dto.setId(parameterContext.getIdentifier()); dto.setName(parameterContext.getName()); @@ -1524,7 +1524,7 @@ public ParameterContextDTO createParameterContextDto(final ParameterContext para final Map parameters = includeInheritedParameters ? parameterContext.getRawEffectiveParameters() : parameterContext.getParameters(); for (final Parameter parameter : parameters.values()) { - parameterEntities.add(createParameterEntity(parameterContext, parameter, revisionManager, parameterContextLookup)); + parameterEntities.add(createParameterEntity(parameterContext, parameter, revisionManager, parameterContextLookup, includeReferences)); } final List parameterContextRefs = new ArrayList<>(); @@ -1584,19 +1584,26 @@ public AssetReferenceDTO createAssetReferenceDto(final Asset asset) { } public ParameterEntity createParameterEntity(final ParameterContext parameterContext, final Parameter parameter, final RevisionManager revisionManager, - final ParameterContextLookup parameterContextLookup) { - final ParameterDTO dto = createParameterDto(parameterContext, parameter, revisionManager, parameterContextLookup); + final ParameterContextLookup parameterContextLookup) { + return createParameterEntity(parameterContext, parameter, revisionManager, parameterContextLookup, true); + } + + public ParameterEntity createParameterEntity(final ParameterContext parameterContext, final Parameter parameter, final RevisionManager revisionManager, + final ParameterContextLookup parameterContextLookup, final boolean includeReferences) { + final ParameterDTO dto = createParameterDto(parameterContext, parameter, revisionManager, parameterContextLookup, includeReferences); final ParameterEntity entity = new ParameterEntity(); entity.setParameter(dto); - final boolean canWrite = isWritable(dto.getReferencingComponents()); - entity.setCanWrite(canWrite); + // canWrite depends on the permissions of every component referencing this parameter, so it must always be determined, + // even when includeReferences is false and the full AffectedComponentEntity set is not built for the response. + final Set referencingComponents = getReferencingComponents(parameterContext, parameter.getDescriptor()); + entity.setCanWrite(isWritable(referencingComponents)); return entity; } public ParameterDTO createParameterDto(final ParameterContext parameterContext, final Parameter parameter, - final RevisionManager revisionManager, final ParameterContextLookup parameterContextLookup) { + final RevisionManager revisionManager, final ParameterContextLookup parameterContextLookup, final boolean includeReferences) { final ParameterDescriptor descriptor = parameter.getDescriptor(); final ParameterDTO dto = new ParameterDTO(); @@ -1610,14 +1617,11 @@ public ParameterDTO createParameterDto(final ParameterContext parameterContext, final List assets = parameter.getReferencedAssets(); dto.setReferencedAssets(assets == null ? List.of() : parameter.getReferencedAssets().stream().map(this::createAssetReferenceDto).toList()); - final ParameterReferenceManager parameterReferenceManager = parameterContext.getParameterReferenceManager(); - - final Set referencingComponents = new HashSet<>(); - referencingComponents.addAll(parameterReferenceManager.getProcessorsReferencing(parameterContext, descriptor.getName())); - referencingComponents.addAll(parameterReferenceManager.getControllerServicesReferencing(parameterContext, descriptor.getName())); - - final Set referencingComponentEntities = createAffectedComponentEntities(referencingComponents, revisionManager); - dto.setReferencingComponents(referencingComponentEntities); + if (includeReferences) { + final Set referencingComponents = getReferencingComponents(parameterContext, descriptor); + final Set referencingComponentEntities = createAffectedComponentEntities(referencingComponents, revisionManager); + dto.setReferencingComponents(referencingComponentEntities); + } final ParameterContext containingParameterContext = resolveContainingParameterContext(parameterContext, parameter, parameterContextLookup); @@ -3243,10 +3247,19 @@ private List createBulletins(final ComponentNode componentNode) { return bulletins; } - private boolean isWritable(final Collection affectedComponentEntities) { - for (final AffectedComponentEntity affectedComponent : affectedComponentEntities) { - final PermissionsDTO permissions = affectedComponent.getPermissions(); - if (!permissions.getCanRead() || !permissions.getCanWrite()) { + private Set getReferencingComponents(final ParameterContext parameterContext, final ParameterDescriptor descriptor) { + final ParameterReferenceManager parameterReferenceManager = parameterContext.getParameterReferenceManager(); + + final Set referencingComponents = new HashSet<>(); + referencingComponents.addAll(parameterReferenceManager.getProcessorsReferencing(parameterContext, descriptor.getName())); + referencingComponents.addAll(parameterReferenceManager.getControllerServicesReferencing(parameterContext, descriptor.getName())); + return referencingComponents; + } + + private boolean isWritable(final Set referencingComponents) { + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + for (final ComponentNode referencingComponent : referencingComponents) { + if (!referencingComponent.isAuthorized(authorizer, RequestAction.READ, user) || !referencingComponent.isAuthorized(authorizer, RequestAction.WRITE, user)) { return false; } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java index ea915377e956..e2bc29b60e94 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/ParameterUpdateManager.java @@ -233,10 +233,10 @@ private ParameterContextEntity performParameterContextUpdate(final AsynchronousW throw new LifecycleManagementException("Failed to update Flow on all nodes in cluster due to " + explanation); } - return serviceFacade.getParameterContext(updatedContext.getId(), false, user); + return serviceFacade.getParameterContext(updatedContext.getId(), false, user, false); } else { serviceFacade.verifyUpdateParameterContext(updatedContext.getComponent(), true); - return serviceFacade.updateParameterContext(revision, updatedContext.getComponent()); + return serviceFacade.updateParameterContext(revision, updatedContext.getComponent(), false); } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java index e73cdf17023e..61192cc060b4 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/StandardNiFiServiceFacadeTest.java @@ -2384,19 +2384,19 @@ public void testGetConnectorParameterContextReturnsEntityWhenContextBound() { final ParameterContextDTO parameterContextDto = new ParameterContextDTO(); parameterContextDto.setId(parameterContextId); parameterContextDto.setName("context-name"); - when(dtoFactory.createParameterContextDto(eq(parameterContext), eq(revisionManager), eq(true), any(ParameterContextLookup.class))) + when(dtoFactory.createParameterContextDto(eq(parameterContext), eq(revisionManager), eq(true), any(ParameterContextLookup.class), eq(true))) .thenReturn(parameterContextDto); when(dtoFactory.createPermissionsDto(eq(parameterContext), any())).thenReturn(null); when(dtoFactory.createRevisionDTO(any(Revision.class))).thenReturn(new RevisionDTO()); when(revisionManager.getRevision(parameterContextId)).thenReturn(new Revision(1L, null, parameterContextId)); - final ParameterContextEntity entity = serviceFacade.getConnectorParameterContext(connectorId, processGroupId); + final ParameterContextEntity entity = serviceFacade.getConnectorParameterContext(connectorId, processGroupId, true); assertNotNull(entity); assertEquals(parameterContextId, entity.getId()); final ArgumentCaptor lookupCaptor = ArgumentCaptor.forClass(ParameterContextLookup.class); - verify(dtoFactory).createParameterContextDto(eq(parameterContext), eq(revisionManager), eq(true), lookupCaptor.capture()); + verify(dtoFactory).createParameterContextDto(eq(parameterContext), eq(revisionManager), eq(true), lookupCaptor.capture(), eq(true)); assertNotNull(lookupCaptor.getValue()); assertNull(lookupCaptor.getValue().getParameterContext("any-id")); assertFalse(lookupCaptor.getValue().hasParameterContext("any-id")); @@ -2423,7 +2423,7 @@ public void testGetConnectorParameterContextReturnsNullWhenNoBoundContext() { when(managedProcessGroup.findProcessGroup(processGroupId)).thenReturn(targetProcessGroup); when(targetProcessGroup.getParameterContext()).thenReturn(null); - final ParameterContextEntity entity = serviceFacade.getConnectorParameterContext(connectorId, processGroupId); + final ParameterContextEntity entity = serviceFacade.getConnectorParameterContext(connectorId, processGroupId, true); assertNull(entity); verifyNoInteractions(dtoFactory); @@ -2446,7 +2446,7 @@ public void testGetConnectorParameterContextThrowsWhenProcessGroupNotFound() { when(flowContext.getManagedProcessGroup()).thenReturn(managedProcessGroup); when(managedProcessGroup.findProcessGroup(processGroupId)).thenReturn(null); - assertThrows(ResourceNotFoundException.class, () -> serviceFacade.getConnectorParameterContext(connectorId, processGroupId)); + assertThrows(ResourceNotFoundException.class, () -> serviceFacade.getConnectorParameterContext(connectorId, processGroupId, true)); } private StandardNiFiServiceFacade createBranchTestFacade(final ProcessGroupDAO branchProcessGroupDAO, final FlowRegistryDAO flowRegistryDAO, diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java index b09de3509bed..280bc3761430 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestConnectorResource.java @@ -597,27 +597,27 @@ public void testGetControllerServicesFromConnectorProcessGroupNotAuthorized() { @Test public void testGetParameterContextForConnectorProcessGroup() { final ParameterContextEntity responseEntity = createParameterContextEntity(); - when(serviceFacade.getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID)).thenReturn(responseEntity); + when(serviceFacade.getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID, true)).thenReturn(responseEntity); - try (Response response = connectorResource.getParameterContextForConnectorProcessGroup(CONNECTOR_ID, PROCESS_GROUP_ID)) { + try (Response response = connectorResource.getParameterContextForConnectorProcessGroup(CONNECTOR_ID, PROCESS_GROUP_ID, true)) { assertEquals(200, response.getStatus()); assertEquals(responseEntity, response.getEntity()); } verify(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); - verify(serviceFacade).getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID); + verify(serviceFacade).getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID, true); } @Test public void testGetParameterContextForConnectorProcessGroupReturnsNoContentWhenUnbound() { - when(serviceFacade.getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID)).thenReturn(null); + when(serviceFacade.getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID, true)).thenReturn(null); - try (Response response = connectorResource.getParameterContextForConnectorProcessGroup(CONNECTOR_ID, PROCESS_GROUP_ID)) { + try (Response response = connectorResource.getParameterContextForConnectorProcessGroup(CONNECTOR_ID, PROCESS_GROUP_ID, true)) { assertEquals(204, response.getStatus()); } verify(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); - verify(serviceFacade).getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID); + verify(serviceFacade).getConnectorParameterContext(CONNECTOR_ID, PROCESS_GROUP_ID, true); } @Test @@ -625,10 +625,10 @@ public void testGetParameterContextForConnectorProcessGroupNotAuthorized() { doThrow(AccessDeniedException.class).when(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); assertThrows(AccessDeniedException.class, () -> - connectorResource.getParameterContextForConnectorProcessGroup(CONNECTOR_ID, PROCESS_GROUP_ID)); + connectorResource.getParameterContextForConnectorProcessGroup(CONNECTOR_ID, PROCESS_GROUP_ID, true)); verify(serviceFacade).authorizeAccess(any(AuthorizeAccess.class)); - verify(serviceFacade, never()).getConnectorParameterContext(anyString(), anyString()); + verify(serviceFacade, never()).getConnectorParameterContext(anyString(), anyString(), eq(true)); } @Test diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/dto/DtoFactoryTest.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/dto/DtoFactoryTest.java index b8d84fb4d6bf..7c4e26efcf4e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/dto/DtoFactoryTest.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/dto/DtoFactoryTest.java @@ -27,6 +27,8 @@ import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.connectable.Connection; import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ProcessorNode; +import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.controller.queue.FlowFileQueue; import org.apache.nifi.controller.queue.LoadBalanceCompression; import org.apache.nifi.controller.queue.LoadBalanceStrategy; @@ -50,9 +52,14 @@ import org.apache.nifi.registry.flow.FlowRegistryClientNode; import org.apache.nifi.registry.flow.diff.DifferenceType; import org.apache.nifi.registry.flow.diff.FlowDifference; +import org.apache.nifi.reporting.Bulletin; +import org.apache.nifi.util.MockBulletinRepository; +import org.apache.nifi.web.Revision; import org.apache.nifi.web.api.entity.AllowableValueEntity; +import org.apache.nifi.web.api.entity.ComponentEntity; import org.apache.nifi.web.api.entity.ParameterContextReferenceEntity; import org.apache.nifi.web.revision.RevisionManager; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -776,7 +783,7 @@ void testCreateParameterDtoResolvesSourceContextWhenParameterContextIdIsNull() { final ParameterContextLookup lookup = mock(ParameterContextLookup.class); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup); + final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup, true); assertEquals("param-name", dto.getName()); assertEquals("param-value", dto.getValue()); @@ -803,7 +810,7 @@ void testCreateParameterDtoResolvesSourceContextWhenParameterContextIdMatchesCur final ParameterContextLookup lookup = mock(ParameterContextLookup.class); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup); + final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup, true); assertFalse(dto.getInherited()); assertEquals(contextId, dto.getParameterContext().getId()); @@ -828,7 +835,7 @@ void testCreateParameterDtoResolvesSourceContextFromInheritedGraph() { final ParameterContextLookup lookup = mock(ParameterContextLookup.class); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(childContext, parameter, mock(RevisionManager.class), lookup); + final ParameterDTO dto = dtoFactory.createParameterDto(childContext, parameter, mock(RevisionManager.class), lookup, true); assertTrue(dto.getInherited()); assertEquals(parentId, dto.getParameterContext().getId()); @@ -855,7 +862,7 @@ void testCreateParameterDtoResolvesSourceContextFromTransitiveInheritedGraph() { final ParameterContextLookup lookup = mock(ParameterContextLookup.class); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(childContext, parameter, mock(RevisionManager.class), lookup); + final ParameterDTO dto = dtoFactory.createParameterDto(childContext, parameter, mock(RevisionManager.class), lookup, true); assertTrue(dto.getInherited()); assertEquals(grandparentId, dto.getParameterContext().getId()); @@ -881,7 +888,7 @@ void testCreateParameterDtoFallsBackToLookupWhenSourceNotReachableInGraph() { when(lookup.getParameterContext(externalId)).thenReturn(externalContext); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup); + final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup, true); assertTrue(dto.getInherited()); assertEquals(externalId, dto.getParameterContext().getId()); @@ -903,7 +910,7 @@ void testCreateParameterDtoFallsBackToCurrentContextWhenSourceNotReachableInGrap .build(); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), ParameterContextLookup.EMPTY); + final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), ParameterContextLookup.EMPTY, true); assertFalse(dto.getInherited()); assertEquals(contextId, dto.getParameterContext().getId()); @@ -928,7 +935,7 @@ void testCreateParameterDtoResolvesSourceContextFromDiamondInheritanceGraph() { .build(); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(contextA, parameter, mock(RevisionManager.class), ParameterContextLookup.EMPTY); + final ParameterDTO dto = dtoFactory.createParameterDto(contextA, parameter, mock(RevisionManager.class), ParameterContextLookup.EMPTY, true); assertTrue(dto.getInherited()); assertEquals(contextDId, dto.getParameterContext().getId()); @@ -958,7 +965,7 @@ void testCreateParameterDtoInheritanceGraphHandlesCycles() { when(lookup.getParameterContext(missingId)).thenReturn(fallbackContext); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(childContext, parameter, mock(RevisionManager.class), lookup); + final ParameterDTO dto = dtoFactory.createParameterDto(childContext, parameter, mock(RevisionManager.class), lookup, true); assertTrue(dto.getInherited()); assertEquals(missingId, dto.getParameterContext().getId()); @@ -978,12 +985,68 @@ void testCreateParameterDtoSensitiveValueIsMasked() { .build(); final DtoFactory dtoFactory = newDtoFactoryForParameters(); - final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), mock(ParameterContextLookup.class)); + final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), mock(ParameterContextLookup.class), true); assertTrue(dto.getSensitive()); assertEquals(DtoFactory.SENSITIVE_VALUE_MASK, dto.getValue()); } + + + @Test + void testCreateParameterDtoReferencesIncluded() { + final String processorId = "processor-1"; + final String controllerId = "controller-1"; + + final ParameterDTO dto = getDtoForParameterWithReferences(processorId, controllerId, true); + + Set referencedIdSet = dto.getReferencingComponents().stream().map(ComponentEntity::getId).collect(Collectors.toSet()); + assertEquals(Set.of(processorId, controllerId), referencedIdSet); + } + + @Test + void testCreateParameterDtoReferencesExcluded() { + final String processorId = "processor-1"; + final String controllerId = "controller-1"; + + final ParameterDTO dto = getDtoForParameterWithReferences(processorId, controllerId, false); + + assertNull(dto.getReferencingComponents()); + } + + private static @NonNull ParameterDTO getDtoForParameterWithReferences(String processorId, String controllerId, boolean includeReferences) { + final String contextId = "context-1"; + ProcessorNode referencingProcessor = mock(ProcessorNode.class); + when(referencingProcessor.getIdentifier()).thenReturn(processorId); + when(referencingProcessor.getDesiredState()).thenReturn(ScheduledState.RUNNING); + ControllerServiceNode referencingControllerService = mock(ControllerServiceNode.class); + when(referencingControllerService.getIdentifier()).thenReturn(controllerId); + when(referencingControllerService.getState()).thenReturn(ControllerServiceState.ENABLED); + RevisionManager revisionManager = mock(RevisionManager.class); + when(revisionManager.getRevision(eq(processorId))).thenReturn(new Revision(0L, "client-1", processorId)); + when(revisionManager.getRevision(eq(controllerId))).thenReturn(new Revision(0L, "client-1", controllerId)); + + final ParameterContext parameterContext = createMockParameterContextWithRefs(contextId, "context-1-name", + Collections.emptyList(), Set.of(referencingControllerService), Set.of(referencingProcessor)); + + final Parameter parameter = new Parameter.Builder() + .name("my-param") + .value("my-value") + .sensitive(false) + .build(); + + final DtoFactory dtoFactory = newDtoFactoryForParameters(); + dtoFactory.setBulletinRepository(new MockBulletinRepository() { + @Override + public List findBulletinsForSource(String sourceId, String groupId) { + return List.of(); + } + }); + + final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, revisionManager, mock(ParameterContextLookup.class), includeReferences); + return dto; + } + private static DtoFactory newDtoFactoryForParameters() { final DtoFactory dtoFactory = new DtoFactory(); dtoFactory.setEntityFactory(new EntityFactory()); @@ -997,9 +1060,29 @@ private static ParameterContext createMockParameterContext(final String id, fina return context; } + private static ParameterContext createMockParameterContextWithRefs(final String id, final String name, final List inherited, + Set controllerRefs, Set processorRefs) { + final ParameterContext context = mock(ParameterContext.class); + configureBaseParameterContextWithRefs(context, id, name, controllerRefs, processorRefs); + when(context.getInheritedParameterContexts()).thenReturn(inherited); + return context; + } + + private static void configureBaseParameterContext(final ParameterContext context, final String id, final String name) { when(context.getIdentifier()).thenReturn(id); when(context.getName()).thenReturn(name); when(context.getParameterReferenceManager()).thenReturn(ParameterReferenceManager.EMPTY); } + + private static void configureBaseParameterContextWithRefs(final ParameterContext context, final String id, final String name, + Set controllerRefs, Set processorRefs) { + when(context.getIdentifier()).thenReturn(id); + when(context.getName()).thenReturn(name); + ParameterReferenceManager parameterReferenceManager = mock(ParameterReferenceManager.class); + when(parameterReferenceManager.getProcessGroupsBound(any(ParameterContext.class))).thenReturn(Set.of()); + when(parameterReferenceManager.getControllerServicesReferencing(any(ParameterContext.class), anyString())).thenReturn(controllerRefs); + when(parameterReferenceManager.getProcessorsReferencing(any(ParameterContext.class), anyString())).thenReturn(processorRefs); + when(context.getParameterReferenceManager()).thenReturn(parameterReferenceManager); + } } diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/service/connector.service.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/service/connector.service.ts index 2c8dcb56744f..40028f236d4e 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/service/connector.service.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/service/connector.service.ts @@ -134,12 +134,13 @@ export class ConnectorService { getConnectorParameterContext( connectorId: string, - processGroupId: string + processGroupId: string, + includeReferencingComponents: boolean ): Observable { return this.httpClient .get( `${ConnectorService.API}/connectors/${connectorId}/flow/process-groups/${processGroupId}/parameter-context`, - { observe: 'response' } + { observe: 'response', params: { includeReferencingComponents } } ) .pipe(map((response) => (response.status === 204 ? null : response.body))); } diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.spec.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.spec.ts index 3c6567eccbf5..d531dbfa43b2 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.spec.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.spec.ts @@ -1452,7 +1452,11 @@ describe('ConnectorCanvasEffects', () => { const result = await firstValueFrom(effects.loadConnectorParameterContext$); - expect(mockConnectorService.getConnectorParameterContext).toHaveBeenCalledWith('connector-123', 'pg-abc'); + expect(mockConnectorService.getConnectorParameterContext).toHaveBeenCalledWith( + 'connector-123', + 'pg-abc', + false + ); expect(result).toEqual(loadConnectorParameterContextSuccess({ parameterContext })); }); diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.ts index f75e4481e4d1..b481986553f4 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connector-canvas/connector-canvas.effects.ts @@ -264,21 +264,23 @@ export class ConnectorCanvasEffects { this.actions$.pipe( ofType(ConnectorCanvasActions.loadConnectorParameterContext), switchMap((action) => - this.connectorService.getConnectorParameterContext(action.connectorId, action.processGroupId).pipe( - map((parameterContext) => - ConnectorCanvasActions.loadConnectorParameterContextSuccess({ parameterContext }) - ), - catchError((error) => - of( - ConnectorCanvasActions.loadConnectorParameterContextFailure({ - errorContext: { - errors: [this.errorHelper.getErrorString(error)], - context: action.errorContext - } - }) + this.connectorService + .getConnectorParameterContext(action.connectorId, action.processGroupId, false) + .pipe( + map((parameterContext) => + ConnectorCanvasActions.loadConnectorParameterContextSuccess({ parameterContext }) + ), + catchError((error) => + of( + ConnectorCanvasActions.loadConnectorParameterContextFailure({ + errorContext: { + errors: [this.errorHelper.getErrorString(error)], + context: action.errorContext + } + }) + ) ) ) - ) ) ) ); diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter-helper.service.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter-helper.service.ts index c34034ec3e06..47277bbd43b4 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter-helper.service.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter-helper.service.ts @@ -59,7 +59,7 @@ export class ParameterHelperService { parameterContextId: string ): (name: string, sensitive: boolean, value: string | null) => Observable { return (name: string, sensitive: boolean, value: string | null) => { - return this.parameterContextService.getParameterContext(parameterContextId, false).pipe( + return this.parameterContextService.getParameterContext(parameterContextId, false, false).pipe( catchError((errorResponse: HttpErrorResponse) => { this.store.dispatch( ErrorActions.snackBarError({ error: this.errorHelper.getErrorString(errorResponse) }) diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter.service.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter.service.ts index d92dc8acf6c9..290dae9bd2be 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter.service.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/parameter.service.ts @@ -28,31 +28,50 @@ export class ParameterService { private static readonly API: string = '../nifi-api'; - getParameterContext(id: string, includeInheritedParameters: boolean): Observable { + getParameterContext( + id: string, + includeInheritedParameters: boolean, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.get(`${ParameterService.API}/parameter-contexts/${id}`, { params: { - includeInheritedParameters + includeInheritedParameters, + includeReferencingComponents } }); } - submitParameterContextUpdate(configureParameterContext: SubmitParameterContextUpdate): Observable { + submitParameterContextUpdate( + configureParameterContext: SubmitParameterContextUpdate, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.post( `${ParameterService.API}/parameter-contexts/${configureParameterContext.id}/update-requests`, - configureParameterContext.payload + configureParameterContext.payload, + { params: { includeReferencingComponents } } ); } - pollParameterContextUpdate(parameterContextId: string, requestId: string): Observable { + pollParameterContextUpdate( + parameterContextId: string, + requestId: string, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.get( - `${ParameterService.API}/parameter-contexts/${parameterContextId}/update-requests/${requestId}` + `${ParameterService.API}/parameter-contexts/${parameterContextId}/update-requests/${requestId}`, + { params: { includeReferencingComponents } } ); } - deleteParameterContextUpdate(parameterContextId: string, requestId: string): Observable { + deleteParameterContextUpdate( + parameterContextId: string, + requestId: string, + includeReferencingComponents: boolean + ): Observable { const params = new HttpParams({ fromObject: { - disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged() + disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), + includeReferencingComponents } }); return this.httpClient.delete( diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts index f0fc80574cb9..12565fff4cde 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts @@ -348,7 +348,7 @@ export class ControllerServicesEffects { switchMap(([request, parameterContextReference, processGroupId]) => { if (parameterContextReference && parameterContextReference.permissions.canRead) { return from( - this.parameterContextService.getParameterContext(parameterContextReference.id, true) + this.parameterContextService.getParameterContext(parameterContextReference.id, true, false) ).pipe( map((parameterContext) => { return [request, parameterContext, processGroupId]; diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts index a66564ab5bc6..8193ef7bf8cc 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/flow/flow.effects.ts @@ -350,7 +350,7 @@ export class FlowEffects { case ComponentType.Processor: return of(FlowActions.openNewProcessorDialog({ request })); case ComponentType.ProcessGroup: - return from(this.parameterContextService.getParameterContexts()).pipe( + return from(this.parameterContextService.getParameterContexts(false)).pipe( concatLatestFrom(() => this.store.select(selectCurrentParameterContext)), map(([response, parameterContext]) => { const dialogRequest: CreateProcessGroupDialogRequest = { @@ -646,7 +646,7 @@ export class FlowEffects { map((action) => action.request), concatLatestFrom(() => this.store.select(selectCurrentProcessGroupId)), switchMap(([request]) => - from(this.parameterContextService.getParameterContexts()).pipe( + from(this.parameterContextService.getParameterContexts(false)).pipe( concatLatestFrom(() => this.store.select(selectCurrentParameterContext)), map(([response, parameterContext]) => { const dialogRequest: GroupComponentsDialogRequest = { @@ -1320,7 +1320,7 @@ export class FlowEffects { case ComponentType.Connection: return of(FlowActions.openEditConnectionDialog({ request })); case ComponentType.ProcessGroup: - return from(this.parameterContextService.getParameterContexts()).pipe( + return from(this.parameterContextService.getParameterContexts(false)).pipe( map((response) => { const editComponentDialogRequest = { ...request, @@ -1354,7 +1354,7 @@ export class FlowEffects { ofType(FlowActions.editCurrentProcessGroup), map((action) => action.request), switchMap((request) => { - return from(this.parameterContextService.getParameterContexts()).pipe( + return from(this.parameterContextService.getParameterContexts(false)).pipe( switchMap((parameterContextResponse) => from(this.flowService.getProcessGroup(request.id)).pipe( map((response) => @@ -1505,7 +1505,7 @@ export class FlowEffects { switchMap(([request, parameterContextReference, processGroupId]) => { if (parameterContextReference && parameterContextReference.permissions.canRead) { return from( - this.parameterContextService.getParameterContext(parameterContextReference.id) + this.parameterContextService.getParameterContext(parameterContextReference.id, true, false) ).pipe( map((parameterContext) => { return [request, parameterContext, processGroupId]; diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/parameter/parameter.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/parameter/parameter.effects.ts index 536512d7dc60..2edbaebc2528 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/parameter/parameter.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/parameter/parameter.effects.ts @@ -65,7 +65,7 @@ export class ParameterEffects { ofType(ParameterActions.submitParameterContextUpdateRequest), map((action) => action.request), switchMap((request) => - from(this.parameterService.submitParameterContextUpdate(request)).pipe( + from(this.parameterService.submitParameterContextUpdate(request, false)).pipe( map((response) => ParameterActions.submitParameterContextUpdateRequestSuccess({ response: { @@ -123,7 +123,8 @@ export class ParameterEffects { from( this.parameterService.pollParameterContextUpdate( parameterContextId, - updateRequest.request.requestId + updateRequest.request.requestId, + false ) ).pipe( map((response) => @@ -173,7 +174,8 @@ export class ParameterEffects { return from( this.parameterService.deleteParameterContextUpdate( parameterContextId, - updateRequest.request.requestId + updateRequest.request.requestId, + false ) ).pipe( map(() => ParameterActions.editParameterContextComplete()), @@ -279,7 +281,7 @@ export class ParameterEffects { ofType(ParameterActions.createParameterContext), map((action) => action.request), switchMap((request) => - from(this.parameterContextService.createParameterContext(request)).pipe( + from(this.parameterContextService.createParameterContext(request, false)).pipe( map((response) => ParameterActions.createParameterContextSuccess({ response: { diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts index 83d1bc466ab4..f81bc94efa09 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/service/parameter-contexts.service.ts @@ -31,42 +31,63 @@ export class ParameterContextService { private static readonly API: string = '../nifi-api'; - getParameterContexts(): Observable { - return this.httpClient.get(`${ParameterContextService.API}/flow/parameter-contexts`); + getParameterContexts(includeReferencingComponents: boolean): Observable { + return this.httpClient.get(`${ParameterContextService.API}/flow/parameter-contexts`, { + params: { includeReferencingComponents } + }); } - createParameterContext(createParameterContext: CreateParameterContextRequest): Observable { + createParameterContext( + createParameterContext: CreateParameterContextRequest, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.post( `${ParameterContextService.API}/parameter-contexts`, - createParameterContext.payload + createParameterContext.payload, + { params: { includeReferencingComponents } } ); } - getParameterContext(id: string, includeInheritedParameters = true): Observable { + getParameterContext(id: string, includeInheritedParameters: boolean, includeReferencingComponents: boolean): Observable { return this.httpClient.get(`${ParameterContextService.API}/parameter-contexts/${id}`, { params: { - includeInheritedParameters + includeInheritedParameters, + includeReferencingComponents } }); } - submitParameterContextUpdate(configureParameterContext: SubmitParameterContextUpdate): Observable { + submitParameterContextUpdate( + configureParameterContext: SubmitParameterContextUpdate, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.post( `${ParameterContextService.API}/parameter-contexts/${configureParameterContext.id}/update-requests`, - configureParameterContext.payload + configureParameterContext.payload, + { params: { includeReferencingComponents } } ); } - pollParameterContextUpdate(parameterContextId: string, requestId: string): Observable { + pollParameterContextUpdate( + parameterContextId: string, + requestId: string, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.get( - `${ParameterContextService.API}/parameter-contexts/${parameterContextId}/update-requests/${requestId}` + `${ParameterContextService.API}/parameter-contexts/${parameterContextId}/update-requests/${requestId}`, + { params: { includeReferencingComponents } } ); } - deleteParameterContextUpdate(parameterContextId: string, requestId: string): Observable { + deleteParameterContextUpdate( + parameterContextId: string, + requestId: string, + includeReferencingComponents: boolean + ): Observable { const params = new HttpParams({ fromObject: { - disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged() + disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), + includeReferencingComponents } }); return this.httpClient.delete( @@ -75,12 +96,16 @@ export class ParameterContextService { ); } - deleteParameterContext(deleteParameterContext: DeleteParameterContextRequest): Observable { + deleteParameterContext( + deleteParameterContext: DeleteParameterContextRequest, + includeReferencingComponents: boolean + ): Observable { const entity: ParameterContextEntity = deleteParameterContext.parameterContext; const params = new HttpParams({ fromObject: { ...this.client.getRevision(entity), - disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged() + disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), + includeReferencingComponents } }); return this.httpClient.delete(`${ParameterContextService.API}/parameter-contexts/${entity.id}`, { params }); diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.spec.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.spec.ts index 544b5ce1630f..d838e1aac25b 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.spec.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.spec.ts @@ -272,7 +272,8 @@ describe('ParameterContextListingEffects', () => { effects.deleteParameterContextUpdateRequest$.subscribe(() => { expect(parameterContextService.deleteParameterContextUpdate).toHaveBeenCalledWith( parameterContextId, - mockUpdateRequest.requestId + mockUpdateRequest.requestId, + false ); }); }); @@ -295,7 +296,8 @@ describe('ParameterContextListingEffects', () => { effects.deleteParameterContextUpdateRequest$.subscribe(() => { expect(parameterContextService.deleteParameterContextUpdate).toHaveBeenCalledWith( parameterContextId, - mockUpdateRequest.requestId + mockUpdateRequest.requestId, + false ); }); }); diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts index 74b9a005cb8b..14a4e7908d30 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts @@ -74,7 +74,7 @@ export class ParameterContextListingEffects { ofType(ParameterContextListingActions.loadParameterContexts), concatLatestFrom(() => this.store.select(selectParameterContextLoadedTimestamp)), switchMap(([, loadedTimestamp]) => - from(this.parameterContextService.getParameterContexts()).pipe( + from(this.parameterContextService.getParameterContexts(false)).pipe( map((response) => ParameterContextListingActions.loadParameterContextsSuccess({ response: { @@ -195,7 +195,7 @@ export class ParameterContextListingEffects { ofType(ParameterContextListingActions.createParameterContext), map((action) => action.request), switchMap((request) => - from(this.parameterContextService.createParameterContext(request)).pipe( + from(this.parameterContextService.createParameterContext(request, false)).pipe( map((response) => ParameterContextListingActions.createParameterContextSuccess({ response: { @@ -291,7 +291,7 @@ export class ParameterContextListingEffects { ofType(ParameterContextListingActions.getEffectiveParameterContextAndOpenDialog), map((action) => action.request), switchMap((request) => - from(this.parameterContextService.getParameterContext(request.id, true)).pipe( + from(this.parameterContextService.getParameterContext(request.id, true, true)).pipe( map((response) => ParameterContextListingActions.openParameterContextDialog({ request: { @@ -434,7 +434,7 @@ export class ParameterContextListingEffects { ofType(ParameterContextListingActions.submitParameterContextUpdateRequest), map((action) => action.request), switchMap((request) => - from(this.parameterContextService.submitParameterContextUpdate(request)).pipe( + from(this.parameterContextService.submitParameterContextUpdate(request, false)).pipe( map((response) => ParameterContextListingActions.submitParameterContextUpdateRequestSuccess({ response: { @@ -501,7 +501,8 @@ export class ParameterContextListingEffects { from( this.parameterContextService.pollParameterContextUpdate( parameterContextId, - updateRequest.request.requestId + updateRequest.request.requestId, + false ) ).pipe( map((response) => @@ -557,7 +558,7 @@ export class ParameterContextListingEffects { ]), tap(([, parameterContextId, updateRequest]) => { this.parameterContextService - .deleteParameterContextUpdate(parameterContextId, updateRequest.request.requestId) + .deleteParameterContextUpdate(parameterContextId, updateRequest.request.requestId, false) .subscribe((response) => { this.store.dispatch( ParameterContextListingActions.deleteParameterContextUpdateRequestSuccess({ @@ -606,7 +607,7 @@ export class ParameterContextListingEffects { ofType(ParameterContextListingActions.deleteParameterContext), map((action) => action.request), switchMap((request) => - from(this.parameterContextService.deleteParameterContext(request)).pipe( + from(this.parameterContextService.deleteParameterContext(request, false)).pipe( map((response) => ParameterContextListingActions.deleteParameterContextSuccess({ response: { diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/service/parameter-provider.service.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/service/parameter-provider.service.ts index 1b24905f2d75..eba98b72da66 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/service/parameter-provider.service.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/service/parameter-provider.service.ts @@ -96,7 +96,10 @@ export class ParameterProviderService implements PropertyDescriptorRetriever { ); } - fetchParameters(request: FetchParameterProviderParametersRequest): Observable { + fetchParameters( + request: FetchParameterProviderParametersRequest, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.post( `${ParameterProviderService.API}/parameter-providers/${request.id}/parameters/fetch-requests`, { @@ -104,31 +107,44 @@ export class ParameterProviderService implements PropertyDescriptorRetriever { revision: request.revision, disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged() }, - { params: { disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged() } } + { + params: { + disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), + includeReferencingComponents + } + } ); } - applyParameters(request: ParameterProviderParameterApplicationEntity): Observable { + applyParameters( + request: ParameterProviderParameterApplicationEntity, + includeReferencingComponents: boolean + ): Observable { return this.httpClient.post( `${ParameterProviderService.API}/parameter-providers/${request.id}/apply-parameters-requests`, - request + request, + { params: { includeReferencingComponents } } ); } pollParameterProviderParametersUpdateRequest( - updateRequest: ParameterProviderApplyParametersRequest + updateRequest: ParameterProviderApplyParametersRequest, + includeReferencingComponents: boolean ): Observable { return this.httpClient.get( - `${ParameterProviderService.API}/parameter-providers/${updateRequest.parameterProvider.id}/apply-parameters-requests/${updateRequest.requestId}` + `${ParameterProviderService.API}/parameter-providers/${updateRequest.parameterProvider.id}/apply-parameters-requests/${updateRequest.requestId}`, + { params: { includeReferencingComponents } } ); } deleteParameterProviderParametersUpdateRequest( - updateRequest: ParameterProviderApplyParametersRequest + updateRequest: ParameterProviderApplyParametersRequest, + includeReferencingComponents: boolean ): Observable { const params = new HttpParams({ fromObject: { - disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged() + disconnectedNodeAcknowledged: this.clusterConnectionService.isDisconnectionAcknowledged(), + includeReferencingComponents } }); return this.httpClient.delete( diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.spec.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.spec.ts index 0d67d37677e8..e7b8cc5ad71d 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.spec.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.spec.ts @@ -469,7 +469,7 @@ describe('ParameterProvidersEffects', () => { response: { parameterProvider: mockResponse } }) ); - expect(mockParameterProviderService.fetchParameters).toHaveBeenCalledWith(mockRequest); + expect(mockParameterProviderService.fetchParameters).toHaveBeenCalledWith(mockRequest, true); }); it('should handle error when fetching parameters fails', async () => { diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts index 52ae6dc5494e..edf5779a9458 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/settings/state/parameter-providers/parameter-providers.effects.ts @@ -550,7 +550,7 @@ export class ParameterProvidersEffects { ofType(ParameterProviderActions.fetchParameterProviderParametersAndOpenDialog), map((action) => action.request), switchMap((request) => - from(this.parameterProviderService.fetchParameters(request)).pipe( + from(this.parameterProviderService.fetchParameters(request, true)).pipe( map((response: ParameterProviderEntity) => ParameterProviderActions.fetchParameterProviderParametersSuccess({ response: { parameterProvider: response } @@ -680,7 +680,7 @@ export class ParameterProvidersEffects { map((action) => action.request), switchMap((request) => from( - this.parameterProviderService.applyParameters(request).pipe( + this.parameterProviderService.applyParameters(request, false).pipe( map((response: any) => ParameterProviderActions.submitParameterProviderParametersUpdateRequestSuccess({ response: { @@ -739,7 +739,10 @@ export class ParameterProvidersEffects { switchMap(([, updateRequest]) => { if (updateRequest) { return from( - this.parameterProviderService.pollParameterProviderParametersUpdateRequest(updateRequest) + this.parameterProviderService.pollParameterProviderParametersUpdateRequest( + updateRequest, + false + ) ).pipe( map((response) => ParameterProviderActions.pollParameterProviderParametersUpdateRequestSuccess({ @@ -789,7 +792,7 @@ export class ParameterProvidersEffects { tap(([, updateRequest]) => { if (updateRequest) { this.parameterProviderService - .deleteParameterProviderParametersUpdateRequest(updateRequest) + .deleteParameterProviderParametersUpdateRequest(updateRequest, false) .subscribe(); } })