From ff98d823e20f5042dfbb05d9f8efda0daf3d3ba4 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Fri, 29 Apr 2016 14:49:13 -0400 Subject: [PATCH] NIFI-1554: - Populating component entities in the REST API to decouple key fields from the configuration DTOs. - Added initial support for components in UI when access isn't allowed. Formal styling to come later. --- .../apache/nifi/authorization/Resource.java | 2 +- .../nifi-administration/pom.xml | 38 - .../org/apache/nifi/user/NiFiUserGroup.java | 2 + .../resources/nifi-administration-context.xml | 5 - .../nifi/web/api/dto/AccessPolicyDTO.java | 62 ++ ...iFiComponentDTO.java => ComponentDTO.java} | 28 +- .../nifi/web/api/dto/ConnectionDTO.java | 2 +- .../web/api/dto/ControllerServiceDTO.java | 2 +- .../nifi/web/api/dto/DimensionsDTO.java | 61 ++ .../apache/nifi/web/api/dto/FunnelDTO.java | 2 +- .../org/apache/nifi/web/api/dto/LabelDTO.java | 2 +- .../org/apache/nifi/web/api/dto/PortDTO.java | 2 +- .../nifi/web/api/dto/ProcessGroupDTO.java | 20 +- .../apache/nifi/web/api/dto/ProcessorDTO.java | 2 +- .../web/api/dto/RemoteProcessGroupDTO.java | 2 +- .../nifi/web/api/dto/ReportingTaskDTO.java | 2 +- .../apache/nifi/web/api/dto/SnippetDTO.java | 19 +- .../web/api/dto/flow/FlowBreadcrumbDTO.java | 80 ++ .../apache/nifi/web/api/dto/flow/FlowDTO.java | 174 +++++ .../web/api/dto/flow/ProcessGroupFlowDTO.java | 112 +++ .../nifi/web/api/entity/ComponentEntity.java | 119 +++ .../nifi/web/api/entity/ConnectionEntity.java | 107 ++- .../web/api/entity/ConnectionsEntity.java | 14 +- .../api/entity/ControllerServiceEntity.java | 2 +- .../apache/nifi/web/api/entity/Entity.java | 5 +- ...{OutputPortEntity.java => FlowEntity.java} | 23 +- .../nifi/web/api/entity/FunnelEntity.java | 12 +- .../nifi/web/api/entity/FunnelsEntity.java | 14 +- .../nifi/web/api/entity/InputPortsEntity.java | 14 +- .../nifi/web/api/entity/LabelEntity.java | 29 +- .../nifi/web/api/entity/LabelsEntity.java | 14 +- .../web/api/entity/OutputPortsEntity.java | 14 +- .../{InputPortEntity.java => PortEntity.java} | 25 +- .../web/api/entity/ProcessGroupEntity.java | 12 +- .../api/entity/ProcessGroupFlowEntity.java | 44 ++ .../web/api/entity/ProcessGroupsEntity.java | 15 +- .../nifi/web/api/entity/ProcessorEntity.java | 15 +- .../nifi/web/api/entity/ProcessorsEntity.java | 14 +- .../api/entity/RemoteProcessGroupEntity.java | 12 +- .../api/entity/RemoteProcessGroupsEntity.java | 14 +- .../src/main/xsd/authorizations.xsd | 1 - .../nifi-framework-authorization/pom.xml | 59 +- .../authorization/AccessDeniedException.java | 39 + .../authorization/AuthorizerFactoryBean.java | 49 +- ...tandardAuthorizerConfigurationContext.java | 0 ...andardAuthorizerInitializationContext.java | 0 .../authorization/resource/Authorizable.java | 129 ++++ .../resource/ResourceFactory.java | 1 - .../authorization/resource/ResourceType.java | 1 + .../nifi/authorization}/user/NiFiUser.java | 2 +- .../authorization}/user/NiFiUserDetails.java | 3 +- .../authorization}/user/NiFiUserUtils.java | 32 +- .../nifi-framework-authorization-context.xml | 26 + .../src/main/xsd/authorizers.xsd | 0 .../manager/impl/WebClusterManager.java | 42 +- .../nifi-framework-core-api/pom.xml | 4 + .../apache/nifi/connectable/Connectable.java | 3 +- .../apache/nifi/connectable/Connection.java | 3 +- .../apache/nifi/controller/AbstractPort.java | 48 +- .../apache/nifi/controller/ProcessorNode.java | 14 +- .../nifi/controller/StandardFunnel.java | 49 +- .../apache/nifi/controller/label/Label.java | 3 +- .../org/apache/nifi/groups/ProcessGroup.java | 3 +- .../nifi/groups/RemoteProcessGroup.java | 3 +- .../nifi/connectable/StandardConnection.java | 48 +- .../controller/StandardProcessorNode.java | 60 +- .../nifi/controller/label/StandardLabel.java | 23 +- .../nifi/fingerprint/FingerprintFactory.java | 6 +- .../nifi/groups/StandardProcessGroup.java | 42 +- .../remote/StandardRemoteProcessGroup.java | 70 +- .../org/apache/nifi/util/SnippetUtils.java | 22 +- .../controller/StandardFlowServiceTest.java | 1 - .../zookeeper/TestZooKeeperStateProvider.java | 13 +- .../nifi/remote/StandardRemoteGroupPort.java | 6 + .../nifi/audit/ComponentStateAuditor.java | 4 +- .../apache/nifi/audit/ControllerAuditor.java | 4 +- .../nifi/audit/ControllerServiceAuditor.java | 4 +- .../org/apache/nifi/audit/FunnelAuditor.java | 4 +- .../org/apache/nifi/audit/PortAuditor.java | 4 +- .../nifi/audit/ProcessGroupAuditor.java | 4 +- .../apache/nifi/audit/ProcessorAuditor.java | 4 +- .../nifi/audit/RelationshipAuditor.java | 4 +- .../nifi/audit/RemoteProcessGroupAuditor.java | 4 +- .../nifi/audit/ReportingTaskAuditor.java | 4 +- .../org/apache/nifi/audit/SnippetAuditor.java | 4 +- .../apache/nifi/web/NiFiServiceFacade.java | 107 +-- .../nifi/web/NiFiWebApiConfiguration.java | 1 + .../nifi/web/StandardNiFiContentAccess.java | 4 +- .../nifi/web/StandardNiFiServiceFacade.java | 584 +++++++++++---- .../StandardNiFiWebConfigurationContext.java | 18 +- .../nifi/web/StandardNiFiWebContext.java | 16 +- .../org/apache/nifi/web/UpdateResult.java | 40 + .../apache/nifi/web/api/AccessResource.java | 6 +- .../nifi/web/api/ApplicationResource.java | 2 +- .../apache/nifi/web/api/ClusterResource.java | 223 ------ .../nifi/web/api/ConnectionResource.java | 83 +-- .../nifi/web/api/ControllerResource.java | 4 +- .../web/api/ControllerServiceResource.java | 50 -- .../org/apache/nifi/web/api/FlowResource.java | 257 ++++++- .../apache/nifi/web/api/FunnelResource.java | 84 +-- .../nifi/web/api/InputPortResource.java | 92 ++- .../apache/nifi/web/api/LabelResource.java | 84 +-- .../nifi/web/api/OutputPortResource.java | 92 ++- .../nifi/web/api/ProcessGroupResource.java | 668 ++++++----------- .../nifi/web/api/ProcessorResource.java | 102 +-- .../web/api/RemoteProcessGroupResource.java | 88 ++- .../apache/nifi/web/api/TemplateResource.java | 8 - .../config/AccessDeniedExceptionMapper.java | 7 +- .../apache/nifi/web/api/dto/DtoFactory.java | 171 ++++- .../nifi/web/api/dto/EntityFactory.java | 155 ++++ .../nifi/web/controller/ControllerFacade.java | 17 +- .../org/apache/nifi/web/dao/TemplateDAO.java | 3 +- .../web/dao/impl/StandardConnectionDAO.java | 19 +- .../apache/nifi/web/filter/RequestLogger.java | 4 +- .../main/resources/nifi-web-api-context.xml | 20 +- .../nifi/integration/NiFiWebApiTest.java | 30 +- .../AccessTokenEndpointTest.java | 4 +- .../accesscontrol/AdminAccessControlTest.java | 22 +- .../accesscontrol/DfmAccessControlTest.java | 144 ++-- .../ReadOnlyAccessControlTest.java | 20 +- .../nifi-web/nifi-web-content-viewer/pom.xml | 5 + .../nifi/web/ContentViewerController.java | 2 +- .../web/StandardOptimisticLockingManager.java | 3 +- .../nifi-web/nifi-web-security/pom.xml | 4 + .../security/NiFiAuthenticationFilter.java | 2 +- .../web/security/ProxiedEntitiesUtils.java | 2 +- .../anonymous/NiFiAnonymousUserFilter.java | 5 +- .../jwt/JwtAuthenticationProvider.java | 4 +- .../node/NodeAuthorizedUserFilter.java | 5 +- .../otp/OtpAuthenticationProvider.java | 4 +- .../x509/X509AuthenticationProvider.java | 33 +- .../resources/nifi-web-security-context.xml | 3 +- .../otp/OtpAuthenticationProviderTest.java | 2 +- .../nf-ng-breadcrumbs-controller.js | 12 +- .../main/webapp/js/nf/canvas/nf-actions.js | 171 ++--- .../main/webapp/js/nf/canvas/nf-birdseye.js | 28 +- .../webapp/js/nf/canvas/nf-canvas-header.js | 20 +- .../webapp/js/nf/canvas/nf-canvas-toolbar.js | 93 +-- .../webapp/js/nf/canvas/nf-canvas-toolbox.js | 50 +- .../webapp/js/nf/canvas/nf-canvas-utils.js | 118 +-- .../src/main/webapp/js/nf/canvas/nf-canvas.js | 29 +- .../webapp/js/nf/canvas/nf-connectable.js | 10 +- .../nf/canvas/nf-connection-configuration.js | 66 +- .../main/webapp/js/nf/canvas/nf-connection.js | 662 +++++++++-------- .../webapp/js/nf/canvas/nf-context-menu.js | 115 ++- .../main/webapp/js/nf/canvas/nf-draggable.js | 62 +- .../src/main/webapp/js/nf/canvas/nf-funnel.js | 62 +- .../src/main/webapp/js/nf/canvas/nf-go-to.js | 24 +- .../js/nf/canvas/nf-label-configuration.js | 6 +- .../src/main/webapp/js/nf/canvas/nf-label.js | 276 +++---- .../js/nf/canvas/nf-port-configuration.js | 17 +- .../webapp/js/nf/canvas/nf-port-details.js | 2 +- .../src/main/webapp/js/nf/canvas/nf-port.js | 218 +++--- .../canvas/nf-process-group-configuration.js | 8 +- .../js/nf/canvas/nf-process-group-details.js | 2 +- .../webapp/js/nf/canvas/nf-process-group.js | 689 +++++++++--------- .../nf/canvas/nf-processor-configuration.js | 16 +- .../main/webapp/js/nf/canvas/nf-processor.js | 262 +++---- .../webapp/js/nf/canvas/nf-queue-listing.js | 2 +- .../nf-remote-process-group-configuration.js | 8 +- .../canvas/nf-remote-process-group-details.js | 2 +- .../canvas/nf-remote-process-group-ports.js | 10 +- .../js/nf/canvas/nf-remote-process-group.js | 657 ++++++++--------- .../main/webapp/js/nf/canvas/nf-snippet.js | 16 +- .../webapp/js/nf/nf-connection-details.js | 16 +- .../main/webapp/js/nf/nf-processor-details.js | 4 +- .../nf-ng-breadcrumbs-directive-view.html | 2 +- 167 files changed, 5203 insertions(+), 3821 deletions(-) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicyDTO.java rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/{NiFiComponentDTO.java => ComponentDTO.java} (85%) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DimensionsDTO.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowBreadcrumbDTO.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowDTO.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/ProcessGroupFlowDTO.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentEntity.java rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/{OutputPortEntity.java => FlowEntity.java} (67%) rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/{InputPortEntity.java => PortEntity.java} (72%) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupFlowEntity.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AccessDeniedException.java rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-administration => nifi-framework-authorization}/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java (89%) rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-administration => nifi-framework-authorization}/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java (100%) rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-administration => nifi-framework-authorization}/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java (100%) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-administration/src/main/java/org/apache/nifi => nifi-framework-authorization/src/main/java/org/apache/nifi/authorization}/user/NiFiUser.java (98%) rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security => nifi-framework-authorization/src/main/java/org/apache/nifi/authorization}/user/NiFiUserDetails.java (96%) rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security => nifi-framework-authorization/src/main/java/org/apache/nifi/authorization}/user/NiFiUserUtils.java (65%) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/nifi-framework-authorization-context.xml rename nifi-nar-bundles/nifi-framework-bundle/nifi-framework/{nifi-administration => nifi-framework-authorization}/src/main/xsd/authorizers.xsd (100%) create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/UpdateResult.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/Resource.java b/nifi-api/src/main/java/org/apache/nifi/authorization/Resource.java index 7756bda6c2..661b3269e6 100644 --- a/nifi-api/src/main/java/org/apache/nifi/authorization/Resource.java +++ b/nifi-api/src/main/java/org/apache/nifi/authorization/Resource.java @@ -29,7 +29,7 @@ public interface Resource { String getIdentifier(); /** - * The name of this resource. + * The name of this resource. May be null. * * @return name of this resource */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/pom.xml index c9a9c0efc4..2aac20980c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/pom.xml @@ -21,40 +21,6 @@ 1.0.0-SNAPSHOT nifi-administration - - - - src/main/resources - - - src/main/xsd - - - - - org.codehaus.mojo - jaxb2-maven-plugin - - - current - - xjc - - - org.apache.nifi.authorization.generated - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - **/authorization/generated/*.java, - - - - org.apache.nifi @@ -116,9 +82,5 @@ org.apache.commons commons-collections4 - - org.apache.nifi - nifi-expression-language - diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUserGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUserGroup.java index 7586fd13c0..e4b71308ab 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUserGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUserGroup.java @@ -16,6 +16,8 @@ */ package org.apache.nifi.user; +import org.apache.nifi.authorization.user.NiFiUser; + import java.util.Set; /** diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml index deec0739df..e717686421 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml @@ -18,11 +18,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> - - - - - diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicyDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicyDTO.java new file mode 100644 index 0000000000..15643624c5 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicyDTO.java @@ -0,0 +1,62 @@ +/* + * 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.web.api.dto; + +import com.wordnik.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlType; + +/** + * Details for the access configuration. + */ +@XmlType(name = "accessPolicy") +public class AccessPolicyDTO { + + private Boolean canRead; + private Boolean canWrite; + + /** + * @return Indicates whether the user can read a given resource. + */ + @ApiModelProperty( + value = "Indicates whether the user can read a given resource.", + readOnly = true + ) + public Boolean getCanRead() { + return canRead; + } + + public void setCanRead(Boolean canRead) { + this.canRead = canRead; + } + + /** + * @return Indicates whether the user can write a given resource. + */ + @ApiModelProperty( + value = "Indicates whether the user can write a given resource.", + readOnly = true + ) + public Boolean getCanWrite() { + return canWrite; + } + + public void setCanWrite(Boolean canWrite) { + this.canWrite = canWrite; + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/NiFiComponentDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentDTO.java similarity index 85% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/NiFiComponentDTO.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentDTO.java index e89fb5df33..ca5e06fa1d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/NiFiComponentDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentDTO.java @@ -22,25 +22,13 @@ import javax.xml.bind.annotation.XmlType; /** * Base class for all nifi components. */ -@XmlType(name = "nifiComponent") -public class NiFiComponentDTO { +@XmlType(name = "component") +public class ComponentDTO { private String id; private String uri; - private PositionDTO position; private String parentGroupId; - - public NiFiComponentDTO() { - } - - public NiFiComponentDTO(final String id) { - this.id = id; - } - - public NiFiComponentDTO(final String id, final double x, final double y) { - this.id = id; - this.position = new PositionDTO(x, y); - } + private PositionDTO position; /** * The id for this component. @@ -88,19 +76,19 @@ public class NiFiComponentDTO { this.uri = uri; } - public void setPosition(final PositionDTO position) { - this.position = position; - } - /** * The position of this component in the UI if applicable, null otherwise. * * @return The position */ @ApiModelProperty( - value = "The position of this component in the UI if applicable." + value = "The position of this component in the UI if applicable." ) public PositionDTO getPosition() { return position; } + + public void setPosition(final PositionDTO position) { + this.position = position; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConnectionDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConnectionDTO.java index 96da9e3748..e4ea0cc53a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConnectionDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConnectionDTO.java @@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlType; * A connection between two connectable components. */ @XmlType(name = "connection") -public class ConnectionDTO extends NiFiComponentDTO { +public class ConnectionDTO extends ComponentDTO { private ConnectableDTO source; private ConnectableDTO destination; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java index 5d51698375..f40e1810bb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceDTO.java @@ -26,7 +26,7 @@ import javax.xml.bind.annotation.XmlType; * A Controller Service that can be shared by other components */ @XmlType(name = "controllerService") -public class ControllerServiceDTO extends NiFiComponentDTO { +public class ControllerServiceDTO extends ComponentDTO { private String name; private String type; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DimensionsDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DimensionsDTO.java new file mode 100644 index 0000000000..58df0c05db --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DimensionsDTO.java @@ -0,0 +1,61 @@ +/* + * 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.web.api.dto; + +import com.wordnik.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlType; + +/** + * A position on the canvas. + */ +@XmlType(name = "dimensions") +public class DimensionsDTO { + + private Double width; + private Double height; + + /* getters / setters */ + + /** + * @return height of the label in pixels when at a 1:1 scale + */ + @ApiModelProperty( + value = "The height of the label in pixels when at a 1:1 scale." + ) + public Double getHeight() { + return height; + } + + public void setHeight(Double height) { + this.height = height; + } + + /** + * @return width of the label in pixels when at a 1:1 scale + */ + @ApiModelProperty( + value = "The width of the label in pixels when at a 1:1 scale." + ) + public Double getWidth() { + return width; + } + + public void setWidth(Double width) { + this.width = width; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FunnelDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FunnelDTO.java index 1240501693..4687737aee 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FunnelDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FunnelDTO.java @@ -22,7 +22,7 @@ import javax.xml.bind.annotation.XmlType; * Details of a funnel. */ @XmlType(name = "funnel") -public class FunnelDTO extends NiFiComponentDTO { +public class FunnelDTO extends ComponentDTO { public FunnelDTO() { } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java index e9016dbd7e..063ff6546c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/LabelDTO.java @@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlType; * Details of a label. */ @XmlType(name = "label") -public class LabelDTO extends NiFiComponentDTO { +public class LabelDTO extends ComponentDTO { private String label; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PortDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PortDTO.java index 489ed0c11d..f8e4081c57 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PortDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PortDTO.java @@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlType; * The details for a port within this NiFi flow. */ @XmlType(name = "port") -public class PortDTO extends NiFiComponentDTO { +public class PortDTO extends ComponentDTO { private String name; private String comments; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java index 93c4ea9f70..224db57469 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessGroupDTO.java @@ -23,14 +23,12 @@ import javax.xml.bind.annotation.XmlType; * The details for a process group within this NiFi flow. */ @XmlType(name = "processGroup") -public class ProcessGroupDTO extends NiFiComponentDTO { +public class ProcessGroupDTO extends ComponentDTO { private String name; private String comments; private Boolean running; - private ProcessGroupDTO parent; - private Integer runningCount; private Integer stoppedCount; private Integer invalidCount; @@ -63,22 +61,6 @@ public class ProcessGroupDTO extends NiFiComponentDTO { this.name = name; } - /** - * This Process Group's parent - * - * @return This Process Group's parent - */ - @ApiModelProperty( - value = "The part of the process group." - ) - public ProcessGroupDTO getParent() { - return parent; - } - - public void setParent(ProcessGroupDTO parent) { - this.parent = parent; - } - /** * @return comments for this process group */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java index b0b9daae59..dbd06a3ede 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ProcessorDTO.java @@ -26,7 +26,7 @@ import javax.xml.bind.annotation.XmlType; * Details for a processor within this NiFi. */ @XmlType(name = "processor") -public class ProcessorDTO extends NiFiComponentDTO { +public class ProcessorDTO extends ComponentDTO { private String name; private String type; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/RemoteProcessGroupDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/RemoteProcessGroupDTO.java index 2e30001026..b303d4d04a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/RemoteProcessGroupDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/RemoteProcessGroupDTO.java @@ -27,7 +27,7 @@ import org.apache.nifi.web.api.dto.util.DateTimeAdapter; * Details of a remote process group in this NiFi. */ @XmlType(name = "remoteProcessGroup") -public class RemoteProcessGroupDTO extends NiFiComponentDTO { +public class RemoteProcessGroupDTO extends ComponentDTO { private String targetUri; private Boolean targetSecure; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java index 182535d915..5972ac7dce 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ReportingTaskDTO.java @@ -26,7 +26,7 @@ import javax.xml.bind.annotation.XmlType; * Component that is capable of reporting internal NiFi state to an external service */ @XmlType(name = "reportingTask") -public class ReportingTaskDTO extends NiFiComponentDTO { +public class ReportingTaskDTO extends ComponentDTO { private String name; private String type; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SnippetDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SnippetDTO.java index 431df1755b..bf5d3190dc 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SnippetDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/SnippetDTO.java @@ -17,9 +17,10 @@ package org.apache.nifi.web.api.dto; import com.wordnik.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlType; import java.util.HashSet; import java.util.Set; -import javax.xml.bind.annotation.XmlType; /** * The contents of a snippet of a flow. @@ -42,8 +43,6 @@ public class SnippetDTO { private Set labels = new HashSet<>(); private Set funnels = new HashSet<>(); - private FlowSnippetDTO contents; - /** * @return id of this snippet */ @@ -230,18 +229,4 @@ public class SnippetDTO { this.remoteProcessGroups = remoteProcessGroups; } - /** - * @return the contents of the configuration for this snippet - */ - @ApiModelProperty( - value = "The contents of the configuration for the snippet." - ) - public FlowSnippetDTO getContents() { - return contents; - } - - public void setContents(FlowSnippetDTO contents) { - this.contents = contents; - } - } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowBreadcrumbDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowBreadcrumbDTO.java new file mode 100644 index 0000000000..afdfb64afe --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowBreadcrumbDTO.java @@ -0,0 +1,80 @@ +/* + * 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.web.api.dto.flow; + +import com.wordnik.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlType; + +/** + * Breadcrumb for the flow. + */ +@XmlType(name = "flowBreadcrumb") +public class FlowBreadcrumbDTO { + + private String id; + private String name; + private FlowBreadcrumbDTO parentBreadcrumb; + + /** + * The id for this group. + * + * @return The id + */ + @ApiModelProperty( + value = "The id of the group." + ) + public String getId() { + return this.id; + } + + public void setId(final String id) { + this.id = id; + } + + /** + * The name for this group. + * + * @return The name + */ + @ApiModelProperty( + value = "The id of the group." + ) + public String getName() { + return this.name; + } + + public void setName(final String name) { + this.name = name; + } + + /** + * The parent breadcrumb for this breadcrumb. + * + * @return The parent breadcrumb for this breadcrumb + */ + @ApiModelProperty( + value = "The parent breadcrumb for this breadcrumb." + ) + public FlowBreadcrumbDTO getParentBreadcrumb() { + return parentBreadcrumb; + } + + public void setParentBreadcrumb(FlowBreadcrumbDTO parentBreadcrumb) { + this.parentBreadcrumb = parentBreadcrumb; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowDTO.java new file mode 100644 index 0000000000..a3a3ae723e --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/FlowDTO.java @@ -0,0 +1,174 @@ +/* + * 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.web.api.dto.flow; + +import com.wordnik.swagger.annotations.ApiModelProperty; +import org.apache.nifi.web.api.entity.ConnectionEntity; +import org.apache.nifi.web.api.entity.ControllerServiceEntity; +import org.apache.nifi.web.api.entity.FunnelEntity; +import org.apache.nifi.web.api.entity.LabelEntity; +import org.apache.nifi.web.api.entity.PortEntity; +import org.apache.nifi.web.api.entity.ProcessGroupEntity; +import org.apache.nifi.web.api.entity.ProcessorEntity; +import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; + +import javax.xml.bind.annotation.XmlType; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * The structure of the flow. + */ +@XmlType(name = "flow") +public class FlowDTO { + + private Set processGroups = new LinkedHashSet<>(); + private Set remoteProcessGroups = new LinkedHashSet<>(); + private Set processors = new LinkedHashSet<>(); + private Set inputPorts = new LinkedHashSet<>(); + private Set outputPorts = new LinkedHashSet<>(); + private Set connections = new LinkedHashSet<>(); + private Set labels = new LinkedHashSet<>(); + private Set funnels = new LinkedHashSet<>(); + private Set controllerServices = new LinkedHashSet<>(); + + /** + * @return connections in this flow + */ + @ApiModelProperty( + value = "The connections in this flow." + ) + public Set getConnections() { + return connections; + } + + public void setConnections(Set connections) { + this.connections = connections; + } + + /** + * @return input ports in this flow + */ + @ApiModelProperty( + value = "The input ports in this flow." + ) + public Set getInputPorts() { + return inputPorts; + } + + public void setInputPorts(Set inputPorts) { + this.inputPorts = inputPorts; + } + + /** + * @return labels in this flow + */ + @ApiModelProperty( + value = "The labels in this flow." + ) + public Set getLabels() { + return labels; + } + + public void setLabels(Set labels) { + this.labels = labels; + } + + /** + * @return funnels in this flow + */ + @ApiModelProperty( + value = "The funnels in this flow." + ) + public Set getFunnels() { + return funnels; + } + + public void setFunnels(Set funnels) { + this.funnels = funnels; + } + + /** + * @return output ports in this flow + */ + @ApiModelProperty( + value = "The output ports in this flow." + ) + public Set getOutputPorts() { + return outputPorts; + } + + public void setOutputPorts(Set outputPorts) { + this.outputPorts = outputPorts; + } + + /** + * @return process groups in this flow + */ + @ApiModelProperty( + value = "The process groups in this flow." + ) + public Set getProcessGroups() { + return processGroups; + } + + public void setProcessGroups(Set processGroups) { + this.processGroups = processGroups; + } + + /** + * @return processors in this flow + */ + @ApiModelProperty( + value = "The processors in this flow." + ) + public Set getProcessors() { + return processors; + } + + public void setProcessors(Set processors) { + this.processors = processors; + } + + /** + * @return remote process groups in this flow + */ + @ApiModelProperty( + value = "The remote process groups in this flow." + ) + public Set getRemoteProcessGroups() { + return remoteProcessGroups; + } + + public void setRemoteProcessGroups(Set remoteProcessGroups) { + this.remoteProcessGroups = remoteProcessGroups; + } + + /** + * @return the Controller Services in this flow + */ + @ApiModelProperty( + value = "The controller services in this flow." + ) + public Set getControllerServices() { + return controllerServices; + } + + public void setControllerServices(Set controllerServices) { + this.controllerServices = controllerServices; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/ProcessGroupFlowDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/ProcessGroupFlowDTO.java new file mode 100644 index 0000000000..b651efcc59 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/flow/ProcessGroupFlowDTO.java @@ -0,0 +1,112 @@ +/* + * 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.web.api.dto.flow; + +import com.wordnik.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlType; + +/** + * The NiFi flow starting at a given Process Group. + */ +@XmlType(name = "processGroupflow") +public class ProcessGroupFlowDTO { + + private String id; + private String uri; + private String parentGroupId; + private FlowBreadcrumbDTO breadcrumb; + private FlowDTO flow; + + /** + * @return contents of this process group. This field will be populated if the request is marked verbose + */ + @ApiModelProperty( + value = "The flow structure starting at this Process Group." + ) + public FlowDTO getFlow() { + return flow; + } + + public void setFlow(FlowDTO flow) { + this.flow = flow; + } + + /** + * The id for this component. + * + * @return The id + */ + @ApiModelProperty( + value = "The id of the component." + ) + public String getId() { + return this.id; + } + + public void setId(final String id) { + this.id = id; + } + + /** + * The breadcrumb for this ProcessGroup flow. + * + * @return The breadcrumb for this ProcessGroup flow + */ + @ApiModelProperty( + value = "The breadcrumb of the process group." + ) + public FlowBreadcrumbDTO getBreadcrumb() { + return breadcrumb; + } + + public void setBreadcrumb(FlowBreadcrumbDTO breadcrumb) { + this.breadcrumb = breadcrumb; + } + + /** + * @return id for the parent group of this component if applicable, null otherwise + */ + @ApiModelProperty( + value = "The id of parent process group of this component if applicable." + ) + public String getParentGroupId() { + return parentGroupId; + } + + public void setParentGroupId(String parentGroupId) { + this.parentGroupId = parentGroupId; + } + + /** + * The uri for linking to this component in this NiFi. + * + * @return The uri + */ + @ApiModelProperty( + value = "The URI for futures requests to the component." + ) + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentEntity.java new file mode 100644 index 0000000000..e0c85faa8f --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentEntity.java @@ -0,0 +1,119 @@ +/* + * 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.web.api.entity; + +import com.wordnik.swagger.annotations.ApiModelProperty; +import org.apache.nifi.web.api.dto.AccessPolicyDTO; +import org.apache.nifi.web.api.dto.PositionDTO; +import org.apache.nifi.web.api.dto.RevisionDTO; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * A base type for request/response entities. + */ +@XmlRootElement(name = "entity") +public class ComponentEntity extends Entity { + + private RevisionDTO revision; + private String id; + private String uri; + private PositionDTO position; + private AccessPolicyDTO accessPolicy; + + /** + * @return revision for this request/response + */ + @ApiModelProperty( + value = "The revision for this request/response. The revision is required for any mutable flow requests and is included in all responses." + ) + public RevisionDTO getRevision() { + if (revision == null) { + return new RevisionDTO(); + } else { + return revision; + } + } + + public void setRevision(RevisionDTO revision) { + this.revision = revision; + } + + /** + * The id for this component. + * + * @return The id + */ + @ApiModelProperty( + value = "The id of the component." + ) + public String getId() { + return this.id; + } + + public void setId(final String id) { + this.id = id; + } + + /** + * The uri for linking to this component in this NiFi. + * + * @return The uri + */ + @ApiModelProperty( + value = "The URI for futures requests to the component." + ) + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + /** + * The position of this component in the UI if applicable, null otherwise. + * + * @return The position + */ + @ApiModelProperty( + value = "The position of this component in the UI if applicable." + ) + public PositionDTO getPosition() { + return position; + } + + public void setPosition(PositionDTO position) { + this.position = position; + } + + /** + * The access policy for this component. + * + * @return The access policy + */ + @ApiModelProperty( + value = "The access policy for this component." + ) + public AccessPolicyDTO getAccessPolicy() { + return accessPolicy; + } + + public void setAccessPolicy(AccessPolicyDTO accessPolicy) { + this.accessPolicy = accessPolicy; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionEntity.java index b041e51cfc..ed4a38fcc3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionEntity.java @@ -16,26 +16,119 @@ */ package org.apache.nifi.web.api.entity; -import javax.xml.bind.annotation.XmlRootElement; +import com.wordnik.swagger.annotations.ApiModelProperty; import org.apache.nifi.web.api.dto.ConnectionDTO; +import org.apache.nifi.web.api.dto.PositionDTO; + +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; /** * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a ConnectionDTO. */ @XmlRootElement(name = "connectionEntity") -public class ConnectionEntity extends Entity { +public class ConnectionEntity extends ComponentEntity { - private ConnectionDTO connection; + private ConnectionDTO component; + private List bends; + private Integer labelIndex; + private String sourceId; + private String sourceGroupId; + private String destinationId; + private String destinationGroupId; /** * @return RelationshipDTO that is being serialized */ - public ConnectionDTO getConnection() { - return connection; + public ConnectionDTO getComponent() { + return component; } - public void setConnection(ConnectionDTO connection) { - this.connection = connection; + public void setComponent(ConnectionDTO component) { + this.component = component; } + /** + * @return position of the bend points on this connection + */ + @ApiModelProperty( + value = "The bend points on the connection." + ) + public List getBends() { + return bends; + } + + public void setBends(List bends) { + this.bends = bends; + } + + /** + * @return The index of control point that the connection label should be placed over + */ + @ApiModelProperty( + value = "The index of the bend point where to place the connection label." + ) + public Integer getLabelIndex() { + return labelIndex; + } + + public void setLabelIndex(Integer labelIndex) { + this.labelIndex = labelIndex; + } + + /** + * @return The identifier of the source of this connection + */ + @ApiModelProperty( + value = "The identifier of the source of this connection." + ) + public String getSourceId() { + return sourceId; + } + + public void setSourceId(String sourceId) { + this.sourceId = sourceId; + } + + /** + * @return The identifier of the destination of this connection + */ + @ApiModelProperty( + value = "The identifier of the destination of this connection." + ) + public String getDestinationId() { + return destinationId; + } + + public void setDestinationId(String destinationId) { + this.destinationId = destinationId; + } + + /** + * @return The identifier of the group of the source of this connection + */ + @ApiModelProperty( + value = "The identifier of the group of the source of this connection." + ) + public String getSourceGroupId() { + return sourceGroupId; + } + + public void setSourceGroupId(String sourceGroupId) { + this.sourceGroupId = sourceGroupId; + } + + /** + * @return The identifier of the group of the destination of this connection + */ + @ApiModelProperty( + value = "The identifier of the group of the destination of this connection." + ) + public String getDestinationGroupId() { + return destinationGroupId; + } + + public void setDestinationGroupId(String destinationGroupId) { + this.destinationGroupId = destinationGroupId; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionsEntity.java index 5b2b1b0ed0..51f17b9857 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ConnectionsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.ConnectionDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of ConnectionDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of ConnectionEntitys. */ @XmlRootElement(name = "connectionsEntity") public class ConnectionsEntity extends Entity { - private Set connections; + private Set connections; /** - * @return list of ConnectionDTOs that are being serialized + * @return list of ConnectionEntitys that are being serialized */ - public Set getConnections() { + public Set getConnections() { return connections; } - public void setConnections(Set connections) { + public void setConnections(Set connections) { this.connections = connections; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceEntity.java index 8f217b5b28..8e96e48bc6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ControllerServiceEntity.java @@ -23,7 +23,7 @@ import org.apache.nifi.web.api.dto.ControllerServiceDTO; * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a controller service. */ @XmlRootElement(name = "controllerServiceEntity") -public class ControllerServiceEntity extends Entity { +public class ControllerServiceEntity extends ComponentEntity { private ControllerServiceDTO controllerService; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/Entity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/Entity.java index 13c7a70fa9..a961d147af 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/Entity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/Entity.java @@ -17,9 +17,10 @@ package org.apache.nifi.web.api.entity; import com.wordnik.swagger.annotations.ApiModelProperty; -import javax.xml.bind.annotation.XmlRootElement; import org.apache.nifi.web.api.dto.RevisionDTO; +import javax.xml.bind.annotation.XmlRootElement; + /** * A base type for request/response entities. */ @@ -34,6 +35,7 @@ public class Entity { @ApiModelProperty( value = "The revision for this request/response. The revision is required for any mutable flow requests and is included in all responses." ) + @Deprecated public RevisionDTO getRevision() { if (revision == null) { return new RevisionDTO(); @@ -42,6 +44,7 @@ public class Entity { } } + @Deprecated public void setRevision(RevisionDTO revision) { this.revision = revision; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FlowEntity.java similarity index 67% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortEntity.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FlowEntity.java index 4f40aec66e..d9c22b77aa 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FlowEntity.java @@ -16,26 +16,29 @@ */ package org.apache.nifi.web.api.entity; +import org.apache.nifi.web.api.dto.flow.FlowDTO; + import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.PortDTO; /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to an output PortDTO. + * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a FlowDTO. */ -@XmlRootElement(name = "outputPortEntity") -public class OutputPortEntity extends Entity { +@XmlRootElement(name = "flowEntity") +public class FlowEntity extends Entity { - private PortDTO outputPort; + private FlowDTO flow; /** - * @return output PortDTO that are being serialized + * The FlowDTO that is being serialized. + * + * @return The FlowDTO object */ - public PortDTO getOutputPort() { - return outputPort; + public FlowDTO getFlow() { + return flow; } - public void setOutputPort(PortDTO outputPort) { - this.outputPort = outputPort; + public void setFlow(FlowDTO flow) { + this.flow = flow; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelEntity.java index 241ac51439..54ff2ed7ae 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelEntity.java @@ -23,21 +23,21 @@ import org.apache.nifi.web.api.dto.FunnelDTO; * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a FunnelDTO. */ @XmlRootElement(name = "funnelEntity") -public class FunnelEntity extends Entity { +public class FunnelEntity extends ComponentEntity { - private FunnelDTO funnel; + private FunnelDTO component; /** * The FunnelDTO that is being serialized. * * @return The FunnelDTO object */ - public FunnelDTO getFunnel() { - return funnel; + public FunnelDTO getComponent() { + return component; } - public void setFunnel(FunnelDTO funnel) { - this.funnel = funnel; + public void setComponent(FunnelDTO component) { + this.component = component; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelsEntity.java index 34426db42d..246f222c6e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/FunnelsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.FunnelDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of FunnelDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of FunnelEntitys. */ @XmlRootElement(name = "funnelsEntity") public class FunnelsEntity extends Entity { - private Set funnels; + private Set funnels; /** - * @return collection of FunnelDTOs that are being serialized + * @return collection of FunnelEntitys that are being serialized */ - public Set getFunnels() { + public Set getFunnels() { return funnels; } - public void setFunnels(Set labels) { + public void setFunnels(Set labels) { this.funnels = labels; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortsEntity.java index 93a03e7127..ba188814b7 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.PortDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of input PortDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of input InputPortEntitys. */ @XmlRootElement(name = "inputPortsEntity") public class InputPortsEntity extends Entity { - private Set inputPorts; + private Set inputPorts; /** - * @return collection of input PortDTOs that are being serialized + * @return collection of input InputPortEntitys that are being serialized */ - public Set getInputPorts() { + public Set getInputPorts() { return inputPorts; } - public void setInputPorts(Set inputPorts) { + public void setInputPorts(Set inputPorts) { this.inputPorts = inputPorts; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java index 535240c194..48e2aa7c79 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelEntity.java @@ -16,28 +16,43 @@ */ package org.apache.nifi.web.api.entity; -import javax.xml.bind.annotation.XmlRootElement; +import org.apache.nifi.web.api.dto.DimensionsDTO; import org.apache.nifi.web.api.dto.LabelDTO; +import javax.xml.bind.annotation.XmlRootElement; + /** * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a LabelDTO. */ @XmlRootElement(name = "labelEntity") -public class LabelEntity extends Entity { +public class LabelEntity extends ComponentEntity { - private LabelDTO label; + private DimensionsDTO dimensions; + private LabelDTO component; /** * The LabelDTO that is being serialized. * * @return The LabelDTO object */ - public LabelDTO getLabel() { - return label; + public LabelDTO getComponent() { + return component; } - public void setLabel(LabelDTO label) { - this.label = label; + public void setComponent(LabelDTO component) { + this.component = component; } + /** + * The dimensions of this label. + * + * @return The dimensions + */ + public DimensionsDTO getDimensions() { + return dimensions; + } + + public void setDimensions(DimensionsDTO dimensions) { + this.dimensions = dimensions; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelsEntity.java index 05dab6c371..855ce6c1ea 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/LabelsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.LabelDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of LabelDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of LabelEntity's. */ @XmlRootElement(name = "labelsEntity") public class LabelsEntity extends Entity { - private Set labels; + private Set labels; /** - * @return collection of LabelDTOs that are being serialized + * @return collection of LabelEntity's that are being serialized */ - public Set getLabels() { + public Set getLabels() { return labels; } - public void setLabels(Set labels) { + public void setLabels(Set labels) { this.labels = labels; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortsEntity.java index e624c52e02..9b984147a5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/OutputPortsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.PortDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of output PortDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of output OutputPortEntitys. */ @XmlRootElement(name = "outputPortsEntity") public class OutputPortsEntity extends Entity { - private Set outputPorts; + private Set outputPorts; /** - * @return collection of output PortDTOs that are being serialized + * @return collection of output OutputPortEntitys that are being serialized */ - public Set getOutputPorts() { + public Set getOutputPorts() { return outputPorts; } - public void setOutputPorts(Set outputPorts) { + public void setOutputPorts(Set outputPorts) { this.outputPorts = outputPorts; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/PortEntity.java similarity index 72% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortEntity.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/PortEntity.java index f92c47802f..0dc4fdc83f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/InputPortEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/PortEntity.java @@ -16,26 +16,35 @@ */ package org.apache.nifi.web.api.entity; -import javax.xml.bind.annotation.XmlRootElement; import org.apache.nifi.web.api.dto.PortDTO; +import javax.xml.bind.annotation.XmlRootElement; + /** * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to an input PortDTO. */ -@XmlRootElement(name = "inputPortEntity") -public class InputPortEntity extends Entity { +@XmlRootElement(name = "portEntity") +public class PortEntity extends ComponentEntity { - private PortDTO inputPort; + private PortDTO component; + private String portType; /** * @return input PortDTO that are being serialized */ - public PortDTO getInputPort() { - return inputPort; + public PortDTO getComponent() { + return component; } - public void setInputPort(PortDTO inputPort) { - this.inputPort = inputPort; + public void setComponent(PortDTO component) { + this.component = component; } + public String getPortType() { + return portType; + } + + public void setPortType(String portType) { + this.portType = portType; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java index d1ec034271..06e78e5366 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupEntity.java @@ -23,21 +23,21 @@ import org.apache.nifi.web.api.dto.ProcessGroupDTO; * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a ProcessGroupDTO. */ @XmlRootElement(name = "processGroupEntity") -public class ProcessGroupEntity extends Entity { +public class ProcessGroupEntity extends ComponentEntity { - private ProcessGroupDTO processGroup; + private ProcessGroupDTO component; /** * The ProcessGroupDTO that is being serialized. * * @return The ControllerDTO object */ - public ProcessGroupDTO getProcessGroup() { - return processGroup; + public ProcessGroupDTO getComponent() { + return component; } - public void setProcessGroup(ProcessGroupDTO controller) { - this.processGroup = controller; + public void setComponent(ProcessGroupDTO component) { + this.component = component; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupFlowEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupFlowEntity.java new file mode 100644 index 0000000000..8ab1327799 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupFlowEntity.java @@ -0,0 +1,44 @@ +/* + * 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.web.api.entity; + +import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a ProcessGroupFlowDTO. + */ +@XmlRootElement(name = "processGroupFlowEntity") +public class ProcessGroupFlowEntity extends Entity { + + private ProcessGroupFlowDTO processGroupFlow; + + /** + * The ProcessGroupFlowDTO that is being serialized. + * + * @return The ProcessGroupFlowDTO object + */ + public ProcessGroupFlowDTO getProcessGroupFlow() { + return processGroupFlow; + } + + public void setProcessGroupFlow(ProcessGroupFlowDTO flow) { + this.processGroupFlow = flow; + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupsEntity.java index 7acf650e4a..4f222e319f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessGroupsEntity.java @@ -16,28 +16,27 @@ */ package org.apache.nifi.web.api.entity; -import java.util.Set; import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.ProcessGroupDTO; +import java.util.Set; /** - * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a set of ProcessGroupDTOs. + * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a set of ProcessGroupEntitys. */ @XmlRootElement(name = "processGroupsEntity") public class ProcessGroupsEntity extends Entity { - private Set processGroups; + private Set processGroups; /** - * The ProcessGroupDTO that is being serialized. + * The ProcessGroupEntity that is being serialized. * - * @return The ProcessGroupDTOs + * @return The ProcessGroupEntitys */ - public Set getProcessGroups() { + public Set getProcessGroups() { return processGroups; } - public void setProcessGroups(Set processGroups) { + public void setProcessGroups(Set processGroups) { this.processGroups = processGroups; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java index e03bb85ef3..edf3c5e6ac 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorEntity.java @@ -16,28 +16,29 @@ */ package org.apache.nifi.web.api.entity; -import javax.xml.bind.annotation.XmlRootElement; import org.apache.nifi.web.api.dto.ProcessorDTO; +import javax.xml.bind.annotation.XmlRootElement; + /** * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a ProcessorDTO. */ @XmlRootElement(name = "processorEntity") -public class ProcessorEntity extends Entity { +public class ProcessorEntity extends ComponentEntity { - private ProcessorDTO processor; + private ProcessorDTO component; /** * The ProcessorDTO that is being serialized. * * @return The ProcessorDTO object */ - public ProcessorDTO getProcessor() { - return processor; + public ProcessorDTO getComponent() { + return component; } - public void setProcessor(ProcessorDTO processor) { - this.processor = processor; + public void setComponent(ProcessorDTO component) { + this.component = component; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorsEntity.java index 04db99fb32..06ed8f51c0 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ProcessorsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.ProcessorDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of ProcessorDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of ProcessorEntity's. */ @XmlRootElement(name = "processorsEntity") public class ProcessorsEntity extends Entity { - private Set processors; + private Set processors; /** - * @return collection of ProcessorDTOs that are being serialized + * @return collection of ProcessorEntity's that are being serialized */ - public Set getProcessors() { + public Set getProcessors() { return processors; } - public void setProcessors(Set processors) { + public void setProcessors(Set processors) { this.processors = processors; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupEntity.java index ba12f40f3f..3183cde979 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupEntity.java @@ -23,21 +23,21 @@ import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO; * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a RemoteProcessGroupDTO. */ @XmlRootElement(name = "remoteProcessGroupEntity") -public class RemoteProcessGroupEntity extends Entity { +public class RemoteProcessGroupEntity extends ComponentEntity { - private RemoteProcessGroupDTO remoteProcessGroup; + private RemoteProcessGroupDTO component; /** * The RemoteProcessGroupDTO that is being serialized. * * @return The RemoteProcessGroupDTO object */ - public RemoteProcessGroupDTO getRemoteProcessGroup() { - return remoteProcessGroup; + public RemoteProcessGroupDTO getComponent() { + return component; } - public void setRemoteProcessGroup(RemoteProcessGroupDTO remoteProcessGroup) { - this.remoteProcessGroup = remoteProcessGroup; + public void setComponent(RemoteProcessGroupDTO component) { + this.component = component; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupsEntity.java index 42abf238a7..c8fc695b06 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupsEntity.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RemoteProcessGroupsEntity.java @@ -16,27 +16,25 @@ */ package org.apache.nifi.web.api.entity; +import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO; - /** - * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of RemoteProcessGroupDTOs. + * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a list of RemoteProcessGroupEntitys. */ @XmlRootElement(name = "remoteProcessGroupsEntity") public class RemoteProcessGroupsEntity extends Entity { - private Set remoteProcessGroups; + private Set remoteProcessGroups; /** - * @return collection of RemoteProcessGroupDTOs that are being serialized + * @return collection of RemoteProcessGroupEntitys that are being serialized */ - public Set getRemoteProcessGroups() { + public Set getRemoteProcessGroups() { return remoteProcessGroups; } - public void setRemoteProcessGroups(Set remoteProcessGroups) { + public void setRemoteProcessGroups(Set remoteProcessGroups) { this.remoteProcessGroups = remoteProcessGroups; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/xsd/authorizations.xsd b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/xsd/authorizations.xsd index dc17265a03..f659b27b46 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/xsd/authorizations.xsd +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/xsd/authorizations.xsd @@ -28,7 +28,6 @@ - diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/pom.xml index 8532ec513c..918c6cf131 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/pom.xml @@ -21,11 +21,68 @@ 1.0.0-SNAPSHOT nifi-framework-authorization - + + + + src/main/resources + + + src/main/xsd + + + + + org.codehaus.mojo + jaxb2-maven-plugin + + + current + + xjc + + + org.apache.nifi.authorization.generated + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + **/authorization/generated/*.java, + + + + org.apache.nifi nifi-api + + org.apache.nifi + nifi-expression-language + + + org.apache.nifi + nifi-properties + + + org.apache.nifi + nifi-nar-utils + + + org.springframework.security + spring-security-core + + + org.springframework + spring-beans + + + org.apache.commons + commons-lang3 + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AccessDeniedException.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AccessDeniedException.java new file mode 100644 index 0000000000..092e80cb90 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AccessDeniedException.java @@ -0,0 +1,39 @@ +/* + * 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.authorization; + +/** + * Represents any error that might occur while authorizing user requests. + */ +public class AccessDeniedException extends RuntimeException { + + public AccessDeniedException(Throwable cause) { + super(cause); + } + + public AccessDeniedException(String message, Throwable cause) { + super(message, cause); + } + + public AccessDeniedException(String message) { + super(message); + } + + public AccessDeniedException() { + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java similarity index 89% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java index 3d3e826e11..423ae259b3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java @@ -81,38 +81,37 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho @Override public Object getObject() throws Exception { if (authorizer == null) { - // look up the authorizer to use - final String authorizerIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORIZER); - - // ensure the authorizer class name was specified - if (StringUtils.isBlank(authorizerIdentifier)) { - // if configured for ssl, the authorizer must be specified - if (properties.getSslPort() != null) { - throw new Exception("When running securely, the authorizer identifier must be specified in the nifi properties file."); - } - + if (properties.getSslPort() == null) { // use a default authorizer... only allowable when running not securely authorizer = createDefaultAuthorizer(); } else { - final Authorizers authorizerConfiguration = loadAuthorizersConfiguration(); + // look up the authorizer to use + final String authorizerIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORIZER); - // create each authorizer - for (final org.apache.nifi.authorization.generated.Authorizer authorizer : authorizerConfiguration.getAuthorizer()) { - authorizers.put(authorizer.getIdentifier(), createAuthorizer(authorizer.getIdentifier(), authorizer.getClazz())); - } + // ensure the authorizer class name was specified + if (StringUtils.isBlank(authorizerIdentifier)) { + throw new Exception("When running securely, the authorizer identifier must be specified in the nifi properties file."); + } else { + final Authorizers authorizerConfiguration = loadAuthorizersConfiguration(); - // configure each authorizer - for (final org.apache.nifi.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) { - final Authorizer instance = authorizers.get(provider.getIdentifier()); - instance.onConfigured(loadAuthorizerConfiguration(provider)); - } + // create each authorizer + for (final org.apache.nifi.authorization.generated.Authorizer authorizer : authorizerConfiguration.getAuthorizer()) { + authorizers.put(authorizer.getIdentifier(), createAuthorizer(authorizer.getIdentifier(), authorizer.getClazz())); + } - // get the authorizer instance - authorizer = getAuthorizer(authorizerIdentifier); + // configure each authorizer + for (final org.apache.nifi.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) { + final Authorizer instance = authorizers.get(provider.getIdentifier()); + instance.onConfigured(loadAuthorizerConfiguration(provider)); + } - // ensure it was found - if (authorizer == null) { - throw new Exception(String.format("The specified authorizer '%s' could not be found.", authorizerIdentifier)); + // get the authorizer instance + authorizer = getAuthorizer(authorizerIdentifier); + + // ensure it was found + if (authorizer == null) { + throw new Exception(String.format("The specified authorizer '%s' could not be found.", authorizerIdentifier)); + } } } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java similarity index 100% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerConfigurationContext.java diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java similarity index 100% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/StandardAuthorizerInitializationContext.java diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java new file mode 100644 index 0000000000..c897be279b --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java @@ -0,0 +1,129 @@ +/* + * 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.authorization.resource; + +import org.apache.nifi.authorization.AccessDeniedException; +import org.apache.nifi.authorization.AuthorizationRequest; +import org.apache.nifi.authorization.AuthorizationResult; +import org.apache.nifi.authorization.AuthorizationResult.Result; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; + +public interface Authorizable { + + /** + * The parent for this Authorizable. May be null. + * + * @return the parent authorizable or null + */ + Authorizable getParentAuthorizable(); + + /** + * The Resource for this Authorizable. + * + * @return the parent resource + */ + Resource getResource(); + + /** + * Returns whether the current user is authorized for the specified action on the specified resource. This + * method does not imply the user is directly attempting to access the specified resource. If the user is + * attempting a direct access use Authorizable.authorize(). + * + * @param authorizer authorizer + * @param action action + * @return is authorized + */ + default boolean isAuthorized(Authorizer authorizer, RequestAction action) { + return Result.Approved.equals(checkAuthorization(authorizer, action).getResult()); + } + + /** + * Returns the result of an authorization request for the current user for the specified action on the specified + * resource. This method does not imply the user is directly attempting to access the specified resource. If the user is + * attempting a direct access use Authorizable.authorize(). + * + * @param authorizer authorizer + * @param action action + * @return is authorized + */ + default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action) { + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + + // TODO - include user details context + + // build the request + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(user.getIdentity()) + .anonymous(user.isAnonymous()) + .accessAttempt(false) + .action(action) + .resource(getResource()) + .build(); + + // perform the authorization + final AuthorizationResult result = authorizer.authorize(request); + + // verify the results + if (Result.ResourceNotFound.equals(result.getResult())) { + final Authorizable parent = getParentAuthorizable(); + if (parent == null) { + return AuthorizationResult.denied(); + } else { + return parent.checkAuthorization(authorizer, action); + } + } else { + return result; + } + } + + /** + * Authorizes the current user for the specified action on the specified resource. This method does imply the user is + * directly accessing the specified resource. + * + * @param authorizer authorizer + * @param action action + */ + default void authorize(Authorizer authorizer, RequestAction action) throws AccessDeniedException { + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + + // TODO - include user details context + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(user.getIdentity()) + .anonymous(user.isAnonymous()) + .accessAttempt(true) + .action(action) + .resource(getResource()) + .build(); + + final AuthorizationResult result = authorizer.authorize(request); + if (Result.ResourceNotFound.equals(result.getResult())) { + final Authorizable parent = getParentAuthorizable(); + if (parent == null) { + throw new AccessDeniedException("Access is denied"); + } else { + parent.authorize(authorizer, action); + } + } else if (Result.Denied.equals(result.getResult())) { + throw new AccessDeniedException(result.getExplanation()); + } + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java index a641810d4f..ce8f1bf020 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceFactory.java @@ -203,7 +203,6 @@ public final class ResourceFactory { public static Resource getComponentResource(final ResourceType resourceType, final String identifier, final String name) { Objects.requireNonNull(resourceType, "The resource must be specified."); Objects.requireNonNull(identifier, "The component identifier must be specified."); - Objects.requireNonNull(name, "The component name must be specified."); return new Resource() { @Override diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java index 20ace59851..f3e9b6ce4d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/resource/ResourceType.java @@ -20,6 +20,7 @@ public enum ResourceType { Processor("/processors"), InputPort("/input-ports"), OutputPort("/output-ports"), + Funnel("/funnel"), Connection("/connections"), ProcessGroup("/process-groups"), RemoteProcessGroup("/remote-process-groups"), diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java similarity index 98% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java index 3a919ba53f..80e740625f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.nifi.user; +package org.apache.nifi.authorization.user; import java.io.Serializable; import java.util.Objects; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserDetails.java similarity index 96% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserDetails.java index 86668fe5c3..f8b7c1849a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserDetails.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserDetails.java @@ -14,10 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.nifi.web.security.user; +package org.apache.nifi.authorization.user; import org.apache.commons.lang3.StringUtils; -import org.apache.nifi.user.NiFiUser; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java similarity index 65% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java index 255b3d5195..840df69005 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/user/NiFiUserUtils.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java @@ -14,13 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.nifi.web.security.user; +package org.apache.nifi.authorization.user; -import java.util.HashSet; -import java.util.Set; -import org.apache.nifi.user.NiFiUser; import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; @@ -30,32 +26,6 @@ import org.springframework.security.core.context.SecurityContextHolder; */ public final class NiFiUserUtils { - /** - * Return the authorities for the current user. - * - * @return authorities - */ - public static Set getAuthorities() { - Set grantedAuthorities = new HashSet<>(); - - SecurityContext context = SecurityContextHolder.getContext(); - if (context != null) { - Authentication authentication = context.getAuthentication(); - if (authentication != null) { - // get the authorities for the user of the current request - grantedAuthorities.addAll(authentication.getAuthorities()); - } - } - - // convert to a list of authorities - Set authorities = new HashSet<>(grantedAuthorities.size()); - for (GrantedAuthority grantedAuthority : grantedAuthorities) { - authorities.add(grantedAuthority.getAuthority()); - } - - return authorities; - } - /** * Returns the current NiFiUser or null if the current user is not a NiFiUser. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/nifi-framework-authorization-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/nifi-framework-authorization-context.xml new file mode 100644 index 0000000000..71bf684893 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/resources/nifi-framework-authorization-context.xml @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/xsd/authorizers.xsd b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/xsd/authorizers.xsd similarity index 100% rename from nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/xsd/authorizers.xsd rename to nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/xsd/authorizers.xsd diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java index d4ea1d4a97..88da5fff55 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/impl/WebClusterManager.java @@ -3071,7 +3071,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C if (hasSuccessfulClientResponse && isProcessorEndpoint(uri, method)) { final ProcessorEntity responseEntity = clientResponse.getClientResponse().getEntity(ProcessorEntity.class); - final ProcessorDTO processor = responseEntity.getProcessor(); + final ProcessorDTO processor = responseEntity.getComponent(); final Map processorMap = new HashMap<>(); for (final NodeResponse nodeResponse : updatedNodesMap.values()) { @@ -3080,7 +3080,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C } final ProcessorEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(ProcessorEntity.class); - final ProcessorDTO nodeProcessor = nodeResponseEntity.getProcessor(); + final ProcessorDTO nodeProcessor = nodeResponseEntity.getComponent(); processorMap.put(nodeResponse.getNodeId(), nodeProcessor); } @@ -3088,7 +3088,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C clientResponse = new NodeResponse(clientResponse, responseEntity); } else if (hasSuccessfulClientResponse && isProcessorsEndpoint(uri, method)) { final ProcessorsEntity responseEntity = clientResponse.getClientResponse().getEntity(ProcessorsEntity.class); - final Set processors = responseEntity.getProcessors(); + final Set processors = responseEntity.getProcessors(); final Map> processorMap = new HashMap<>(); for (final NodeResponse nodeResponse : updatedNodesMap.values()) { @@ -3097,31 +3097,31 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C } final ProcessorsEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(ProcessorsEntity.class); - final Set nodeProcessors = nodeResponseEntity.getProcessors(); + final Set nodeProcessors = nodeResponseEntity.getProcessors(); - for (final ProcessorDTO nodeProcessor : nodeProcessors) { - Map innerMap = processorMap.get(nodeProcessor.getId()); + for (final ProcessorEntity nodeProcessor : nodeProcessors) { + Map innerMap = processorMap.get(nodeProcessor.getComponent().getId()); if (innerMap == null) { innerMap = new HashMap<>(); - processorMap.put(nodeProcessor.getId(), innerMap); + processorMap.put(nodeProcessor.getComponent().getId(), innerMap); } - innerMap.put(nodeResponse.getNodeId(), nodeProcessor); + innerMap.put(nodeResponse.getNodeId(), nodeProcessor.getComponent()); } } - for (final ProcessorDTO processor : processors) { - final String procId = processor.getId(); + for (final ProcessorEntity processor : processors) { + final String procId = processor.getComponent().getId(); final Map mergeMap = processorMap.get(procId); - mergeProcessorValidationErrors(processor, mergeMap); + mergeProcessorValidationErrors(processor.getComponent(), mergeMap); } // create a new client response clientResponse = new NodeResponse(clientResponse, responseEntity); } else if (hasSuccessfulClientResponse && isProcessGroupEndpoint(uri, method)) { final ProcessGroupEntity responseEntity = clientResponse.getClientResponse().getEntity(ProcessGroupEntity.class); - final ProcessGroupDTO responseDto = responseEntity.getProcessGroup(); + final ProcessGroupDTO responseDto = responseEntity.getComponent(); final FlowSnippetDTO contents = responseDto.getContents(); if (contents == null) { @@ -3138,7 +3138,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C } final ProcessGroupEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(ProcessGroupEntity.class); - final ProcessGroupDTO nodeProcessGroup = nodeResponseEntity.getProcessGroup(); + final ProcessGroupDTO nodeProcessGroup = nodeResponseEntity.getComponent(); for (final ProcessorDTO nodeProcessor : nodeProcessGroup.getContents().getProcessors()) { Map innerMap = processorMap.get(nodeProcessor.getId()); @@ -3242,7 +3242,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C clientResponse = new NodeResponse(clientResponse, responseEntity); } else if (hasSuccessfulClientResponse && isRemoteProcessGroupEndpoint(uri, method)) { final RemoteProcessGroupEntity responseEntity = clientResponse.getClientResponse().getEntity(RemoteProcessGroupEntity.class); - final RemoteProcessGroupDTO remoteProcessGroup = responseEntity.getRemoteProcessGroup(); + final RemoteProcessGroupDTO remoteProcessGroup = responseEntity.getComponent(); final Map remoteProcessGroupMap = new HashMap<>(); for (final NodeResponse nodeResponse : updatedNodesMap.values()) { @@ -3251,7 +3251,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C } final RemoteProcessGroupEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(RemoteProcessGroupEntity.class); - final RemoteProcessGroupDTO nodeRemoteProcessGroup = nodeResponseEntity.getRemoteProcessGroup(); + final RemoteProcessGroupDTO nodeRemoteProcessGroup = nodeResponseEntity.getComponent(); remoteProcessGroupMap.put(nodeResponse.getNodeId(), nodeRemoteProcessGroup); } @@ -3260,7 +3260,7 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C clientResponse = new NodeResponse(clientResponse, responseEntity); } else if (hasSuccessfulClientResponse && isRemoteProcessGroupsEndpoint(uri, method)) { final RemoteProcessGroupsEntity responseEntity = clientResponse.getClientResponse().getEntity(RemoteProcessGroupsEntity.class); - final Set remoteProcessGroups = responseEntity.getRemoteProcessGroups(); + final Set remoteProcessGroups = responseEntity.getRemoteProcessGroups(); final Map> remoteProcessGroupMap = new HashMap<>(); for (final NodeResponse nodeResponse : updatedNodesMap.values()) { @@ -3269,24 +3269,24 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C } final RemoteProcessGroupsEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(RemoteProcessGroupsEntity.class); - final Set nodeRemoteProcessGroups = nodeResponseEntity.getRemoteProcessGroups(); + final Set nodeRemoteProcessGroups = nodeResponseEntity.getRemoteProcessGroups(); - for (final RemoteProcessGroupDTO nodeRemoteProcessGroup : nodeRemoteProcessGroups) { + for (final RemoteProcessGroupEntity nodeRemoteProcessGroup : nodeRemoteProcessGroups) { Map innerMap = remoteProcessGroupMap.get(nodeRemoteProcessGroup.getId()); if (innerMap == null) { innerMap = new HashMap<>(); remoteProcessGroupMap.put(nodeRemoteProcessGroup.getId(), innerMap); } - innerMap.put(nodeResponse.getNodeId(), nodeRemoteProcessGroup); + innerMap.put(nodeResponse.getNodeId(), nodeRemoteProcessGroup.getComponent()); } } - for (final RemoteProcessGroupDTO remoteProcessGroup : remoteProcessGroups) { + for (final RemoteProcessGroupEntity remoteProcessGroup : remoteProcessGroups) { final String remoteProcessGroupId = remoteProcessGroup.getId(); final Map mergeMap = remoteProcessGroupMap.get(remoteProcessGroupId); - mergeRemoteProcessGroup(remoteProcessGroup, mergeMap); + mergeRemoteProcessGroup(remoteProcessGroup.getComponent(), mergeMap); } // create a new client response diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/pom.xml index 62b26114a1..2d0f94b847 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/pom.xml @@ -50,5 +50,9 @@ org.quartz-scheduler quartz + + org.apache.nifi + nifi-framework-authorization + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java index 1a26f39923..d430599056 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.controller.Triggerable; import org.apache.nifi.groups.ProcessGroup; @@ -31,7 +32,7 @@ import org.apache.nifi.scheduling.SchedulingStrategy; /** * Represents a connectable component to which or from which data can flow. */ -public interface Connectable extends Triggerable { +public interface Connectable extends Triggerable, Authorizable { /** * @return the unique identifier for this Connectable diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java index 2e669053f1..1d240b53c1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connection.java @@ -20,13 +20,14 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.controller.queue.FlowFileQueue; import org.apache.nifi.controller.repository.FlowFileRecord; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.processor.FlowFileFilter; import org.apache.nifi.processor.Relationship; -public interface Connection { +public interface Connection extends Authorizable { void enqueue(FlowFileRecord flowFile); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java index e2341715e3..398e4fb375 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java @@ -16,7 +16,25 @@ */ package org.apache.nifi.controller; -import static java.util.Objects.requireNonNull; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.connectable.Connectable; +import org.apache.nifi.connectable.ConnectableType; +import org.apache.nifi.connectable.Connection; +import org.apache.nifi.connectable.Port; +import org.apache.nifi.connectable.Position; +import org.apache.nifi.groups.ProcessGroup; +import org.apache.nifi.processor.ProcessContext; +import org.apache.nifi.processor.ProcessSession; +import org.apache.nifi.processor.ProcessSessionFactory; +import org.apache.nifi.processor.Relationship; +import org.apache.nifi.processor.exception.ProcessException; +import org.apache.nifi.util.FormatUtils; import java.util.ArrayList; import java.util.Collection; @@ -32,22 +50,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import org.apache.nifi.components.ValidationResult; -import org.apache.nifi.connectable.Connectable; -import org.apache.nifi.connectable.ConnectableType; -import org.apache.nifi.connectable.Connection; -import org.apache.nifi.connectable.Port; -import org.apache.nifi.connectable.Position; -import org.apache.nifi.groups.ProcessGroup; -import org.apache.nifi.processor.ProcessContext; -import org.apache.nifi.processor.ProcessSession; -import org.apache.nifi.processor.ProcessSessionFactory; -import org.apache.nifi.processor.Relationship; -import org.apache.nifi.processor.exception.ProcessException; -import org.apache.nifi.util.FormatUtils; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; +import static java.util.Objects.requireNonNull; public abstract class AbstractPort implements Port { @@ -142,6 +145,17 @@ public abstract class AbstractPort implements Port { this.name.set(name); } + @Override + public Authorizable getParentAuthorizable() { + return getProcessGroup(); + } + + @Override + public Resource getResource() { + final ResourceType resourceType = ConnectableType.INPUT_PORT.equals(getConnectableType()) ? ResourceType.InputPort : ResourceType.OutputPort; + return ResourceFactory.getComponentResource(resourceType, getIdentifier(), getName()); + } + @Override public ProcessGroup getProcessGroup() { return processGroup.get(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java index 78135300bd..9929914324 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ProcessorNode.java @@ -16,13 +16,6 @@ */ package org.apache.nifi.controller; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - import org.apache.nifi.annotation.behavior.InputRequirement.Requirement; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.controller.service.ControllerServiceNode; @@ -35,6 +28,13 @@ import org.apache.nifi.scheduling.SchedulingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + public abstract class ProcessorNode extends AbstractConfiguredComponent implements Connectable { private static final Logger logger = LoggerFactory.getLogger(ProcessorNode.class); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java index 9fb13f670e..289f52aff3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java @@ -16,22 +16,12 @@ */ package org.apache.nifi.controller; -import static java.util.Objects.requireNonNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.ConnectableType; @@ -48,8 +38,21 @@ import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.scheduling.SchedulingStrategy; import org.apache.nifi.util.FormatUtils; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static java.util.Objects.requireNonNull; public class StandardFunnel implements Funnel { @@ -116,6 +119,16 @@ public class StandardFunnel implements Funnel { return (Relationship.ANONYMOUS.getName().equals(relationshipName)) ? Relationship.ANONYMOUS : null; } + @Override + public Authorizable getParentAuthorizable() { + return getProcessGroup(); + } + + @Override + public Resource getResource() { + return ResourceFactory.getComponentResource(ResourceType.Funnel, getIdentifier(), getName()); + } + @Override public void addConnection(final Connection connection) throws IllegalArgumentException { writeLock.lock(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java index 97c44b5505..2a95f13e3c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java @@ -18,11 +18,12 @@ package org.apache.nifi.controller.label; import java.util.Map; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.connectable.Position; import org.apache.nifi.connectable.Size; import org.apache.nifi.groups.ProcessGroup; -public interface Label { +public interface Label extends Authorizable { String getIdentifier(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java index 56038fedab..5406954b7a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.Connection; import org.apache.nifi.connectable.Funnel; @@ -40,7 +41,7 @@ import org.apache.nifi.processor.Processor; *

* MUST BE THREAD-SAFE

*/ -public interface ProcessGroup { +public interface ProcessGroup extends Authorizable { /** * @return a reference to this ProcessGroup's parent. This will be diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java index db053135fe..cf0820b75d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java @@ -21,12 +21,13 @@ import java.util.Date; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.connectable.Position; import org.apache.nifi.controller.exception.CommunicationsException; import org.apache.nifi.events.EventReporter; import org.apache.nifi.remote.RemoteGroupPort; -public interface RemoteProcessGroup { +public interface RemoteProcessGroup extends Authorizable { String getIdentifier(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java index 11761470d5..0843743817 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/connectable/StandardConnection.java @@ -16,18 +16,14 @@ */ package org.apache.nifi.connectable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.controller.ProcessScheduler; import org.apache.nifi.controller.StandardFlowFileQueue; import org.apache.nifi.controller.queue.FlowFileQueue; @@ -42,6 +38,17 @@ import org.apache.nifi.processor.Relationship; import org.apache.nifi.provenance.ProvenanceEventRepository; import org.apache.nifi.util.NiFiProperties; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + /** * Models a connection between connectable components. A connection may contain one or more relationships that map the source component to the destination component. */ @@ -94,6 +101,27 @@ public final class StandardConnection implements Connection { this.name.set(name); } + @Override + public Authorizable getParentAuthorizable() { + return getSource(); + } + + @Override + public Resource getResource() { + String name = getName(); + + final Collection relationships = getRelationships(); + if (name == null && CollectionUtils.isNotEmpty(relationships)) { + name = StringUtils.join(relationships.stream().map(relationship -> relationship.getName()).collect(Collectors.toSet()), ", "); + } + + if (name == null) { + name = "Connection"; + } + + return ResourceFactory.getComponentResource(ResourceType.Connection, getIdentifier(), name); + } + @Override public List getBendPoints() { return bendPoints.get(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java index b544f38812..0d168ec564 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java @@ -16,29 +16,6 @@ */ package org.apache.nifi.controller; -import static java.util.Objects.requireNonNull; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.nifi.annotation.behavior.EventDriven; @@ -53,6 +30,10 @@ import org.apache.nifi.annotation.documentation.CapabilityDescription; import org.apache.nifi.annotation.lifecycle.OnScheduled; import org.apache.nifi.annotation.lifecycle.OnStopped; import org.apache.nifi.annotation.lifecycle.OnUnscheduled; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.components.ValidationContext; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.connectable.Connectable; @@ -79,6 +60,29 @@ import org.quartz.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +import static java.util.Objects.requireNonNull; + /** * ProcessorNode provides thread-safe access to a FlowFileProcessor as it exists * within a controlled flow. This node keeps track of the processor, its @@ -194,6 +198,16 @@ public class StandardProcessorNode extends ProcessorNode implements Connectable return comments.get(); } + @Override + public Authorizable getParentAuthorizable() { + return getProcessGroup(); + } + + @Override + public Resource getResource() { + return ResourceFactory.getComponentResource(ResourceType.Processor, getIdentifier(), getName()); + } + /** * Provides and opportunity to retain information about this particular * processor instance diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java index c13dd47119..a95cb45316 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java @@ -16,16 +16,19 @@ */ package org.apache.nifi.controller.label; -import org.apache.nifi.controller.label.Label; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; +import org.apache.nifi.connectable.Position; +import org.apache.nifi.connectable.Size; +import org.apache.nifi.groups.ProcessGroup; + import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import org.apache.nifi.connectable.Position; -import org.apache.nifi.connectable.Size; -import org.apache.nifi.groups.ProcessGroup; - public class StandardLabel implements Label { private final String identifier; @@ -76,6 +79,16 @@ public class StandardLabel implements Label { return identifier; } + @Override + public Authorizable getParentAuthorizable() { + return getProcessGroup(); + } + + @Override + public Resource getResource() { + return ResourceFactory.getComponentResource(ResourceType.Label, getIdentifier(),"Label"); + } + public Map getStyle() { return style.get(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java index 06a5e3dfd0..5cb39e1a1a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/fingerprint/FingerprintFactory.java @@ -52,7 +52,7 @@ import org.apache.nifi.web.api.dto.ControllerServiceDTO; import org.apache.nifi.web.api.dto.FlowSnippetDTO; import org.apache.nifi.web.api.dto.FunnelDTO; import org.apache.nifi.web.api.dto.LabelDTO; -import org.apache.nifi.web.api.dto.NiFiComponentDTO; +import org.apache.nifi.web.api.dto.ComponentDTO; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.api.dto.ProcessorConfigDTO; @@ -321,9 +321,9 @@ public final class FingerprintFactory { } private StringBuilder addSnippetFingerprint(final StringBuilder builder, final FlowSnippetDTO snippet) { - final Comparator componentComparator = new Comparator() { + final Comparator componentComparator = new Comparator() { @Override - public int compare(final NiFiComponentDTO o1, final NiFiComponentDTO o2) { + public int compare(final ComponentDTO o1, final ComponentDTO o2) { if (o1 == null && o2 == null) { return 0; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java index db99771c3b..f06ff882dd 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java @@ -16,26 +16,16 @@ */ package org.apache.nifi.groups; -import static java.util.Objects.requireNonNull; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.nifi.annotation.lifecycle.OnRemoved; import org.apache.nifi.annotation.lifecycle.OnShutdown; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.state.StateManager; import org.apache.nifi.components.state.StateManagerProvider; @@ -66,6 +56,20 @@ import org.apache.nifi.util.ReflectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static java.util.Objects.requireNonNull; + public final class StandardProcessGroup implements ProcessGroup { private final String id; @@ -118,6 +122,16 @@ public final class StandardProcessGroup implements ProcessGroup { parent.set(newParent); } + @Override + public Authorizable getParentAuthorizable() { + return getParent(); + } + + @Override + public Resource getResource() { + return ResourceFactory.getComponentResource(ResourceType.ProcessGroup, getIdentifier(), getName()); + } + @Override public String getIdentifier() { return id; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java index 11d7b2f7f3..cdabecad9d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java @@ -16,31 +16,14 @@ */ package org.apache.nifi.remote; -import static java.util.Objects.requireNonNull; - -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import javax.net.ssl.SSLContext; -import javax.ws.rs.core.Response; - +import com.sun.jersey.api.client.ClientHandlerException; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.ClientResponse.Status; +import com.sun.jersey.api.client.UniformInterfaceException; +import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.connectable.Connection; import org.apache.nifi.connectable.Port; @@ -67,10 +50,29 @@ import org.apache.nifi.web.api.entity.ControllerEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.ClientResponse.Status; -import com.sun.jersey.api.client.UniformInterfaceException; +import javax.net.ssl.SSLContext; +import javax.ws.rs.core.Response; +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static java.util.Objects.requireNonNull; /** * Represents the Root Process Group of a remote NiFi Instance. Holds information about that remote instance, as well as {@link IncomingPort}s and {@link OutgoingPort}s for communicating with the @@ -203,6 +205,16 @@ public class StandardRemoteProcessGroup implements RemoteProcessGroup { return id; } + @Override + public Authorizable getParentAuthorizable() { + return getProcessGroup(); + } + + @Override + public Resource getResource() { + return ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, getIdentifier(), getName()); + } + @Override public ProcessGroup getProcessGroup() { return processGroup.get(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/util/SnippetUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/util/SnippetUtils.java index 1521f54d57..87bc98178b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/util/SnippetUtils.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/util/SnippetUtils.java @@ -26,7 +26,7 @@ import java.util.Map; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.FlowSnippetDTO; -import org.apache.nifi.web.api.dto.NiFiComponentDTO; +import org.apache.nifi.web.api.dto.ComponentDTO; import org.apache.nifi.web.api.dto.PositionDTO; /** @@ -50,7 +50,7 @@ public final class SnippetUtils { final Collection connections = getConnections(snippet); // get the components and their positions from the template contents - final Collection components = getComponents(snippet); + final Collection components = getComponents(snippet); // only perform the operation if there are components in this snippet if (connections.isEmpty() && components.isEmpty()) { @@ -58,7 +58,7 @@ public final class SnippetUtils { } // get the component positions from the snippet contents - final Map componentPositionLookup = getPositionLookup(components); + final Map componentPositionLookup = getPositionLookup(components); final Map> connectionPositionLookup = getConnectionPositionLookup(connections); final PositionDTO currentOrigin = getOrigin(componentPositionLookup.values(), connectionPositionLookup.values()); @@ -101,8 +101,8 @@ public final class SnippetUtils { * @param contents snippet * @return component dtos */ - private static Collection getComponents(FlowSnippetDTO contents) { - final Collection components = new HashSet<>(); + private static Collection getComponents(FlowSnippetDTO contents) { + final Collection components = new HashSet<>(); // add all components if (contents.getInputPorts() != null) { @@ -136,11 +136,11 @@ public final class SnippetUtils { * @param components components * @return component and position map */ - private static Map getPositionLookup(Collection components) { - final Map positionLookup = new HashMap<>(); + private static Map getPositionLookup(Collection components) { + final Map positionLookup = new HashMap<>(); // determine the position for each component - for (final NiFiComponentDTO component : components) { + for (final ComponentDTO component : components) { positionLookup.put(component, new PositionDTO(component.getPosition().getX(), component.getPosition().getY())); } @@ -223,9 +223,9 @@ public final class SnippetUtils { * @param componentPositionLookup lookup * @param connectionPositionLookup lookup */ - private static void applyUpdatedPositions(final Map componentPositionLookup, final Map> connectionPositionLookup) { - for (final Map.Entry entry : componentPositionLookup.entrySet()) { - final NiFiComponentDTO component = entry.getKey(); + private static void applyUpdatedPositions(final Map componentPositionLookup, final Map> connectionPositionLookup) { + for (final Map.Entry entry : componentPositionLookup.entrySet()) { + final ComponentDTO component = entry.getKey(); final PositionDTO position = entry.getValue(); component.setPosition(position); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/StandardFlowServiceTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/StandardFlowServiceTest.java index 9fb62dfe95..6e1b6c881c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/StandardFlowServiceTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/StandardFlowServiceTest.java @@ -161,7 +161,6 @@ public class StandardFlowServiceTest { return; } - assertEquals(expected.getParent(), actual.getParent()); Assert.assertEquals(expected.getComments(), actual.getComments()); assertEquals(expected.getContents(), actual.getContents()); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/state/providers/zookeeper/TestZooKeeperStateProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/state/providers/zookeeper/TestZooKeeperStateProvider.java index f8015d28fd..e174acdaff 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/state/providers/zookeeper/TestZooKeeperStateProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/state/providers/zookeeper/TestZooKeeperStateProvider.java @@ -17,12 +17,6 @@ package org.apache.nifi.controller.state.providers.zookeeper; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.net.ssl.SSLContext; - import org.apache.curator.test.TestingServer; import org.apache.nifi.attribute.expression.language.StandardPropertyValue; import org.apache.nifi.components.PropertyDescriptor; @@ -36,6 +30,11 @@ import org.junit.Before; import org.junit.Test; import org.testng.Assert; +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + public class TestZooKeeperStateProvider extends AbstractTestStateProvider { private StateProvider provider; @@ -147,7 +146,7 @@ public class TestZooKeeperStateProvider extends AbstractTestStateProvider { } catch (final StateTooLargeException stle) { // expected behavior. } catch (final Exception e) { - Assert.fail("Expected StateTooLargeException"); + Assert.fail("Expected StateTooLargeException", e); } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRemoteGroupPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRemoteGroupPort.java index 552c0c652f..b44f562ebb 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRemoteGroupPort.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRemoteGroupPort.java @@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference; import javax.net.ssl.SSLContext; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.connectable.Connection; @@ -107,6 +108,11 @@ public class StandardRemoteGroupPort extends RemoteGroupPort { return getConnectableType() == ConnectableType.REMOTE_OUTPUT_PORT; } + @Override + public Authorizable getParentAuthorizable() { + return getRemoteProcessGroup(); + } + @Override public void shutdown() { super.shutdown(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java index 5a5d1601b3..8e75cdcbea 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java @@ -21,12 +21,12 @@ import org.apache.nifi.action.Component; import org.apache.nifi.action.FlowChangeAction; import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.components.state.StateMap; import org.apache.nifi.controller.ProcessorNode; import org.apache.nifi.controller.ReportingTaskNode; import org.apache.nifi.controller.service.ControllerServiceNode; -import org.apache.nifi.user.NiFiUser; -import org.apache.nifi.web.security.user.NiFiUserUtils; +import org.apache.nifi.authorization.user.NiFiUser; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java index 4357633338..5a6c59099e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java @@ -24,8 +24,8 @@ import org.apache.nifi.action.Component; import org.apache.nifi.action.FlowChangeAction; import org.apache.nifi.action.Operation; import org.apache.nifi.action.details.FlowChangeConfigureDetails; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.web.controller.ControllerFacade; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java index af8428d494..1fb5bb7c2d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java @@ -30,13 +30,13 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.controller.ConfiguredComponent; import org.apache.nifi.controller.ProcessorNode; import org.apache.nifi.controller.ReportingTaskNode; import org.apache.nifi.controller.ScheduledState; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.controller.service.ControllerServiceNode; import org.apache.nifi.controller.service.ControllerServiceReference; import org.apache.nifi.controller.service.ControllerServiceState; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java index 40f0f340f6..7230f9ce8e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java @@ -23,9 +23,9 @@ import org.apache.nifi.action.Component; import org.apache.nifi.action.FlowChangeAction; import org.apache.nifi.action.Operation; import org.apache.nifi.action.details.ActionDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.connectable.Funnel; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.dao.FunnelDAO; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java index dff311e50e..3e5b0b57f1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java @@ -23,14 +23,14 @@ import org.apache.nifi.action.FlowChangeAction; import org.apache.nifi.action.Operation; import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.connectable.Port; import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.remote.RootGroupPort; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.dao.PortDAO; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java index 89871e6a88..04dca11870 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java @@ -26,9 +26,9 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; import org.apache.nifi.action.details.FlowChangeMoveDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.groups.ProcessGroup; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.dao.ProcessGroupDAO; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java index d6bf700def..718def0205 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java @@ -34,12 +34,12 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.controller.ProcessorNode; import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.processor.Relationship; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.ProcessorConfigDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; import org.apache.nifi.web.dao.ProcessorDAO; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java index 8a776364c3..1780790d26 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java @@ -32,6 +32,7 @@ import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.ConnectDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; import org.apache.nifi.action.details.FlowChangeConnectDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.Connection; import org.apache.nifi.connectable.Funnel; @@ -42,8 +43,7 @@ import org.apache.nifi.flowfile.FlowFilePrioritizer; import org.apache.nifi.processor.Relationship; import org.apache.nifi.remote.RemoteGroupPort; import org.apache.nifi.remote.TransferDirection; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.dao.ConnectionDAO; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java index 0495e99056..e19bf29cf6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java @@ -23,14 +23,14 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeRemoteProcessGroupDetails; import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.groups.RemoteProcessGroup; import org.apache.nifi.remote.RemoteGroupPort; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.RemoteProcessGroupContentsDTO; import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO; import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO; import org.apache.nifi.web.dao.RemoteProcessGroupDAO; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java index 77df12ae87..2e242d2f1d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java @@ -30,11 +30,11 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; import org.apache.nifi.action.details.ActionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.controller.ReportingTaskNode; import org.apache.nifi.controller.ScheduledState; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.ReportingTaskDTO; import org.apache.nifi.web.dao.ReportingTaskDAO; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java index 3fcc419c1f..b71636be3d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java @@ -26,6 +26,7 @@ import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; import org.apache.nifi.action.component.details.FlowChangeRemoteProcessGroupDetails; import org.apache.nifi.action.details.ConnectDetails; import org.apache.nifi.action.details.FlowChangeConnectDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.connectable.Connection; import org.apache.nifi.connectable.Funnel; @@ -34,7 +35,7 @@ import org.apache.nifi.controller.ProcessorNode; import org.apache.nifi.controller.Snippet; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.RemoteProcessGroup; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.web.api.dto.ConnectableDTO; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.FlowSnippetDTO; @@ -51,7 +52,6 @@ import org.apache.nifi.web.dao.ProcessGroupDAO; import org.apache.nifi.web.dao.ProcessorDAO; import org.apache.nifi.web.dao.RemoteProcessGroupDAO; import org.apache.nifi.web.dao.SnippetDAO; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java index 67f24e17d4..ba9d0ff7b0 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java @@ -34,7 +34,6 @@ import org.apache.nifi.web.api.dto.CountersDTO; import org.apache.nifi.web.api.dto.DocumentedTypeDTO; import org.apache.nifi.web.api.dto.DropRequestDTO; import org.apache.nifi.web.api.dto.FlowFileDTO; -import org.apache.nifi.web.api.dto.FlowSnippetDTO; import org.apache.nifi.web.api.dto.FunnelDTO; import org.apache.nifi.web.api.dto.LabelDTO; import org.apache.nifi.web.api.dto.ListingRequestDTO; @@ -54,6 +53,8 @@ import org.apache.nifi.web.api.dto.TemplateDTO; import org.apache.nifi.web.api.dto.action.ActionDTO; import org.apache.nifi.web.api.dto.action.HistoryDTO; import org.apache.nifi.web.api.dto.action.HistoryQueryDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO; import org.apache.nifi.web.api.dto.provenance.ProvenanceDTO; import org.apache.nifi.web.api.dto.provenance.ProvenanceEventDTO; import org.apache.nifi.web.api.dto.provenance.ProvenanceOptionsDTO; @@ -66,6 +67,13 @@ import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO; import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.StatusHistoryDTO; +import org.apache.nifi.web.api.entity.ConnectionEntity; +import org.apache.nifi.web.api.entity.FunnelEntity; +import org.apache.nifi.web.api.entity.LabelEntity; +import org.apache.nifi.web.api.entity.PortEntity; +import org.apache.nifi.web.api.entity.ProcessGroupEntity; +import org.apache.nifi.web.api.entity.ProcessorEntity; +import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; import java.util.Date; import java.util.List; @@ -318,7 +326,7 @@ public interface NiFiServiceFacade { * @param originY y * @return snapshot */ - ConfigurationSnapshot createTemplateInstance(Revision revision, String groupId, Double originX, Double originY, String templateId); + ConfigurationSnapshot createTemplateInstance(Revision revision, String groupId, Double originX, Double originY, String templateId); /** * Gets the template with the specified id. @@ -361,7 +369,7 @@ public interface NiFiServiceFacade { * @param processorDTO The processor DTO * @return The new processor DTO */ - ConfigurationSnapshot createProcessor(Revision revision, String groupId, ProcessorDTO processorDTO); + ProcessorEntity createProcessor(Revision revision, String groupId, ProcessorDTO processorDTO); /** * Gets the Processor transfer object for the specified id. @@ -369,7 +377,7 @@ public interface NiFiServiceFacade { * @param id Id of the processor to return * @return The Processor transfer object */ - ProcessorDTO getProcessor(String id); + ProcessorEntity getProcessor(String id); /** * Gets the processor status. @@ -402,7 +410,7 @@ public interface NiFiServiceFacade { * @param groupId group * @return List of all the Processor transfer object */ - Set getProcessors(String groupId); + Set getProcessors(String groupId); /** * Verifies the specified processor can be updated. @@ -418,7 +426,7 @@ public interface NiFiServiceFacade { * @param processorDTO The processorDTO * @return The updated processor */ - ConfigurationSnapshot updateProcessor(Revision revision, ProcessorDTO processorDTO); + UpdateResult updateProcessor(Revision revision, ProcessorDTO processorDTO); /** * Verifies the specified processor can be removed. @@ -434,7 +442,7 @@ public interface NiFiServiceFacade { * @param processorId The processor id to delete * @return snapshot */ - ConfigurationSnapshot deleteProcessor(Revision revision, String processorId); + ProcessorEntity deleteProcessor(Revision revision, String processorId); // ---------------------------------------- // Connections methods @@ -446,7 +454,7 @@ public interface NiFiServiceFacade { * @param groupId group * @return The Connection transfer objects */ - Set getConnections(String groupId); + Set getConnections(String groupId); /** * Gets the specified Connection transfer object. @@ -454,7 +462,7 @@ public interface NiFiServiceFacade { * @param connectionId The ID of the connection * @return The Connection transfer object */ - ConnectionDTO getConnection(String connectionId); + ConnectionEntity getConnection(String connectionId); /** * Gets the status of the specified connection. @@ -480,7 +488,7 @@ public interface NiFiServiceFacade { * @param connectionDTO The Connection DTO * @return The Connection DTO */ - ConfigurationSnapshot createConnection(Revision revision, String groupId, ConnectionDTO connectionDTO); + ConnectionEntity createConnection(Revision revision, String groupId, ConnectionDTO connectionDTO); /** * Determines if this connection can be listed. @@ -511,7 +519,7 @@ public interface NiFiServiceFacade { * @param connectionDTO The Connection DTO * @return The Connection DTO */ - ConfigurationSnapshot updateConnection(Revision revision, ConnectionDTO connectionDTO); + UpdateResult updateConnection(Revision revision, ConnectionDTO connectionDTO); /** * Determines if this connection can be removed. @@ -527,7 +535,7 @@ public interface NiFiServiceFacade { * @param connectionId The ID of the connection * @return snapshot */ - ConfigurationSnapshot deleteConnection(Revision revision, String connectionId); + ConnectionEntity deleteConnection(Revision revision, String connectionId); /** * Creates a new flow file drop request. @@ -603,7 +611,7 @@ public interface NiFiServiceFacade { * @param inputPortDTO The input PortDTO * @return snapshot */ - ConfigurationSnapshot createInputPort(Revision revision, String groupId, PortDTO inputPortDTO); + PortEntity createInputPort(Revision revision, String groupId, PortDTO inputPortDTO); /** * Gets an input port. @@ -611,7 +619,7 @@ public interface NiFiServiceFacade { * @param inputPortId The input port id * @return port */ - PortDTO getInputPort(String inputPortId); + PortEntity getInputPort(String inputPortId); /** * Gets all input ports in a given group. @@ -619,7 +627,7 @@ public interface NiFiServiceFacade { * @param groupId The id of the group * @return port */ - Set getInputPorts(String groupId); + Set getInputPorts(String groupId); /** * Gets the input port status. @@ -643,7 +651,7 @@ public interface NiFiServiceFacade { * @param inputPortDTO The input PortDTO * @return snapshort */ - ConfigurationSnapshot updateInputPort(Revision revision, PortDTO inputPortDTO); + UpdateResult updateInputPort(Revision revision, PortDTO inputPortDTO); /** * Determines if the input port could be deleted. @@ -659,7 +667,7 @@ public interface NiFiServiceFacade { * @param inputPortId The id of the input port * @return snapshot */ - ConfigurationSnapshot deleteInputPort(Revision revision, String inputPortId); + PortEntity deleteInputPort(Revision revision, String inputPortId); // ---------------------------------------- // OutputPort methods @@ -672,7 +680,7 @@ public interface NiFiServiceFacade { * @param outputPortDTO The output PortDTO * @return snapshot */ - ConfigurationSnapshot createOutputPort(Revision revision, String groupId, PortDTO outputPortDTO); + PortEntity createOutputPort(Revision revision, String groupId, PortDTO outputPortDTO); /** * Gets an output port. @@ -680,7 +688,7 @@ public interface NiFiServiceFacade { * @param outputPortId The output port id * @return port */ - PortDTO getOutputPort(String outputPortId); + PortEntity getOutputPort(String outputPortId); /** * Gets all output ports in a given group. @@ -688,7 +696,7 @@ public interface NiFiServiceFacade { * @param groupId The id of the group * @return ports */ - Set getOutputPorts(String groupId); + Set getOutputPorts(String groupId); /** * Gets the output port status. @@ -712,7 +720,7 @@ public interface NiFiServiceFacade { * @param outputPortDTO The output PortDTO * @return snapshot */ - ConfigurationSnapshot updateOutputPort(Revision revision, PortDTO outputPortDTO); + UpdateResult updateOutputPort(Revision revision, PortDTO outputPortDTO); /** * Determines if the output port could be deleted. @@ -728,7 +736,19 @@ public interface NiFiServiceFacade { * @param outputPortId The id of the output port * @return snapshot */ - ConfigurationSnapshot deleteOutputPort(Revision revision, String outputPortId); + PortEntity deleteOutputPort(Revision revision, String outputPortId); + + // ---------------------------------------- + // Flow methods + // ---------------------------------------- + /** + * Returns the flow. + * + * @param groupId group + * @param recurse recurse + * @return the flow + */ + ConfigurationSnapshot getProcessGroupFlow(String groupId, boolean recurse); // ---------------------------------------- // ProcessGroup methods @@ -741,16 +761,15 @@ public interface NiFiServiceFacade { * @param processGroupDTO The ProcessGroupDTO * @return snapshot */ - ConfigurationSnapshot createProcessGroup(String parentGroupId, Revision revision, ProcessGroupDTO processGroupDTO); + ProcessGroupEntity createProcessGroup(String parentGroupId, Revision revision, ProcessGroupDTO processGroupDTO); /** * Returns the process group. * * @param groupId group - * @param recurse recurse * @return ProcessGroup transfer object */ - ConfigurationSnapshot getProcessGroup(String groupId, boolean recurse); + ProcessGroupEntity getProcessGroup(String groupId); /** * Gets all process groups in the specified parent group. @@ -758,7 +777,7 @@ public interface NiFiServiceFacade { * @param parentGroupId The id of the parent group * @return process group */ - Set getProcessGroups(String parentGroupId); + Set getProcessGroups(String parentGroupId); /** * Verifies the specified process group can be updated. @@ -774,7 +793,7 @@ public interface NiFiServiceFacade { * @param processGroupDTO The ProcessGroupDTO * @return snapshot */ - ConfigurationSnapshot updateProcessGroup(Revision revision, ProcessGroupDTO processGroupDTO); + UpdateResult updateProcessGroup(Revision revision, ProcessGroupDTO processGroupDTO); /** * Verifies the specified process group can be removed. @@ -790,7 +809,7 @@ public interface NiFiServiceFacade { * @param groupId The id of the process group * @return snapshot */ - ConfigurationSnapshot deleteProcessGroup(Revision revision, String groupId); + ProcessGroupEntity deleteProcessGroup(Revision revision, String groupId); // ---------------------------------------- // RemoteProcessGroup methods @@ -803,7 +822,7 @@ public interface NiFiServiceFacade { * @param remoteProcessGroupDTO The RemoteProcessGroupDTO * @return snapshot */ - ConfigurationSnapshot createRemoteProcessGroup(Revision revision, String groupId, RemoteProcessGroupDTO remoteProcessGroupDTO); + RemoteProcessGroupEntity createRemoteProcessGroup(Revision revision, String groupId, RemoteProcessGroupDTO remoteProcessGroupDTO); /** * Gets a remote process group. @@ -811,7 +830,7 @@ public interface NiFiServiceFacade { * @param remoteProcessGroupId The id of the remote process group * @return group */ - RemoteProcessGroupDTO getRemoteProcessGroup(String remoteProcessGroupId); + RemoteProcessGroupEntity getRemoteProcessGroup(String remoteProcessGroupId); /** * Gets all remote process groups in the a given parent group. @@ -819,7 +838,7 @@ public interface NiFiServiceFacade { * @param groupId The id of the parent group * @return group */ - Set getRemoteProcessGroups(String groupId); + Set getRemoteProcessGroups(String groupId); /** * Gets the remote process group status. @@ -867,7 +886,7 @@ public interface NiFiServiceFacade { * @param remoteProcessGroupDTO The RemoteProcessGroupDTO * @return snapshot */ - ConfigurationSnapshot updateRemoteProcessGroup(Revision revision, RemoteProcessGroupDTO remoteProcessGroupDTO); + UpdateResult updateRemoteProcessGroup(Revision revision, RemoteProcessGroupDTO remoteProcessGroupDTO); /** * Updates the specified remote process groups input port. @@ -903,7 +922,7 @@ public interface NiFiServiceFacade { * @param remoteProcessGroupId The id of the remote process group * @return snapshot */ - ConfigurationSnapshot deleteRemoteProcessGroup(Revision revision, String remoteProcessGroupId); + RemoteProcessGroupEntity deleteRemoteProcessGroup(Revision revision, String remoteProcessGroupId); // ---------------------------------------- // Funnel methods @@ -916,7 +935,7 @@ public interface NiFiServiceFacade { * @param funnelDTO funnel * @return The funnel DTO */ - ConfigurationSnapshot createFunnel(Revision revision, String groupId, FunnelDTO funnelDTO); + FunnelEntity createFunnel(Revision revision, String groupId, FunnelDTO funnelDTO); /** * Gets the specified funnel. @@ -924,7 +943,7 @@ public interface NiFiServiceFacade { * @param funnelId The funnel id * @return The funnel transfer object */ - FunnelDTO getFunnel(String funnelId); + FunnelEntity getFunnel(String funnelId); /** * Gets all of the funnels. @@ -932,7 +951,7 @@ public interface NiFiServiceFacade { * @param groupId group * @return The funnel transfer objects */ - Set getFunnels(String groupId); + Set getFunnels(String groupId); /** * Updates the specified label. @@ -941,7 +960,7 @@ public interface NiFiServiceFacade { * @param funnelDTO The funnel DTO * @return The funnel DTO */ - ConfigurationSnapshot updateFunnel(Revision revision, FunnelDTO funnelDTO); + UpdateResult updateFunnel(Revision revision, FunnelDTO funnelDTO); /** * Verifies the specified funnel can be deleted. @@ -957,7 +976,7 @@ public interface NiFiServiceFacade { * @param funnelId The funnel id * @return snapshot */ - ConfigurationSnapshot deleteFunnel(Revision revision, String funnelId); + FunnelEntity deleteFunnel(Revision revision, String funnelId); // ---------------------------------------- // Component state methods @@ -1046,7 +1065,7 @@ public interface NiFiServiceFacade { * @param labelDTO The label DTO * @return The label DTO */ - ConfigurationSnapshot createLabel(Revision revision, String groupId, LabelDTO labelDTO); + LabelEntity createLabel(Revision revision, String groupId, LabelDTO labelDTO); /** * Gets the specified label. @@ -1054,7 +1073,7 @@ public interface NiFiServiceFacade { * @param labelId The label id * @return The label transfer object */ - LabelDTO getLabel(String labelId); + LabelEntity getLabel(String labelId); /** * Gets all of the labels. @@ -1062,7 +1081,7 @@ public interface NiFiServiceFacade { * @param groupId group * @return The label transfer objects */ - Set getLabels(String groupId); + Set getLabels(String groupId); /** * Updates the specified label. @@ -1071,7 +1090,7 @@ public interface NiFiServiceFacade { * @param labelDTO The label DTO * @return The label DTO */ - ConfigurationSnapshot updateLabel(Revision revision, LabelDTO labelDTO); + UpdateResult updateLabel(Revision revision, LabelDTO labelDTO); /** * Deletes the specified label. @@ -1080,7 +1099,7 @@ public interface NiFiServiceFacade { * @param labelId The label id * @return snapshot */ - ConfigurationSnapshot deleteLabel(Revision revision, String labelId); + LabelEntity deleteLabel(Revision revision, String labelId); // ---------------------------------------- // Controller Services methods @@ -1294,7 +1313,7 @@ public interface NiFiServiceFacade { * @param originY y * @return snapshot */ - ConfigurationSnapshot copySnippet(Revision revision, String groupId, String snippetId, Double originX, Double originY); + ConfigurationSnapshot copySnippet(Revision revision, String groupId, String snippetId, Double originX, Double originY); /** * Creates a new snippet. diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java index 58b0af85b3..51fa7a2ebe 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.context.annotation.ImportResource; @Import({NiFiWebApiSecurityConfiguration.class}) @ImportResource({"classpath:nifi-context.xml", "classpath:nifi-administration-context.xml", + "classpath:nifi-framework-authorization-context.xml", "classpath:nifi-cluster-manager-context.xml", "classpath:nifi-cluster-protocol-context.xml", "classpath:nifi-web-security-context.xml", diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java index 66f1546878..36db1d9202 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java @@ -20,6 +20,8 @@ import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse.Status; import com.sun.jersey.core.util.MultivaluedMapImpl; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.AccessDeniedException; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.cluster.manager.NodeResponse; import org.apache.nifi.cluster.manager.exception.UnknownNodeException; import org.apache.nifi.cluster.manager.impl.WebClusterManager; @@ -27,11 +29,9 @@ import org.apache.nifi.cluster.node.Node; import org.apache.nifi.cluster.protocol.NodeIdentifier; import org.apache.nifi.controller.repository.claim.ContentDirection; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.apache.nifi.web.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index dae1ab69ec..b85c15dc05 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -24,7 +24,12 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.details.FlowChangePurgeDetails; import org.apache.nifi.admin.service.AuditService; import org.apache.nifi.admin.service.KeyService; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.context.ClusterContext; import org.apache.nifi.cluster.context.ClusterContextThreadLocal; import org.apache.nifi.cluster.coordination.heartbeat.NodeHeartbeat; @@ -62,13 +67,14 @@ import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.reporting.Bulletin; import org.apache.nifi.reporting.BulletinQuery; import org.apache.nifi.reporting.BulletinRepository; -import org.apache.nifi.user.NiFiUser; import org.apache.nifi.util.FormatUtils; import org.apache.nifi.util.NiFiProperties; +import org.apache.nifi.web.api.dto.AccessPolicyDTO; import org.apache.nifi.web.api.dto.BulletinBoardDTO; import org.apache.nifi.web.api.dto.BulletinDTO; import org.apache.nifi.web.api.dto.BulletinQueryDTO; import org.apache.nifi.web.api.dto.ClusterDTO; +import org.apache.nifi.web.api.dto.ComponentDTO; import org.apache.nifi.web.api.dto.ComponentHistoryDTO; import org.apache.nifi.web.api.dto.ComponentStateDTO; import org.apache.nifi.web.api.dto.ConnectionDTO; @@ -82,12 +88,12 @@ import org.apache.nifi.web.api.dto.CountersSnapshotDTO; import org.apache.nifi.web.api.dto.DocumentedTypeDTO; import org.apache.nifi.web.api.dto.DropRequestDTO; import org.apache.nifi.web.api.dto.DtoFactory; +import org.apache.nifi.web.api.dto.EntityFactory; import org.apache.nifi.web.api.dto.FlowFileDTO; import org.apache.nifi.web.api.dto.FlowSnippetDTO; import org.apache.nifi.web.api.dto.FunnelDTO; import org.apache.nifi.web.api.dto.LabelDTO; import org.apache.nifi.web.api.dto.ListingRequestDTO; -import org.apache.nifi.web.api.dto.NiFiComponentDTO; import org.apache.nifi.web.api.dto.NodeDTO; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.api.dto.PreviousValueDTO; @@ -107,6 +113,8 @@ import org.apache.nifi.web.api.dto.TemplateDTO; import org.apache.nifi.web.api.dto.action.ActionDTO; import org.apache.nifi.web.api.dto.action.HistoryDTO; import org.apache.nifi.web.api.dto.action.HistoryQueryDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO; import org.apache.nifi.web.api.dto.provenance.ProvenanceDTO; import org.apache.nifi.web.api.dto.provenance.ProvenanceEventDTO; import org.apache.nifi.web.api.dto.provenance.ProvenanceOptionsDTO; @@ -119,6 +127,13 @@ import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO; import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.StatusHistoryDTO; +import org.apache.nifi.web.api.entity.ConnectionEntity; +import org.apache.nifi.web.api.entity.FunnelEntity; +import org.apache.nifi.web.api.entity.LabelEntity; +import org.apache.nifi.web.api.entity.PortEntity; +import org.apache.nifi.web.api.entity.ProcessGroupEntity; +import org.apache.nifi.web.api.entity.ProcessorEntity; +import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; import org.apache.nifi.web.controller.ControllerFacade; import org.apache.nifi.web.dao.ConnectionDAO; import org.apache.nifi.web.dao.ControllerServiceDAO; @@ -131,7 +146,6 @@ import org.apache.nifi.web.dao.RemoteProcessGroupDAO; import org.apache.nifi.web.dao.ReportingTaskDAO; import org.apache.nifi.web.dao.SnippetDAO; import org.apache.nifi.web.dao.TemplateDAO; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.apache.nifi.web.util.SnippetUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -192,6 +206,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { // properties private NiFiProperties properties; private DtoFactory dtoFactory; + private EntityFactory entityFactory; + + private Authorizer authorizer; // ----------------------------------------- // Verification Operations @@ -345,43 +362,73 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { // Write Operations // ----------------------------------------- @Override - public ConfigurationSnapshot updateConnection(final Revision revision, final ConnectionDTO connectionDTO) { + public UpdateResult updateConnection(final Revision revision, final ConnectionDTO connectionDTO) { // if connection does not exist, then create new connection if (connectionDAO.hasConnection(connectionDTO.getId()) == false) { - return createConnection(revision, connectionDTO.getParentGroupId(), connectionDTO); + return new UpdateResult<>(createConnection(revision, connectionDTO.getParentGroupId(), connectionDTO), true); } - return updateComponent(revision, () -> connectionDAO.updateConnection(connectionDTO), connection -> dtoFactory.createConnectionDto(connection)); + final Connection connectionNode = connectionDAO.getConnection(connectionDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent( + revision, + connectionNode, + () -> connectionDAO.updateConnection(connectionDTO), + connection -> dtoFactory.createConnectionDto(connection)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(connectionNode); + return new UpdateResult<>(entityFactory.createConnectionEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy), false); } @Override - public ConfigurationSnapshot updateProcessor(final Revision revision, final ProcessorDTO processorDTO) { + public UpdateResult updateProcessor(final Revision revision, final ProcessorDTO processorDTO) { // if processor does not exist, then create new processor if (processorDAO.hasProcessor(processorDTO.getId()) == false) { - return createProcessor(revision, processorDTO.getParentGroupId(), processorDTO); + return new UpdateResult<>(createProcessor(revision, processorDTO.getParentGroupId(), processorDTO), true); } - return updateComponent(revision, () -> processorDAO.updateProcessor(processorDTO), proc -> dtoFactory.createProcessorDto(proc)); + // get the component, ensure we have access to it, and perform the update request + final ProcessorNode processorNode = processorDAO.getProcessor(processorDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent(revision, + processorNode, + () -> processorDAO.updateProcessor(processorDTO), + proc -> dtoFactory.createProcessorDto(proc)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(processorNode); + return new UpdateResult<>(entityFactory.createProcessorEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy), false); } @Override - public ConfigurationSnapshot updateLabel(final Revision revision, final LabelDTO labelDTO) { + public UpdateResult updateLabel(final Revision revision, final LabelDTO labelDTO) { // if label does not exist, then create new label if (labelDAO.hasLabel(labelDTO.getId()) == false) { - return createLabel(revision, labelDTO.getParentGroupId(), labelDTO); + return new UpdateResult<>(createLabel(revision, labelDTO.getParentGroupId(), labelDTO), false); } - return updateComponent(revision, () -> labelDAO.updateLabel(labelDTO), label -> dtoFactory.createLabelDto(label)); + final Label labelNode = labelDAO.getLabel(labelDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent(revision, + labelNode, + () -> labelDAO.updateLabel(labelDTO), + label -> dtoFactory.createLabelDto(label)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(labelNode); + return new UpdateResult<>(entityFactory.createLabelEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy), false); } @Override - public ConfigurationSnapshot updateFunnel(final Revision revision, final FunnelDTO funnelDTO) { + public UpdateResult updateFunnel(final Revision revision, final FunnelDTO funnelDTO) { // if label does not exist, then create new label if (funnelDAO.hasFunnel(funnelDTO.getId()) == false) { - return createFunnel(revision, funnelDTO.getParentGroupId(), funnelDTO); + return new UpdateResult<>(createFunnel(revision, funnelDTO.getParentGroupId(), funnelDTO), true); } - return updateComponent(revision, () -> funnelDAO.updateFunnel(funnelDTO), funnel -> dtoFactory.createFunnelDto(funnel)); + final Funnel funnelNode = funnelDAO.getFunnel(funnelDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent(revision, + funnelNode, + () -> funnelDAO.updateFunnel(funnelDTO), + funnel -> dtoFactory.createFunnelDto(funnel)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(funnelNode); + return new UpdateResult<>(entityFactory.createFunnelEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy), false); } @@ -398,10 +445,18 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { * * @return A ConfigurationSnapshot that represents the new configuration */ - private ConfigurationSnapshot updateComponent(final Revision revision, final Supplier daoUpdate, final Function dtoCreation) { + private ConfigurationSnapshot updateComponent(final Revision revision, final Authorizable authorizable, final Supplier daoUpdate, final Function + dtoCreation) { return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { @Override public ConfigurationResult execute() { + // ensure write access to the flow + authorizable.authorize(authorizer, RequestAction.WRITE); + + // also ensure read access to the flow as the component must be read in order to generate a response + authorizable.authorize(authorizer, RequestAction.READ); + + // get the updated component final C component = daoUpdate.get(); // save updated controller @@ -439,52 +494,77 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { return createSnippet(revision, snippetDto); } - return updateComponent(revision, + final ProcessGroup processGroup = processGroupDAO.getProcessGroup(snippetDto.getParentGroupId()); + return updateComponent( + revision, + processGroup, () -> snippetDAO.updateSnippet(snippetDto), snippet -> { - final SnippetDTO responseSnippetDto = dtoFactory.createSnippetDto(snippet); - responseSnippetDto.setContents(snippetUtils.populateFlowSnippet(snippet, false, false)); - return responseSnippetDto; + return dtoFactory.createSnippetDto(snippet); }); } @Override - public ConfigurationSnapshot updateInputPort(final Revision revision, final PortDTO inputPortDTO) { + public UpdateResult updateInputPort(final Revision revision, final PortDTO inputPortDTO) { // if input port does not exist, then create new input port if (inputPortDAO.hasPort(inputPortDTO.getId()) == false) { - return createInputPort(revision, inputPortDTO.getParentGroupId(), inputPortDTO); + return new UpdateResult<>(createInputPort(revision, inputPortDTO.getParentGroupId(), inputPortDTO), true); } - return updateComponent(revision, () -> inputPortDAO.updatePort(inputPortDTO), port -> dtoFactory.createPortDto(port)); + final Port inputPortNode = inputPortDAO.getPort(inputPortDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent(revision, + inputPortNode, + () -> inputPortDAO.updatePort(inputPortDTO), + port -> dtoFactory.createPortDto(port)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(inputPortNode); + return new UpdateResult<>(entityFactory.createPortEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy), false); } @Override - public ConfigurationSnapshot updateOutputPort(final Revision revision, final PortDTO outputPortDTO) { + public UpdateResult updateOutputPort(final Revision revision, final PortDTO outputPortDTO) { // if output port does not exist, then create new output port if (outputPortDAO.hasPort(outputPortDTO.getId()) == false) { - return createOutputPort(revision, outputPortDTO.getParentGroupId(), outputPortDTO); + return new UpdateResult<>(createOutputPort(revision, outputPortDTO.getParentGroupId(), outputPortDTO), true); } - return updateComponent(revision, () -> outputPortDAO.updatePort(outputPortDTO), port -> dtoFactory.createPortDto(port)); + final Port outputPortNode = outputPortDAO.getPort(outputPortDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent(revision, + outputPortNode, + () -> outputPortDAO.updatePort(outputPortDTO), + port -> dtoFactory.createPortDto(port)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(outputPortNode); + return new UpdateResult<>(entityFactory.createPortEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy), false); } @Override - public ConfigurationSnapshot updateRemoteProcessGroup(final Revision revision, final RemoteProcessGroupDTO remoteProcessGroupDTO) { + public UpdateResult updateRemoteProcessGroup(final Revision revision, final RemoteProcessGroupDTO remoteProcessGroupDTO) { // if controller reference does not exist, then create new controller reference if (remoteProcessGroupDAO.hasRemoteProcessGroup(remoteProcessGroupDTO.getId()) == false) { - return createRemoteProcessGroup(revision, remoteProcessGroupDTO.getParentGroupId(), remoteProcessGroupDTO); + return new UpdateResult<>(createRemoteProcessGroup(revision, remoteProcessGroupDTO.getParentGroupId(), remoteProcessGroupDTO), true); } - return updateComponent(revision, + final RemoteProcessGroup remoteProcessGroupNode = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent( + revision, + remoteProcessGroupNode, () -> remoteProcessGroupDAO.updateRemoteProcessGroup(remoteProcessGroupDTO), remoteProcessGroup -> dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(remoteProcessGroupNode); + final RevisionDTO updateRevision = dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()); + return new UpdateResult<>(entityFactory.createRemoteProcessGroupEntity(snapshot.getConfiguration(), updateRevision, accessPolicy), false); } @Override public ConfigurationSnapshot updateRemoteProcessGroupInputPort( final Revision revision, final String remoteProcessGroupId, final RemoteProcessGroupPortDTO remoteProcessGroupPortDTO) { - return updateComponent(revision, + final RemoteProcessGroup remoteProcessGroupNode = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupPortDTO.getGroupId()); + return updateComponent( + revision, + remoteProcessGroupNode, () -> remoteProcessGroupDAO.updateRemoteProcessGroupInputPort(remoteProcessGroupId, remoteProcessGroupPortDTO), remoteGroupPort -> dtoFactory.createRemoteProcessGroupPortDto(remoteGroupPort)); } @@ -493,28 +573,42 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { public ConfigurationSnapshot updateRemoteProcessGroupOutputPort( final Revision revision, final String remoteProcessGroupId, final RemoteProcessGroupPortDTO remoteProcessGroupPortDTO) { - return updateComponent(revision, + final RemoteProcessGroup remoteProcessGroupNode = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupPortDTO.getGroupId()); + return updateComponent( + revision, + remoteProcessGroupNode, () -> remoteProcessGroupDAO.updateRemoteProcessGroupOutputPort(remoteProcessGroupId, remoteProcessGroupPortDTO), remoteGroupPort -> dtoFactory.createRemoteProcessGroupPortDto(remoteGroupPort)); } @Override - public ConfigurationSnapshot updateProcessGroup(final Revision revision, final ProcessGroupDTO processGroupDTO) { + public UpdateResult updateProcessGroup(final Revision revision, final ProcessGroupDTO processGroupDTO) { // if process group does not exist, then create new process group if (processGroupDAO.hasProcessGroup(processGroupDTO.getId()) == false) { if (processGroupDTO.getParentGroupId() == null) { throw new IllegalArgumentException("Unable to create the specified process group since the parent group was not specified."); } else { - return createProcessGroup(processGroupDTO.getParentGroupId(), revision, processGroupDTO); + return new UpdateResult<>(createProcessGroup(processGroupDTO.getParentGroupId(), revision, processGroupDTO), true); } } - return updateComponent(revision, () -> processGroupDAO.updateProcessGroup(processGroupDTO), processGroup -> dtoFactory.createProcessGroupDto(processGroup)); + final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(processGroupDTO.getId()); + final ConfigurationSnapshot snapshot = updateComponent(revision, + processGroupNode, + () -> processGroupDAO.updateProcessGroup(processGroupDTO), + processGroup -> dtoFactory.createProcessGroupDto(processGroup)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(processGroupNode); + final RevisionDTO updatedRevision = dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()); + return new UpdateResult<>(entityFactory.createProcessGroupEntity(snapshot.getConfiguration(), updatedRevision, accessPolicy), false); } @Override public ConfigurationSnapshot updateControllerConfiguration(final Revision revision, final ControllerConfigurationDTO controllerConfigurationDTO) { - return updateComponent(revision, + + return updateComponent( + revision, + controllerFacade, () -> { // update the controller configuration through the proxy if (controllerConfigurationDTO.getName() != null) { @@ -611,21 +705,33 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot deleteConnection(final Revision revision, final String connectionId) { - return deleteComponent(revision, () -> connectionDAO.deleteConnection(connectionId)); + public ConnectionEntity deleteConnection(final Revision revision, final String connectionId) { + final Connection connection = connectionDAO.getConnection(connectionId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + connection, + () -> connectionDAO.deleteConnection(connectionId)); + + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(connection); + return entityFactory.createConnectionEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override public DropRequestDTO deleteFlowFileDropRequest(String connectionId, String dropRequestId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); + return dtoFactory.createDropRequestDTO(connectionDAO.deleteFlowFileDropRequest(connectionId, dropRequestId)); } @Override public ListingRequestDTO deleteFlowFileListingRequest(String connectionId, String listingRequestId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); + final ListingRequestDTO listRequest = dtoFactory.createListingRequestDTO(connectionDAO.deleteFlowFileListingRequest(connectionId, listingRequestId)); // include whether the source and destination are running - final Connection connection = connectionDAO.getConnection(connectionId); if (connection.getSource() != null) { listRequest.setSourceRunning(connection.getSource().isRunning()); } @@ -637,18 +743,36 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot deleteProcessor(final Revision revision, final String processorId) { - return deleteComponent(revision, () -> processorDAO.deleteProcessor(processorId)); + public ProcessorEntity deleteProcessor(final Revision revision, final String processorId) { + final ProcessorNode processor = processorDAO.getProcessor(processorId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + processor, + () -> processorDAO.deleteProcessor(processorId)); + + return entityFactory.createProcessorEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } @Override - public ConfigurationSnapshot deleteLabel(final Revision revision, final String labelId) { - return deleteComponent(revision, () -> labelDAO.deleteLabel(labelId)); + public LabelEntity deleteLabel(final Revision revision, final String labelId) { + final Label label = labelDAO.getLabel(labelId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + label, + () -> labelDAO.deleteLabel(labelId)); + + return entityFactory.createLabelEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } @Override - public ConfigurationSnapshot deleteFunnel(final Revision revision, final String funnelId) { - return deleteComponent(revision, () -> funnelDAO.deleteFunnel(funnelId)); + public FunnelEntity deleteFunnel(final Revision revision, final String funnelId) { + final Funnel funnel = funnelDAO.getFunnel(funnelId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + funnel, + () -> funnelDAO.deleteFunnel(funnelId)); + + return entityFactory.createFunnelEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } /** @@ -658,10 +782,13 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { * @param action the action that deletes the component via the appropriate DAO object * @return a ConfigurationSnapshot that represents the new configuration */ - private ConfigurationSnapshot deleteComponent(final Revision revision, final Runnable action) { + private ConfigurationSnapshot deleteComponent(final Revision revision, final Authorizable authorizable, final Runnable action) { return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { @Override public ConfigurationResult execute() { + // ensure access to the component + authorizable.authorize(authorizer, RequestAction.WRITE); + action.run(); // save the flow @@ -688,27 +815,55 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override public ConfigurationSnapshot deleteSnippet(final Revision revision, final String snippetId) { - return deleteComponent(revision, () -> snippetDAO.deleteSnippet(snippetId)); + final Snippet snippet = snippetDAO.getSnippet(snippetId); + final ProcessGroup processGroup = processGroupDAO.getProcessGroup(snippet.getParentGroupId()); + return deleteComponent(revision, + processGroup, + () -> snippetDAO.deleteSnippet(snippetId)); } @Override - public ConfigurationSnapshot deleteInputPort(final Revision revision, final String inputPortId) { - return deleteComponent(revision, () -> inputPortDAO.deletePort(inputPortId)); + public PortEntity deleteInputPort(final Revision revision, final String inputPortId) { + final Port port = inputPortDAO.getPort(inputPortId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + port, + () -> inputPortDAO.deletePort(inputPortId)); + + return entityFactory.createPortEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } @Override - public ConfigurationSnapshot deleteOutputPort(final Revision revision, final String outputPortId) { - return deleteComponent(revision, () -> outputPortDAO.deletePort(outputPortId)); + public PortEntity deleteOutputPort(final Revision revision, final String outputPortId) { + final Port port = outputPortDAO.getPort(outputPortId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + port, + () -> outputPortDAO.deletePort(outputPortId)); + + return entityFactory.createPortEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } @Override - public ConfigurationSnapshot deleteProcessGroup(final Revision revision, final String groupId) { - return deleteComponent(revision, () -> processGroupDAO.deleteProcessGroup(groupId)); + public ProcessGroupEntity deleteProcessGroup(final Revision revision, final String groupId) { + final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + processGroup, + () -> processGroupDAO.deleteProcessGroup(groupId)); + + return entityFactory.createProcessGroupEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } @Override - public ConfigurationSnapshot deleteRemoteProcessGroup(final Revision revision, final String remoteProcessGroupId) { - return deleteComponent(revision, () -> remoteProcessGroupDAO.deleteRemoteProcessGroup(remoteProcessGroupId)); + public RemoteProcessGroupEntity deleteRemoteProcessGroup(final Revision revision, final String remoteProcessGroupId) { + final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId); + final ConfigurationSnapshot snapshot = deleteComponent( + revision, + remoteProcessGroup, + () -> remoteProcessGroupDAO.deleteRemoteProcessGroup(remoteProcessGroupId)); + + return entityFactory.createRemoteProcessGroupEntity(null, dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), null); } @Override @@ -718,21 +873,34 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot createConnection(final Revision revision, final String groupId, final ConnectionDTO connectionDTO) { - return createComponent(revision, connectionDTO, () -> connectionDAO.createConnection(groupId, connectionDTO), connection -> dtoFactory.createConnectionDto(connection)); + public ConnectionEntity createConnection(final Revision revision, final String groupId, final ConnectionDTO connectionDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + connectionDTO, + () -> connectionDAO.createConnection(groupId, connectionDTO), + connection -> dtoFactory.createConnectionDto(connection)); + + final Connection connection = connectionDAO.getConnection(connectionDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(connection); + return entityFactory.createConnectionEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override public DropRequestDTO createFlowFileDropRequest(String connectionId, String dropRequestId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); return dtoFactory.createDropRequestDTO(connectionDAO.createFlowFileDropRequest(connectionId, dropRequestId)); } @Override public ListingRequestDTO createFlowFileListingRequest(String connectionId, String listingRequestId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); + + // create the listing request final ListingRequestDTO listRequest = dtoFactory.createListingRequestDTO(connectionDAO.createFlowFileListingRequest(connectionId, listingRequestId)); // include whether the source and destination are running - final Connection connection = connectionDAO.getConnection(connectionId); if (connection.getSource() != null) { listRequest.setSourceRunning(connection.getSource().isRunning()); } @@ -744,13 +912,29 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot createProcessor(final Revision revision, final String groupId, final ProcessorDTO processorDTO) { - return createComponent(revision, processorDTO, () -> processorDAO.createProcessor(groupId, processorDTO), processor -> dtoFactory.createProcessorDto(processor)); + public ProcessorEntity createProcessor(final Revision revision, final String groupId, final ProcessorDTO processorDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + processorDTO, + () -> processorDAO.createProcessor(groupId, processorDTO), + processor -> dtoFactory.createProcessorDto(processor)); + + final ProcessorNode processor = processorDAO.getProcessor(processorDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(processor); + return entityFactory.createProcessorEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override - public ConfigurationSnapshot createLabel(final Revision revision, final String groupId, final LabelDTO labelDTO) { - return createComponent(revision, labelDTO, () -> labelDAO.createLabel(groupId, labelDTO), label -> dtoFactory.createLabelDto(label)); + public LabelEntity createLabel(final Revision revision, final String groupId, final LabelDTO labelDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + labelDTO, + () -> labelDAO.createLabel(groupId, labelDTO), + label -> dtoFactory.createLabelDto(label)); + + final Label label = labelDAO.getLabel(labelDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(label); + return entityFactory.createLabelEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } /** @@ -766,7 +950,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { * * @return a ConfigurationSnapshot that represents the updated configuration */ - private ConfigurationSnapshot createComponent(final Revision revision, final NiFiComponentDTO componentDto, + private ConfigurationSnapshot createComponent(final Revision revision, final ComponentDTO componentDto, final Supplier daoCreation, final Function dtoCreation) { return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { @@ -777,6 +961,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { componentDto.setId(UUID.randomUUID().toString()); } + // ensure access to process group + final ProcessGroup parent = processGroupDAO.getProcessGroup(componentDto.getParentGroupId()); + parent.authorize(authorizer, RequestAction.WRITE); + // add the component final C component = daoCreation.get(); @@ -801,14 +989,22 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override - public ConfigurationSnapshot createFunnel(final Revision revision, final String groupId, final FunnelDTO funnelDTO) { - return createComponent(revision, funnelDTO, () -> funnelDAO.createFunnel(groupId, funnelDTO), funnel -> dtoFactory.createFunnelDto(funnel)); + public FunnelEntity createFunnel(final Revision revision, final String groupId, final FunnelDTO funnelDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + funnelDTO, + () -> funnelDAO.createFunnel(groupId, funnelDTO), + funnel -> dtoFactory.createFunnelDto(funnel)); + + final Funnel funnel = funnelDAO.getFunnel(funnelDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(funnel); + return entityFactory.createFunnelEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } - private void validateSnippetContents(final FlowSnippetDTO flowSnippet) { + private void validateSnippetContents(final FlowSnippetDTO flow) { // validate any processors - if (flowSnippet.getProcessors() != null) { - for (final ProcessorDTO processorDTO : flowSnippet.getProcessors()) { + if (flow.getProcessors() != null) { + for (final ProcessorDTO processorDTO : flow.getProcessors()) { final ProcessorNode processorNode = processorDAO.getProcessor(processorDTO.getId()); final Collection validationErrors = processorNode.getValidationErrors(); if (validationErrors != null && !validationErrors.isEmpty()) { @@ -821,8 +1017,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } } - if (flowSnippet.getInputPorts() != null) { - for (final PortDTO portDTO : flowSnippet.getInputPorts()) { + if (flow.getInputPorts() != null) { + for (final PortDTO portDTO : flow.getInputPorts()) { final Port port = inputPortDAO.getPort(portDTO.getId()); final Collection validationErrors = port.getValidationErrors(); if (validationErrors != null && !validationErrors.isEmpty()) { @@ -835,8 +1031,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } } - if (flowSnippet.getOutputPorts() != null) { - for (final PortDTO portDTO : flowSnippet.getOutputPorts()) { + if (flow.getOutputPorts() != null) { + for (final PortDTO portDTO : flow.getOutputPorts()) { final Port port = outputPortDAO.getPort(portDTO.getId()); final Collection validationErrors = port.getValidationErrors(); if (validationErrors != null && !validationErrors.isEmpty()) { @@ -850,8 +1046,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } // get any remote process group issues - if (flowSnippet.getRemoteProcessGroups() != null) { - for (final RemoteProcessGroupDTO remoteProcessGroupDTO : flowSnippet.getRemoteProcessGroups()) { + if (flow.getRemoteProcessGroups() != null) { + for (final RemoteProcessGroupDTO remoteProcessGroupDTO : flow.getRemoteProcessGroups()) { final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupDTO.getId()); if (remoteProcessGroup.getAuthorizationIssue() != null) { remoteProcessGroupDTO.setAuthorizationIssues(Arrays.asList(remoteProcessGroup.getAuthorizationIssue())); @@ -861,35 +1057,31 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot copySnippet(final Revision revision, final String groupId, final String snippetId, final Double originX, final Double originY) { - return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { + public ConfigurationSnapshot copySnippet(final Revision revision, final String groupId, final String snippetId, final Double originX, final Double originY) { + return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { @Override - public ConfigurationResult execute() { + public ConfigurationResult execute() { String id = snippetId; - // ensure id is set - if (StringUtils.isBlank(id)) { - id = UUID.randomUUID().toString(); - } - // create the new snippet - final FlowSnippetDTO flowSnippet = snippetDAO.copySnippet(groupId, id, originX, originY); + final FlowSnippetDTO snippet = snippetDAO.copySnippet(groupId, id, originX, originY); // validate the new snippet - validateSnippetContents(flowSnippet); + validateSnippetContents(snippet); // save the flow controllerFacade.save(); - return new ConfigurationResult() { + return new ConfigurationResult() { @Override public boolean isNew() { return false; } @Override - public FlowSnippetDTO getConfiguration() { - return flowSnippet; + public FlowDTO getConfiguration() { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + return dtoFactory.createFlowDto(group, snippet); } }; } @@ -909,7 +1101,6 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { // add the snippet final Snippet snippet = snippetDAO.createSnippet(snippetDTO); final SnippetDTO responseSnippetDTO = dtoFactory.createSnippetDto(snippet); - responseSnippetDTO.setContents(snippetUtils.populateFlowSnippet(snippet, false, false)); return new ConfigurationResult() { @Override @@ -927,27 +1118,53 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot createInputPort(final Revision revision, final String groupId, final PortDTO inputPortDTO) { - return createComponent(revision, inputPortDTO, () -> inputPortDAO.createPort(groupId, inputPortDTO), port -> dtoFactory.createPortDto(port)); + public PortEntity createInputPort(final Revision revision, final String groupId, final PortDTO inputPortDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + inputPortDTO, + () -> inputPortDAO.createPort(groupId, inputPortDTO), + port -> dtoFactory.createPortDto(port)); + + final Port port = inputPortDAO.getPort(inputPortDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(port); + return entityFactory.createPortEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override - public ConfigurationSnapshot createOutputPort(final Revision revision, final String groupId, final PortDTO outputPortDTO) { - return createComponent(revision, outputPortDTO, () -> outputPortDAO.createPort(groupId, outputPortDTO), port -> dtoFactory.createPortDto(port)); + public PortEntity createOutputPort(final Revision revision, final String groupId, final PortDTO outputPortDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + outputPortDTO, + () -> outputPortDAO.createPort(groupId, outputPortDTO), + port -> dtoFactory.createPortDto(port)); + + final Port port = outputPortDAO.getPort(outputPortDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(port); + return entityFactory.createPortEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override - public ConfigurationSnapshot createProcessGroup(final String parentGroupId, final Revision revision, final ProcessGroupDTO processGroupDTO) { - return createComponent(revision, processGroupDTO, + public ProcessGroupEntity createProcessGroup(final String parentGroupId, final Revision revision, final ProcessGroupDTO processGroupDTO) { + final ConfigurationSnapshot snapshot = createComponent(revision, processGroupDTO, () -> processGroupDAO.createProcessGroup(parentGroupId, processGroupDTO), processGroup -> dtoFactory.createProcessGroupDto(processGroup)); + + final ProcessGroup processGroup = processGroupDAO.getProcessGroup(processGroupDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(processGroup); + return entityFactory.createProcessGroupEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override - public ConfigurationSnapshot createRemoteProcessGroup(final Revision revision, final String groupId, final RemoteProcessGroupDTO remoteProcessGroupDTO) { - return createComponent(revision, remoteProcessGroupDTO, + public RemoteProcessGroupEntity createRemoteProcessGroup(final Revision revision, final String groupId, final RemoteProcessGroupDTO remoteProcessGroupDTO) { + final ConfigurationSnapshot snapshot = createComponent( + revision, + remoteProcessGroupDTO, () -> remoteProcessGroupDAO.createRemoteProcessGroup(groupId, remoteProcessGroupDTO), remoteProcessGroup -> dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup)); + + final RemoteProcessGroup remoteProcessGroup = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupDTO.getId()); + final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(remoteProcessGroup); + return entityFactory.createRemoteProcessGroupEntity(snapshot.getConfiguration(), dtoFactory.createRevisionDTO(snapshot.getVersion(), revision.getClientId()), accessPolicy); } @Override @@ -993,29 +1210,30 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot createTemplateInstance(final Revision revision, final String groupId, final Double originX, final Double originY, final String templateId) { - return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { + public ConfigurationSnapshot createTemplateInstance(final Revision revision, final String groupId, final Double originX, final Double originY, final String templateId) { + return optimisticLockingManager.configureFlow(revision, new ConfigurationRequest() { @Override - public ConfigurationResult execute() { + public ConfigurationResult execute() { // instantiate the template - there is no need to make another copy of the flow snippet since the actual template // was copied and this dto is only used to instantiate it's components (which as already completed) - final FlowSnippetDTO flowSnippet = templateDAO.instantiateTemplate(groupId, originX, originY, templateId); + final FlowSnippetDTO snippet = templateDAO.instantiateTemplate(groupId, originX, originY, templateId); // validate the new snippet - validateSnippetContents(flowSnippet); + validateSnippetContents(snippet); // save the flow controllerFacade.save(); - return new ConfigurationResult() { + return new ConfigurationResult() { @Override public boolean isNew() { return false; } @Override - public FlowSnippetDTO getConfiguration() { - return flowSnippet; + public FlowDTO getConfiguration() { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + return dtoFactory.createFlowDto(group, snippet); } }; } @@ -1367,30 +1585,39 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public Set getConnections(String groupId) { - Set connectionDtos = new LinkedHashSet<>(); + public Set getConnections(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + Set connections = new LinkedHashSet<>(); for (Connection connection : connectionDAO.getConnections(groupId)) { - connectionDtos.add(dtoFactory.createConnectionDto(connection)); + connections.add(entityFactory.createConnectionEntity(dtoFactory.createConnectionDto(connection), null, dtoFactory.createAccessPolicyDto(connection))); } - return connectionDtos; + return connections; } @Override - public ConnectionDTO getConnection(String connectionId) { - return dtoFactory.createConnectionDto(connectionDAO.getConnection(connectionId)); + public ConnectionEntity getConnection(String connectionId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.READ); + return entityFactory.createConnectionEntity(dtoFactory.createConnectionDto(connectionDAO.getConnection(connectionId)), null, dtoFactory.createAccessPolicyDto(connection)); } @Override public DropRequestDTO getFlowFileDropRequest(String connectionId, String dropRequestId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); return dtoFactory.createDropRequestDTO(connectionDAO.getFlowFileDropRequest(connectionId, dropRequestId)); } @Override public ListingRequestDTO getFlowFileListingRequest(String connectionId, String listingRequestId) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); + final ListingRequestDTO listRequest = dtoFactory.createListingRequestDTO(connectionDAO.getFlowFileListingRequest(connectionId, listingRequestId)); // include whether the source and destination are running - final Connection connection = connectionDAO.getConnection(connectionId); if (connection.getSource() != null) { listRequest.setSourceRunning(connection.getSource().isRunning()); } @@ -1403,6 +1630,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override public FlowFileDTO getFlowFile(String connectionId, String flowFileUuid) { + final Connection connection = connectionDAO.getConnection(connectionId); + connection.authorize(authorizer, RequestAction.WRITE); return dtoFactory.createFlowFileDTO(connectionDAO.getFlowFile(connectionId, flowFileUuid)); } @@ -1417,12 +1646,15 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public Set getProcessors(String groupId) { - Set processorDtos = new LinkedHashSet<>(); + public Set getProcessors(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + Set processors = new LinkedHashSet<>(); for (ProcessorNode processor : processorDAO.getProcessors(groupId)) { - processorDtos.add(dtoFactory.createProcessorDto(processor)); + processors.add(entityFactory.createProcessorEntity(dtoFactory.createProcessorDto(processor), null, dtoFactory.createAccessPolicyDto(processor))); } - return processorDtos; + return processors; } @Override @@ -1470,10 +1702,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ProcessorDTO getProcessor(String id) { + public ProcessorEntity getProcessor(String id) { final ProcessorNode processor = processorDAO.getProcessor(id); - final ProcessorDTO processorDto = dtoFactory.createProcessorDto(processor); - return processorDto; + processor.authorize(authorizer, RequestAction.READ); + return entityFactory.createProcessorEntity(dtoFactory.createProcessorDto(processor), null, dtoFactory.createAccessPolicyDto(processor)); } @Override @@ -1662,80 +1894,103 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public Set getLabels(String groupId) { - Set labelDtos = new LinkedHashSet<>(); + public Set getLabels(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + Set labels = new LinkedHashSet<>(); for (Label label : labelDAO.getLabels(groupId)) { - labelDtos.add(dtoFactory.createLabelDto(label)); + labels.add(entityFactory.createLabelEntity(dtoFactory.createLabelDto(label), null, dtoFactory.createAccessPolicyDto(label))); } - return labelDtos; + return labels; } @Override - public LabelDTO getLabel(String labelId) { - return dtoFactory.createLabelDto(labelDAO.getLabel(labelId)); + public LabelEntity getLabel(String labelId) { + final Label label = labelDAO.getLabel(labelId); + label.authorize(authorizer, RequestAction.READ); + return entityFactory.createLabelEntity(dtoFactory.createLabelDto(label), null, dtoFactory.createAccessPolicyDto(label)); } @Override - public Set getFunnels(String groupId) { - Set funnelDtos = new LinkedHashSet<>(); + public Set getFunnels(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + final Set funnelDtos = new LinkedHashSet<>(); for (Funnel funnel : funnelDAO.getFunnels(groupId)) { - funnelDtos.add(dtoFactory.createFunnelDto(funnel)); + funnelDtos.add(entityFactory.createFunnelEntity(dtoFactory.createFunnelDto(funnel), null, dtoFactory.createAccessPolicyDto(funnel))); } return funnelDtos; } @Override - public FunnelDTO getFunnel(String funnelId) { - return dtoFactory.createFunnelDto(funnelDAO.getFunnel(funnelId)); + public FunnelEntity getFunnel(String funnelId) { + final Funnel funnel = funnelDAO.getFunnel(funnelId); + funnel.authorize(authorizer, RequestAction.READ); + return entityFactory.createFunnelEntity(dtoFactory.createFunnelDto(funnel), null, dtoFactory.createAccessPolicyDto(funnel)); } @Override public SnippetDTO getSnippet(String snippetId) { final Snippet snippet = snippetDAO.getSnippet(snippetId); final SnippetDTO snippetDTO = dtoFactory.createSnippetDto(snippet); - snippetDTO.setContents(snippetUtils.populateFlowSnippet(snippet, false, false)); return snippetDTO; } @Override - public Set getInputPorts(String groupId) { - Set portDtos = new LinkedHashSet<>(); + public Set getInputPorts(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + final Set ports = new LinkedHashSet<>(); for (Port port : inputPortDAO.getPorts(groupId)) { - portDtos.add(dtoFactory.createPortDto(port)); + ports.add(entityFactory.createPortEntity(dtoFactory.createPortDto(port), null, dtoFactory.createAccessPolicyDto(port))); } - return portDtos; + return ports; } @Override - public Set getOutputPorts(String groupId) { - Set portDtos = new LinkedHashSet<>(); + public Set getOutputPorts(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + Set ports = new LinkedHashSet<>(); for (Port port : outputPortDAO.getPorts(groupId)) { - portDtos.add(dtoFactory.createPortDto(port)); + ports.add(entityFactory.createPortEntity(dtoFactory.createPortDto(port), null, dtoFactory.createAccessPolicyDto(port))); } - return portDtos; + return ports; } @Override - public Set getProcessGroups(String parentGroupId) { - Set processGroupDtos = new LinkedHashSet<>(); - for (ProcessGroup groups : processGroupDAO.getProcessGroups(parentGroupId)) { - processGroupDtos.add(dtoFactory.createProcessGroupDto(groups)); + public Set getProcessGroups(String parentGroupId) { + final ProcessGroup parentGroup = processGroupDAO.getProcessGroup(parentGroupId); + parentGroup.authorize(authorizer, RequestAction.READ); + + Set processGroups = new LinkedHashSet<>(); + for (ProcessGroup group : processGroupDAO.getProcessGroups(parentGroupId)) { + processGroups.add(entityFactory.createProcessGroupEntity(dtoFactory.createProcessGroupDto(group), null, dtoFactory.createAccessPolicyDto(group))); } - return processGroupDtos; + return processGroups; } @Override - public Set getRemoteProcessGroups(String groupId) { - Set remoteProcessGroupDtos = new LinkedHashSet<>(); - for (RemoteProcessGroup remoteProcessGroup : remoteProcessGroupDAO.getRemoteProcessGroups(groupId)) { - remoteProcessGroupDtos.add(dtoFactory.createRemoteProcessGroupDto(remoteProcessGroup)); + public Set getRemoteProcessGroups(String groupId) { + final ProcessGroup group = processGroupDAO.getProcessGroup(groupId); + group.authorize(authorizer, RequestAction.READ); + + Set remoteProcessGroups = new LinkedHashSet<>(); + for (RemoteProcessGroup rpg : remoteProcessGroupDAO.getRemoteProcessGroups(groupId)) { + remoteProcessGroups.add(entityFactory.createRemoteProcessGroupEntity(dtoFactory.createRemoteProcessGroupDto(rpg), null, dtoFactory.createAccessPolicyDto(rpg))); } - return remoteProcessGroupDtos; + return remoteProcessGroups; } @Override - public PortDTO getInputPort(String inputPortId) { - return dtoFactory.createPortDto(inputPortDAO.getPort(inputPortId)); + public PortEntity getInputPort(String inputPortId) { + final Port port = inputPortDAO.getPort(inputPortId); + port.authorize(authorizer, RequestAction.READ); + return entityFactory.createPortEntity(dtoFactory.createPortDto(port), null, dtoFactory.createAccessPolicyDto(port)); } @Override @@ -1744,8 +1999,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public PortDTO getOutputPort(String outputPortId) { - return dtoFactory.createPortDto(outputPortDAO.getPort(outputPortId)); + public PortEntity getOutputPort(String outputPortId) { + final Port port = outputPortDAO.getPort(outputPortId); + port.authorize(authorizer, RequestAction.READ); + return entityFactory.createPortEntity(dtoFactory.createPortDto(port), null, dtoFactory.createAccessPolicyDto(port)); } @Override @@ -1754,8 +2011,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public RemoteProcessGroupDTO getRemoteProcessGroup(String remoteProcessGroupId) { - return dtoFactory.createRemoteProcessGroupDto(remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId)); + public RemoteProcessGroupEntity getRemoteProcessGroup(String remoteProcessGroupId) { + final RemoteProcessGroup rpg = remoteProcessGroupDAO.getRemoteProcessGroup(remoteProcessGroupId); + rpg.authorize(authorizer, RequestAction.READ); + return entityFactory.createRemoteProcessGroupEntity(dtoFactory.createRemoteProcessGroupDto(rpg), null, dtoFactory.createAccessPolicyDto(rpg)); } @Override @@ -1769,13 +2028,20 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public ConfigurationSnapshot getProcessGroup(String groupId, final boolean recurse) { + public ConfigurationSnapshot getProcessGroupFlow(String groupId, boolean recurse) { ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId); Revision revision = optimisticLockingManager.getLastModification().getRevision(); - ConfigurationSnapshot response = new ConfigurationSnapshot<>(revision.getVersion(), dtoFactory.createProcessGroupDto(processGroup, recurse)); + ConfigurationSnapshot response = new ConfigurationSnapshot<>(revision.getVersion(), dtoFactory.createProcessGroupFlowDto(processGroup, recurse)); return response; } + @Override + public ProcessGroupEntity getProcessGroup(String groupId) { + final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId); + processGroup.authorize(authorizer, RequestAction.READ); + return entityFactory.createProcessGroupEntity(dtoFactory.createProcessGroupDto(processGroup), null, dtoFactory.createAccessPolicyDto(processGroup)); + } + @Override public Set getControllerServices() { final Set controllerServiceDtos = new LinkedHashSet<>(); @@ -2014,6 +2280,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { this.dtoFactory = dtoFactory; } + public void setEntityFactory(EntityFactory entityFactory) { + this.entityFactory = entityFactory; + } + public void setInputPortDAO(PortDAO inputPortDAO) { this.inputPortDAO = inputPortDAO; } @@ -2042,6 +2312,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { this.snippetUtils = snippetUtils; } + public void setAuthorizer(Authorizer authorizer) { + this.authorizer = authorizer; + } + private boolean isPrimaryNode(String nodeId) { final Node primaryNode = clusterManager.getPrimaryNode(); return (primaryNode != null && primaryNode.getNodeId().getId().equals(nodeId)); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java index b8f135015e..2eb7bd66ce 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java @@ -25,12 +25,14 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; import org.apache.nifi.admin.service.AuditService; +import org.apache.nifi.authorization.user.NiFiUserDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.manager.NodeResponse; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.controller.ControllerService; import org.apache.nifi.controller.ControllerServiceLookup; import org.apache.nifi.controller.reporting.ReportingTaskProvider; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.api.dto.ControllerServiceDTO; import org.apache.nifi.web.api.dto.ProcessorConfigDTO; @@ -40,8 +42,6 @@ import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.entity.ControllerServiceEntity; import org.apache.nifi.web.api.entity.ProcessorEntity; import org.apache.nifi.web.api.entity.ReportingTaskEntity; -import org.apache.nifi.web.security.user.NiFiUserDetails; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.apache.nifi.web.util.ClientResponseUtils; import org.apache.nifi.web.util.WebUtils; import org.slf4j.Logger; @@ -288,7 +288,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration // create the request URL URI requestUrl; try { - String path = "/nifi-api/cluster/processors/" + URLEncoder.encode(id, "UTF-8"); + String path = "/nifi-api/processors/" + URLEncoder.encode(id, "UTF-8"); requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null); } catch (final URISyntaxException | UnsupportedEncodingException use) { throw new ClusterRequestException(use); @@ -309,9 +309,9 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration if (entity == null) { entity = nodeResponse.getClientResponse().getEntity(ProcessorEntity.class); } - processor = entity.getProcessor(); + processor = entity.getComponent(); } else { - processor = serviceFacade.getProcessor(id); + processor = serviceFacade.getProcessor(id).getComponent(); } // return the processor info @@ -328,7 +328,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration // create the request URL URI requestUrl; try { - String path = "/nifi-api/cluster/processors/" + URLEncoder.encode(id, "UTF-8"); + String path = "/nifi-api/processors/" + URLEncoder.encode(id, "UTF-8"); requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null); } catch (final URISyntaxException | UnsupportedEncodingException use) { throw new ClusterRequestException(use); @@ -345,7 +345,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration // create the processor dto ProcessorDTO processorDto = new ProcessorDTO(); - processorEntity.setProcessor(processorDto); + processorEntity.setComponent(processorDto); processorDto.setId(id); // create the processor configuration with the given annotation data @@ -368,7 +368,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration if (entity == null) { entity = nodeResponse.getClientResponse().getEntity(ProcessorEntity.class); } - processor = entity.getProcessor(); + processor = entity.getComponent(); } else { final ConfigurationSnapshot response = serviceFacade.setProcessorAnnotationData(revision, id, annotationData); processor = response.getConfiguration(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebContext.java index 158dbfad62..6180cee8b5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebContext.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebContext.java @@ -25,18 +25,18 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.action.component.details.FlowChangeExtensionDetails; import org.apache.nifi.action.details.FlowChangeConfigureDetails; import org.apache.nifi.admin.service.AuditService; +import org.apache.nifi.authorization.user.NiFiUserDetails; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.manager.NodeResponse; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.controller.ControllerService; import org.apache.nifi.controller.ControllerServiceLookup; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.api.dto.ProcessorConfigDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.entity.ProcessorEntity; -import org.apache.nifi.web.security.user.NiFiUserDetails; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.apache.nifi.web.util.ClientResponseUtils; import org.apache.nifi.web.util.WebUtils; import org.slf4j.Logger; @@ -166,7 +166,7 @@ public class StandardNiFiWebContext implements NiFiWebContext { // create the request URL URI requestUrl; try { - String path = "/nifi-api/cluster/processors/" + URLEncoder.encode(processorId, "UTF-8"); + String path = "/nifi-api/processors/" + URLEncoder.encode(processorId, "UTF-8"); requestUrl = new URI(config.getScheme(), null, "localhost", 0, path, null, null); } catch (final URISyntaxException | UnsupportedEncodingException use) { throw new ClusterRequestException(use); @@ -200,9 +200,9 @@ public class StandardNiFiWebContext implements NiFiWebContext { if (entity == null) { entity = nodeResponse.getClientResponse().getEntity(ProcessorEntity.class); } - processor = entity.getProcessor(); + processor = entity.getComponent(); } else { - processor = serviceFacade.getProcessor(processorId); + processor = serviceFacade.getProcessor(processorId).getComponent(); } // return the processor info @@ -233,7 +233,7 @@ public class StandardNiFiWebContext implements NiFiWebContext { // create the request URL URI requestUrl; try { - String path = "/nifi-api/cluster/processors/" + URLEncoder.encode(processorId, "UTF-8"); + String path = "/nifi-api/processors/" + URLEncoder.encode(processorId, "UTF-8"); requestUrl = new URI(config.getScheme(), null, "localhost", 0, path, null, null); } catch (final URISyntaxException | UnsupportedEncodingException use) { throw new ClusterRequestException(use); @@ -250,7 +250,7 @@ public class StandardNiFiWebContext implements NiFiWebContext { // create the processor dto ProcessorDTO processorDto = new ProcessorDTO(); - processorEntity.setProcessor(processorDto); + processorEntity.setComponent(processorDto); processorDto.setId(processorId); // create the processor configuration with the given annotation data diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/UpdateResult.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/UpdateResult.java new file mode 100644 index 0000000000..66247e38d8 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/UpdateResult.java @@ -0,0 +1,40 @@ +/* + * 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.web; + +/** + * Result from an update operation. + */ +@SuppressWarnings("serial") +public class UpdateResult { + + private final T result; + private final boolean isNew; + + public UpdateResult(T result, boolean isNew) { + this.result = result; + this.isNew = isNew; + } + + public T getResult() { + return result; + } + + public boolean isNew() { + return isNew; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java index bb8e701c0b..22ebf29313 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java @@ -29,8 +29,10 @@ import org.apache.nifi.authentication.LoginCredentials; import org.apache.nifi.authentication.LoginIdentityProvider; import org.apache.nifi.authentication.exception.IdentityAccessException; import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException; +import org.apache.nifi.authorization.AccessDeniedException; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.security.util.CertificateUtils; -import org.apache.nifi.user.NiFiUser; import org.apache.nifi.util.FormatUtils; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.api.dto.AccessConfigurationDTO; @@ -48,12 +50,10 @@ import org.apache.nifi.web.security.kerberos.KerberosService; import org.apache.nifi.web.security.otp.OtpService; import org.apache.nifi.web.security.token.LoginAuthenticationToken; import org.apache.nifi.web.security.token.OtpAuthenticationToken; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.apache.nifi.web.security.x509.X509CertificateExtractor; import org.apache.nifi.web.security.x509.X509IdentityProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AccountStatusException; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.core.Authentication; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java index 966aa29cc3..8026400512 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java @@ -26,6 +26,7 @@ import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.nifi.action.Action; import org.apache.nifi.action.FlowChangeAction; import org.apache.nifi.action.Operation; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.cluster.context.ClusterContext; import org.apache.nifi.cluster.context.ClusterContextThreadLocal; import org.apache.nifi.cluster.manager.impl.WebClusterManager; @@ -33,7 +34,6 @@ import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.api.entity.Entity; import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.nifi.web.security.jwt.JwtAuthenticationFilter; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.apache.nifi.web.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ClusterResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ClusterResource.java index 526663287c..1dce576d3a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ClusterResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ClusterResource.java @@ -24,34 +24,23 @@ import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; -import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.cluster.node.Node; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.IllegalClusterResourceRequestException; import org.apache.nifi.web.NiFiServiceFacade; -import org.apache.nifi.web.Revision; import org.apache.nifi.web.api.dto.ClusterDTO; import org.apache.nifi.web.api.dto.NodeDTO; -import org.apache.nifi.web.api.dto.ProcessorConfigDTO; -import org.apache.nifi.web.api.dto.ProcessorDTO; import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.dto.search.NodeSearchResultDTO; import org.apache.nifi.web.api.entity.ClusterEntity; import org.apache.nifi.web.api.entity.ClusterSearchResultsEntity; -import org.apache.nifi.web.api.entity.ProcessorEntity; import org.apache.nifi.web.api.request.ClientIdParameter; -import org.apache.nifi.web.api.request.LongParameter; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; -import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.HEAD; -import javax.ws.rs.PUT; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; @@ -233,218 +222,6 @@ public class ClusterResource extends ApplicationResource { throw new IllegalClusterResourceRequestException("Only a cluster manager can process the request."); } - /** - * Gets the processor. - * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. - * @param id The id of the processor - * @return A processorEntity - */ - @GET - @Consumes(MediaType.WILDCARD) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - @Path("/processors/{id}") - // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')") - @ApiOperation( - value = "Gets the specified processor", - response = ProcessorEntity.class, - authorizations = { - @Authorization(value = "Read Only", type = "ROLE_MONITOR"), - @Authorization(value = "DFM", type = "ROLE_DFM"), - @Authorization(value = "Admin", type = "ROLE_ADMIN") - } - ) - @ApiResponses( - value = { - @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), - @ApiResponse(code = 401, message = "Client could not be authenticated."), - @ApiResponse(code = 403, message = "Client is not authorized to make this request."), - @ApiResponse(code = 404, message = "The specified resource could not be found."), - @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") - } - ) - public Response getProcessor( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, - @ApiParam( - value = "The processor id.", - required = true - ) - @PathParam("id") String id) { - - if (!properties.isClusterManager()) { - - final ProcessorDTO dto = serviceFacade.getProcessor(id); - - // create the revision - RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create entity - final ProcessorEntity entity = new ProcessorEntity(); - entity.setProcessor(dto); - entity.setRevision(revision); - - // generate the response - return generateOkResponse(entity).build(); - } - - throw new IllegalClusterResourceRequestException("Only a node can process the request."); - } - - /** - * Updates the processors annotation data. - * - * @param httpServletRequest request - * @param version The revision is used to verify the client is working with the latest version of the flow. - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. - * @param processorId The id of the processor. - * @param annotationData The annotation data to set. - * @return A processorEntity. - */ - @PUT - @Consumes(MediaType.APPLICATION_FORM_URLENCODED) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - @Path("/processors/{id}") - // TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')") - public Response updateProcessor( - @Context HttpServletRequest httpServletRequest, - @FormParam(VERSION) LongParameter version, - @FormParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, - @PathParam("id") String processorId, - @FormParam("annotationData") String annotationData) { - - if (!properties.isClusterManager()) { - - // create the processor configuration with the given annotation data - ProcessorConfigDTO configDto = new ProcessorConfigDTO(); - configDto.setAnnotationData(annotationData); - - // create the processor dto - ProcessorDTO processorDto = new ProcessorDTO(); - processorDto.setId(processorId); - processorDto.setConfig(configDto); - - // create the revision - RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - if (version != null) { - revision.setVersion(version.getLong()); - } - - // create the processor entity - ProcessorEntity processorEntity = new ProcessorEntity(); - processorEntity.setRevision(revision); - processorEntity.setProcessor(processorDto); - - return updateProcessor(httpServletRequest, processorId, processorEntity); - } - - throw new IllegalClusterResourceRequestException("Only a node can process the request."); - } - - /** - * Updates the processors annotation data. - * - * @param httpServletRequest request - * @param processorId The id of the processor. - * @param processorEntity A processorEntity. - * @return A processorEntity. - */ - @PUT - @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - @Path("/processors/{id}") - // TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')") - @ApiOperation( - value = "Updates processor annotation data", - response = ProcessorEntity.class, - authorizations = { - @Authorization(value = "Read Only", type = "ROLE_MONITOR"), - @Authorization(value = "DFM", type = "ROLE_DFM"), - @Authorization(value = "Admin", type = "ROLE_ADMIN") - } - ) - @ApiResponses( - value = { - @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), - @ApiResponse(code = 401, message = "Client could not be authenticated."), - @ApiResponse(code = 403, message = "Client is not authorized to make this request."), - @ApiResponse(code = 404, message = "The specified resource could not be found."), - @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") - } - ) - public Response updateProcessor( - @Context HttpServletRequest httpServletRequest, - @ApiParam( - value = "The processor id.", - required = true - ) - @PathParam("id") final String processorId, - @ApiParam( - value = "The processor configuration details. The only configuration that will be honored at this endpoint is the processor annontation data.", - required = true - ) - final ProcessorEntity processorEntity) { - - if (!properties.isClusterManager()) { - - if (processorEntity == null || processorEntity.getProcessor() == null) { - throw new IllegalArgumentException("Processor details must be specified."); - } - - if (processorEntity.getRevision() == null) { - throw new IllegalArgumentException("Revision must be specified."); - } - - // ensure the same id is being used - ProcessorDTO requestProcessorDTO = processorEntity.getProcessor(); - if (!processorId.equals(requestProcessorDTO.getId())) { - throw new IllegalArgumentException(String.format("The processor id (%s) in the request body does " - + "not equal the processor id of the requested resource (%s).", requestProcessorDTO.getId(), processorId)); - } - - // get the processor configuration - ProcessorConfigDTO config = requestProcessorDTO.getConfig(); - if (config == null) { - throw new IllegalArgumentException("Processor configuration must be specified."); - } - - // handle expects request (usually from the cluster manager) - final String expects = httpServletRequest.getHeader(WebClusterManager.NCM_EXPECTS_HTTP_HEADER); - if (expects != null) { - serviceFacade.verifyUpdateProcessor(requestProcessorDTO); - return generateContinueResponse().build(); - } - - // update the processor - final RevisionDTO revision = processorEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.setProcessorAnnotationData( - new Revision(revision.getVersion(), revision.getClientId()), processorId, config.getAnnotationData()); - - // get the processor dto - final ProcessorDTO responseProcessorDTO = controllerResponse.getConfiguration(); - - // update the revision - RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // generate the response entity - final ProcessorEntity entity = new ProcessorEntity(); - entity.setRevision(updatedRevision); - entity.setProcessor(responseProcessorDTO); - - return generateOkResponse(entity).build(); - } - - throw new IllegalClusterResourceRequestException("Only a node can process the request."); - } - // setters public void setServiceFacade(NiFiServiceFacade serviceFacade) { this.serviceFacade = serviceFacade; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java index 7d5df509f1..d02c1ef324 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectionResource.java @@ -25,9 +25,9 @@ import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.FlowFileSummaryDTO; import org.apache.nifi.web.api.dto.ListingRequestDTO; @@ -69,6 +69,32 @@ public class ConnectionResource extends ApplicationResource { private WebClusterManager clusterManager; private NiFiProperties properties; + /** + * Populate the URIs for the specified connections. + * + * @param connectionEntities connections + * @return dtos + */ + public Set populateRemainingConnectionEntitiesContent(Set connectionEntities) { + for (ConnectionEntity connectionEntity : connectionEntities) { + populateRemainingConnectionEntityContent(connectionEntity); + } + return connectionEntities; + } + + /** + * Populate the URIs for the specified connection. + * + * @param connectionEntity connection + * @return dto + */ + public ConnectionEntity populateRemainingConnectionEntityContent(ConnectionEntity connectionEntity) { + if (connectionEntity.getComponent() != null) { + populateRemainingConnectionContent(connectionEntity.getComponent()); + } + return connectionEntity; + } + /** * Populate the URIs for the specified connections. * @@ -129,7 +155,6 @@ public class ConnectionResource extends ApplicationResource { /** * Retrieves the specified connection. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the connection. * @return A connectionEntity. */ @@ -157,11 +182,6 @@ public class ConnectionResource extends ApplicationResource { } ) public Response getConnection( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The connection id.", required = true @@ -174,16 +194,8 @@ public class ConnectionResource extends ApplicationResource { } // get the specified relationship - ConnectionDTO connection = serviceFacade.getConnection(id); - - // create the revision - RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity - ConnectionEntity entity = new ConnectionEntity(); - entity.setRevision(revision); - entity.setConnection(populateRemainingConnectionContent(connection)); + ConnectionEntity entity = serviceFacade.getConnection(id); + populateRemainingConnectionEntityContent(entity); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -230,7 +242,7 @@ public class ConnectionResource extends ApplicationResource { required = true ) ConnectionEntity connectionEntity) { - if (connectionEntity == null || connectionEntity.getConnection() == null) { + if (connectionEntity == null || connectionEntity.getComponent() == null) { throw new IllegalArgumentException("Connection details must be specified."); } @@ -239,7 +251,7 @@ public class ConnectionResource extends ApplicationResource { } // ensure the ids are the same - final ConnectionDTO connection = connectionEntity.getConnection(); + final ConnectionDTO connection = connectionEntity.getComponent(); if (!id.equals(connection.getId())) { throw new IllegalArgumentException(String.format("The connection id " + "(%s) in the request body does not equal the connection id of the " @@ -265,26 +277,14 @@ public class ConnectionResource extends ApplicationResource { // update the relationship target final RevisionDTO revision = connectionEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.updateConnection( - new Revision(revision.getVersion(), revision.getClientId()), connection); + final UpdateResult updateResult = serviceFacade.updateConnection(new Revision(revision.getVersion(), revision.getClientId()), connection); - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // marshall the target and add the source processor - final ConnectionDTO connectionDTO = controllerResponse.getConfiguration(); - populateRemainingConnectionContent(connectionDTO); - - // create the response entity - ConnectionEntity entity = new ConnectionEntity(); - entity.setRevision(updatedRevision); - entity.setConnection(connectionDTO); + final ConnectionEntity entity = updateResult.getResult(); + populateRemainingConnectionEntityContent(entity); // generate the response - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(connectionDTO.getUri()), entity)).build(); + if (updateResult.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -357,16 +357,7 @@ public class ConnectionResource extends ApplicationResource { } // delete the connection - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteConnection(new Revision(clientVersion, clientId.getClientId()), id); - - // create the revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(clientId.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // create the response entity - final ConnectionEntity entity = new ConnectionEntity(); - entity.setRevision(updatedRevision); + final ConnectionEntity entity = serviceFacade.deleteConnection(new Revision(clientVersion, clientId.getClientId()), id); // generate the response return clusterContext(generateOkResponse(entity)).build(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java index 10f44563e8..8add2bb9aa 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java @@ -24,6 +24,7 @@ import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.context.ClusterContext; import org.apache.nifi.cluster.context.ClusterContextThreadLocal; import org.apache.nifi.cluster.manager.NodeResponse; @@ -31,7 +32,7 @@ import org.apache.nifi.cluster.manager.exception.UnknownNodeException; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.cluster.node.Node; import org.apache.nifi.cluster.protocol.NodeIdentifier; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; @@ -50,7 +51,6 @@ import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.ReportingTaskEntity; import org.apache.nifi.web.api.entity.ReportingTasksEntity; import org.apache.nifi.web.api.request.ClientIdParameter; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.apache.nifi.web.util.Availability; import javax.servlet.http.HttpServletRequest; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java index 849d9f257f..3cfae3a766 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java @@ -152,9 +152,6 @@ public class ControllerServiceResource extends ApplicationResource { /** * Retrieves the specified controller service. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param availability Whether the controller service is available on the * NCM only (ncm) or on the nodes only (node). If this instance is not * clustered all services should use the node availability. @@ -185,11 +182,6 @@ public class ControllerServiceResource extends ApplicationResource { } ) public Response getControllerService( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "Whether the controller service is available on the NCM or nodes. If the NiFi is standalone the availability should be NODE.", allowableValues = "NCM, NODE", @@ -212,13 +204,8 @@ public class ControllerServiceResource extends ApplicationResource { // get the controller service final ControllerServiceDTO controllerService = serviceFacade.getControllerService(id); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // create the response entity final ControllerServiceEntity entity = new ControllerServiceEntity(); - entity.setRevision(revision); entity.setControllerService(populateRemainingControllerServiceContent(availability, controllerService)); return clusterContext(generateOkResponse(entity)).build(); @@ -227,9 +214,6 @@ public class ControllerServiceResource extends ApplicationResource { /** * Returns the descriptor for the specified property. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param availability avail * @param id The id of the controller service. * @param propertyName The property @@ -259,11 +243,6 @@ public class ControllerServiceResource extends ApplicationResource { } ) public Response getPropertyDescriptor( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "Whether the controller service is available on the NCM or nodes. If the NiFi is standalone the availability should be NODE.", allowableValues = "NCM, NODE", @@ -296,13 +275,8 @@ public class ControllerServiceResource extends ApplicationResource { // get the property descriptor final PropertyDescriptorDTO descriptor = serviceFacade.getControllerServicePropertyDescriptor(id, propertyName); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // generate the response entity final PropertyDescriptorEntity entity = new PropertyDescriptorEntity(); - entity.setRevision(revision); entity.setPropertyDescriptor(descriptor); // generate the response @@ -312,7 +286,6 @@ public class ControllerServiceResource extends ApplicationResource { /** * Gets the state for a controller service. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param availability Whether the controller service is available on the * NCM only (ncm) or on the nodes only (node). If this instance is not * clustered all services should use the node availability. @@ -341,11 +314,6 @@ public class ControllerServiceResource extends ApplicationResource { } ) public Response getState( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "Whether the controller service is available on the NCM or nodes. If the NiFi is standalone the availability should be NODE.", allowableValues = "NCM, NODE", @@ -368,13 +336,8 @@ public class ControllerServiceResource extends ApplicationResource { // get the component state final ComponentStateDTO state = serviceFacade.getControllerServiceState(id); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // generate the response entity final ComponentStateEntity entity = new ComponentStateEntity(); - entity.setRevision(revision); entity.setComponentState(state); // generate the response @@ -465,9 +428,6 @@ public class ControllerServiceResource extends ApplicationResource { /** * Retrieves the references of the specified controller service. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param availability Whether the controller service is available on the * NCM only (ncm) or on the nodes only (node). If this instance is not * clustered all services should use the node availability. @@ -498,11 +458,6 @@ public class ControllerServiceResource extends ApplicationResource { } ) public Response getControllerServiceReferences( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "Whether the controller service is available on the NCM or nodes. If the NiFi is standalone the availability should be NODE.", allowableValues = "NCM, NODE", @@ -525,13 +480,8 @@ public class ControllerServiceResource extends ApplicationResource { // get the controller service final Set controllerServiceReferences = serviceFacade.getControllerServiceReferencingComponents(id); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // create the response entity final ControllerServiceReferencingComponentsEntity entity = new ControllerServiceReferencingComponentsEntity(); - entity.setRevision(revision); entity.setControllerServiceReferencingComponents(controllerServiceReferences); return clusterContext(generateOkResponse(entity)).build(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java index e1beecc650..337cb67504 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java @@ -24,20 +24,32 @@ import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.AccessDeniedException; +import org.apache.nifi.authorization.AuthorizationRequest; +import org.apache.nifi.authorization.AuthorizationResult; +import org.apache.nifi.authorization.AuthorizationResult.Result; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.manager.NodeResponse; import org.apache.nifi.cluster.manager.exception.UnknownNodeException; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.cluster.node.Node; import org.apache.nifi.cluster.protocol.NodeIdentifier; -import org.apache.nifi.user.NiFiUser; import org.apache.nifi.util.NiFiProperties; +import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.api.dto.AboutDTO; import org.apache.nifi.web.api.dto.BannerDTO; import org.apache.nifi.web.api.dto.BulletinBoardDTO; import org.apache.nifi.web.api.dto.BulletinQueryDTO; import org.apache.nifi.web.api.dto.ControllerConfigurationDTO; +import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO; import org.apache.nifi.web.api.dto.search.SearchResultsDTO; import org.apache.nifi.web.api.dto.status.ConnectionStatusDTO; import org.apache.nifi.web.api.dto.status.ControllerStatusDTO; @@ -58,6 +70,8 @@ import org.apache.nifi.web.api.entity.Entity; import org.apache.nifi.web.api.entity.IdentityEntity; import org.apache.nifi.web.api.entity.PortStatusEntity; import org.apache.nifi.web.api.entity.PrioritizerTypesEntity; +import org.apache.nifi.web.api.entity.ProcessGroupEntity; +import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity; import org.apache.nifi.web.api.entity.ProcessorStatusEntity; import org.apache.nifi.web.api.entity.ProcessorTypesEntity; @@ -69,7 +83,6 @@ import org.apache.nifi.web.api.request.BulletinBoardPatternParameter; import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.nifi.web.api.request.IntegerParameter; import org.apache.nifi.web.api.request.LongParameter; -import org.apache.nifi.web.security.user.NiFiUserUtils; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; @@ -92,7 +105,7 @@ import java.util.Set; @Path("/flow") @Api( value = "/flow", - description = "Endpoint for accessing the flow structure and component statuses." + description = "Endpoint for accessing the flow structure and component status." ) public class FlowResource extends ApplicationResource { @@ -101,10 +114,164 @@ public class FlowResource extends ApplicationResource { private NiFiServiceFacade serviceFacade; private WebClusterManager clusterManager; private NiFiProperties properties; + private Authorizer authorizer; @Context private ResourceContext resourceContext; + private ProcessorResource processorResource; + private InputPortResource inputPortResource; + private OutputPortResource outputPortResource; + private FunnelResource funnelResource; + private LabelResource labelResource; + private RemoteProcessGroupResource remoteProcessGroupResource; + private ConnectionResource connectionResource; + private TemplateResource templateResource; + private ProcessGroupResource processGroupResource; + private ControllerServiceResource controllerServiceResource; + + /** + * Populates the remaining fields in the specified process group. + * + * @param flow group + * @return group dto + */ + private ProcessGroupFlowDTO populateRemainingFlowContent(ProcessGroupFlowDTO flow) { + FlowDTO flowStructure = flow.getFlow(); + + // populate the remaining fields for the processors, connections, process group refs, remote process groups, and labels if appropriate + if (flowStructure != null) { + populateRemainingFlowStructure(flowStructure); + } + + // set the process group uri + flow.setUri(generateResourceUri("flow", "process-groups", flow.getId())); + + return flow; + } + + /** + * Populates the remaining content of the specified snippet. + */ + private FlowDTO populateRemainingFlowStructure(FlowDTO flowStructure) { + processorResource.populateRemainingProcessorEntitiesContent(flowStructure.getProcessors()); + connectionResource.populateRemainingConnectionEntitiesContent(flowStructure.getConnections()); + inputPortResource.populateRemainingInputPortEntitiesContent(flowStructure.getInputPorts()); + outputPortResource.populateRemainingOutputPortEntitiesContent(flowStructure.getOutputPorts()); + remoteProcessGroupResource.populateRemainingRemoteProcessGroupEntitiesContent(flowStructure.getRemoteProcessGroups()); + funnelResource.populateRemainingFunnelEntitiesContent(flowStructure.getFunnels()); + labelResource.populateRemainingLabelEntitiesContent(flowStructure.getLabels()); + processGroupResource.populateRemainingProcessGroupEntitiesContent(flowStructure.getProcessGroups()); + + // go through each process group child and populate its uri + for (final ProcessGroupEntity processGroupEntity : flowStructure.getProcessGroups()) { + final ProcessGroupDTO processGroup = processGroupEntity.getComponent(); + if (processGroup != null) { + processGroup.setContents(null); + } + } + + return flowStructure; + } + + private void authorizeFlow() { + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .resource(ResourceFactory.getFlowResource()) + .identity(user.getIdentity()) + .anonymous(user.isAnonymous()) + .accessAttempt(true) + .action(RequestAction.READ) + .build(); + + final AuthorizationResult result = authorizer.authorize(request); + if (!Result.Approved.equals(result.getResult())) { + final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied"; + throw new AccessDeniedException(message); + } + } + + // ---- + // flow + // ---- + + /** + * Retrieves the contents of the specified group. + * + * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. + * @param recursive Optional recursive flag that defaults to false. If set to true, all descendent groups and their content will be included if the verbose flag is also set to true. + * @param groupId The id of the process group. + * @return A processGroupEntity. + */ + @GET + @Consumes(MediaType.WILDCARD) + @Produces(MediaType.APPLICATION_JSON) + @Path("process-groups/{id}") + // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')") + @ApiOperation( + value = "Gets a process group", + response = ProcessGroupEntity.class, + authorizations = { + @Authorization(value = "Read Only", type = "ROLE_MONITOR"), + @Authorization(value = "Data Flow Manager", type = "ROLE_DFM"), + @Authorization(value = "Administrator", type = "ROLE_ADMIN") + } + ) + @ApiResponses( + value = { + @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), + @ApiResponse(code = 401, message = "Client could not be authenticated."), + @ApiResponse(code = 403, message = "Client is not authorized to make this request."), + @ApiResponse(code = 404, message = "The specified resource could not be found."), + @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") + } + ) + public Response getFlow( + @ApiParam( + value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", + required = false + ) + @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, + @ApiParam( + value = "The process group id.", + required = false + ) + @PathParam("id") String groupId, + @ApiParam( + value = "Whether the response should contain all encapsulated components or just the immediate children.", + required = false + ) + @QueryParam("recursive") @DefaultValue(RECURSIVE) Boolean recursive) { + + authorizeFlow(); + + // replicate if cluster manager + if (properties.isClusterManager()) { + return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); + } + + // get this process group contents + final ConfigurationSnapshot controllerResponse = serviceFacade.getProcessGroupFlow(groupId, recursive); + final ProcessGroupFlowDTO flow = controllerResponse.getConfiguration(); + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(clientId.getClientId()); + revision.setVersion(controllerResponse.getVersion()); + + // create the response entity + final ProcessGroupFlowEntity processGroupEntity = new ProcessGroupFlowEntity(); + processGroupEntity.setRevision(revision); + processGroupEntity.setProcessGroupFlow(populateRemainingFlowContent(flow)); + + return clusterContext(generateOkResponse(processGroupEntity)).build(); + } + + // ------ + // search + // ------ + /** * Performs a search request in this flow. * @@ -134,6 +301,8 @@ public class FlowResource extends ApplicationResource { } ) public Response searchFlow(@QueryParam("q") @DefaultValue(StringUtils.EMPTY) String value) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -186,6 +355,8 @@ public class FlowResource extends ApplicationResource { } ) public Response getRevision() { + authorizeFlow(); + // create the current revision final RevisionDTO revision = serviceFacade.getRevision(); @@ -232,6 +403,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + authorizeFlow(); + if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); } @@ -327,6 +500,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + authorizeFlow(); + // get the banner from the properties - will come from the NCM when clustered final String bannerText = properties.getBannerText(); @@ -383,6 +558,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -442,6 +619,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam("serviceType") String serviceType) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -495,6 +674,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -548,6 +729,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -601,6 +784,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -708,6 +893,8 @@ public class FlowResource extends ApplicationResource { ) @QueryParam("limit") IntegerParameter limit) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -807,6 +994,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException("Nodewise requests cannot be directed at a specific node."); @@ -907,6 +1096,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException("Nodewise requests cannot be directed at a specific node."); @@ -1007,6 +1198,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException("Nodewise requests cannot be directed at a specific node."); @@ -1107,6 +1300,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException("Nodewise requests cannot be directed at a specific node."); @@ -1216,6 +1411,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String groupId) { + authorizeFlow(); + // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException("Nodewise requests cannot be directed at a specific node."); @@ -1337,6 +1534,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException("Nodewise requests cannot be directed at a specific node."); @@ -1431,6 +1630,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -1490,6 +1691,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String groupId) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -1553,6 +1756,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -1616,6 +1821,8 @@ public class FlowResource extends ApplicationResource { ) @PathParam("id") String id) { + authorizeFlow(); + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); @@ -1646,6 +1853,50 @@ public class FlowResource extends ApplicationResource { this.clusterManager = clusterManager; } + public void setProcessorResource(ProcessorResource processorResource) { + this.processorResource = processorResource; + } + + public void setInputPortResource(InputPortResource inputPortResource) { + this.inputPortResource = inputPortResource; + } + + public void setOutputPortResource(OutputPortResource outputPortResource) { + this.outputPortResource = outputPortResource; + } + + public void setFunnelResource(FunnelResource funnelResource) { + this.funnelResource = funnelResource; + } + + public void setLabelResource(LabelResource labelResource) { + this.labelResource = labelResource; + } + + public void setRemoteProcessGroupResource(RemoteProcessGroupResource remoteProcessGroupResource) { + this.remoteProcessGroupResource = remoteProcessGroupResource; + } + + public void setConnectionResource(ConnectionResource connectionResource) { + this.connectionResource = connectionResource; + } + + public void setTemplateResource(TemplateResource templateResource) { + this.templateResource = templateResource; + } + + public void setProcessGroupResource(ProcessGroupResource processGroupResource) { + this.processGroupResource = processGroupResource; + } + + public void setControllerServiceResource(ControllerServiceResource controllerServiceResource) { + this.controllerServiceResource = controllerServiceResource; + } + + public void setAuthorizer(Authorizer authorizer) { + this.authorizer = authorizer; + } + public void setProperties(NiFiProperties properties) { this.properties = properties; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FunnelResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FunnelResource.java index 1c4a0eab9b..b3a050f151 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FunnelResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FunnelResource.java @@ -25,9 +25,9 @@ import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.FunnelDTO; import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.entity.FunnelEntity; @@ -71,6 +71,32 @@ public class FunnelResource extends ApplicationResource { private WebClusterManager clusterManager; private NiFiProperties properties; + /** + * Populates the uri for the specified funnels. + * + * @param funnelEntities funnels + * @return funnels + */ + public Set populateRemainingFunnelEntitiesContent(Set funnelEntities) { + for (FunnelEntity funnelEntity : funnelEntities) { + populateRemainingFunnelEntityContent(funnelEntity); + } + return funnelEntities; + } + + /** + * Populates the uri for the specified funnel. + * + * @param funnelEntity funnel + * @return funnel + */ + public FunnelEntity populateRemainingFunnelEntityContent(FunnelEntity funnelEntity) { + if (funnelEntity.getComponent() != null) { + populateRemainingFunnelContent(funnelEntity.getComponent()); + } + return funnelEntity; + } + /** * Populates the uri for the specified funnels. * @@ -96,9 +122,6 @@ public class FunnelResource extends ApplicationResource { /** * Retrieves the specified funnel. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param id The id of the funnel to retrieve * @return A funnelEntity. */ @@ -126,11 +149,6 @@ public class FunnelResource extends ApplicationResource { } ) public Response getFunnel( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The funnel id.", required = true @@ -143,16 +161,8 @@ public class FunnelResource extends ApplicationResource { } // get the funnel - final FunnelDTO funnel = serviceFacade.getFunnel(id); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity - final FunnelEntity entity = new FunnelEntity(); - entity.setRevision(revision); - entity.setFunnel(populateRemainingFunnelContent(funnel)); + final FunnelEntity entity = serviceFacade.getFunnel(id); + populateRemainingFunnelEntityContent(entity); return clusterContext(generateOkResponse(entity)).build(); } @@ -198,7 +208,7 @@ public class FunnelResource extends ApplicationResource { required = true ) FunnelEntity funnelEntity) { - if (funnelEntity == null || funnelEntity.getFunnel() == null) { + if (funnelEntity == null || funnelEntity.getComponent() == null) { throw new IllegalArgumentException("Funnel details must be specified."); } @@ -207,7 +217,7 @@ public class FunnelResource extends ApplicationResource { } // ensure the ids are the same - final FunnelDTO requestFunnelDTO = funnelEntity.getFunnel(); + final FunnelDTO requestFunnelDTO = funnelEntity.getComponent(); if (!id.equals(requestFunnelDTO.getId())) { throw new IllegalArgumentException(String.format("The funnel id (%s) in the request body does not equal the " + "funnel id of the requested resource (%s).", requestFunnelDTO.getId(), id)); @@ -231,25 +241,15 @@ public class FunnelResource extends ApplicationResource { // update the funnel final RevisionDTO revision = funnelEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.updateFunnel( + final UpdateResult updateResult = serviceFacade.updateFunnel( new Revision(revision.getVersion(), revision.getClientId()), requestFunnelDTO); // get the results - final FunnelDTO responseFunnelDTO = controllerResponse.getConfiguration(); - populateRemainingFunnelContent(responseFunnelDTO); + final FunnelEntity entity = updateResult.getResult(); + populateRemainingFunnelEntityContent(entity); - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final FunnelEntity entity = new FunnelEntity(); - entity.setRevision(updatedRevision); - entity.setFunnel(responseFunnelDTO); - - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(responseFunnelDTO.getUri()), entity)).build(); + if (updateResult.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -325,17 +325,7 @@ public class FunnelResource extends ApplicationResource { } // delete the specified funnel - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteFunnel(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final FunnelEntity entity = new FunnelEntity(); - entity.setRevision(revision); - + final FunnelEntity entity = serviceFacade.deleteFunnel(new Revision(clientVersion, clientId.getClientId()), id); return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/InputPortResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/InputPortResource.java index 1d0629fadc..a378ec3e52 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/InputPortResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/InputPortResource.java @@ -25,12 +25,12 @@ import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.api.dto.RevisionDTO; -import org.apache.nifi.web.api.entity.InputPortEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.nifi.web.api.request.LongParameter; @@ -67,6 +67,32 @@ public class InputPortResource extends ApplicationResource { private WebClusterManager clusterManager; private NiFiProperties properties; + /** + * Populates the uri for the specified input ports. + * + * @param inputPortEntites ports + * @return ports + */ + public Set populateRemainingInputPortEntitiesContent(Set inputPortEntites) { + for (PortEntity inputPortEntity : inputPortEntites) { + populateRemainingInputPortEntityContent(inputPortEntity); + } + return inputPortEntites; + } + + /** + * Populates the uri for the specified input port. + * + * @param inputPortEntity port + * @return ports + */ + public PortEntity populateRemainingInputPortEntityContent(PortEntity inputPortEntity) { + if (inputPortEntity.getComponent() != null) { + populateRemainingInputPortContent(inputPortEntity.getComponent()); + } + return inputPortEntity; + } + /** * Populates the uri for the specified input ports. * @@ -92,7 +118,6 @@ public class InputPortResource extends ApplicationResource { /** * Retrieves the specified input port. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the input port to retrieve * @return A inputPortEntity. */ @@ -103,7 +128,7 @@ public class InputPortResource extends ApplicationResource { // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')") @ApiOperation( value = "Gets an input port", - response = InputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Read Only", type = "ROLE_MONITOR"), @Authorization(value = "Data Flow Manager", type = "ROLE_DFM"), @@ -120,11 +145,6 @@ public class InputPortResource extends ApplicationResource { } ) public Response getInputPort( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The input port id.", required = true @@ -137,16 +157,8 @@ public class InputPortResource extends ApplicationResource { } // get the port - final PortDTO port = serviceFacade.getInputPort(id); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity - final InputPortEntity entity = new InputPortEntity(); - entity.setRevision(revision); - entity.setInputPort(populateRemainingInputPortContent(port)); + final PortEntity entity = serviceFacade.getInputPort(id); + populateRemainingInputPortEntityContent(entity); return clusterContext(generateOkResponse(entity)).build(); } @@ -166,7 +178,7 @@ public class InputPortResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Updates an input port", - response = InputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -190,9 +202,9 @@ public class InputPortResource extends ApplicationResource { @ApiParam( value = "The input port configuration details.", required = true - ) InputPortEntity portEntity) { + ) PortEntity portEntity) { - if (portEntity == null || portEntity.getInputPort() == null) { + if (portEntity == null || portEntity.getComponent() == null) { throw new IllegalArgumentException("Input port details must be specified."); } @@ -201,7 +213,7 @@ public class InputPortResource extends ApplicationResource { } // ensure the ids are the same - final PortDTO requestPortDTO = portEntity.getInputPort(); + final PortDTO requestPortDTO = portEntity.getComponent(); if (!id.equals(requestPortDTO.getId())) { throw new IllegalArgumentException(String.format("The input port id (%s) in the request body does not equal the " + "input port id of the requested resource (%s).", requestPortDTO.getId(), id)); @@ -226,25 +238,15 @@ public class InputPortResource extends ApplicationResource { // update the input port final RevisionDTO revision = portEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.updateInputPort( + final UpdateResult updateResult = serviceFacade.updateInputPort( new Revision(revision.getVersion(), revision.getClientId()), requestPortDTO); - // get the results - final PortDTO responsePortDTO = controllerResponse.getConfiguration(); - populateRemainingInputPortContent(responsePortDTO); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - // build the response entity - final InputPortEntity entity = new InputPortEntity(); - entity.setRevision(updatedRevision); - entity.setInputPort(responsePortDTO); + final PortEntity entity = updateResult.getResult(); + populateRemainingInputPortEntityContent(entity); - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(responsePortDTO.getUri()), entity)).build(); + if (updateResult.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -266,7 +268,7 @@ public class InputPortResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Deletes an input port", - response = InputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -317,17 +319,7 @@ public class InputPortResource extends ApplicationResource { } // delete the specified input port - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteInputPort(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final InputPortEntity entity = new InputPortEntity(); - entity.setRevision(revision); - + final PortEntity entity = serviceFacade.deleteInputPort(new Revision(clientVersion, clientId.getClientId()), id); return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/LabelResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/LabelResource.java index 411bad2e72..65dbb75a22 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/LabelResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/LabelResource.java @@ -25,9 +25,9 @@ import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.LabelDTO; import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.entity.LabelEntity; @@ -71,6 +71,32 @@ public class LabelResource extends ApplicationResource { private WebClusterManager clusterManager; private NiFiProperties properties; + /** + * Populates the uri for the specified labels. + * + * @param labelEntities labels + * @return entites + */ + public Set populateRemainingLabelEntitiesContent(Set labelEntities) { + for (LabelEntity labelEntity : labelEntities) { + populateRemainingLabelEntityContent(labelEntity); + } + return labelEntities; + } + + /** + * Populates the uri for the specified labels. + * + * @param labelEntity label + * @return entities + */ + public LabelEntity populateRemainingLabelEntityContent(LabelEntity labelEntity) { + if (labelEntity.getComponent() != null) { + populateRemainingLabelContent(labelEntity.getComponent()); + } + return labelEntity; + } + /** * Populates the uri for the specified labels. * @@ -96,7 +122,6 @@ public class LabelResource extends ApplicationResource { /** * Retrieves the specified label. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the label to retrieve * @return A labelEntity. */ @@ -124,11 +149,6 @@ public class LabelResource extends ApplicationResource { } ) public Response getLabel( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The label id.", required = true @@ -141,16 +161,8 @@ public class LabelResource extends ApplicationResource { } // get the label - final LabelDTO label = serviceFacade.getLabel(id); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity - final LabelEntity entity = new LabelEntity(); - entity.setRevision(revision); - entity.setLabel(populateRemainingLabelContent(label)); + final LabelEntity entity = serviceFacade.getLabel(id); + populateRemainingLabelEntityContent(entity); return clusterContext(generateOkResponse(entity)).build(); } @@ -196,7 +208,7 @@ public class LabelResource extends ApplicationResource { required = true ) LabelEntity labelEntity) { - if (labelEntity == null || labelEntity.getLabel() == null) { + if (labelEntity == null || labelEntity.getComponent() == null) { throw new IllegalArgumentException("Label details must be specified."); } @@ -205,7 +217,7 @@ public class LabelResource extends ApplicationResource { } // ensure the ids are the same - final LabelDTO requestLabelDTO = labelEntity.getLabel(); + final LabelDTO requestLabelDTO = labelEntity.getComponent(); if (!id.equals(requestLabelDTO.getId())) { throw new IllegalArgumentException(String.format("The label id (%s) in the request body does not equal the " + "label id of the requested resource (%s).", requestLabelDTO.getId(), id)); @@ -229,25 +241,13 @@ public class LabelResource extends ApplicationResource { // update the label final RevisionDTO revision = labelEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.updateLabel( + final UpdateResult result = serviceFacade.updateLabel( new Revision(revision.getVersion(), revision.getClientId()), requestLabelDTO); + final LabelEntity entity = result.getResult(); + populateRemainingLabelEntityContent(entity); - // get the results - final LabelDTO responseLabelDTO = controllerResponse.getConfiguration(); - populateRemainingLabelContent(responseLabelDTO); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final LabelEntity entity = new LabelEntity(); - entity.setRevision(updatedRevision); - entity.setLabel(responseLabelDTO); - - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(responseLabelDTO.getUri()), entity)).build(); + if (result.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -319,17 +319,7 @@ public class LabelResource extends ApplicationResource { } // delete the specified label - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteLabel(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final LabelEntity entity = new LabelEntity(); - entity.setRevision(revision); - + final LabelEntity entity = serviceFacade.deleteLabel(new Revision(clientVersion, clientId.getClientId()), id); return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/OutputPortResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/OutputPortResource.java index 13353908f8..398350f1c6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/OutputPortResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/OutputPortResource.java @@ -25,12 +25,12 @@ import com.wordnik.swagger.annotations.Authorization; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.cluster.manager.impl.WebClusterManager; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.api.dto.RevisionDTO; -import org.apache.nifi.web.api.entity.OutputPortEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.nifi.web.api.request.LongParameter; import org.slf4j.Logger; @@ -71,6 +71,32 @@ public class OutputPortResource extends ApplicationResource { private WebClusterManager clusterManager; private NiFiProperties properties; + /** + * Populates the uri for the specified output ports. + * + * @param outputPortEntities ports + * @return dtos + */ + public Set populateRemainingOutputPortEntitiesContent(Set outputPortEntities) { + for (PortEntity outputPortEntity : outputPortEntities) { + populateRemainingOutputPortEntityContent(outputPortEntity); + } + return outputPortEntities; + } + + /** + * Populates the uri for the specified output ports. + * + * @param outputPortEntity ports + * @return dtos + */ + public PortEntity populateRemainingOutputPortEntityContent(PortEntity outputPortEntity) { + if (outputPortEntity.getComponent() != null) { + populateRemainingOutputPortContent(outputPortEntity.getComponent()); + } + return outputPortEntity; + } + /** * Populates the uri for the specified output ports. * @@ -96,7 +122,6 @@ public class OutputPortResource extends ApplicationResource { /** * Retrieves the specified output port. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the output port to retrieve * @return A outputPortEntity. */ @@ -107,7 +132,7 @@ public class OutputPortResource extends ApplicationResource { // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')") @ApiOperation( value = "Gets an output port", - response = OutputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Read Only", type = "ROLE_MONITOR"), @Authorization(value = "Data Flow Manager", type = "ROLE_DFM"), @@ -124,11 +149,6 @@ public class OutputPortResource extends ApplicationResource { } ) public Response getOutputPort( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The output port id.", required = true @@ -141,16 +161,8 @@ public class OutputPortResource extends ApplicationResource { } // get the port - final PortDTO port = serviceFacade.getOutputPort(id); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity - final OutputPortEntity entity = new OutputPortEntity(); - entity.setRevision(revision); - entity.setOutputPort(populateRemainingOutputPortContent(port)); + final PortEntity entity = serviceFacade.getOutputPort(id); + populateRemainingOutputPortEntityContent(entity); return clusterContext(generateOkResponse(entity)).build(); } @@ -170,7 +182,7 @@ public class OutputPortResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Updates an output port", - response = OutputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -194,9 +206,9 @@ public class OutputPortResource extends ApplicationResource { @ApiParam( value = "The output port configuration details.", required = true - ) OutputPortEntity portEntity) { + ) PortEntity portEntity) { - if (portEntity == null || portEntity.getOutputPort() == null) { + if (portEntity == null || portEntity.getComponent() == null) { throw new IllegalArgumentException("Output port details must be specified."); } @@ -205,7 +217,7 @@ public class OutputPortResource extends ApplicationResource { } // ensure the ids are the same - PortDTO requestPortDTO = portEntity.getOutputPort(); + PortDTO requestPortDTO = portEntity.getComponent(); if (!id.equals(requestPortDTO.getId())) { throw new IllegalArgumentException(String.format("The output port id (%s) in the request body does not equal the " + "output port id of the requested resource (%s).", requestPortDTO.getId(), id)); @@ -230,25 +242,15 @@ public class OutputPortResource extends ApplicationResource { // update the output port final RevisionDTO revision = portEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.updateOutputPort( + final UpdateResult updateResult = serviceFacade.updateOutputPort( new Revision(revision.getVersion(), revision.getClientId()), requestPortDTO); // get the results - final PortDTO responsePortDTO = controllerResponse.getConfiguration(); - populateRemainingOutputPortContent(responsePortDTO); + final PortEntity entity = updateResult.getResult(); + populateRemainingOutputPortEntityContent(entity); - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final OutputPortEntity entity = new OutputPortEntity(); - entity.setRevision(updatedRevision); - entity.setOutputPort(responsePortDTO); - - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(responsePortDTO.getUri()), entity)).build(); + if (updateResult.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -270,7 +272,7 @@ public class OutputPortResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Deletes an output port", - response = OutputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -321,17 +323,7 @@ public class OutputPortResource extends ApplicationResource { } // delete the specified output port - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteOutputPort(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final OutputPortEntity entity = new OutputPortEntity(); - entity.setRevision(revision); - + final PortEntity entity = serviceFacade.deleteOutputPort(new Revision(clientVersion, clientId.getClientId()), id); return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java index 208d30db9f..49a32641e2 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java @@ -32,34 +32,31 @@ import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.ControllerServiceDTO; -import org.apache.nifi.web.api.dto.FlowSnippetDTO; -import org.apache.nifi.web.api.dto.FunnelDTO; -import org.apache.nifi.web.api.dto.LabelDTO; -import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.api.dto.ProcessGroupDTO; -import org.apache.nifi.web.api.dto.ProcessorDTO; import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO; import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.dto.SnippetDTO; import org.apache.nifi.web.api.dto.TemplateDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionsEntity; import org.apache.nifi.web.api.entity.ControllerServiceEntity; import org.apache.nifi.web.api.entity.ControllerServicesEntity; import org.apache.nifi.web.api.entity.CopySnippetRequestEntity; import org.apache.nifi.web.api.entity.CreateTemplateRequestEntity; +import org.apache.nifi.web.api.entity.FlowEntity; import org.apache.nifi.web.api.entity.FlowSnippetEntity; import org.apache.nifi.web.api.entity.FunnelEntity; import org.apache.nifi.web.api.entity.FunnelsEntity; -import org.apache.nifi.web.api.entity.InputPortEntity; import org.apache.nifi.web.api.entity.InputPortsEntity; import org.apache.nifi.web.api.entity.InstantiateTemplateRequestEntity; import org.apache.nifi.web.api.entity.LabelEntity; import org.apache.nifi.web.api.entity.LabelsEntity; -import org.apache.nifi.web.api.entity.OutputPortEntity; import org.apache.nifi.web.api.entity.OutputPortsEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.ProcessGroupsEntity; import org.apache.nifi.web.api.entity.ProcessorEntity; @@ -138,6 +135,32 @@ public class ProcessGroupResource extends ApplicationResource { private TemplateResource templateResource; private ControllerServiceResource controllerServiceResource; + /** + * Populates the remaining fields in the specified process groups. + * + * @param processGroupEntities groups + * @return group dto + */ + public Set populateRemainingProcessGroupEntitiesContent(Set processGroupEntities) { + for (ProcessGroupEntity processGroupEntity : processGroupEntities) { + populateRemainingProcessGroupEntityContent(processGroupEntity); + } + return processGroupEntities; + } + + /** + * Populates the remaining fields in the specified process group. + * + * @param processGroupEntity group + * @return group dto + */ + public ProcessGroupEntity populateRemainingProcessGroupEntityContent(ProcessGroupEntity processGroupEntity) { + if (processGroupEntity.getComponent() != null) { + populateRemainingProcessGroupContent(processGroupEntity.getComponent()); + } + return processGroupEntity; + } + /** * Populates the remaining fields in the specified process groups. * @@ -158,37 +181,28 @@ public class ProcessGroupResource extends ApplicationResource { * @return group dto */ private ProcessGroupDTO populateRemainingProcessGroupContent(ProcessGroupDTO processGroup) { - FlowSnippetDTO flowSnippet = processGroup.getContents(); - - // populate the remaining fields for the processors, connections, process group refs, remote process groups, and labels if appropriate - if (flowSnippet != null) { - populateRemainingSnippetContent(flowSnippet); - } - - // set the process group uri processGroup.setUri(generateResourceUri("process-groups", processGroup.getId())); - return processGroup; } /** * Populates the remaining content of the specified snippet. */ - private FlowSnippetDTO populateRemainingSnippetContent(FlowSnippetDTO snippet) { - processorResource.populateRemainingProcessorsContent(snippet.getProcessors()); - connectionResource.populateRemainingConnectionsContent(snippet.getConnections()); - inputPortResource.populateRemainingInputPortsContent(snippet.getInputPorts()); - outputPortResource.populateRemainingOutputPortsContent(snippet.getOutputPorts()); - remoteProcessGroupResource.populateRemainingRemoteProcessGroupsContent(snippet.getRemoteProcessGroups()); - funnelResource.populateRemainingFunnelsContent(snippet.getFunnels()); - labelResource.populateRemainingLabelsContent(snippet.getLabels()); + private FlowDTO populateRemainingSnippetContent(FlowDTO flow) { + processorResource.populateRemainingProcessorEntitiesContent(flow.getProcessors()); + connectionResource.populateRemainingConnectionEntitiesContent(flow.getConnections()); + inputPortResource.populateRemainingInputPortEntitiesContent(flow.getInputPorts()); + outputPortResource.populateRemainingOutputPortEntitiesContent(flow.getOutputPorts()); + remoteProcessGroupResource.populateRemainingRemoteProcessGroupEntitiesContent(flow.getRemoteProcessGroups()); + funnelResource.populateRemainingFunnelEntitiesContent(flow.getFunnels()); + labelResource.populateRemainingLabelEntitiesContent(flow.getLabels()); // go through each process group child and populate its uri - if (snippet.getProcessGroups() != null) { - populateRemainingProcessGroupsContent(snippet.getProcessGroups()); + if (flow.getProcessGroups() != null) { + populateRemainingProcessGroupEntitiesContent(flow.getProcessGroups()); } - return snippet; + return flow; } /** @@ -196,26 +210,17 @@ public class ProcessGroupResource extends ApplicationResource { */ private SnippetDTO populateRemainingSnippetContent(SnippetDTO snippet) { String snippetGroupId = snippet.getParentGroupId(); - FlowSnippetDTO snippetContents = snippet.getContents(); // populate the snippet href snippet.setUri(generateResourceUri("process-groups", snippetGroupId, "snippets", snippet.getId())); - // populate the snippet content uris - if (snippet.getContents() != null) { - populateRemainingSnippetContent(snippetContents); - } - return snippet; } /** * Retrieves the contents of the specified group. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. - * @param recursive Optional recursive flag that defaults to false. If set to true, all descendent groups and their content will be included if the verbose flag is also set to true. * @param groupId The id of the process group. - * @param verbose Optional verbose flag that defaults to false. If the verbose flag is set to true processor configuration and property details will be included in the response. * @return A processGroupEntity. */ @GET @@ -242,55 +247,27 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getProcessGroup( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = false ) - @PathParam("id") String groupId, - @ApiParam( - value = "Whether the response should contain all encapsulated components or just the immediate children.", - required = false - ) - @QueryParam("recursive") @DefaultValue(RECURSIVE) Boolean recursive, - @ApiParam( - value = "Whether to include any encapulated components or just details about the process group.", - required = false - ) - @QueryParam("verbose") @DefaultValue(VERBOSE) Boolean verbose) { + @PathParam("id") String groupId) { // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); } - // only recurse if the request is verbose and recursive - final boolean recurse = verbose && recursive; - // get this process group contents - final ConfigurationSnapshot controllerResponse = serviceFacade.getProcessGroup(groupId, recurse); - final ProcessGroupDTO processGroup = controllerResponse.getConfiguration(); + final ProcessGroupEntity entity = serviceFacade.getProcessGroup(groupId); + populateRemainingProcessGroupEntityContent(entity); - // prune the response if necessary - if (!verbose) { - processGroup.setContents(null); + if (entity.getComponent() != null) { + entity.getComponent().setContents(null); } - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - // create the response entity - final ProcessGroupEntity processGroupEntity = new ProcessGroupEntity(); - processGroupEntity.setRevision(revision); - processGroupEntity.setProcessGroup(populateRemainingProcessGroupContent(processGroup)); - - return clusterContext(generateOkResponse(processGroupEntity)).build(); + return clusterContext(generateOkResponse(entity)).build(); } /** @@ -335,7 +312,7 @@ public class ProcessGroupResource extends ApplicationResource { ) ProcessGroupEntity processGroupEntity) { - if (processGroupEntity == null || processGroupEntity.getProcessGroup() == null) { + if (processGroupEntity == null || processGroupEntity.getComponent() == null) { throw new IllegalArgumentException("Process group details must be specified."); } @@ -344,7 +321,7 @@ public class ProcessGroupResource extends ApplicationResource { } // ensure the same id is being used - final ProcessGroupDTO requestProcessGroupDTO = processGroupEntity.getProcessGroup(); + final ProcessGroupDTO requestProcessGroupDTO = processGroupEntity.getComponent(); if (!id.equals(requestProcessGroupDTO.getId())) { throw new IllegalArgumentException(String.format("The process group id (%s) in the request body does " + "not equal the process group id of the requested resource (%s).", requestProcessGroupDTO.getId(), id)); @@ -363,22 +340,12 @@ public class ProcessGroupResource extends ApplicationResource { // update the process group final RevisionDTO revision = processGroupEntity.getRevision(); - final ConfigurationSnapshot response = serviceFacade.updateProcessGroup( - new Revision(revision.getVersion(), revision.getClientId()), requestProcessGroupDTO); - final ProcessGroupDTO processGroup = response.getConfiguration(); + final UpdateResult updateResult = serviceFacade.updateProcessGroup(new Revision(revision.getVersion(), revision.getClientId()), requestProcessGroupDTO); + final ProcessGroupEntity entity = updateResult.getResult(); + populateRemainingProcessGroupEntityContent(entity); - // create the revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(response.getVersion()); - - // create the response entity - final ProcessGroupEntity entity = new ProcessGroupEntity(); - entity.setRevision(updatedRevision); - entity.setProcessGroup(populateRemainingProcessGroupContent(processGroup)); - - if (response.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(processGroup.getUri()), entity)).build(); + if (updateResult.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -451,16 +418,7 @@ public class ProcessGroupResource extends ApplicationResource { } // delete the process group - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteProcessGroup(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - - // create the response entity - final ProcessGroupEntity entity = new ProcessGroupEntity(); - entity.setRevision(revision); + final ProcessGroupEntity entity = serviceFacade.deleteProcessGroup(new Revision(clientVersion, clientId.getClientId()), id); // create the response return clusterContext(generateOkResponse(entity)).build(); @@ -508,7 +466,7 @@ public class ProcessGroupResource extends ApplicationResource { ) ProcessGroupEntity processGroupEntity) { - if (processGroupEntity == null || processGroupEntity.getProcessGroup() == null) { + if (processGroupEntity == null || processGroupEntity.getComponent() == null) { throw new IllegalArgumentException("Process group details must be specified."); } @@ -516,10 +474,16 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (processGroupEntity.getProcessGroup().getId() != null) { + if (processGroupEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Process group ID cannot be specified."); } + if (processGroupEntity.getComponent().getParentGroupId() != null && !groupId.equals(processGroupEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + processGroupEntity.getComponent().getParentGroupId(), groupId)); + } + processGroupEntity.getComponent().setParentGroupId(groupId); + if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(processGroupEntity), getHeaders()).getResponse(); } @@ -533,36 +497,24 @@ public class ProcessGroupResource extends ApplicationResource { // set the processor id as appropriate final ClusterContext clusterContext = ClusterContextThreadLocal.getContext(); if (clusterContext != null) { - processGroupEntity.getProcessGroup().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); + processGroupEntity.getComponent().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); } else { - processGroupEntity.getProcessGroup().setId(UUID.randomUUID().toString()); + processGroupEntity.getComponent().setId(UUID.randomUUID().toString()); } // create the process group contents final RevisionDTO revision = processGroupEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createProcessGroup(groupId, - new Revision(revision.getVersion(), revision.getClientId()), processGroupEntity.getProcessGroup()); - final ProcessGroupDTO processGroup = controllerResponse.getConfiguration(); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // create the response entity - final ProcessGroupEntity entity = new ProcessGroupEntity(); - entity.setRevision(updatedRevision); - entity.setProcessGroup(populateRemainingProcessGroupContent(processGroup)); + final ProcessGroupEntity entity = serviceFacade.createProcessGroup(groupId, new Revision(revision.getVersion(), revision.getClientId()), processGroupEntity.getComponent()); + populateRemainingProcessGroupEntityContent(entity); // generate a 201 created response - String uri = processGroup.getUri(); + String uri = entity.getComponent().getUri(); return clusterContext(generateCreatedResponse(URI.create(uri), entity)).build(); } /** * Retrieves all the processors in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @return A processorsEntity. */ @GET @@ -589,7 +541,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getProcessGroups( - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -602,16 +553,18 @@ public class ProcessGroupResource extends ApplicationResource { } // get the process groups - final Set processGroupDTOs = serviceFacade.getProcessGroups(groupId); + final Set entities = serviceFacade.getProcessGroups(groupId); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); + // always prune the contents + for (final ProcessGroupEntity entity : entities) { + if (entity.getComponent() != null) { + entity.getComponent().setContents(null); + } + } // create the response entity final ProcessGroupsEntity entity = new ProcessGroupsEntity(); - entity.setRevision(revision); - entity.setProcessGroups(populateRemainingProcessGroupsContent(processGroupDTOs)); + entity.setProcessGroups(populateRemainingProcessGroupEntitiesContent(entities)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -663,7 +616,7 @@ public class ProcessGroupResource extends ApplicationResource { ) ProcessorEntity processorEntity) { - if (processorEntity == null || processorEntity.getProcessor() == null) { + if (processorEntity == null || processorEntity.getComponent() == null) { throw new IllegalArgumentException("Processor details must be specified."); } @@ -671,14 +624,20 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (processorEntity.getProcessor().getId() != null) { + if (processorEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Processor ID cannot be specified."); } - if (StringUtils.isBlank(processorEntity.getProcessor().getType())) { + if (StringUtils.isBlank(processorEntity.getComponent().getType())) { throw new IllegalArgumentException("The type of processor to create must be specified."); } + if (processorEntity.getComponent().getParentGroupId() != null && !groupId.equals(processorEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + processorEntity.getComponent().getParentGroupId(), groupId)); + } + processorEntity.getComponent().setParentGroupId(groupId); + if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(processorEntity), getHeaders()).getResponse(); } @@ -692,37 +651,25 @@ public class ProcessGroupResource extends ApplicationResource { // set the processor id as appropriate final ClusterContext clusterContext = ClusterContextThreadLocal.getContext(); if (clusterContext != null) { - processorEntity.getProcessor().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); + processorEntity.getComponent().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); } else { - processorEntity.getProcessor().setId(UUID.randomUUID().toString()); + processorEntity.getComponent().setId(UUID.randomUUID().toString()); } // create the new processor final RevisionDTO revision = processorEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createProcessor( - new Revision(revision.getVersion(), revision.getClientId()), groupId, processorEntity.getProcessor()); - final ProcessorDTO processor = controllerResponse.getConfiguration(); - processorResource.populateRemainingProcessorContent(processor); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // generate the response entity - final ProcessorEntity entity = new ProcessorEntity(); - entity.setRevision(updatedRevision); - entity.setProcessor(processor); + final ProcessorEntity entity = serviceFacade.createProcessor(new Revision(revision.getVersion(), revision.getClientId()), groupId, processorEntity.getComponent()); + processorResource.populateRemainingProcessorEntityContent(entity); // generate a 201 created response - String uri = processor.getUri(); + String uri = entity.getComponent().getUri(); return clusterContext(generateCreatedResponse(URI.create(uri), entity)).build(); } /** * Retrieves all the processors in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. + * @param groupId group id * @return A processorsEntity. */ @GET @@ -749,7 +696,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getProcessors( - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -762,16 +708,11 @@ public class ProcessGroupResource extends ApplicationResource { } // get the processors - final Set processorDTOs = serviceFacade.getProcessors(groupId); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); + final Set processors = serviceFacade.getProcessors(groupId); // create the response entity final ProcessorsEntity entity = new ProcessorsEntity(); - entity.setRevision(revision); - entity.setProcessors(processorResource.populateRemainingProcessorsContent(processorDTOs)); + entity.setProcessors(processorResource.populateRemainingProcessorEntitiesContent(processors)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -796,7 +737,7 @@ public class ProcessGroupResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Creates an input port", - response = InputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -820,9 +761,9 @@ public class ProcessGroupResource extends ApplicationResource { @ApiParam( value = "The input port configuration details.", required = true - ) InputPortEntity portEntity) { + ) PortEntity portEntity) { - if (portEntity == null || portEntity.getInputPort() == null) { + if (portEntity == null || portEntity.getComponent() == null) { throw new IllegalArgumentException("Port details must be specified."); } @@ -830,10 +771,16 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (portEntity.getInputPort().getId() != null) { + if (portEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Input port ID cannot be specified."); } + if (portEntity.getComponent().getParentGroupId() != null && !groupId.equals(portEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + portEntity.getComponent().getParentGroupId(), groupId)); + } + portEntity.getComponent().setParentGroupId(groupId); + if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(portEntity), getHeaders()).getResponse(); } @@ -847,36 +794,23 @@ public class ProcessGroupResource extends ApplicationResource { // set the processor id as appropriate final ClusterContext clusterContext = ClusterContextThreadLocal.getContext(); if (clusterContext != null) { - portEntity.getInputPort().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); + portEntity.getComponent().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); } else { - portEntity.getInputPort().setId(UUID.randomUUID().toString()); + portEntity.getComponent().setId(UUID.randomUUID().toString()); } // create the input port and generate the json final RevisionDTO revision = portEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createInputPort( - new Revision(revision.getVersion(), revision.getClientId()), groupId, portEntity.getInputPort()); - final PortDTO port = controllerResponse.getConfiguration(); - inputPortResource.populateRemainingInputPortContent(port); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final InputPortEntity entity = new InputPortEntity(); - entity.setRevision(updatedRevision); - entity.setInputPort(port); + final PortEntity entity = serviceFacade.createInputPort(new Revision(revision.getVersion(), revision.getClientId()), groupId, portEntity.getComponent()); + inputPortResource.populateRemainingInputPortEntityContent(entity); // build the response - return clusterContext(generateCreatedResponse(URI.create(port.getUri()), entity)).build(); + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } /** * Retrieves all the of input ports in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @return A inputPortsEntity. */ @GET @@ -903,11 +837,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getInputPorts( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -920,16 +849,10 @@ public class ProcessGroupResource extends ApplicationResource { } // get all the input ports - final Set inputPorts = inputPortResource.populateRemainingInputPortsContent(serviceFacade.getInputPorts(groupId)); + final Set inputPorts = serviceFacade.getInputPorts(groupId); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity final InputPortsEntity entity = new InputPortsEntity(); - entity.setRevision(revision); - entity.setInputPorts(inputPorts); + entity.setInputPorts(inputPortResource.populateRemainingInputPortEntitiesContent(inputPorts)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -954,7 +877,7 @@ public class ProcessGroupResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Creates an output port", - response = OutputPortEntity.class, + response = PortEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -978,9 +901,9 @@ public class ProcessGroupResource extends ApplicationResource { @ApiParam( value = "The output port configuration.", required = true - ) OutputPortEntity portEntity) { + ) PortEntity portEntity) { - if (portEntity == null || portEntity.getOutputPort() == null) { + if (portEntity == null || portEntity.getComponent() == null) { throw new IllegalArgumentException("Port details must be specified."); } @@ -988,10 +911,16 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (portEntity.getOutputPort().getId() != null) { + if (portEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Output port ID cannot be specified."); } + if (portEntity.getComponent().getParentGroupId() != null && !groupId.equals(portEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + portEntity.getComponent().getParentGroupId(), groupId)); + } + portEntity.getComponent().setParentGroupId(groupId); + if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(portEntity), getHeaders()).getResponse(); } @@ -1005,36 +934,24 @@ public class ProcessGroupResource extends ApplicationResource { // set the processor id as appropriate final ClusterContext clusterContext = ClusterContextThreadLocal.getContext(); if (clusterContext != null) { - portEntity.getOutputPort().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); + portEntity.getComponent().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); } else { - portEntity.getOutputPort().setId(UUID.randomUUID().toString()); + portEntity.getComponent().setId(UUID.randomUUID().toString()); } // create the output port and generate the json final RevisionDTO revision = portEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createOutputPort( - new Revision(revision.getVersion(), revision.getClientId()), groupId, portEntity.getOutputPort()); - final PortDTO port = controllerResponse.getConfiguration(); - outputPortResource.populateRemainingOutputPortContent(port); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final OutputPortEntity entity = new OutputPortEntity(); - entity.setRevision(updatedRevision); - entity.setOutputPort(port); + final PortEntity entity = serviceFacade.createOutputPort( + new Revision(revision.getVersion(), revision.getClientId()), groupId, portEntity.getComponent()); + outputPortResource.populateRemainingOutputPortEntityContent(entity); // build the response - return clusterContext(generateCreatedResponse(URI.create(port.getUri()), entity)).build(); + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } /** * Retrieves all the of output ports in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @return A outputPortsEntity. */ @GET @@ -1061,11 +978,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getOutputPorts( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -1078,16 +990,11 @@ public class ProcessGroupResource extends ApplicationResource { } // get all the output ports - final Set outputPorts = outputPortResource.populateRemainingOutputPortsContent(serviceFacade.getOutputPorts(groupId)); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); + final Set outputPorts = serviceFacade.getOutputPorts(groupId); // create the response entity final OutputPortsEntity entity = new OutputPortsEntity(); - entity.setRevision(revision); - entity.setOutputPorts(outputPorts); + entity.setOutputPorts(outputPortResource.populateRemainingOutputPortEntitiesContent(outputPorts)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -1138,7 +1045,7 @@ public class ProcessGroupResource extends ApplicationResource { required = true ) FunnelEntity funnelEntity) { - if (funnelEntity == null || funnelEntity.getFunnel() == null) { + if (funnelEntity == null || funnelEntity.getComponent() == null) { throw new IllegalArgumentException("Funnel details must be specified."); } @@ -1146,17 +1053,18 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (funnelEntity.getFunnel().getId() != null) { + if (funnelEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Funnel ID cannot be specified."); } - if (properties.isClusterManager()) { - // change content type to JSON for serializing entity if request came through overloaded endpoint - final Map headersToOverride = new HashMap<>(); - headersToOverride.put("content-type", MediaType.APPLICATION_JSON); + if (funnelEntity.getComponent().getParentGroupId() != null && !groupId.equals(funnelEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + funnelEntity.getComponent().getParentGroupId(), groupId)); + } + funnelEntity.getComponent().setParentGroupId(groupId); - // replicate the request - return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(funnelEntity), getHeaders(headersToOverride)).getResponse(); + if (properties.isClusterManager()) { + return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(funnelEntity), getHeaders()).getResponse(); } // handle expects request (usually from the cluster manager) @@ -1168,38 +1076,23 @@ public class ProcessGroupResource extends ApplicationResource { // set the processor id as appropriate final ClusterContext clusterContext = ClusterContextThreadLocal.getContext(); if (clusterContext != null) { - funnelEntity.getFunnel().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); + funnelEntity.getComponent().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); } else { - funnelEntity.getFunnel().setId(UUID.randomUUID().toString()); + funnelEntity.getComponent().setId(UUID.randomUUID().toString()); } // create the funnel and generate the json final RevisionDTO revision = funnelEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createFunnel( - new Revision(revision.getVersion(), revision.getClientId()), groupId, funnelEntity.getFunnel()); - final FunnelDTO funnel = controllerResponse.getConfiguration(); - funnelResource.populateRemainingFunnelContent(funnel); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final FunnelEntity entity = new FunnelEntity(); - entity.setRevision(updatedRevision); - entity.setFunnel(funnel); + final FunnelEntity entity = serviceFacade.createFunnel(new Revision(revision.getVersion(), revision.getClientId()), groupId, funnelEntity.getComponent()); + funnelResource.populateRemainingFunnelEntityContent(entity); // build the response - return clusterContext(generateCreatedResponse(URI.create(funnel.getUri()), entity)).build(); + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } /** * Retrieves all the of funnels in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @return A funnelsEntity. */ @GET @@ -1226,11 +1119,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getFunnels( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -1243,16 +1131,11 @@ public class ProcessGroupResource extends ApplicationResource { } // get all the funnels - final Set funnels = funnelResource.populateRemainingFunnelsContent(serviceFacade.getFunnels(groupId)); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); + final Set funnels = serviceFacade.getFunnels(groupId); // create the response entity final FunnelsEntity entity = new FunnelsEntity(); - entity.setRevision(revision); - entity.setFunnels(funnels); + entity.setFunnels(funnelResource.populateRemainingFunnelEntitiesContent(funnels)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -1303,7 +1186,7 @@ public class ProcessGroupResource extends ApplicationResource { required = true ) LabelEntity labelEntity) { - if (labelEntity == null || labelEntity.getLabel() == null) { + if (labelEntity == null || labelEntity.getComponent() == null) { throw new IllegalArgumentException("Label details must be specified."); } @@ -1311,10 +1194,16 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (labelEntity.getLabel().getId() != null) { + if (labelEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Label ID cannot be specified."); } + if (labelEntity.getComponent().getParentGroupId() != null && !groupId.equals(labelEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + labelEntity.getComponent().getParentGroupId(), groupId)); + } + labelEntity.getComponent().setParentGroupId(groupId); + if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(labelEntity), getHeaders()).getResponse(); } @@ -1328,41 +1217,29 @@ public class ProcessGroupResource extends ApplicationResource { // set the processor id as appropriate final ClusterContext clusterContext = ClusterContextThreadLocal.getContext(); if (clusterContext != null) { - labelEntity.getLabel().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); + labelEntity.getComponent().setId(UUID.nameUUIDFromBytes(clusterContext.getIdGenerationSeed().getBytes(StandardCharsets.UTF_8)).toString()); } else { - labelEntity.getLabel().setId(UUID.randomUUID().toString()); + labelEntity.getComponent().setId(UUID.randomUUID().toString()); } // create the label and generate the json final RevisionDTO revision = labelEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createLabel( - new Revision(revision.getVersion(), revision.getClientId()), groupId, labelEntity.getLabel()); - final LabelDTO label = controllerResponse.getConfiguration(); - labelResource.populateRemainingLabelContent(label); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final LabelEntity entity = new LabelEntity(); - entity.setRevision(updatedRevision); - entity.setLabel(label); + final LabelEntity entity = serviceFacade.createLabel( + new Revision(revision.getVersion(), revision.getClientId()), groupId, labelEntity.getComponent()); + labelResource.populateRemainingLabelEntityContent(entity); // build the response - return clusterContext(generateCreatedResponse(URI.create(label.getUri()), entity)).build(); + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } /** * Retrieves all the of labels in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @return A labelsEntity. */ @GET @Consumes(MediaType.WILDCARD) - @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces(MediaType.APPLICATION_JSON) @Path("{id}/labels") // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')") @ApiOperation( @@ -1384,11 +1261,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getLabels( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -1401,16 +1273,11 @@ public class ProcessGroupResource extends ApplicationResource { } // get all the labels - final Set labels = labelResource.populateRemainingLabelsContent(serviceFacade.getLabels(groupId)); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); + final Set labels = serviceFacade.getLabels(groupId); // create the response entity final LabelsEntity entity = new LabelsEntity(); - entity.setRevision(revision); - entity.setLabels(labels); + entity.setLabels(labelResource.populateRemainingLabelEntitiesContent(labels)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -1461,7 +1328,7 @@ public class ProcessGroupResource extends ApplicationResource { required = true ) RemoteProcessGroupEntity remoteProcessGroupEntity) { - if (remoteProcessGroupEntity == null || remoteProcessGroupEntity.getRemoteProcessGroup() == null) { + if (remoteProcessGroupEntity == null || remoteProcessGroupEntity.getComponent() == null) { throw new IllegalArgumentException("Remote process group details must be specified."); } @@ -1469,7 +1336,7 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - final RemoteProcessGroupDTO requestProcessGroupDTO = remoteProcessGroupEntity.getRemoteProcessGroup(); + final RemoteProcessGroupDTO requestProcessGroupDTO = remoteProcessGroupEntity.getComponent(); if (requestProcessGroupDTO.getId() != null) { throw new IllegalArgumentException("Remote process group ID cannot be specified."); @@ -1479,14 +1346,14 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("The URI of the process group must be specified."); } - // if cluster manager, convert POST to PUT (to maintain same ID across nodes) and replicate - if (properties.isClusterManager()) { - // change content type to JSON for serializing entity if request came through overloaded endpoint - final Map headersToOverride = new HashMap<>(); - headersToOverride.put("content-type", MediaType.APPLICATION_JSON); + if (requestProcessGroupDTO.getParentGroupId() != null && !groupId.equals(requestProcessGroupDTO.getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + requestProcessGroupDTO.getParentGroupId(), groupId)); + } + requestProcessGroupDTO.setParentGroupId(groupId); - // replicate the request - return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(remoteProcessGroupEntity), getHeaders(headersToOverride)).getResponse(); + if (properties.isClusterManager()) { + return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(remoteProcessGroupEntity), getHeaders()).getResponse(); } // handle expects request (usually from the cluster manager) @@ -1531,30 +1398,15 @@ public class ProcessGroupResource extends ApplicationResource { // create the remote process group final RevisionDTO revision = remoteProcessGroupEntity.getRevision(); - final ConfigurationSnapshot controllerResponse - = serviceFacade.createRemoteProcessGroup(new Revision(revision.getVersion(), revision.getClientId()), groupId, requestProcessGroupDTO); + final RemoteProcessGroupEntity entity = serviceFacade.createRemoteProcessGroup(new Revision(revision.getVersion(), revision.getClientId()), groupId, requestProcessGroupDTO); + remoteProcessGroupResource.populateRemainingRemoteProcessGroupEntityContent(entity); - // prepare the response - final RemoteProcessGroupDTO remoteProcessGroup = controllerResponse.getConfiguration(); - remoteProcessGroupResource.populateRemainingRemoteProcessGroupContent(remoteProcessGroup); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final RemoteProcessGroupEntity entity = new RemoteProcessGroupEntity(); - entity.setRevision(updatedRevision); - entity.setRemoteProcessGroup(remoteProcessGroup); - - return clusterContext(generateCreatedResponse(URI.create(remoteProcessGroup.getUri()), entity)).build(); + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } /** * Retrieves all the of remote process groups in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param verbose Optional verbose flag that defaults to false. If the verbose flag is set to true remote group contents (ports) will be included. * @return A remoteProcessGroupEntity. */ @@ -1582,11 +1434,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getRemoteProcessGroups( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "Whether to include any encapulated ports or just details about the remote process group.", required = false @@ -1603,24 +1450,21 @@ public class ProcessGroupResource extends ApplicationResource { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); } - // get all the labels - final Set remoteProcessGroups = serviceFacade.getRemoteProcessGroups(groupId); + // get all the remote process groups + final Set remoteProcessGroups = serviceFacade.getRemoteProcessGroups(groupId); // prune response as necessary if (!verbose) { - for (RemoteProcessGroupDTO remoteProcessGroup : remoteProcessGroups) { - remoteProcessGroup.setContents(null); + for (RemoteProcessGroupEntity remoteProcessGroupEntity : remoteProcessGroups) { + if (remoteProcessGroupEntity.getComponent() != null) { + remoteProcessGroupEntity.getComponent().setContents(null); + } } } - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // create the response entity final RemoteProcessGroupsEntity entity = new RemoteProcessGroupsEntity(); - entity.setRevision(revision); - entity.setRemoteProcessGroups(remoteProcessGroupResource.populateRemainingRemoteProcessGroupsContent(remoteProcessGroups)); + entity.setRemoteProcessGroups(remoteProcessGroupResource.populateRemainingRemoteProcessGroupEntitiesContent(remoteProcessGroups)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -1671,11 +1515,11 @@ public class ProcessGroupResource extends ApplicationResource { required = true ) ConnectionEntity connectionEntity) { - if (connectionEntity == null || connectionEntity.getConnection() == null) { + if (connectionEntity == null || connectionEntity.getComponent() == null) { throw new IllegalArgumentException("Connection details must be specified."); } - if (connectionEntity.getConnection().getId() != null) { + if (connectionEntity.getComponent().getId() != null) { throw new IllegalArgumentException("Connection ID cannot be specified."); } @@ -1683,17 +1527,18 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("Revision must be specified."); } - if (properties.isClusterManager()) { - // change content type to JSON for serializing entity if request came through overloaded endpoint - final Map headersToOverride = new HashMap<>(); - headersToOverride.put("content-type", MediaType.APPLICATION_JSON); + if (connectionEntity.getComponent().getParentGroupId() != null && !groupId.equals(connectionEntity.getComponent().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + connectionEntity.getComponent().getParentGroupId(), groupId)); + } + connectionEntity.getComponent().setParentGroupId(groupId); - // replicate the request - return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(connectionEntity), getHeaders(headersToOverride)).getResponse(); + if (properties.isClusterManager()) { + return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(connectionEntity), getHeaders()).getResponse(); } // get the connection - final ConnectionDTO connection = connectionEntity.getConnection(); + final ConnectionDTO connection = connectionEntity.getComponent(); // handle expects request (usually from the cluster manager) final String expects = httpServletRequest.getHeader(WebClusterManager.NCM_EXPECTS_HTTP_HEADER); @@ -1712,33 +1557,17 @@ public class ProcessGroupResource extends ApplicationResource { // create the new relationship target final RevisionDTO revision = connectionEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.createConnection( - new Revision(revision.getVersion(), revision.getClientId()), groupId, connection); - ConnectionDTO connectionDTO = controllerResponse.getConfiguration(); - - // marshall the target and add the source processor - connectionResource.populateRemainingConnectionContent(connectionDTO); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // create the response entity - ConnectionEntity entity = new ConnectionEntity(); - entity.setRevision(updatedRevision); - entity.setConnection(connectionDTO); + final ConnectionEntity entity = serviceFacade.createConnection(new Revision(revision.getVersion(), revision.getClientId()), groupId, connection); + connectionResource.populateRemainingConnectionEntityContent(entity); // extract the href and build the response - String href = connectionDTO.getUri(); - - return clusterContext(generateCreatedResponse(URI.create(href), entity)).build(); + String uri = entity.getComponent().getUri(); + return clusterContext(generateCreatedResponse(URI.create(uri), entity)).build(); } /** * Gets all the connections. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @return A connectionsEntity. */ @GET @@ -1765,11 +1594,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getConnections( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -1782,16 +1606,11 @@ public class ProcessGroupResource extends ApplicationResource { } // all of the relationships for the specified source processor - Set connections = serviceFacade.getConnections(groupId); - - // create the revision - RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); + Set connections = serviceFacade.getConnections(groupId); // create the client response entity ConnectionsEntity entity = new ConnectionsEntity(); - entity.setRevision(revision); - entity.setConnections(connectionResource.populateRemainingConnectionsContent(connections)); + entity.setConnections(connectionResource.populateRemainingConnectionEntitiesContent(connections)); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -1861,6 +1680,12 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("The group id must be specified when creating a snippet."); } + if (snippetEntity.getSnippet().getParentGroupId() != null && !groupId.equals(snippetEntity.getSnippet().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + snippetEntity.getSnippet().getParentGroupId(), groupId)); + } + snippetEntity.getSnippet().setParentGroupId(groupId); + if (properties.isClusterManager()) { return (Response) clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(snippetEntity), getHeaders()).getResponse(); } @@ -1886,9 +1711,6 @@ public class ProcessGroupResource extends ApplicationResource { // get the snippet final SnippetDTO snippet = response.getConfiguration(); - // always prune the response when creating - snippet.setContents(null); - // get the updated revision final RevisionDTO updatedRevision = new RevisionDTO(); updatedRevision.setClientId(revision.getClientId()); @@ -1906,11 +1728,6 @@ public class ProcessGroupResource extends ApplicationResource { /** * Retrieves the specified snippet. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. - * @param verbose Whether or not to include the contents of the snippet in - * the response. * @param id The id of the snippet to retrieve. * @return A snippetEntity. */ @@ -1938,16 +1755,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getSnippet( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, - @ApiParam( - value = "Whether to include configuration details for the components specified in the snippet.", - required = false - ) - @QueryParam("verbose") @DefaultValue(VERBOSE) Boolean verbose, @ApiParam( value = "The process group id.", required = true @@ -1967,14 +1774,8 @@ public class ProcessGroupResource extends ApplicationResource { // get the snippet final SnippetDTO snippet = serviceFacade.getSnippet(id); - // prune the response if necessary - if (!verbose) { - snippet.setContents(null); - } - // create the revision final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); // create the response entity final SnippetEntity entity = new SnippetEntity(); @@ -2066,9 +1867,6 @@ public class ProcessGroupResource extends ApplicationResource { // get the results final SnippetDTO snippet = controllerResponse.getConfiguration(); - // always prune update responses - snippet.setContents(null); - // get the updated revision final RevisionDTO updatedRevision = new RevisionDTO(); updatedRevision.setClientId(revision.getClientId()); @@ -2241,18 +2039,16 @@ public class ProcessGroupResource extends ApplicationResource { // copy the specified snippet final RevisionDTO requestRevision = copySnippetEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.copySnippet( + final ConfigurationSnapshot controllerResponse = serviceFacade.copySnippet( new Revision(requestRevision.getVersion(), requestRevision.getClientId()), groupId, copySnippetEntity.getSnippetId(), copySnippetEntity.getOriginX(), copySnippetEntity.getOriginY()); // get the snippet - final FlowSnippetDTO flowSnippet = controllerResponse.getConfiguration(); + final FlowDTO flow = controllerResponse.getConfiguration(); // prune response as necessary - for (ProcessGroupDTO group : flowSnippet.getProcessGroups()) { - if (group.getContents() != null) { - group.setContents(null); - } + for (ProcessGroupEntity childGroupEntity : flow.getProcessGroups()) { + childGroupEntity.getComponent().setContents(null); } // get the updated revision @@ -2261,9 +2057,9 @@ public class ProcessGroupResource extends ApplicationResource { revision.setVersion(controllerResponse.getVersion()); // create the response entity - final FlowSnippetEntity entity = new FlowSnippetEntity(); + final FlowEntity entity = new FlowEntity(); entity.setRevision(revision); - entity.setContents(populateRemainingSnippetContent(flowSnippet)); + entity.setFlow(populateRemainingSnippetContent(flow)); // generate the response return clusterContext(generateCreatedResponse(getAbsolutePath(), entity)).build(); @@ -2282,7 +2078,7 @@ public class ProcessGroupResource extends ApplicationResource { * @param httpServletRequest request * @param groupId The group id * @param instantiateTemplateRequestEntity The instantiate template request - * @return A flowSnippetEntity. + * @return A flowEntity. */ @POST @Consumes(MediaType.APPLICATION_JSON) @@ -2291,7 +2087,7 @@ public class ProcessGroupResource extends ApplicationResource { // TODO - @PreAuthorize("hasRole('ROLE_DFM')") @ApiOperation( value = "Instantiates a template", - response = FlowSnippetEntity.class, + response = FlowEntity.class, authorizations = { @Authorization(value = "Data Flow Manager", type = "ROLE_DFM") } @@ -2335,17 +2131,15 @@ public class ProcessGroupResource extends ApplicationResource { // create the template and generate the json final RevisionDTO requestRevision = instantiateTemplateRequestEntity.getRevision(); - final ConfigurationSnapshot response = serviceFacade.createTemplateInstance( + final ConfigurationSnapshot response = serviceFacade.createTemplateInstance( new Revision(requestRevision.getVersion(), requestRevision.getClientId()), groupId, instantiateTemplateRequestEntity.getOriginX(), instantiateTemplateRequestEntity.getOriginY(), instantiateTemplateRequestEntity.getTemplateId()); - final FlowSnippetDTO flowSnippet = response.getConfiguration(); + final FlowDTO flowSnippet = response.getConfiguration(); // prune response as necessary - for (ProcessGroupDTO group : flowSnippet.getProcessGroups()) { - if (group.getContents() != null) { - group.setContents(null); - } + for (ProcessGroupEntity childGroupEntity : flowSnippet.getProcessGroups()) { + childGroupEntity.getComponent().setContents(null); } // get the updated revision @@ -2354,9 +2148,9 @@ public class ProcessGroupResource extends ApplicationResource { revision.setVersion(response.getVersion()); // create the response entity - final FlowSnippetEntity entity = new FlowSnippetEntity(); + final FlowEntity entity = new FlowEntity(); entity.setRevision(revision); - entity.setContents(populateRemainingSnippetContent(flowSnippet)); + entity.setFlow(populateRemainingSnippetContent(flowSnippet)); // generate the response return clusterContext(generateCreatedResponse(getAbsolutePath(), entity)).build(); @@ -2369,9 +2163,6 @@ public class ProcessGroupResource extends ApplicationResource { /** * Retrieves all the of templates in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @return A templatesEntity. */ @GET @@ -2401,12 +2192,7 @@ public class ProcessGroupResource extends ApplicationResource { value = "The process group id.", required = true ) - @PathParam("id") String groupId, - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + @PathParam("id") String groupId) { // replicate if cluster manager if (properties.isClusterManager()) { @@ -2418,7 +2204,6 @@ public class ProcessGroupResource extends ApplicationResource { // create the revision final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); // create the response entity final TemplatesEntity entity = new TemplatesEntity(); @@ -2470,6 +2255,8 @@ public class ProcessGroupResource extends ApplicationResource { required = true ) CreateTemplateRequestEntity createTemplateRequestEntity) { + // TODO - verify parent group id + // replicate if cluster manager if (properties.isClusterManager()) { return clusterManager.applyRequest(HttpMethod.POST, getAbsolutePath(), updateClientId(createTemplateRequestEntity), getHeaders()).getResponse(); @@ -2716,6 +2503,12 @@ public class ProcessGroupResource extends ApplicationResource { throw new IllegalArgumentException("The type of controller service to create must be specified."); } + if (controllerServiceEntity.getControllerService().getParentGroupId() != null && !groupId.equals(controllerServiceEntity.getControllerService().getParentGroupId())) { + throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s", + controllerServiceEntity.getControllerService().getParentGroupId(), groupId)); + } + controllerServiceEntity.getControllerService().setParentGroupId(groupId); + // get the revision final RevisionDTO revision = controllerServiceEntity.getRevision(); @@ -2749,8 +2542,8 @@ public class ProcessGroupResource extends ApplicationResource { // build the response entity final ControllerServiceEntity entity = new ControllerServiceEntity(); - entity.setRevision(updatedRevision); entity.setControllerService(controllerServiceResource.populateRemainingControllerServiceContent(availability, controllerService)); + entity.setRevision(updatedRevision); // build the response return clusterContext(generateCreatedResponse(URI.create(controllerService.getUri()), entity)).build(); @@ -2759,9 +2552,6 @@ public class ProcessGroupResource extends ApplicationResource { /** * Retrieves all the of controller services in this NiFi. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param availability Whether the controller service is available on the * NCM only (ncm) or on the nodes only (node). If this instance is not * clustered all services should use the node availability. @@ -2790,11 +2580,6 @@ public class ProcessGroupResource extends ApplicationResource { } ) public Response getControllerServices( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The process group id.", required = true @@ -2819,7 +2604,6 @@ public class ProcessGroupResource extends ApplicationResource { // create the revision final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); // create the response entity final ControllerServicesEntity entity = new ControllerServicesEntity(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java index 620256143e..9dddd70622 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessorResource.java @@ -34,6 +34,7 @@ import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; import org.apache.nifi.web.UiExtensionType; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.ComponentStateDTO; import org.apache.nifi.web.api.dto.ProcessorConfigDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; @@ -86,6 +87,34 @@ public class ProcessorResource extends ApplicationResource { @Context private ServletContext servletContext; + /** + * Populate the uri's for the specified processors and their relationships. + * + * @param processorEntities processors + * @return dtos + */ + public Set populateRemainingProcessorEntitiesContent(Set processorEntities) { + for (ProcessorEntity processorEntity : processorEntities) { + if (processorEntity.getComponent() != null) { + populateRemainingProcessorContent(processorEntity.getComponent()); + } + } + return processorEntities; + } + + /** + * Populate the uri's for the specified processors and their relationships. + * + * @param processorEntity processors + * @return dtos + */ + public ProcessorEntity populateRemainingProcessorEntityContent(ProcessorEntity processorEntity) { + if (processorEntity.getComponent() != null) { + populateRemainingProcessorContent(processorEntity.getComponent()); + } + return processorEntity; + } + /** * Populate the uri's for the specified processors and their relationships. * @@ -133,7 +162,6 @@ public class ProcessorResource extends ApplicationResource { /** * Retrieves the specified processor. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the processor to retrieve. * @return A processorEntity. */ @@ -161,11 +189,6 @@ public class ProcessorResource extends ApplicationResource { } ) public Response getProcessor( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The processor id.", required = true @@ -178,16 +201,8 @@ public class ProcessorResource extends ApplicationResource { } // get the specified processor - final ProcessorDTO processor = serviceFacade.getProcessor(id); - - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // generate the response entity - final ProcessorEntity entity = new ProcessorEntity(); - entity.setRevision(revision); - entity.setProcessor(populateRemainingProcessorContent(processor)); + final ProcessorEntity entity = serviceFacade.getProcessor(id); + populateRemainingProcessorEntityContent(entity); // generate the response return clusterContext(generateOkResponse(entity)).build(); @@ -196,7 +211,6 @@ public class ProcessorResource extends ApplicationResource { /** * Returns the descriptor for the specified property. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the processor * @param propertyName The property * @return a propertyDescriptorEntity @@ -254,13 +268,8 @@ public class ProcessorResource extends ApplicationResource { // get the property descriptor final PropertyDescriptorDTO descriptor = serviceFacade.getProcessorPropertyDescriptor(id, propertyName); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // generate the response entity final PropertyDescriptorEntity entity = new PropertyDescriptorEntity(); - entity.setRevision(revision); entity.setPropertyDescriptor(descriptor); // generate the response @@ -270,7 +279,6 @@ public class ProcessorResource extends ApplicationResource { /** * Gets the state for a processor. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the processor * @return a componentStateEntity */ @@ -296,11 +304,6 @@ public class ProcessorResource extends ApplicationResource { } ) public Response getState( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The processor id.", required = true @@ -315,13 +318,8 @@ public class ProcessorResource extends ApplicationResource { // get the component state final ComponentStateDTO state = serviceFacade.getProcessorState(id); - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - // generate the response entity final ComponentStateEntity entity = new ComponentStateEntity(); - entity.setRevision(revision); entity.setComponentState(state); // generate the response @@ -446,7 +444,7 @@ public class ProcessorResource extends ApplicationResource { ) ProcessorEntity processorEntity) { - if (processorEntity == null || processorEntity.getProcessor() == null) { + if (processorEntity == null || processorEntity.getComponent() == null) { throw new IllegalArgumentException("Processor details must be specified."); } @@ -455,7 +453,7 @@ public class ProcessorResource extends ApplicationResource { } // ensure the same id is being used - final ProcessorDTO requestProcessorDTO = processorEntity.getProcessor(); + final ProcessorDTO requestProcessorDTO = processorEntity.getComponent(); if (!id.equals(requestProcessorDTO.getId())) { throw new IllegalArgumentException(String.format("The processor id (%s) in the request body does " + "not equal the processor id of the requested resource (%s).", requestProcessorDTO.getId(), id)); @@ -485,25 +483,12 @@ public class ProcessorResource extends ApplicationResource { // update the processor final RevisionDTO revision = processorEntity.getRevision(); - final ConfigurationSnapshot controllerResponse = serviceFacade.updateProcessor( - new Revision(revision.getVersion(), revision.getClientId()), requestProcessorDTO); + final UpdateResult result = serviceFacade.updateProcessor(new Revision(revision.getVersion(), revision.getClientId()), requestProcessorDTO); + final ProcessorEntity entity = result.getResult(); + populateRemainingProcessorEntityContent(entity); - // get the processor dto - final ProcessorDTO responseProcessorDTO = controllerResponse.getConfiguration(); - populateRemainingProcessorContent(responseProcessorDTO); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // generate the response entity - final ProcessorEntity entity = new ProcessorEntity(); - entity.setRevision(updatedRevision); - entity.setProcessor(responseProcessorDTO); - - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(responseProcessorDTO.getUri()), entity)).build(); + if (result.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } @@ -576,16 +561,7 @@ public class ProcessorResource extends ApplicationResource { } // delete the processor - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteProcessor(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(clientId.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // generate the response entity - final ProcessorEntity entity = new ProcessorEntity(); - entity.setRevision(updatedRevision); + final ProcessorEntity entity = serviceFacade.deleteProcessor(new Revision(clientVersion, clientId.getClientId()), id); // generate the response return clusterContext(generateOkResponse(entity)).build(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java index d1999d9b5b..64fe273d7a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/RemoteProcessGroupResource.java @@ -28,6 +28,7 @@ import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.ConfigurationSnapshot; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.Revision; +import org.apache.nifi.web.UpdateResult; import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO; import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO; import org.apache.nifi.web.api.dto.RevisionDTO; @@ -71,6 +72,32 @@ public class RemoteProcessGroupResource extends ApplicationResource { private WebClusterManager clusterManager; private NiFiProperties properties; + /** + * Populates the remaining content for each remote process group. The uri must be generated and the remote process groups name must be retrieved. + * + * @param remoteProcessGroupEntities groups + * @return dtos + */ + public Set populateRemainingRemoteProcessGroupEntitiesContent(Set remoteProcessGroupEntities) { + for (RemoteProcessGroupEntity remoteProcessEntities : remoteProcessGroupEntities) { + populateRemainingRemoteProcessGroupEntityContent(remoteProcessEntities); + } + return remoteProcessGroupEntities; + } + + /** + * Populates the remaining content for each remote process group. The uri must be generated and the remote process groups name must be retrieved. + * + * @param remoteProcessGroupEntity groups + * @return dtos + */ + public RemoteProcessGroupEntity populateRemainingRemoteProcessGroupEntityContent(RemoteProcessGroupEntity remoteProcessGroupEntity) { + if (remoteProcessGroupEntity.getComponent() != null) { + populateRemainingRemoteProcessGroupContent(remoteProcessGroupEntity.getComponent()); + } + return remoteProcessGroupEntity; + } + /** * Populates the remaining content for each remote process group. The uri must be generated and the remote process groups name must be retrieved. * @@ -100,7 +127,6 @@ public class RemoteProcessGroupResource extends ApplicationResource { /** * Retrieves the specified remote process group. * - * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param verbose Optional verbose flag that defaults to false. If the verbose flag is set to true remote group contents (ports) will be included. * @param id The id of the remote process group to retrieve * @return A remoteProcessGroupEntity. @@ -129,11 +155,6 @@ public class RemoteProcessGroupResource extends ApplicationResource { } ) public Response getRemoteProcessGroup( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "Whether to include any encapulated ports or just details about the remote process group.", required = false @@ -150,23 +171,17 @@ public class RemoteProcessGroupResource extends ApplicationResource { return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse(); } - // get the label - final RemoteProcessGroupDTO remoteProcessGroup = serviceFacade.getRemoteProcessGroup(id); + // get the remote process group + final RemoteProcessGroupEntity entity = serviceFacade.getRemoteProcessGroup(id); + populateRemainingRemoteProcessGroupEntityContent(entity); // prune the response as necessary if (!verbose) { - remoteProcessGroup.setContents(null); + if (entity.getComponent() != null) { + entity.getComponent().setContents(null); + } } - // create the revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - - // create the response entity - final RemoteProcessGroupEntity entity = new RemoteProcessGroupEntity(); - entity.setRevision(revision); - entity.setRemoteProcessGroup(populateRemainingRemoteProcessGroupContent(remoteProcessGroup)); - return clusterContext(generateOkResponse(entity)).build(); } @@ -236,18 +251,7 @@ public class RemoteProcessGroupResource extends ApplicationResource { clientVersion = version.getLong(); } - final ConfigurationSnapshot controllerResponse = serviceFacade.deleteRemoteProcessGroup(new Revision(clientVersion, clientId.getClientId()), id); - - // get the updated revision - final RevisionDTO revision = new RevisionDTO(); - revision.setClientId(clientId.getClientId()); - revision.setVersion(controllerResponse.getVersion()); - - // create the response entity - final RemoteProcessGroupEntity entity = new RemoteProcessGroupEntity(); - entity.setRevision(revision); - - // create the response + final RemoteProcessGroupEntity entity = serviceFacade.deleteRemoteProcessGroup(new Revision(clientVersion, clientId.getClientId()), id); return clusterContext(generateOkResponse(entity)).build(); } @@ -463,7 +467,7 @@ public class RemoteProcessGroupResource extends ApplicationResource { @PathParam("id") String id, RemoteProcessGroupEntity remoteProcessGroupEntity) { - if (remoteProcessGroupEntity == null || remoteProcessGroupEntity.getRemoteProcessGroup() == null) { + if (remoteProcessGroupEntity == null || remoteProcessGroupEntity.getComponent() == null) { throw new IllegalArgumentException("Remote process group details must be specified."); } @@ -472,7 +476,7 @@ public class RemoteProcessGroupResource extends ApplicationResource { } // ensure the ids are the same - final RemoteProcessGroupDTO requestRemoteProcessGroup = remoteProcessGroupEntity.getRemoteProcessGroup(); + final RemoteProcessGroupDTO requestRemoteProcessGroup = remoteProcessGroupEntity.getComponent(); if (!id.equals(requestRemoteProcessGroup.getId())) { throw new IllegalArgumentException(String.format("The remote process group id (%s) in the request body does not equal the " + "remote process group id of the requested resource (%s).", requestRemoteProcessGroup.getId(), id)); @@ -530,24 +534,14 @@ public class RemoteProcessGroupResource extends ApplicationResource { // update the specified remote process group final RevisionDTO revision = remoteProcessGroupEntity.getRevision(); - final ConfigurationSnapshot controllerResponse + final UpdateResult updateResult = serviceFacade.updateRemoteProcessGroup(new Revision(revision.getVersion(), revision.getClientId()), requestRemoteProcessGroup); - final RemoteProcessGroupDTO responseRemoteProcessGroup = controllerResponse.getConfiguration(); - populateRemainingRemoteProcessGroupContent(responseRemoteProcessGroup); + final RemoteProcessGroupEntity entity = updateResult.getResult(); + populateRemainingRemoteProcessGroupEntityContent(entity); - // get the updated revision - final RevisionDTO updatedRevision = new RevisionDTO(); - updatedRevision.setClientId(revision.getClientId()); - updatedRevision.setVersion(controllerResponse.getVersion()); - - // build the response entity - final RemoteProcessGroupEntity entity = new RemoteProcessGroupEntity(); - entity.setRevision(updatedRevision); - entity.setRemoteProcessGroup(responseRemoteProcessGroup); - - if (controllerResponse.isNew()) { - return clusterContext(generateCreatedResponse(URI.create(responseRemoteProcessGroup.getUri()), entity)).build(); + if (updateResult.isNew()) { + return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build(); } else { return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java index 5657fff656..ceb9455398 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java @@ -89,9 +89,6 @@ public class TemplateResource extends ApplicationResource { /** * Retrieves the specified template. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. * @param id The id of the template to retrieve * @return A templateEntity. */ @@ -119,11 +116,6 @@ public class TemplateResource extends ApplicationResource { } ) public Response exportTemplate( - @ApiParam( - value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", - required = false - ) - @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @ApiParam( value = "The template id.", required = true diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AccessDeniedExceptionMapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AccessDeniedExceptionMapper.java index 5d50e7010b..3af22c9d67 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AccessDeniedExceptionMapper.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AccessDeniedExceptionMapper.java @@ -19,12 +19,13 @@ package org.apache.nifi.web.api.config; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; + +import org.apache.nifi.authorization.AccessDeniedException; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.access.AccessDeniedException; /** * Maps access denied exceptions into a client response. diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index 79e1d55668..afcf86ad49 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@ -34,7 +34,10 @@ import org.apache.nifi.action.details.PurgeDetails; import org.apache.nifi.annotation.behavior.Stateful; import org.apache.nifi.annotation.documentation.CapabilityDescription; import org.apache.nifi.annotation.documentation.Tags; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.cluster.coordination.heartbeat.NodeHeartbeat; import org.apache.nifi.cluster.event.Event; import org.apache.nifi.cluster.manager.StatusMerger; @@ -113,6 +116,9 @@ import org.apache.nifi.web.api.dto.action.details.ConfigureDetailsDTO; import org.apache.nifi.web.api.dto.action.details.ConnectDetailsDTO; import org.apache.nifi.web.api.dto.action.details.MoveDetailsDTO; import org.apache.nifi.web.api.dto.action.details.PurgeDetailsDTO; +import org.apache.nifi.web.api.dto.flow.FlowBreadcrumbDTO; +import org.apache.nifi.web.api.dto.flow.FlowDTO; +import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO; import org.apache.nifi.web.api.dto.provenance.lineage.LineageDTO; import org.apache.nifi.web.api.dto.provenance.lineage.LineageRequestDTO; import org.apache.nifi.web.api.dto.provenance.lineage.LineageRequestDTO.LineageRequestType; @@ -163,6 +169,8 @@ public final class DtoFactory { }; private ControllerServiceLookup controllerServiceLookup; + private EntityFactory entityFactory; + private Authorizer authorizer; /** * Creates an ActionDTO for the specified Action. @@ -537,6 +545,7 @@ public final class DtoFactory { if (connection == null) { return null; } + final ConnectionDTO dto = new ConnectionDTO(); dto.setId(connection.getIdentifier()); @@ -652,6 +661,9 @@ public final class DtoFactory { if (funnel == null) { return null; } + if (!funnel.isAuthorized(authorizer, RequestAction.READ)) { + return null; + } final FunnelDTO dto = new FunnelDTO(); dto.setId(funnel.getIdentifier()); @@ -1385,27 +1397,34 @@ public final class DtoFactory { } /** - * Creates a ProcessGroupDTO from the specified parent ProcessGroup. + * Creates a FlowBreadcrumbDTO from the specified parent ProcessGroup. * * @param parentGroup group * @return dto */ - private ProcessGroupDTO createParentProcessGroupDto(final ProcessGroup parentGroup) { + private FlowBreadcrumbDTO createBreadcrumbDto(final ProcessGroup parentGroup) { if (parentGroup == null) { return null; } - final ProcessGroupDTO dto = new ProcessGroupDTO(); + final FlowBreadcrumbDTO dto = new FlowBreadcrumbDTO(); dto.setId(parentGroup.getIdentifier()); dto.setName(parentGroup.getName()); if (parentGroup.getParent() != null) { - dto.setParent(createParentProcessGroupDto(parentGroup.getParent())); + dto.setParentBreadcrumb(createBreadcrumbDto(parentGroup.getParent())); } return dto; } + public AccessPolicyDTO createAccessPolicyDto(final Authorizable authorizable) { + final AccessPolicyDTO dto = new AccessPolicyDTO(); + dto.setCanRead(authorizable.isAuthorized(authorizer, RequestAction.READ)); + dto.setCanWrite(authorizable.isAuthorized(authorizer, RequestAction.WRITE)); + return dto; + } + /** * Creates a ProcessGroupDTO from the specified ProcessGroup. * @@ -1416,6 +1435,125 @@ public final class DtoFactory { return createProcessGroupDto(group, false); } + public ProcessGroupFlowDTO createProcessGroupFlowDto(final ProcessGroup group, final boolean recurse) { + final ProcessGroupFlowDTO dto = new ProcessGroupFlowDTO(); + dto.setId(group.getIdentifier()); + dto.setBreadcrumb(createBreadcrumbDto(group)); + dto.setFlow(createFlowDto(group)); + + final ProcessGroup parent = group.getParent(); + if (parent != null) { + dto.setParentGroupId(parent.getIdentifier()); + } + + return dto; + } + + public FlowDTO createFlowDto(final ProcessGroup group, final FlowSnippetDTO snippet) { + if (snippet == null) { + return null; + } + + final FlowDTO flow = new FlowDTO(); + + for (final ConnectionDTO connection : snippet.getConnections()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getConnection(connection.getId())); + flow.getConnections().add(entityFactory.createConnectionEntity(connection, null, accessPolicy)); + } + + for (final ControllerServiceDTO controllerService : snippet.getControllerServices()) { + flow.getControllerServices().add(entityFactory.createControllerServiceEntity(controllerService, null, null)); + } + + for (final FunnelDTO funnel : snippet.getFunnels()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getFunnel(funnel.getId())); + flow.getFunnels().add(entityFactory.createFunnelEntity(funnel, null, accessPolicy)); + } + + for (final PortDTO inputPort : snippet.getInputPorts()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getInputPort(inputPort.getId())); + flow.getInputPorts().add(entityFactory.createPortEntity(inputPort, null, accessPolicy)); + } + + for (final PortDTO outputPort : snippet.getOutputPorts()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getOutputPort(outputPort.getId())); + flow.getOutputPorts().add(entityFactory.createPortEntity(outputPort, null, accessPolicy)); + } + + for (final LabelDTO label : snippet.getLabels()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getLabel(label.getId())); + flow.getLabels().add(entityFactory.createLabelEntity(label, null, accessPolicy)); + } + + for (final ProcessGroupDTO processGroup : snippet.getProcessGroups()) { + // clear the contents as we only return a single level/group at a time + processGroup.setContents(null); + + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getProcessGroup(processGroup.getId())); + flow.getProcessGroups().add(entityFactory.createProcessGroupEntity(processGroup, null, accessPolicy)); + } + + for (final ProcessorDTO processor : snippet.getProcessors()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getProcessor(processor.getId())); + flow.getProcessors().add(entityFactory.createProcessorEntity(processor, null, accessPolicy)); + } + + for (final RemoteProcessGroupDTO remoteProcessGroup : snippet.getRemoteProcessGroups()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(group.getRemoteProcessGroup(remoteProcessGroup.getId())); + flow.getRemoteProcessGroups().add(entityFactory.createRemoteProcessGroupEntity(remoteProcessGroup, null, accessPolicy)); + } + + return flow; + } + + public FlowDTO createFlowDto(final ProcessGroup group) { + final FlowDTO dto = new FlowDTO(); + + for (final ProcessorNode procNode : group.getProcessors()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(procNode); + dto.getProcessors().add(entityFactory.createProcessorEntity(createProcessorDto(procNode), null, accessPolicy)); + } + + for (final Connection connNode : group.getConnections()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(connNode); + dto.getConnections().add(entityFactory.createConnectionEntity(createConnectionDto(connNode), null, accessPolicy)); + } + + for (final Label label : group.getLabels()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(label); + dto.getLabels().add(entityFactory.createLabelEntity(createLabelDto(label), null, accessPolicy)); + } + + for (final Funnel funnel : group.getFunnels()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(funnel); + dto.getFunnels().add(entityFactory.createFunnelEntity(createFunnelDto(funnel), null, accessPolicy)); + } + + for (final ProcessGroup childGroup : group.getProcessGroups()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(childGroup); + dto.getProcessGroups().add(entityFactory.createProcessGroupEntity(createProcessGroupDto(childGroup), null, accessPolicy)); + } + + for (final RemoteProcessGroup rpg : group.getRemoteProcessGroups()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(rpg); + dto.getRemoteProcessGroups().add(entityFactory.createRemoteProcessGroupEntity(createRemoteProcessGroupDto(rpg), null, accessPolicy)); + } + + for (final Port inputPort : group.getInputPorts()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(inputPort); + dto.getInputPorts().add(entityFactory.createPortEntity(createPortDto(inputPort), null, accessPolicy)); + } + + for (final Port outputPort : group.getOutputPorts()) { + final AccessPolicyDTO accessPolicy = createAccessPolicyDto(outputPort); + dto.getOutputPorts().add(entityFactory.createPortEntity(createPortDto(outputPort), null, accessPolicy)); + } + + // TODO - controller services once they are accessible from the group + + return dto; + } + /** * Creates a ProcessGroupDTO from the specified ProcessGroup. * @@ -1449,7 +1587,6 @@ public final class DtoFactory { ProcessGroup parentGroup = group.getParent(); if (parentGroup != null) { dto.setParentGroupId(parentGroup.getIdentifier()); - dto.setParent(createParentProcessGroupDto(parentGroup)); } final ProcessGroupCounts counts = group.getCounts(); @@ -1480,7 +1617,6 @@ public final class DtoFactory { final FlowSnippetDTO dto = new FlowSnippetDTO(); for (final ProcessorNode procNode : group.getProcessors()) { - // authorization check dto.getProcessors().add(createProcessorDto(procNode)); } @@ -2121,7 +2257,6 @@ public final class DtoFactory { copy.setPosition(original.getPosition()); copy.setWidth(original.getWidth()); copy.setHeight(original.getHeight()); - copy.setUri(original.getUri()); return copy; } @@ -2139,7 +2274,6 @@ public final class DtoFactory { copy.setReferencingComponents(copy(original.getReferencingComponents())); copy.setState(original.getState()); copy.setType(original.getType()); - copy.setUri(original.getUri()); copy.setValidationErrors(copy(original.getValidationErrors())); return copy; } @@ -2149,7 +2283,6 @@ public final class DtoFactory { copy.setId(original.getId()); copy.setParentGroupId(original.getParentGroupId()); copy.setPosition(original.getPosition()); - copy.setUri(original.getUri()); return copy; } @@ -2198,7 +2331,6 @@ public final class DtoFactory { copy.setState(original.getState()); copy.setStyle(copy(original.getStyle())); copy.setType(original.getType()); - copy.setUri(original.getUri()); copy.setSupportsParallelProcessing(original.getSupportsParallelProcessing()); copy.setSupportsEventDriven(original.getSupportsEventDriven()); copy.setValidationErrors(copy(original.getValidationErrors())); @@ -2242,7 +2374,6 @@ public final class DtoFactory { copy.setBackPressureDataSizeThreshold(original.getBackPressureDataSizeThreshold()); copy.setPrioritizers(copy(original.getPrioritizers())); copy.setSource(original.getSource()); - copy.setUri(original.getUri()); copy.setzIndex(original.getzIndex()); copy.setLabelIndex(original.getLabelIndex()); copy.setBends(copy(original.getBends())); @@ -2271,7 +2402,6 @@ public final class DtoFactory { copy.setName(original.getName()); copy.setComments(original.getComments()); copy.setParentGroupId(original.getParentGroupId()); - copy.setUri(original.getUri()); copy.setState(original.getState()); copy.setType(original.getType()); copy.setTransmitting(original.isTransmitting()); @@ -2300,14 +2430,12 @@ public final class DtoFactory { public ProcessGroupDTO copy(final ProcessGroupDTO original, final boolean deep) { final ProcessGroupDTO copy = new ProcessGroupDTO(); copy.setComments(original.getComments()); - copy.setContents(copy(original.getContents(), deep)); copy.setPosition(original.getPosition()); copy.setId(original.getId()); copy.setInputPortCount(original.getInputPortCount()); copy.setInvalidCount(original.getInvalidCount()); copy.setName(original.getName()); copy.setOutputPortCount(original.getOutputPortCount()); - copy.setParent(original.getParent()); copy.setParentGroupId(original.getParentGroupId()); copy.setRunning(original.isRunning()); @@ -2316,7 +2444,6 @@ public final class DtoFactory { copy.setDisabledCount(original.getDisabledCount()); copy.setActiveRemotePortCount(original.getActiveRemotePortCount()); copy.setInactiveRemotePortCount(original.getInactiveRemotePortCount()); - copy.setUri(original.getUri()); return copy; } @@ -2356,7 +2483,6 @@ public final class DtoFactory { copy.setInactiveRemoteOutputPortCount(original.getInactiveRemoteOutputPortCount()); copy.setParentGroupId(original.getParentGroupId()); copy.setTargetUri(original.getTargetUri()); - copy.setUri(original.getUri()); copy.setContents(copyContents); @@ -2545,6 +2671,12 @@ public final class DtoFactory { return revisionDTO; } + public RevisionDTO createRevisionDTO(final Long version, final String clientId) { + final RevisionDTO dto = new RevisionDTO(); + dto.setVersion(version); + dto.setClientId(clientId); + return dto; + } public NodeDTO createNodeDTO(Node node, NodeHeartbeat nodeHeartbeat, List events, boolean primary) { final NodeDTO nodeDto = new NodeDTO(); @@ -2599,4 +2731,11 @@ public final class DtoFactory { this.controllerServiceLookup = lookup; } + public void setAuthorizer(Authorizer authorizer) { + this.authorizer = authorizer; + } + + public void setEntityFactory(EntityFactory entityFactory) { + this.entityFactory = entityFactory; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java new file mode 100644 index 0000000000..0d46d94d1e --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java @@ -0,0 +1,155 @@ +/* + * 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.web.api.dto; + +import org.apache.nifi.web.api.entity.ConnectionEntity; +import org.apache.nifi.web.api.entity.ControllerServiceEntity; +import org.apache.nifi.web.api.entity.FunnelEntity; +import org.apache.nifi.web.api.entity.LabelEntity; +import org.apache.nifi.web.api.entity.PortEntity; +import org.apache.nifi.web.api.entity.ProcessGroupEntity; +import org.apache.nifi.web.api.entity.ProcessorEntity; +import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; + +public final class EntityFactory { + + public ProcessorEntity createProcessorEntity(final ProcessorDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final ProcessorEntity entity = new ProcessorEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + + public PortEntity createPortEntity(final PortDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final PortEntity entity = new PortEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + entity.setPortType(dto.getType()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + + public ProcessGroupEntity createProcessGroupEntity(final ProcessGroupDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final ProcessGroupEntity entity = new ProcessGroupEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + + public LabelEntity createLabelEntity(final LabelDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final LabelEntity entity = new LabelEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + + final DimensionsDTO dimensions = new DimensionsDTO(); + dimensions.setHeight(dto.getHeight()); + dimensions.setWidth(dto.getWidth()); + entity.setDimensions(dimensions); + + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + + public FunnelEntity createFunnelEntity(final FunnelDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final FunnelEntity entity = new FunnelEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + + public ConnectionEntity createConnectionEntity(final ConnectionDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final ConnectionEntity entity = new ConnectionEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + entity.setBends(dto.getBends()); + entity.setLabelIndex(dto.getLabelIndex()); + entity.setSourceId(dto.getSource().getId()); + entity.setSourceGroupId(dto.getSource().getGroupId()); + entity.setDestinationId(dto.getDestination().getId()); + entity.setDestinationGroupId(dto.getDestination().getGroupId()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + + public ControllerServiceEntity createControllerServiceEntity(final ControllerServiceDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final ControllerServiceEntity entity = new ControllerServiceEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setControllerService(dto); + } + } + return entity; + } + + public RemoteProcessGroupEntity createRemoteProcessGroupEntity(final RemoteProcessGroupDTO dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) { + final RemoteProcessGroupEntity entity = new RemoteProcessGroupEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setAccessPolicy(accessPolicy); + entity.setId(dto.getId()); + entity.setPosition(dto.getPosition()); + if (accessPolicy != null && accessPolicy.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java index e8686a309c..40e2ee8426 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java @@ -21,8 +21,11 @@ import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.admin.service.KeyService; import org.apache.nifi.authorization.Resource; +import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.resource.ResourceType; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.protocol.NodeIdentifier; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.connectable.Connectable; @@ -79,7 +82,6 @@ import org.apache.nifi.search.SearchContext; import org.apache.nifi.search.SearchResult; import org.apache.nifi.search.Searchable; import org.apache.nifi.services.FlowService; -import org.apache.nifi.user.NiFiUser; import org.apache.nifi.util.FormatUtils; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.DownloadableContent; @@ -108,7 +110,6 @@ import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO; import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.StatusHistoryDTO; import org.apache.nifi.web.security.ProxiedEntitiesUtils; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -132,7 +133,7 @@ import java.util.TimeZone; import java.util.TreeSet; import java.util.concurrent.TimeUnit; -public class ControllerFacade { +public class ControllerFacade implements Authorizable { private static final Logger logger = LoggerFactory.getLogger(ControllerFacade.class); @@ -177,6 +178,16 @@ public class ControllerFacade { flowController.setName(name); } + @Override + public Authorizable getParentAuthorizable() { + return null; + } + + @Override + public Resource getResource() { + return ResourceFactory.getControllerResource(); + } + /** * Sets the comments of this controller. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java index 014a607607..13fe66d396 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/TemplateDAO.java @@ -16,11 +16,12 @@ */ package org.apache.nifi.web.dao; -import java.util.Set; import org.apache.nifi.controller.Template; import org.apache.nifi.web.api.dto.FlowSnippetDTO; import org.apache.nifi.web.api.dto.TemplateDTO; +import java.util.Set; + public interface TemplateDAO { /** diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java index 29bd9b3b12..8a6bc3e55f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java @@ -16,7 +16,10 @@ */ package org.apache.nifi.web.dao.impl; -import org.apache.nifi.admin.service.KeyService; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.connectable.Connection; @@ -34,7 +37,6 @@ import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.RemoteProcessGroup; import org.apache.nifi.processor.Relationship; import org.apache.nifi.remote.RemoteGroupPort; -import org.apache.nifi.user.NiFiUser; import org.apache.nifi.util.FormatUtils; import org.apache.nifi.web.DownloadableContent; import org.apache.nifi.web.ResourceNotFoundException; @@ -43,7 +45,6 @@ import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.PositionDTO; import org.apache.nifi.web.dao.ConnectionDAO; import org.apache.nifi.web.security.ProxiedEntitiesUtils; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,7 +64,7 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO private static final Logger logger = LoggerFactory.getLogger(StandardConnectionDAO.class); private FlowController flowController; - private KeyService keyService; + private Authorizer authorizer; private Connection locateConnection(final String connectionId) { final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId()); @@ -292,6 +293,9 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO source = sourceGroup.getConnectable(sourceConnectableDTO.getId()); } + // ensure the user has write access to the source component + source.authorize(authorizer, RequestAction.WRITE); + // find the destination final Connectable destination; if (ConnectableType.REMOTE_INPUT_PORT.name().equals(destinationConnectableDTO.getType())) { @@ -315,6 +319,9 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO destination = destinationGroup.getConnectable(destinationConnectableDTO.getId()); } + // ensure the user has write access to the source component + destination.authorize(authorizer, RequestAction.WRITE); + // determine the relationships final Set relationships = new HashSet<>(); if (isNotNull(connectionDTO.getSelectedRelationships())) { @@ -612,7 +619,7 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO this.flowController = flowController; } - public void setKeyService(KeyService keyService) { - this.keyService = keyService; + public void setAuthorizer(Authorizer authorizer) { + this.authorizer = authorizer; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/filter/RequestLogger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/filter/RequestLogger.java index 9f63611b0b..bb30a1ecfc 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/filter/RequestLogger.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/filter/RequestLogger.java @@ -26,9 +26,9 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.logging.NiFiLog; -import org.apache.nifi.web.security.user.NiFiUserUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml index 0f79369165..9f13a23a88 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml @@ -49,9 +49,14 @@
+ + + + + @@ -81,7 +86,7 @@ - + @@ -115,6 +120,7 @@ + @@ -133,6 +139,7 @@ + @@ -158,8 +165,19 @@ + + + + + + + + + + + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/NiFiWebApiTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/NiFiWebApiTest.java index dbe158a6e1..eecc28ac5f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/NiFiWebApiTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/NiFiWebApiTest.java @@ -19,8 +19,6 @@ package org.apache.nifi.integration; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse.Status; -import java.util.HashSet; -import java.util.Set; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.integration.accesscontrol.DfmAccessControlTest; import org.apache.nifi.integration.util.NiFiTestUser; @@ -34,13 +32,15 @@ import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.api.dto.ProcessorDTO; import org.apache.nifi.web.api.dto.RevisionDTO; import org.apache.nifi.web.api.entity.ConnectionEntity; -import org.apache.nifi.web.api.entity.InputPortEntity; import org.apache.nifi.web.api.entity.LabelEntity; -import org.apache.nifi.web.api.entity.OutputPortEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.ProcessorEntity; import org.junit.Ignore; +import java.util.HashSet; +import java.util.Set; + /** * */ @@ -66,7 +66,7 @@ public class NiFiWebApiTest { // create the local selection processor entity ProcessorEntity processorEntity = new ProcessorEntity(); processorEntity.setRevision(revision); - processorEntity.setProcessor(processorDTO); + processorEntity.setComponent(processorDTO); // add the processor ClientResponse response = dfm.testPost(baseUrl + "/controller/process-groups/root/processors", processorEntity); @@ -81,7 +81,7 @@ public class NiFiWebApiTest { // get the processors id processorEntity = response.getEntity(ProcessorEntity.class); - processorDTO = processorEntity.getProcessor(); + processorDTO = processorEntity.getComponent(); String localSelectionId = processorDTO.getId(); // ----------------------------------------------- @@ -95,7 +95,7 @@ public class NiFiWebApiTest { // create the termination processor entity processorEntity = new ProcessorEntity(); processorEntity.setRevision(revision); - processorEntity.setProcessor(processorDTO); + processorEntity.setComponent(processorDTO); // add the processor response = dfm.testPost(baseUrl + "/controller/process-groups/root/processors", processorEntity); @@ -110,7 +110,7 @@ public class NiFiWebApiTest { // get the processors id processorEntity = response.getEntity(ProcessorEntity.class); - processorDTO = processorEntity.getProcessor(); + processorDTO = processorEntity.getComponent(); String terminationId = processorDTO.getId(); // ----------------------------------------------- @@ -137,7 +137,7 @@ public class NiFiWebApiTest { // create the connection entity ConnectionEntity connectionEntity = new ConnectionEntity(); connectionEntity.setRevision(revision); - connectionEntity.setConnection(connectionDTO); + connectionEntity.setComponent(connectionDTO); // add the processor response = dfm.testPost(baseUrl + "/controller/process-groups/root/connections", connectionEntity); @@ -160,7 +160,7 @@ public class NiFiWebApiTest { // create the label entity LabelEntity labelEntity = new LabelEntity(); labelEntity.setRevision(revision); - labelEntity.setLabel(labelDTO); + labelEntity.setComponent(labelDTO); // add the label response = dfm.testPost(baseUrl + "/controller/process-groups/root/labels", labelEntity); @@ -183,7 +183,7 @@ public class NiFiWebApiTest { // create the process group entity ProcessGroupEntity processGroupEntity = new ProcessGroupEntity(); processGroupEntity.setRevision(revision); - processGroupEntity.setProcessGroup(processGroup); + processGroupEntity.setComponent(processGroup); // add the process group response = dfm.testPost(baseUrl + "/controller/process-groups/root/process-group-references", processGroupEntity); @@ -204,9 +204,9 @@ public class NiFiWebApiTest { inputPort.setName("input"); // create the input port entity - InputPortEntity inputPortEntity = new InputPortEntity(); + PortEntity inputPortEntity = new PortEntity(); inputPortEntity.setRevision(revision); - inputPortEntity.setInputPort(inputPort); + inputPortEntity.setComponent(inputPort); // add the input port response = dfm.testPost(baseUrl + "/controller/process-groups/root/input-ports", inputPortEntity); @@ -227,9 +227,9 @@ public class NiFiWebApiTest { outputPort.setName("output"); // create the process group entity - OutputPortEntity outputPortEntity = new OutputPortEntity(); + PortEntity outputPortEntity = new PortEntity(); outputPortEntity.setRevision(revision); - outputPortEntity.setOutputPort(outputPort); + outputPortEntity.setComponent(outputPort); // add the output port response = dfm.testPost(baseUrl + "/controller/process-groups/root/output-ports", outputPortEntity); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessTokenEndpointTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessTokenEndpointTest.java index 5b96c6e52f..e43747d7c9 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessTokenEndpointTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AccessTokenEndpointTest.java @@ -166,7 +166,7 @@ public class AccessTokenEndpointTest { // create the entity body ProcessorEntity entity = new ProcessorEntity(); entity.setRevision(revision); - entity.setProcessor(processor); + entity.setComponent(processor); // perform the request ClientResponse response = TOKEN_USER.testPostWithHeaders(url, entity, headers); @@ -178,7 +178,7 @@ public class AccessTokenEndpointTest { entity = response.getEntity(ProcessorEntity.class); // verify creation - processor = entity.getProcessor(); + processor = entity.getComponent(); Assert.assertEquals("Copy", processor.getName()); Assert.assertEquals("org.apache.nifi.integration.util.SourceTestProcessor", processor.getType()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java index dd69954f4b..12693b26c7 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java @@ -17,9 +17,7 @@ package org.apache.nifi.integration.accesscontrol; import com.sun.jersey.api.client.ClientResponse; -import java.io.File; -import java.util.HashMap; -import java.util.Map; +import org.apache.commons.collections4.CollectionUtils; import org.apache.nifi.integration.NiFiWebApiTest; import org.apache.nifi.integration.util.NiFiTestServer; import org.apache.nifi.integration.util.NiFiTestUser; @@ -35,12 +33,11 @@ import org.apache.nifi.web.api.entity.BannerEntity; import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionsEntity; import org.apache.nifi.web.api.entity.ControllerConfigurationEntity; -import org.apache.nifi.web.api.entity.InputPortEntity; import org.apache.nifi.web.api.entity.InputPortsEntity; import org.apache.nifi.web.api.entity.LabelEntity; import org.apache.nifi.web.api.entity.LabelsEntity; -import org.apache.nifi.web.api.entity.OutputPortEntity; import org.apache.nifi.web.api.entity.OutputPortsEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.entity.PrioritizerTypesEntity; import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.ProcessGroupsEntity; @@ -49,13 +46,16 @@ import org.apache.nifi.web.api.entity.ProcessorTypesEntity; import org.apache.nifi.web.api.entity.ProcessorsEntity; import org.apache.nifi.web.api.entity.UserEntity; import org.apache.nifi.web.api.entity.UsersEntity; -import org.apache.commons.collections4.CollectionUtils; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; +import java.io.File; +import java.util.HashMap; +import java.util.Map; + /** * Access control test for the admin user. */ @@ -129,7 +129,7 @@ public class AdminAccessControlTest { Assert.assertNotNull(processGroupEntity); // extract the process group dto - ProcessGroupDTO processGroupDTO = processGroupEntity.getProcessGroup(); + ProcessGroupDTO processGroupDTO = processGroupEntity.getComponent(); FlowSnippetDTO processGroupContentsDTO = processGroupDTO.getContents(); // verify graph @@ -634,7 +634,7 @@ public class AdminAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - InputPortEntity entity = new InputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request @@ -659,7 +659,7 @@ public class AdminAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - InputPortEntity entity = new InputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request @@ -724,7 +724,7 @@ public class AdminAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - OutputPortEntity entity = new OutputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request @@ -749,7 +749,7 @@ public class AdminAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - OutputPortEntity entity = new OutputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/DfmAccessControlTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/DfmAccessControlTest.java index 914cf600fa..ecbb3746b5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/DfmAccessControlTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/DfmAccessControlTest.java @@ -20,19 +20,6 @@ import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.multipart.BodyPart; import com.sun.jersey.multipart.FormDataBodyPart; import com.sun.jersey.multipart.FormDataMultiPart; -import java.io.File; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import javax.ws.rs.core.MediaType; -import org.junit.Assert; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.integration.NiFiWebApiTest; @@ -57,12 +44,11 @@ import org.apache.nifi.web.api.entity.BannerEntity; import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionsEntity; import org.apache.nifi.web.api.entity.ControllerConfigurationEntity; -import org.apache.nifi.web.api.entity.InputPortEntity; import org.apache.nifi.web.api.entity.InputPortsEntity; import org.apache.nifi.web.api.entity.LabelEntity; import org.apache.nifi.web.api.entity.LabelsEntity; -import org.apache.nifi.web.api.entity.OutputPortEntity; import org.apache.nifi.web.api.entity.OutputPortsEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.entity.PrioritizerTypesEntity; import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.ProcessGroupsEntity; @@ -71,10 +57,24 @@ import org.apache.nifi.web.api.entity.ProcessorTypesEntity; import org.apache.nifi.web.api.entity.ProcessorsEntity; import org.apache.nifi.web.api.entity.TemplateEntity; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; +import javax.ws.rs.core.MediaType; +import java.io.File; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + /** * Access control test for the dfm user. */ @@ -159,7 +159,7 @@ public class DfmAccessControlTest { Assert.assertNotNull(processGroupEntity); // extract the process group dto - ProcessGroupDTO processGroupDTO = processGroupEntity.getProcessGroup(); + ProcessGroupDTO processGroupDTO = processGroupEntity.getComponent(); FlowSnippetDTO processGroupContentsDTO = processGroupDTO.getContents(); // verify graph @@ -371,7 +371,7 @@ public class DfmAccessControlTest { // create the entity body ProcessGroupEntity entity = new ProcessGroupEntity(); entity.setRevision(revision); - entity.setProcessGroup(processGroup); + entity.setComponent(processGroup); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + processGroup.getId(), entity); @@ -401,7 +401,7 @@ public class DfmAccessControlTest { // create the entity body ProcessGroupEntity entity = new ProcessGroupEntity(); entity.setRevision(revision); - entity.setProcessGroup(processGroup); + entity.setComponent(processGroup); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + processGroup.getId(), entity); @@ -411,8 +411,8 @@ public class DfmAccessControlTest { // get the result entity = response.getEntity(ProcessGroupEntity.class); - Assert.assertNotNull(entity.getProcessGroup()); - Assert.assertEquals("new group name", entity.getProcessGroup().getName()); + Assert.assertNotNull(entity.getComponent()); + Assert.assertEquals("new group name", entity.getComponent().getName()); } /** @@ -436,7 +436,7 @@ public class DfmAccessControlTest { // create the entity body ProcessorEntity entity = new ProcessorEntity(); entity.setRevision(revision); - entity.setProcessor(processor); + entity.setComponent(processor); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + processor.getId(), entity); @@ -466,7 +466,7 @@ public class DfmAccessControlTest { // create the entity body ProcessorEntity entity = new ProcessorEntity(); entity.setRevision(revision); - entity.setProcessor(processor); + entity.setComponent(processor); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + processor.getId(), entity); @@ -476,8 +476,8 @@ public class DfmAccessControlTest { // get the result entity = response.getEntity(ProcessorEntity.class); - Assert.assertNotNull(entity.getProcessor()); - Assert.assertEquals("new processor name", entity.getProcessor().getName()); + Assert.assertNotNull(entity.getComponent()); + Assert.assertEquals("new processor name", entity.getComponent().getName()); } /** @@ -501,7 +501,7 @@ public class DfmAccessControlTest { // create the entity body ConnectionEntity entity = new ConnectionEntity(); entity.setRevision(revision); - entity.setConnection(connection); + entity.setComponent(connection); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + connection.getId(), entity); @@ -531,7 +531,7 @@ public class DfmAccessControlTest { // create the entity body LabelEntity entity = new LabelEntity(); entity.setRevision(revision); - entity.setLabel(label); + entity.setComponent(label); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + label.getId(), entity); @@ -541,8 +541,8 @@ public class DfmAccessControlTest { // get the result entity = response.getEntity(LabelEntity.class); - Assert.assertNotNull(entity.getLabel()); - Assert.assertEquals("new label", entity.getLabel().getLabel()); + Assert.assertNotNull(entity.getComponent()); + Assert.assertEquals("new label", entity.getComponent().getLabel()); } /** @@ -564,9 +564,9 @@ public class DfmAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - InputPortEntity entity = new InputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); - entity.setInputPort(inputPort); + entity.setComponent(inputPort); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + inputPort.getId(), entity); @@ -575,9 +575,9 @@ public class DfmAccessControlTest { Assert.assertEquals(200, response.getStatus()); // get the result - entity = response.getEntity(InputPortEntity.class); - Assert.assertNotNull(entity.getInputPort()); - Assert.assertEquals("new input port name", entity.getInputPort().getName()); + entity = response.getEntity(PortEntity.class); + Assert.assertNotNull(entity.getComponent()); + Assert.assertEquals("new input port name", entity.getComponent().getName()); } /** @@ -599,9 +599,9 @@ public class DfmAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - OutputPortEntity entity = new OutputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); - entity.setOutputPort(outputPort); + entity.setComponent(outputPort); // perform the request ClientResponse response = DFM_USER.testPut(url + "/" + outputPort.getId(), entity); @@ -610,9 +610,9 @@ public class DfmAccessControlTest { Assert.assertEquals(200, response.getStatus()); // get the result - entity = response.getEntity(OutputPortEntity.class); - Assert.assertNotNull(entity.getOutputPort()); - Assert.assertEquals("new output port name", entity.getOutputPort().getName()); + entity = response.getEntity(PortEntity.class); + Assert.assertNotNull(entity.getComponent()); + Assert.assertEquals("new output port name", entity.getComponent().getName()); } // ---------------------------------------------- @@ -761,15 +761,15 @@ public class DfmAccessControlTest { // get the process group dtos ProcessGroupsEntity processGroupEntity = response.getEntity(ProcessGroupsEntity.class); - Collection processGroups = processGroupEntity.getProcessGroups(); + Collection processGroups = processGroupEntity.getProcessGroups(); // ensure the correct number of processor groups Assert.assertFalse(processGroups.isEmpty()); // use the first process group as the target - Iterator processorIter = processGroups.iterator(); + Iterator processorIter = processGroups.iterator(); Assert.assertTrue(processorIter.hasNext()); - return processorIter.next(); + return processorIter.next().getComponent(); } private ProcessorDTO getRandomProcessor() throws Exception { @@ -783,15 +783,15 @@ public class DfmAccessControlTest { // get the processor dtos ProcessorsEntity processorsEntity = response.getEntity(ProcessorsEntity.class); - Collection processors = processorsEntity.getProcessors(); + Collection processors = processorsEntity.getProcessors(); // ensure the correct number of processors Assert.assertFalse(processors.isEmpty()); // use the first processor as the target - Iterator processorIter = processors.iterator(); + Iterator processorIter = processors.iterator(); Assert.assertTrue(processorIter.hasNext()); - return processorIter.next(); + return processorIter.next().getComponent(); } private ConnectionDTO getRandomConnection() throws Exception { @@ -805,15 +805,15 @@ public class DfmAccessControlTest { // get the connection dtos ConnectionsEntity connectionEntity = response.getEntity(ConnectionsEntity.class); - Collection connections = connectionEntity.getConnections(); + Collection connections = connectionEntity.getConnections(); // ensure the correct number of connections Assert.assertFalse(connections.isEmpty()); // use the first connection as the target - Iterator connectionIter = connections.iterator(); + Iterator connectionIter = connections.iterator(); Assert.assertTrue(connectionIter.hasNext()); - return connectionIter.next(); + return connectionIter.next().getComponent(); } private LabelDTO getRandomLabel() throws Exception { @@ -827,15 +827,15 @@ public class DfmAccessControlTest { // get the label dtos LabelsEntity labelEntity = response.getEntity(LabelsEntity.class); - Collection labels = labelEntity.getLabels(); + Collection labels = labelEntity.getLabels(); // ensure the correct number of labels Assert.assertFalse(labels.isEmpty()); // use the first label as the target - Iterator labelIter = labels.iterator(); + Iterator labelIter = labels.iterator(); Assert.assertTrue(labelIter.hasNext()); - return labelIter.next(); + return labelIter.next().getComponent(); } private PortDTO getRandomInputPort() throws Exception { @@ -849,15 +849,15 @@ public class DfmAccessControlTest { // get the port dtos InputPortsEntity inputPortsEntity = response.getEntity(InputPortsEntity.class); - Collection inputPorts = inputPortsEntity.getInputPorts(); + Collection inputPorts = inputPortsEntity.getInputPorts(); // ensure the correct number of ports Assert.assertFalse(inputPorts.isEmpty()); // use the first port as the target - Iterator inputPortsIter = inputPorts.iterator(); + Iterator inputPortsIter = inputPorts.iterator(); Assert.assertTrue(inputPortsIter.hasNext()); - return inputPortsIter.next(); + return inputPortsIter.next().getComponent(); } private PortDTO getRandomOutputPort() throws Exception { @@ -871,15 +871,15 @@ public class DfmAccessControlTest { // get the port dtos OutputPortsEntity outputPortsEntity = response.getEntity(OutputPortsEntity.class); - Collection outputPorts = outputPortsEntity.getOutputPorts(); + Collection outputPorts = outputPortsEntity.getOutputPorts(); // ensure the correct number of ports Assert.assertFalse(outputPorts.isEmpty()); // use the first port as the target - Iterator inputPortsIter = outputPorts.iterator(); + Iterator inputPortsIter = outputPorts.iterator(); Assert.assertTrue(inputPortsIter.hasNext()); - return inputPortsIter.next(); + return inputPortsIter.next().getComponent(); } // ---------------------------------------------- @@ -900,7 +900,7 @@ public class DfmAccessControlTest { // create the entity body ProcessGroupEntity entity = new ProcessGroupEntity(); entity.setRevision(revision); - entity.setProcessGroup(processGroup); + entity.setComponent(processGroup); // perform the request ClientResponse response = DFM_USER.testPost(url, entity); @@ -912,7 +912,7 @@ public class DfmAccessControlTest { entity = response.getEntity(ProcessGroupEntity.class); // verify creation - processGroup = entity.getProcessGroup(); + processGroup = entity.getComponent(); Assert.assertEquals("Group1", processGroup.getName()); // get the process group @@ -932,9 +932,9 @@ public class DfmAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - InputPortEntity entity = new InputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); - entity.setInputPort(portDTO); + entity.setComponent(portDTO); // perform the request ClientResponse response = DFM_USER.testPost(url, entity); @@ -943,10 +943,10 @@ public class DfmAccessControlTest { Assert.assertEquals(201, response.getStatus()); // get the entity body - entity = response.getEntity(InputPortEntity.class); + entity = response.getEntity(PortEntity.class); // verify creation - portDTO = entity.getInputPort(); + portDTO = entity.getComponent(); Assert.assertEquals("Input Port", portDTO.getName()); // get the process group @@ -966,9 +966,9 @@ public class DfmAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - OutputPortEntity entity = new OutputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); - entity.setOutputPort(portDTO); + entity.setComponent(portDTO); // perform the request ClientResponse response = DFM_USER.testPost(url, entity); @@ -977,10 +977,10 @@ public class DfmAccessControlTest { Assert.assertEquals(201, response.getStatus()); // get the entity body - entity = response.getEntity(OutputPortEntity.class); + entity = response.getEntity(PortEntity.class); // verify creation - portDTO = entity.getOutputPort(); + portDTO = entity.getComponent(); Assert.assertEquals("Output Port", portDTO.getName()); // get the process group @@ -1003,7 +1003,7 @@ public class DfmAccessControlTest { // create the entity body ProcessorEntity entity = new ProcessorEntity(); entity.setRevision(revision); - entity.setProcessor(processor); + entity.setComponent(processor); // perform the request ClientResponse response = DFM_USER.testPost(url, entity); @@ -1015,7 +1015,7 @@ public class DfmAccessControlTest { entity = response.getEntity(ProcessorEntity.class); // verify creation - processor = entity.getProcessor(); + processor = entity.getComponent(); Assert.assertEquals("Copy", processor.getName()); Assert.assertEquals("org.apache.nifi.integration.util.SourceTestProcessor", processor.getType()); @@ -1054,7 +1054,7 @@ public class DfmAccessControlTest { // create the entity body ConnectionEntity entity = new ConnectionEntity(); entity.setRevision(revision); - entity.setConnection(connection); + entity.setComponent(connection); // perform the request ClientResponse response = DFM_USER.testPost(url, entity); @@ -1066,7 +1066,7 @@ public class DfmAccessControlTest { entity = response.getEntity(ConnectionEntity.class); // verify the results - connection = entity.getConnection(); + connection = entity.getComponent(); Assert.assertEquals(sourceId, connection.getSource().getId()); Assert.assertEquals(targetId, connection.getDestination().getId()); Assert.assertEquals(1, connection.getSelectedRelationships().size()); @@ -1091,7 +1091,7 @@ public class DfmAccessControlTest { // create the entity body LabelEntity entity = new LabelEntity(); entity.setRevision(revision); - entity.setLabel(label); + entity.setComponent(label); // perform the request ClientResponse response = DFM_USER.testPost(url, entity); @@ -1103,7 +1103,7 @@ public class DfmAccessControlTest { entity = response.getEntity(LabelEntity.class); // verify the results - label = entity.getLabel(); + label = entity.getComponent(); Assert.assertEquals("Label2", label.getLabel()); // get the label id diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ReadOnlyAccessControlTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ReadOnlyAccessControlTest.java index 2ed653a9e4..98a8cd05d2 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ReadOnlyAccessControlTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/ReadOnlyAccessControlTest.java @@ -17,9 +17,6 @@ package org.apache.nifi.integration.accesscontrol; import com.sun.jersey.api.client.ClientResponse; -import java.io.File; -import java.util.HashMap; -import java.util.Map; import org.apache.nifi.integration.NiFiWebApiTest; import org.apache.nifi.integration.util.NiFiTestServer; import org.apache.nifi.integration.util.NiFiTestUser; @@ -34,12 +31,11 @@ import org.apache.nifi.web.api.entity.BannerEntity; import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionsEntity; import org.apache.nifi.web.api.entity.ControllerConfigurationEntity; -import org.apache.nifi.web.api.entity.InputPortEntity; import org.apache.nifi.web.api.entity.InputPortsEntity; import org.apache.nifi.web.api.entity.LabelEntity; import org.apache.nifi.web.api.entity.LabelsEntity; -import org.apache.nifi.web.api.entity.OutputPortEntity; import org.apache.nifi.web.api.entity.OutputPortsEntity; +import org.apache.nifi.web.api.entity.PortEntity; import org.apache.nifi.web.api.entity.PrioritizerTypesEntity; import org.apache.nifi.web.api.entity.ProcessGroupEntity; import org.apache.nifi.web.api.entity.ProcessGroupsEntity; @@ -52,6 +48,10 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; +import java.io.File; +import java.util.HashMap; +import java.util.Map; + /** * Access control test for a read only user. */ @@ -125,7 +125,7 @@ public class ReadOnlyAccessControlTest { Assert.assertNotNull(processGroupEntity); // extract the process group dto - ProcessGroupDTO processGroupDTO = processGroupEntity.getProcessGroup(); + ProcessGroupDTO processGroupDTO = processGroupEntity.getComponent(); FlowSnippetDTO processGroupContentsDTO = processGroupDTO.getContents(); // verify graph @@ -625,7 +625,7 @@ public class ReadOnlyAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - InputPortEntity entity = new InputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request @@ -650,7 +650,7 @@ public class ReadOnlyAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - InputPortEntity entity = new InputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request @@ -715,7 +715,7 @@ public class ReadOnlyAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - OutputPortEntity entity = new OutputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request @@ -740,7 +740,7 @@ public class ReadOnlyAccessControlTest { revision.setVersion(NiFiTestUser.REVISION); // create the entity body - OutputPortEntity entity = new OutputPortEntity(); + PortEntity entity = new PortEntity(); entity.setRevision(revision); // perform the request diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/pom.xml index 22b387c6d5..9a7c69edb8 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/pom.xml @@ -41,6 +41,11 @@ nifi-utils provided + + org.apache.nifi + nifi-framework-authorization + provided + org.apache.commons commons-lang3 diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/src/main/java/org/apache/nifi/web/ContentViewerController.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/src/main/java/org/apache/nifi/web/ContentViewerController.java index 50ca101fc3..00dc06fa48 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/src/main/java/org/apache/nifi/web/ContentViewerController.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-content-viewer/src/main/java/org/apache/nifi/web/ContentViewerController.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.AccessDeniedException; import org.apache.nifi.stream.io.StreamUtils; import org.apache.nifi.web.ViewableContent.DisplayMode; import org.apache.tika.detect.DefaultDetector; @@ -39,7 +40,6 @@ import org.apache.tika.metadata.Metadata; import org.apache.tika.mime.MediaType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.access.AccessDeniedException; /** * Controller servlet for viewing content. This is responsible for generating diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java index 16b55ee871..3bc22f75f5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/StandardOptimisticLockingManager.java @@ -18,9 +18,10 @@ package org.apache.nifi.web; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; + +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.context.ClusterContext; import org.apache.nifi.cluster.context.ClusterContextThreadLocal; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml index 931f682258..97a90d3efd 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml @@ -77,6 +77,10 @@ org.apache.nifi nifi-framework-core + + org.apache.nifi + nifi-framework-authorization + io.jsonwebtoken jjwt diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java index 7108edb5e6..817480fbb3 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java @@ -25,8 +25,8 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.security.user.NiFiUserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authentication.AuthenticationManager; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java index 1b2f28ad6f..605e98b840 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java @@ -23,7 +23,7 @@ import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java index 3de5a2d13a..6c14ca5336 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/anonymous/NiFiAnonymousUserFilter.java @@ -16,9 +16,9 @@ */ package org.apache.nifi.web.security.anonymous; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.web.security.token.NiFiAuthenticationToken; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; @@ -41,6 +41,7 @@ public class NiFiAnonymousUserFilter extends AnonymousAuthenticationFilter { @Override protected Authentication createAuthentication(HttpServletRequest request) { + // TODO - conditional anonymous authentication return new NiFiAuthenticationToken(new NiFiUserDetails(NiFiUser.ANONYMOUS)); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java index 289cc87ed5..7634123073 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/jwt/JwtAuthenticationProvider.java @@ -17,10 +17,10 @@ package org.apache.nifi.web.security.jwt; import io.jsonwebtoken.JwtException; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.web.security.InvalidAuthenticationException; import org.apache.nifi.web.security.token.NiFiAuthenticationToken; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java index 03e1400cf8..8451c7c686 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java @@ -24,11 +24,12 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; + +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.controller.FlowController; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.authentication.AuthenticationResponse; -import org.apache.nifi.web.security.user.NiFiUserDetails; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.security.token.NiFiAuthenticationToken; import org.apache.nifi.web.security.x509.X509CertificateExtractor; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java index 411efc11e5..8f2712cdf5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/otp/OtpAuthenticationProvider.java @@ -16,10 +16,10 @@ */ package org.apache.nifi.web.security.otp; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.web.security.InvalidAuthenticationException; import org.apache.nifi.web.security.token.NiFiAuthenticationToken; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java index 2593f92380..43d69588c1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java @@ -18,11 +18,18 @@ package org.apache.nifi.web.security.x509; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.authentication.AuthenticationResponse; -import org.apache.nifi.user.NiFiUser; +import org.apache.nifi.authorization.AuthorizationRequest; +import org.apache.nifi.authorization.AuthorizationResult; +import org.apache.nifi.authorization.AuthorizationResult.Result; +import org.apache.nifi.authorization.Authorizer; +import org.apache.nifi.authorization.RequestAction; +import org.apache.nifi.authorization.resource.ResourceFactory; +import org.apache.nifi.authorization.user.NiFiUser; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.web.security.InvalidAuthenticationException; import org.apache.nifi.web.security.ProxiedEntitiesUtils; +import org.apache.nifi.web.security.UntrustedProxyException; import org.apache.nifi.web.security.token.NiFiAuthenticationToken; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -37,9 +44,11 @@ import java.util.ListIterator; public class X509AuthenticationProvider implements AuthenticationProvider { private X509IdentityProvider certificateIdentityProvider; + private Authorizer authorizer; - public X509AuthenticationProvider(X509IdentityProvider certificateIdentityProvider) { + public X509AuthenticationProvider(final X509IdentityProvider certificateIdentityProvider, final Authorizer authorizer) { this.certificateIdentityProvider = certificateIdentityProvider; + this.authorizer = authorizer; } @Override @@ -64,6 +73,24 @@ public class X509AuthenticationProvider implements AuthenticationProvider { // add the chain as appropriate to each proxy NiFiUser proxy = null; for (final ListIterator chainIter = proxyChain.listIterator(proxyChain.size()); chainIter.hasPrevious();) { + final String identity = chainIter.previous(); + + if (chainIter.hasPrevious()) { + // authorize this proxy in order to authenticate this user + final AuthorizationRequest proxyAuthorizationRequest = new AuthorizationRequest.Builder() + .identity(identity) + .anonymous(false) + .accessAttempt(true) + .action(RequestAction.WRITE) + .resource(ResourceFactory.getProxyResource()) + .build(); + + final AuthorizationResult proxyAuthorizationResult = authorizer.authorize(proxyAuthorizationRequest); + if (!Result.Approved.equals(proxyAuthorizationResult.getResult())) { + throw new UntrustedProxyException(String.format("Untrusted proxy %s", identity)); + } + } + proxy = new NiFiUser(chainIter.previous(), proxy); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml index 12d8594a24..b4c3176de7 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/resources/nifi-web-security-context.xml @@ -41,7 +41,8 @@ - + + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java index a95c1a0626..3fffad16a5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/otp/OtpAuthenticationProviderTest.java @@ -16,8 +16,8 @@ */ package org.apache.nifi.web.security.otp; +import org.apache.nifi.authorization.user.NiFiUserDetails; import org.apache.nifi.web.security.token.NiFiAuthenticationToken; -import org.apache.nifi.web.security.user.NiFiUserDetails; import org.junit.Before; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js index 6f27e41ebd..1785ce3da6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-breadcrumbs-controller.js @@ -38,15 +38,15 @@ nf.ng.BreadcrumbsCtrl = (function () { /** * Generate the breadcrumbs. * - * @param {object} processGroup The process group used to generate breadcrumbs + * @param {object} breadcrumb The breadcrumb */ - generateBreadcrumbs: function (processGroup) { + generateBreadcrumbs: function (breadcrumb) { //explicitly sanitize processGroup.name - processGroup.name = $sanitize(processGroup.name); - this.breadcrumbs.unshift(processGroup); + breadcrumb.name = $sanitize(breadcrumb.name); + this.breadcrumbs.unshift(breadcrumb); - if (nf.Common.isDefinedAndNotNull(processGroup.parent)) { - this.generateBreadcrumbs(processGroup.parent); + if (nf.Common.isDefinedAndNotNull(breadcrumb.parentBreadcrumb)) { + this.generateBreadcrumbs(breadcrumb.parentBreadcrumb); } }, diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js index e950080b70..59f56fca3b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js @@ -87,23 +87,16 @@ nf.Actions = (function () { // create a method for updating process groups and processors var updateProcessGroup = function (response) { - if (nf.Common.isDefinedAndNotNull(response.processGroup)) { - if (nf.Common.isDefinedAndNotNull(response.processGroup.contents)) { - var contents = response.processGroup.contents; - - // update all the components in the contents - nf.Graph.set(contents); - - // update each process group - $.each(contents.processGroups, function (_, processGroup) { - // reload the group's connections - var connections = nf.Connection.getComponentConnections(processGroup.id); - $.each(connections, function (_, connection) { - nf.Connection.reload(connection); - }); - }); - } - } + $.ajax({ + type: 'GET', + url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(response.id), + data: { + verbose: true + }, + dataType: 'json' + }).done(function (response) { + nf.Graph.set(response.processGroupFlow.flow); + }); }; return { @@ -122,7 +115,7 @@ nf.Actions = (function () { enterGroup: function (selection) { if (selection.size() === 1 && nf.CanvasUtils.isProcessGroup(selection)) { var selectionData = selection.datum(); - nf.CanvasUtils.enterGroup(selectionData.component.id); + nf.CanvasUtils.enterGroup(selectionData.id); } }, @@ -168,7 +161,7 @@ nf.Actions = (function () { if (refreshTimestamp === remoteProcessGroup.flowRefreshed) { schedule(nextDelay); } else { - nf.RemoteProcessGroup.set(response.remoteProcessGroup); + nf.RemoteProcessGroup.set(response); // reload the group's connections var connections = nf.Connection.getComponentConnections(remoteProcessGroup.id); @@ -372,7 +365,7 @@ nf.Actions = (function () { }; } else { var selectionData = selection.datum(); - var selectionPosition = selectionData.component.position; + var selectionPosition = selectionData.position; box = { x: selectionPosition.x, @@ -413,20 +406,15 @@ nf.Actions = (function () { var selected = d3.select(this); // build the entity - var entity = {}; - entity[nf[d.type].getEntityKey(d)] = { - 'id': d.component.id, - 'state': 'STOPPED' + var entity = { + 'component': { + 'id': d.id, + 'state': 'STOPPED' + } }; enableRequests.push(updateResource(d.component.uri, entity).done(function (response) { - if (nf.CanvasUtils.isProcessor(selected)) { - nf.Processor.set(response.processor); - } else if (nf.CanvasUtils.isInputPort(selected)) { - nf.Port.set(response.inputPort); - } else if (nf.CanvasUtils.isOutputPort(selected)) { - nf.Port.set(response.outputPort); - } + nf[d.type].set(response); })); }); @@ -460,20 +448,15 @@ nf.Actions = (function () { var selected = d3.select(this); // build the entity - var entity = {}; - entity[nf[d.type].getEntityKey(d)] = { - 'id': d.component.id, - 'state': 'DISABLED' + var entity = { + 'component': { + 'id': d.id, + 'state': 'DISABLED' + } }; disableRequests.push(updateResource(d.component.uri, entity).done(function (response) { - if (nf.CanvasUtils.isProcessor(selected)) { - nf.Processor.set(response.processor); - } else if (nf.CanvasUtils.isInputPort(selected)) { - nf.Port.set(response.inputPort); - } else if (nf.CanvasUtils.isOutputPort(selected)) { - nf.Port.set(response.outputPort); - } + nf[d.type].set(response); })); }); @@ -497,7 +480,7 @@ nf.Actions = (function () { // open the provenance page with the specified component nf.Shell.showPage('provenance?' + $.param({ - componentId: selectionData.component.id + componentId: selectionData.id })); } }, @@ -511,7 +494,7 @@ nf.Actions = (function () { if (selection.empty()) { // build the entity var entity = { - 'processGroup': { + 'component': { 'id': nf.Canvas.getGroupId(), 'running': true } @@ -538,7 +521,7 @@ nf.Actions = (function () { // processor endpoint does not use running flag... var component = { - 'id': d.component.id, + 'id': d.id, }; if (nf.CanvasUtils.isProcessor(selected) || nf.CanvasUtils.isInputPort(selected) || nf.CanvasUtils.isOutputPort(selected)) { component['state'] = 'RUNNING'; @@ -547,24 +530,21 @@ nf.Actions = (function () { } // build the entity - var entity = {}; - entity[nf[d.type].getEntityKey(d)] = component; + var entity = { + 'component': component + }; startRequests.push(updateResource(d.component.uri, entity).done(function (response) { - if (nf.CanvasUtils.isProcessor(selected)) { - nf.Processor.set(response.processor); - } else if (nf.CanvasUtils.isProcessGroup(selected)) { - nf.ProcessGroup.set(response.processGroup); + if (nf.CanvasUtils.isProcessGroup(selected)) { + nf.ProcessGroup.set(response); // reload the group's connections - var connections = nf.Connection.getComponentConnections(response.processGroup.id); + var connections = nf.Connection.getComponentConnections(response.id); $.each(connections, function (_, connection) { nf.Connection.reload(connection); }); - } else if (nf.CanvasUtils.isInputPort(selected)) { - nf.Port.set(response.inputPort); - } else if (nf.CanvasUtils.isOutputPort(selected)) { - nf.Port.set(response.outputPort); + } else { + nf[d.type].set(response); } })); }); @@ -588,7 +568,7 @@ nf.Actions = (function () { if (selection.empty()) { // build the entity var entity = { - 'processGroup': { + 'component': { 'id': nf.Canvas.getGroupId(), 'running': false } @@ -615,7 +595,7 @@ nf.Actions = (function () { // processor endpoint does not use running flag... var component = { - 'id': d.component.id, + 'id': d.id, }; if (nf.CanvasUtils.isProcessor(selected) || nf.CanvasUtils.isInputPort(selected) || nf.CanvasUtils.isOutputPort(selected)) { component['state'] = 'STOPPED'; @@ -624,24 +604,21 @@ nf.Actions = (function () { } // build the entity - var entity = {}; - entity[nf[d.type].getEntityKey(d)] = component; + var entity = { + 'component': component + }; stopRequests.push(updateResource(d.component.uri, entity).done(function (response) { - if (nf.CanvasUtils.isProcessor(selected)) { - nf.Processor.set(response.processor); - } else if (nf.CanvasUtils.isProcessGroup(selected)) { - nf.ProcessGroup.set(response.processGroup); + if (nf.CanvasUtils.isProcessGroup(selected)) { + nf.ProcessGroup.set(response); // reload the group's connections - var connections = nf.Connection.getComponentConnections(response.processGroup.id); + var connections = nf.Connection.getComponentConnections(response.id); $.each(connections, function (_, connection) { nf.Connection.reload(connection); }); - } else if (nf.CanvasUtils.isInputPort(selected)) { - nf.Port.set(response.inputPort); - } else if (nf.CanvasUtils.isOutputPort(selected)) { - nf.Port.set(response.outputPort); + } else { + nf[d.type].set(response); } })); }); @@ -669,15 +646,16 @@ nf.Actions = (function () { // start each selected component componentsToEnable.each(function (d) { // build the entity - var entity = {}; - entity[nf[d.type].getEntityKey()] = { - 'id': d.component.id, - 'transmitting': true + var entity = { + 'component': { + 'id': d.id, + 'transmitting': true + } }; // start transmitting updateResource(d.component.uri, entity).done(function (response) { - nf.RemoteProcessGroup.set(response.remoteProcessGroup); + nf.RemoteProcessGroup.set(response); }); }); }, @@ -695,14 +673,15 @@ nf.Actions = (function () { // stop each selected component componentsToDisable.each(function (d) { // build the entity - var entity = {}; - entity[nf[d.type].getEntityKey()] = { - 'id': d.component.id, - 'transmitting': false + var entity = { + 'component': { + 'id': d.id, + 'transmitting': false + } }; updateResource(d.component.uri, entity).done(function (response) { - nf.RemoteProcessGroup.set(response.remoteProcessGroup); + nf.RemoteProcessGroup.set(response); }); }); }, @@ -735,7 +714,7 @@ nf.Actions = (function () { if (selection.size() === 1) { var selectionData = selection.datum(); if (nf.CanvasUtils.isProcessor(selection)) { - nf.ProcessorDetails.showDetails(nf.Canvas.getGroupId(), selectionData.component.id); + nf.ProcessorDetails.showDetails(nf.Canvas.getGroupId(), selectionData.id); } else if (nf.CanvasUtils.isProcessGroup(selection)) { nf.ProcessGroupDetails.showDetails(selection); } else if (nf.CanvasUtils.isRemoteProcessGroup(selection)) { @@ -743,7 +722,7 @@ nf.Actions = (function () { } else if (nf.CanvasUtils.isInputPort(selection) || nf.CanvasUtils.isOutputPort(selection)) { nf.PortDetails.showDetails(selection); } else if (nf.CanvasUtils.isConnection(selection)) { - nf.ConnectionDetails.showDetails(nf.Canvas.getGroupId(), selectionData.component.id); + nf.ConnectionDetails.showDetails(nf.Canvas.getGroupId(), selectionData.id); } } }, @@ -771,13 +750,13 @@ nf.Actions = (function () { if (selection.size() === 1) { var selectionData = selection.datum(); if (nf.CanvasUtils.isProcessor(selection)) { - nf.StatusHistory.showProcessorChart(nf.Canvas.getGroupId(), selectionData.component.id); + nf.StatusHistory.showProcessorChart(nf.Canvas.getGroupId(), selectionData.id); } else if (nf.CanvasUtils.isProcessGroup(selection)) { - nf.StatusHistory.showProcessGroupChart(nf.Canvas.getGroupId(), selectionData.component.id); + nf.StatusHistory.showProcessGroupChart(nf.Canvas.getGroupId(), selectionData.id); } else if (nf.CanvasUtils.isRemoteProcessGroup(selection)) { - nf.StatusHistory.showRemoteProcessGroupChart(nf.Canvas.getGroupId(), selectionData.component.id); + nf.StatusHistory.showRemoteProcessGroupChart(nf.Canvas.getGroupId(), selectionData.id); } else if (nf.CanvasUtils.isConnection(selection)) { - nf.StatusHistory.showConnectionChart(nf.Canvas.getGroupId(), selectionData.component.id); + nf.StatusHistory.showConnectionChart(nf.Canvas.getGroupId(), selectionData.id); } } }, @@ -828,11 +807,11 @@ nf.Actions = (function () { nf.Client.setRevision(response.revision); // remove the component/connection in question - nf[selectionData.type].remove(selectionData.component.id); + nf[selectionData.type].remove(selectionData.id); // if the selection is a connection, reload the source and destination accordingly if (nf.CanvasUtils.isConnection(selection) === false) { - var connections = nf.Connection.getComponentConnections(selectionData.component.id); + var connections = nf.Connection.getComponentConnections(selectionData.id); if (connections.length > 0) { var ids = []; $.each(connections, function (_, connection) { @@ -869,11 +848,11 @@ nf.Actions = (function () { // go through each component being removed selection.each(function (d) { // remove the corresponding entry - addComponent(d.type, d.component.id); + addComponent(d.type, d.id); // if this is not a connection, see if it has any connections that need to be removed if (d.type !== 'Connection') { - var connections = nf.Connection.getComponentConnections(d.component.id); + var connections = nf.Connection.getComponentConnections(d.id); if (connections.length > 0) { $.each(connections, function (_, connection) { addComponent('Connection', connection.id); @@ -1065,7 +1044,7 @@ nf.Actions = (function () { // issue the request to delete the flow files $.ajax({ type: 'POST', - url: '../nifi-api/flowfile-queues/' + connection.component.id + '/drop-requests', + url: '../nifi-api/flowfile-queues/' + connection.id + '/drop-requests', dataType: 'json', contentType: 'application/json' }).done(function(response) { @@ -1365,10 +1344,10 @@ nf.Actions = (function () { // copy the snippet to the new location nf.Snippet.copy(snippet.id, origin).done(function (copyResponse) { - var snippetContents = copyResponse.contents; + var snippetFlow = copyResponse.flow; // update the graph accordingly - nf.Graph.add(snippetContents, true); + nf.Graph.add(snippetFlow, true); // update component visibility nf.Canvas.View.updateVisibility(); @@ -1424,7 +1403,7 @@ nf.Actions = (function () { // determine the current max zIndex var maxZIndex = -1; $.each(nf.Connection.get(), function (_, otherConnection) { - if (connection.component.id !== otherConnection.component.id && otherConnection.component.zIndex > maxZIndex) { + if (connection.id !== otherConnection.id && otherConnection.component.zIndex > maxZIndex) { maxZIndex = otherConnection.component.zIndex; } }); @@ -1437,8 +1416,8 @@ nf.Actions = (function () { // build the connection entity var connectionEntity = { 'revision': nf.Client.getRevision(), - 'connection': { - 'id': connection.component.id, + 'component': { + 'id': connection.id, 'zIndex': zIndex } }; @@ -1452,7 +1431,7 @@ nf.Actions = (function () { contentType: 'application/json' }).done(function (response) { // update the edge's zIndex - nf.Connection.set(response.connection); + nf.Connection.set(response); nf.Connection.reorder(); // update the revision diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js index 01abd31505..1b2326228a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-birdseye.js @@ -151,50 +151,54 @@ nf.Birdseye = (function () { $.each(components.labels, function (_, d) { var color = nf.Label.defaultColor(); - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; + } } context.fillStyle = color; - context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height); + context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height); }); // funnels context.fillStyle = '#9f6000'; $.each(components.funnels, function (_, d) { - context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height); + context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height); }); // ports context.fillStyle = '#aaa'; $.each(components.ports, function (_, d) { - context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height); + context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height); }); // remote process groups context.fillStyle = '#294c58'; $.each(components.remoteProcessGroups, function (_, d) { - context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height); + context.fillRect(d.position.x, d.position.y, d.dimensions.width, d.dimensions.height); }); // process groups context.fillStyle = '#294c58'; $.each(components.processGroups, function (_, d) { - context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height); + context.fillRect(d.x, d.y, d.dimensions.width, d.dimensions.height); }); // processors $.each(components.processors, function (_, d) { var color = nf.Processor.defaultColor(); - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; + } } context.fillStyle = color; - context.fillRect(d.component.position.x, d.component.position.y, d.dimensions.width, d.dimensions.height); + context.fillRect(d.x, d.y, d.dimensions.width, d.dimensions.height); }); context.restore(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js index 6ed6c5d4bb..fbe4b7df36 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js @@ -166,12 +166,12 @@ nf.CanvasHeader = (function () { if (color !== selectedData.component.style['background-color']) { // build the request entity var entity = { - 'revision': nf.Client.getRevision() - }; - entity[nf[selectedData.type].getEntityKey()] = { - 'id': selectedData.component.id, - 'style': { - 'background-color': color + 'revision': nf.Client.getRevision(), + 'component': { + 'id': selectedData.id, + 'style': { + 'background-color': color + } } }; @@ -186,12 +186,8 @@ nf.CanvasHeader = (function () { // update the revision nf.Client.setRevision(response.revision); - // update the processor - if (nf.CanvasUtils.isProcessor(selected)) { - nf.Processor.set(response.processor); - } else { - nf.Label.set(response.label); - } + // update the component + nf[selectedData.type].set(response); }).fail(function (xhr, status, error) { if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) { nf.Dialog.showOkDialog({ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js index 8aade5cd0e..9cae764084 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbar.js @@ -109,61 +109,62 @@ nf.CanvasToolbar = (function () { } // only refresh the toolbar if DFM - if (nf.Common.isDFM()) { - var selection = nf.CanvasUtils.getSelection(); + var selection = nf.CanvasUtils.getSelection(); + if (nf.CanvasUtils.canModify(selection) === false) { + return; + } - // if all selected components are deletable enable the delete button - if (!selection.empty()) { - var enableDelete = true; - selection.each(function (d) { - if (!nf.CanvasUtils.isDeletable(d3.select(this))) { - enableDelete = false; - return false; - } - }); - if (enableDelete) { - actions['delete'].enable(); - } else { - actions['delete'].disable(); + // if all selected components are deletable enable the delete button + if (!selection.empty()) { + var enableDelete = true; + selection.each(function (d) { + if (!nf.CanvasUtils.isDeletable(d3.select(this))) { + enableDelete = false; + return false; } + }); + if (enableDelete) { + actions['delete'].enable(); } else { actions['delete'].disable(); } + } else { + actions['delete'].disable(); + } - // if there are any copyable components enable the button - if (nf.CanvasUtils.isCopyable(selection)) { - actions['copy'].enable(); - } else { - actions['copy'].disable(); - } + // if there are any copyable components enable the button + if (nf.CanvasUtils.isCopyable(selection)) { + actions['copy'].enable(); + } else { + actions['copy'].disable(); + } - // determine if the selection is groupable - if (!selection.empty() && nf.CanvasUtils.isDisconnected(selection)) { - actions['group'].enable(); - } else { - actions['group'].disable(); - } + // determine if the selection is groupable + if (!selection.empty() && nf.CanvasUtils.isDisconnected(selection)) { + actions['group'].enable(); + } else { + actions['group'].disable(); + } - // if there are any colorable components enable the fill button - if (nf.CanvasUtils.isColorable(selection)) { - actions['fill'].enable(); - } else { - actions['fill'].disable(); - } - - // ensure the selection supports enable - if (nf.CanvasUtils.canEnable(selection)) { - actions['enable'].enable(); - } else { - actions['enable'].disable(); - } + // if there are any colorable components enable the fill button + if (nf.CanvasUtils.isColorable(selection)) { + actions['fill'].enable(); + } else { + actions['fill'].disable(); + } + + // ensure the selection supports enable + if (nf.CanvasUtils.canEnable(selection)) { + actions['enable'].enable(); + } else { + actions['enable'].disable(); + } - // ensure the selection supports disable - if (nf.CanvasUtils.canDisable(selection)) { - actions['disable'].enable(); - } else { - actions['disable'].disable(); - } + // ensure the selection supports disable + if (nf.CanvasUtils.canDisable(selection)) { + actions['disable'].enable(); + } else { + actions['disable'].disable(); } } }; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js index de40653002..aca5a9eb37 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-toolbox.js @@ -363,7 +363,7 @@ nf.CanvasToolbox = (function () { var createProcessor = function (name, processorType, pt) { var processorEntity = { 'revision': nf.Client.getRevision(), - 'processor': { + 'component': { 'type': processorType, 'name': name, 'position': { @@ -381,13 +381,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processor)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // add the processor to the graph nf.Graph.add({ - 'processors': [response.processor] + 'processors': [response] }, true); // update component visibility @@ -454,7 +454,7 @@ nf.CanvasToolbox = (function () { var createInputPort = function (portName, pt) { var inputPortEntity = { 'revision': nf.Client.getRevision(), - 'inputPort': { + 'component': { 'name': portName, 'position': { 'x': pt.x, @@ -471,13 +471,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.inputPort)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // add the port to the graph nf.Graph.add({ - 'inputPorts': [response.inputPort] + 'inputPorts': [response] }, true); // update component visibility @@ -544,7 +544,7 @@ nf.CanvasToolbox = (function () { var createOutputPort = function (portName, pt) { var outputPortEntity = { 'revision': nf.Client.getRevision(), - 'outputPort': { + 'component': { 'name': portName, 'position': { 'x': pt.x, @@ -561,13 +561,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.outputPort)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // add the port to the graph nf.Graph.add({ - 'outputPorts': [response.outputPort] + 'outputPorts': [response] }, true); // update component visibility @@ -588,7 +588,7 @@ nf.CanvasToolbox = (function () { var createGroup = function (groupName, pt) { var processGroupEntity = { 'revision': nf.Client.getRevision(), - 'processGroup': { + 'component': { 'name': groupName, 'position': { 'x': pt.x, @@ -605,13 +605,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processGroup)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); - // add the processor to the graph + // add the process group to the graph nf.Graph.add({ - 'processGroups': [response.processGroup] + 'processGroups': [response] }, true); // update component visibility @@ -675,7 +675,7 @@ nf.CanvasToolbox = (function () { var createRemoteProcessGroup = function (remoteProcessGroupUri, pt) { var remoteProcessGroupEntity = { 'revision': nf.Client.getRevision(), - 'remoteProcessGroup': { + 'component': { 'targetUri': remoteProcessGroupUri, 'position': { 'x': pt.x, @@ -684,7 +684,7 @@ nf.CanvasToolbox = (function () { } }; - // create a new processor of the defined type + // create a new remote process group of the defined type $.ajax({ type: 'POST', url: config.urls.api + '/process-groups/' + encodeURIComponent(nf.Canvas.getGroupId()) + '/remote-process-groups', @@ -692,13 +692,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.remoteProcessGroup)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // add the processor to the graph nf.Graph.add({ - 'remoteProcessGroups': [response.remoteProcessGroup] + 'remoteProcessGroups': [response] }, true); // update component visibility @@ -718,7 +718,7 @@ nf.CanvasToolbox = (function () { var createFunnel = function (pt) { var outputPortEntity = { 'revision': nf.Client.getRevision(), - 'funnel': { + 'component': { 'position': { 'x': pt.x, 'y': pt.y @@ -734,13 +734,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.funnel)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // add the funnel to the graph nf.Graph.add({ - 'funnels': [response.funnel] + 'funnels': [response] }, true); // update the birdseye @@ -841,7 +841,7 @@ nf.CanvasToolbox = (function () { nf.Client.setRevision(response.revision); // populate the graph accordingly - nf.Graph.add(response.contents, true); + nf.Graph.add(response.flow, true); // update component visibility nf.Canvas.View.updateVisibility(); @@ -859,7 +859,7 @@ nf.CanvasToolbox = (function () { var createLabel = function (pt) { var labelEntity = { 'revision': nf.Client.getRevision(), - 'label': { + 'component': { 'width': nf.Label.config.width, 'height': nf.Label.config.height, 'position': { @@ -877,13 +877,13 @@ nf.CanvasToolbox = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.label)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // add the label to the graph nf.Graph.add({ - 'labels': [response.label] + 'labels': [response] }, true); // update the birdseye @@ -1135,7 +1135,7 @@ nf.CanvasToolbox = (function () { // create the group and resolve the deferred accordingly createGroup(groupName, pt).done(function (response) { - deferred.resolve(response.processGroup); + deferred.resolve(response.component); }).fail(function () { deferred.reject(); }); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js index 0a9cf28eb9..55c4b49b5b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js @@ -74,7 +74,7 @@ nf.CanvasUtils = (function () { // go through each component being removed components.each(function (d) { - addComponent(d.type, d.component.id); + addComponent(d.type, d.id); }); // refresh all component types as necessary (handle components that have been removed) @@ -271,7 +271,7 @@ nf.CanvasUtils = (function () { // update the processors positioning updated.attr('transform', function (d) { - return 'translate(' + d.component.position.x + ', ' + d.component.position.y + ')'; + return 'translate(' + d.position.x + ', ' + d.position.y + ')'; }); }, @@ -467,7 +467,7 @@ nf.CanvasUtils = (function () { offset = nf.Common.isDefinedAndNotNull(offset) ? offset : 0; // remove any existing tip if necessary - var tip = d3.select('#bulletin-tip-' + d.component.id); + var tip = d3.select('#bulletin-tip-' + d.id); if (!tip.empty()) { tip.remove(); } @@ -488,7 +488,7 @@ nf.CanvasUtils = (function () { // if there are bulletins generate a tooltip tip = getTooltipContainer().append('div') .attr('id', function () { - return 'bulletin-tip-' + d.component.id; + return 'bulletin-tip-' + d.id; }) .attr('class', 'tooltip nifi-tooltip') .html(function () { @@ -843,6 +843,36 @@ nf.CanvasUtils = (function () { return nf.CanvasUtils.supportsModification(selection); }, + + /** + * Determines whether the components in the specified selection are writable. + * + * @argument {selection} selection The selection + * @return {boolean} Whether the selection is writable + */ + canModify: function (selection) { + var selectionSize = selection.size(); + var writableSize = selection.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).size(); + + return selectionSize === writableSize; + }, + + /** + * Determines whether the components in the specified selection are readable. + * + * @argument {selection} selection The selection + * @return {boolean} Whether the selection is readable + */ + canRead: function (selection) { + var selectionSize = selection.size(); + var readableSize = selection.filter(function (d) { + return d.accessPolicy.canRead; + }).size(); + + return selectionSize === readableSize; + }, /** * Determines whether the specified selection is in a state to support modification. @@ -875,7 +905,7 @@ nf.CanvasUtils = (function () { var isSourceConfigurable = false; var isDestinationConfigurable = false; - var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(selectionData.component); + var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(selectionData); var source = d3.select('#id-' + sourceComponentId); if (!source.empty()) { if (nf.CanvasUtils.isRemoteProcessGroup(source) || nf.CanvasUtils.isProcessGroup(source)) { @@ -885,7 +915,7 @@ nf.CanvasUtils = (function () { } } - var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(selectionData.component); + var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(selectionData); var destination = d3.select('#id-' + destinationComponentId); if (!destination.empty()) { if (nf.CanvasUtils.isRemoteProcessGroup(destination) || nf.CanvasUtils.isProcessGroup(destination)) { @@ -958,12 +988,12 @@ nf.CanvasUtils = (function () { var selected = d3.select(this); if (nf.CanvasUtils.isConnection(selected)) { var sourceIncluded = !selection.filter(function (source) { - var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d.component); - return sourceComponentId === source.component.id; + var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d); + return sourceComponentId === source.id; }).empty(); var destinationIncluded = !selection.filter(function (destination) { - var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d.component); - return destinationComponentId === destination.component.id; + var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d); + return destinationComponentId === destination.id; }).empty(); return sourceIncluded && destinationIncluded; } else { @@ -1026,13 +1056,15 @@ nf.CanvasUtils = (function () { if (source.empty() === false) { var sourceData = source.datum(); - // update the source status if necessary - if (nf.CanvasUtils.isProcessor(source)) { - nf.Processor.reload(sourceData.component); - } else if (nf.CanvasUtils.isInputPort(source)) { - nf.Port.reload(sourceData.component); - } else if (nf.CanvasUtils.isRemoteProcessGroup(source)) { - nf.RemoteProcessGroup.reload(sourceData.component); + if (sourceData.accessPolicy.canRead) { + // update the source status if necessary + if (nf.CanvasUtils.isProcessor(source)) { + nf.Processor.reload(sourceData.component); + } else if (nf.CanvasUtils.isInputPort(source)) { + nf.Port.reload(sourceData.component); + } else if (nf.CanvasUtils.isRemoteProcessGroup(source)) { + nf.RemoteProcessGroup.reload(sourceData.component); + } } } } @@ -1042,11 +1074,13 @@ nf.CanvasUtils = (function () { if (destination.empty() === false) { var destinationData = destination.datum(); - // update the destination component accordingly - if (nf.CanvasUtils.isProcessor(destination)) { - nf.Processor.reload(destinationData.component); - } else if (nf.CanvasUtils.isRemoteProcessGroup(destination)) { - nf.RemoteProcessGroup.reload(destinationData.component); + if (destinationData.accessPolicy.canRead) { + // update the destination component accordingly + if (nf.CanvasUtils.isProcessor(destination)) { + nf.Processor.reload(destinationData.component); + } else if (nf.CanvasUtils.isRemoteProcessGroup(destination)) { + nf.RemoteProcessGroup.reload(destinationData.component); + } } } } @@ -1060,9 +1094,9 @@ nf.CanvasUtils = (function () { * @param {object} connection The connection in question */ getConnectionSourceComponentId: function (connection) { - var sourceId = connection.source.id; - if (connection.source.groupId !== nf.Canvas.getGroupId()) { - sourceId = connection.source.groupId; + var sourceId = connection.sourceId; + if (connection.sourceGroupId !== nf.Canvas.getGroupId()) { + sourceId = connection.sourceGroupId; } return sourceId; }, @@ -1075,9 +1109,9 @@ nf.CanvasUtils = (function () { * @param {object} connection The connection in question */ getConnectionDestinationComponentId: function (connection) { - var destinationId = connection.destination.id; - if (connection.destination.groupId !== nf.Canvas.getGroupId()) { - destinationId = connection.destination.groupId; + var destinationId = connection.destinationId; + if (connection.destinationGroupId !== nf.Canvas.getGroupId()) { + destinationId = connection.destinationGroupId; } return destinationId; }, @@ -1162,11 +1196,11 @@ nf.CanvasUtils = (function () { selection.each(function (d) { var selected = d3.select(this); if (!nf.CanvasUtils.isConnection(selected)) { - if (nf.Common.isUndefined(origin.x) || d.component.position.x < origin.x) { - origin.x = d.component.position.x; + if (nf.Common.isUndefined(origin.x) || d.position.x < origin.x) { + origin.x = d.position.x; } - if (nf.Common.isUndefined(origin.y) || d.component.position.y < origin.y) { - origin.y = d.component.position.y; + if (nf.Common.isUndefined(origin.y) || d.position.y < origin.y) { + origin.y = d.position.y; } } }); @@ -1200,7 +1234,7 @@ nf.CanvasUtils = (function () { var groupData = group.datum(); // move the components into the destination and... - moveComponents(components, groupData.component.id).done(function () { + moveComponents(components, groupData.id).done(function () { // reload the target group nf.ProcessGroup.reload(groupData.component); }); @@ -1223,10 +1257,10 @@ nf.CanvasUtils = (function () { var includesSource = false; var includesDestination = false; selection.each(function (d) { - if (d.component.id === sourceComponentId) { + if (d.id === sourceComponentId) { includesSource = true; } - if (d.component.id === destinationComponentId) { + if (d.id === destinationComponentId) { includesDestination = true; } }); @@ -1237,7 +1271,7 @@ nf.CanvasUtils = (function () { // include all components and connections whose source/destination are also selected return selection.filter(function (d) { if (d.type === 'Connection') { - return keepConnection(d.component); + return keepConnection(d); } else { return true; } @@ -1258,17 +1292,17 @@ nf.CanvasUtils = (function () { selection.filter(function (d) { return d.type === 'Connection'; }).each(function (d) { - connections.set(d.component.id, d.component); + connections.set(d.id, d); }); // include components and ensure their connections are included selection.filter(function (d) { return d.type !== 'Connection'; }).each(function (d) { - components.set(d.component.id, d.component); + components.set(d.id, d.component); // check all connections of this component - $.each(nf.Connection.getComponentConnections(d.component.id), function (_, connection) { + $.each(nf.Connection.getComponentConnections(d.id), function (_, connection) { if (!connections.has(connection.id)) { isDisconnected = false; return false; @@ -1338,7 +1372,7 @@ nf.CanvasUtils = (function () { // check the input ports $.each(inputPorts, function (i, inputPort) { $.each(connections, function (j, connection) { - if (inputPort.component.id === connection.destination.id) { + if (inputPort.id === connection.destination.id) { conflictingPorts.push(nf.Common.escapeHtml(inputPort.component.name)); } }); @@ -1347,7 +1381,7 @@ nf.CanvasUtils = (function () { // check the output ports $.each(outputPorts, function (i, outputPort) { $.each(connections, function (j, connection) { - if (outputPort.component.id === connection.source.id) { + if (outputPort.id === connection.source.id) { conflictingPorts.push(nf.Common.escapeHtml(outputPort.component.name)); } }); @@ -1385,7 +1419,7 @@ nf.CanvasUtils = (function () { }, dataType: 'json' }).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; var processGroupContents = processGroup.contents; var conflictingPorts = []; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js index 175a598544..83de139394 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js @@ -450,8 +450,8 @@ nf.Canvas = (function () { d3.selectAll('g.component').classed('selected', function (d) { // consider it selected if its already selected or enclosed in the bounding box return d3.select(this).classed('selected') || - d.component.position.x >= selectionBoundingBox.x && (d.component.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) && - d.component.position.y >= selectionBoundingBox.y && (d.component.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height); + d.position.x >= selectionBoundingBox.x && (d.position.x + d.dimensions.width) <= (selectionBoundingBox.x + selectionBoundingBox.width) && + d.position.y >= selectionBoundingBox.y && (d.position.y + d.dimensions.height) <= (selectionBoundingBox.y + selectionBoundingBox.height); }); // see if a connection should be selected or not @@ -777,32 +777,31 @@ nf.Canvas = (function () { // load the controller return $.ajax({ type: 'GET', - url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupId), + url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupId), data: { verbose: true }, dataType: 'json' - }).done(function (processGroupResponse) { + }).done(function (flowResponse) { // set the revision - nf.Client.setRevision(processGroupResponse.revision); + nf.Client.setRevision(flowResponse.revision); // get the controller and its contents - var processGroup = processGroupResponse.processGroup; + var processGroupFlow = flowResponse.processGroupFlow; // set the group details - nf.Canvas.setGroupId(processGroup.id); - nf.Canvas.setGroupName(processGroup.name); + nf.Canvas.setGroupId(processGroupFlow.id); // update the breadcrumbs nf.ng.Bridge.call('AppCtrl.ServiceProvider.BreadcrumbsCtrl', 'AppCtrl.ServiceProvider.BreadcrumbsCtrl.resetBreadcrumbs'); nf.ng.Bridge.call('AppCtrl.ServiceProvider.BreadcrumbsCtrl', 'AppCtrl.ServiceProvider.BreadcrumbsCtrl.generateBreadcrumbs', - processGroup); + processGroupFlow.breadcrumb); // set the parent id if applicable - if (nf.Common.isDefinedAndNotNull(processGroup.parent)) { - nf.Canvas.setParentGroupId(processGroup.parent.id); + if (nf.Common.isDefinedAndNotNull(processGroupFlow.parentGroupId)) { + nf.Canvas.setParentGroupId(processGroupFlow.parentGroupId); } else { nf.Canvas.setParentGroupId(null); } @@ -811,7 +810,7 @@ nf.Canvas = (function () { nf.Graph.removeAll(); // refresh the graph - nf.Graph.add(processGroup.contents, false); + nf.Graph.add(processGroupFlow.flow, false); // update the toolbar nf.CanvasToolbar.refresh(); @@ -1253,8 +1252,8 @@ nf.Canvas = (function () { return false; } - var left = d.component.position.x; - var top = d.component.position.y; + var left = d.position.x; + var top = d.position.y; var right = left + d.dimensions.width; var bottom = top + d.dimensions.height; @@ -1283,7 +1282,7 @@ nf.Canvas = (function () { // marks the specific component as visible and determines if its entering or leaving visibility var updateVisibility = function (d, isVisible) { - var selection = d3.select('#id-' + d.component.id); + var selection = d3.select('#id-' + d.id); var visible = isVisible(d); var wasVisible = selection.classed('visible'); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js index 154c14b09e..a49126614c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connectable.js @@ -71,7 +71,7 @@ nf.Connectable = (function () { var position = d3.mouse(canvas.node()); canvas.insert('path', ':first-child') .datum({ - 'sourceId': sourceData.component.id, + 'sourceId': sourceData.id, 'sourceWidth': sourceData.dimensions.width, 'x': position[0], 'y': position[1] @@ -122,7 +122,7 @@ nf.Connectable = (function () { var destinationData = destination.datum(); // show the line preview as appropriate - if (pathDatum.sourceId === destinationData.component.id) { + if (pathDatum.sourceId === destinationData.id) { var x = pathDatum.x; var y = pathDatum.y; var componentOffset = pathDatum.sourceWidth / 2; @@ -132,8 +132,8 @@ nf.Connectable = (function () { } else { // get the position on the destination perimeter var end = nf.CanvasUtils.getPerimeterPoint(pathDatum, { - 'x': destinationData.component.position.x, - 'y': destinationData.component.position.y, + 'x': destinationData.position.x, + 'y': destinationData.position.y, 'width': destinationData.dimensions.width, 'height': destinationData.dimensions.height }); @@ -190,7 +190,7 @@ nf.Connectable = (function () { // create the connection var destinationData = destination.datum(); - nf.ConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.component.id); + nf.ConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.id); } }); }, diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js index be2cb6cf88..e03c60d913 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection-configuration.js @@ -168,8 +168,8 @@ nf.ConnectionConfiguration = (function () { $('#input-port-source-name').text(inputPortData.component.name); // populate the connection source details - $('#connection-source-id').val(inputPortData.component.id); - $('#connection-source-component-id').val(inputPortData.component.id); + $('#connection-source-id').val(inputPortData.id); + $('#connection-source-component-id').val(inputPortData.id); // populate the group details $('#connection-source-group-id').val(nf.Canvas.getGroupId()); @@ -194,8 +194,8 @@ nf.ConnectionConfiguration = (function () { $('#funnel-source').show(); // populate the connection source details - $('#connection-source-id').val(funnelData.component.id); - $('#connection-source-component-id').val(funnelData.component.id); + $('#connection-source-id').val(funnelData.id); + $('#connection-source-component-id').val(funnelData.id); // populate the group details $('#connection-source-group-id').val(nf.Canvas.getGroupId()); @@ -222,8 +222,8 @@ nf.ConnectionConfiguration = (function () { $('#processor-source-type').text(nf.Common.substringAfterLast(processorData.component.type, '.')); // populate the connection source details - $('#connection-source-id').val(processorData.component.id); - $('#connection-source-component-id').val(processorData.component.id); + $('#connection-source-id').val(processorData.id); + $('#connection-source-component-id').val(processorData.id); // populate the group details $('#connection-source-group-id').val(nf.Canvas.getGroupId()); @@ -248,13 +248,13 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', - url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.component.id), + url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.id), data: { verbose: true }, dataType: 'json' }).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; var processGroupContents = processGroup.contents; // only proceed if there are output ports @@ -413,8 +413,8 @@ nf.ConnectionConfiguration = (function () { $('#output-port-destination-name').text(outputPortData.component.name); // populate the connection destination details - $('#connection-destination-id').val(outputPortData.component.id); - $('#connection-destination-component-id').val(outputPortData.component.id); + $('#connection-destination-id').val(outputPortData.id); + $('#connection-destination-component-id').val(outputPortData.id); // populate the group details $('#connection-destination-group-id').val(nf.Canvas.getGroupId()); @@ -431,8 +431,8 @@ nf.ConnectionConfiguration = (function () { $('#funnel-destination').show(); // populate the connection destination details - $('#connection-destination-id').val(funnelData.component.id); - $('#connection-destination-component-id').val(funnelData.component.id); + $('#connection-destination-id').val(funnelData.id); + $('#connection-destination-component-id').val(funnelData.id); // populate the group details $('#connection-destination-group-id').val(nf.Canvas.getGroupId()); @@ -451,8 +451,8 @@ nf.ConnectionConfiguration = (function () { $('#processor-destination-type').text(nf.Common.substringAfterLast(processorData.component.type, '.')); // populate the connection destination details - $('#connection-destination-id').val(processorData.component.id); - $('#connection-destination-component-id').val(processorData.component.id); + $('#connection-destination-id').val(processorData.id); + $('#connection-destination-component-id').val(processorData.id); // populate the group details $('#connection-destination-group-id').val(nf.Canvas.getGroupId()); @@ -473,13 +473,13 @@ nf.ConnectionConfiguration = (function () { $.ajax({ type: 'GET', - url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.component.id), + url: config.urls.api + '/process-groups/' + encodeURIComponent(processGroupData.id), data: { verbose: true }, dataType: 'json' }).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; var processGroupContents = processGroup.contents; // only proceed if there are output ports @@ -628,10 +628,10 @@ nf.ConnectionConfiguration = (function () { $('#read-only-output-port-source').show(); // populate the component information - $('#connection-source-component-id').val(sourceData.component.id); + $('#connection-source-component-id').val(sourceData.id); // populate the group details - $('#connection-source-group-id').val(sourceData.component.id); + $('#connection-source-group-id').val(sourceData.id); $('#connection-source-group-name').text(sourceData.component.name); // resolve the deferred @@ -711,8 +711,8 @@ nf.ConnectionConfiguration = (function () { var bends = []; if (sourceComponentId === destinationComponentId) { var rightCenter = { - x: sourceData.component.position.x + (sourceData.dimensions.width), - y: sourceData.component.position.y + (sourceData.dimensions.height / 2) + x: sourceData.position.x + (sourceData.dimensions.width), + y: sourceData.position.y + (sourceData.dimensions.height / 2) }; var xOffset = nf.Connection.config.selfLoopXOffset; @@ -759,8 +759,8 @@ nf.ConnectionConfiguration = (function () { // if we need to avoid a collision if (avoidCollision === true) { // determine the middle of the source/destination components - var sourceMiddle = [sourceData.component.position.x + (sourceData.dimensions.width / 2), sourceData.component.position.y + (sourceData.dimensions.height / 2)]; - var destinationMiddle = [destinationData.component.position.x + (destinationData.dimensions.width / 2), destinationData.component.position.y + (destinationData.dimensions.height / 2)]; + var sourceMiddle = [sourceData.position.x + (sourceData.dimensions.width / 2), sourceData.position.y + (sourceData.dimensions.height / 2)]; + var destinationMiddle = [destinationData.position.x + (destinationData.dimensions.width / 2), destinationData.position.y + (destinationData.dimensions.height / 2)]; // detect if the line is more horizontal or vertical var slope = ((sourceMiddle[1] - destinationMiddle[1]) / (sourceMiddle[0] - destinationMiddle[0])); @@ -841,7 +841,7 @@ nf.ConnectionConfiguration = (function () { if (validateSettings()) { var connectionEntity = { 'revision': nf.Client.getRevision(), - 'connection': { + 'component': { 'name': connectionName, 'source': { 'id': sourceId, @@ -875,7 +875,7 @@ nf.ConnectionConfiguration = (function () { // add the connection nf.Graph.add({ - 'connections': [response.connection] + 'connections': [response] }, true); // reload the connections source/destination components @@ -925,7 +925,7 @@ nf.ConnectionConfiguration = (function () { if (validateSettings()) { var connectionEntity = { 'revision': nf.Client.getRevision(), - 'connection': { + 'component': { 'id': connectionId, 'name': connectionName, 'destination': { @@ -949,14 +949,12 @@ nf.ConnectionConfiguration = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.connection)) { - var connection = response.connection; - + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // update this connection - nf.Connection.set(connection); + nf.Connection.set(response); // reload the connections source/destination components nf.CanvasUtils.reloadConnectionSourceAndDestination(sourceComponentId, destinationComponentId); @@ -1226,16 +1224,16 @@ nf.ConnectionConfiguration = (function () { */ showConfiguration: function (selection, destination) { return $.Deferred(function (deferred) { - var selectionData = selection.datum(); - var connection = selectionData.component; + var connectionEntry = selection.datum(); + var connection = connectionEntry.component; // identify the source component - var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(connection); + var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(connectionEntry); var source = d3.select('#id-' + sourceComponentId); // identify the destination component if (nf.Common.isUndefinedOrNull(destination)) { - var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(connection); + var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(connectionEntry); destination = d3.select('#id-' + destinationComponentId); } @@ -1283,7 +1281,7 @@ nf.ConnectionConfiguration = (function () { var destinationData = destination.datum(); // when the group ids differ, its a new destination component so we don't want to preselect any port - if (connection.destination.groupId === destinationData.component.id) { + if (connection.destination.groupId === destinationData.id) { $('#input-port-options').combo('setSelectedOption', { value: connection.destination.id }); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js index 8cab85e71f..48f7247f01 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-connection.js @@ -223,9 +223,7 @@ nf.Connection = (function () { * Selects the connection elements against the current connection map. */ var select = function () { - return connectionContainer.selectAll('g.connection').data(connectionMap.values(), function (d) { - return d.component.id; - }); + return connectionContainer.selectAll('g.connection').data(connectionMap.values()); }; var renderConnections = function (entered, selected) { @@ -236,7 +234,7 @@ nf.Connection = (function () { var connection = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': 'connection' }) @@ -268,45 +266,45 @@ nf.Connection = (function () { }) .call(nf.ContextMenu.activate); - if (nf.Common.isDFM()) { - // only support adding bend points when appropriate - selectableConnection.on('dblclick', function (d) { - var position = d3.mouse(this.parentNode); + // only support adding bend points when appropriate + selectableConnection.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).on('dblclick', function (d) { + var position = d3.mouse(this.parentNode); - // find where to put this bend point - var bendIndex = getNearestSegment({ - 'x': position[0], - 'y': position[1] - }, d); + // find where to put this bend point + var bendIndex = getNearestSegment({ + 'x': position[0], + 'y': position[1] + }, d); - // copy the original to restore if necessary - var bends = d.component.bends.slice(); + // copy the original to restore if necessary + var bends = d.component.bends.slice(); - // add it to the collection of points - bends.splice(bendIndex, 0, { - 'x': position[0], - 'y': position[1] - }); - - var connection = { - id: d.component.id, - bends: bends - }; - - // update the label index if necessary - var labelIndex = d.component.labelIndex; - if (bends.length === 1) { - connection.labelIndex = 0; - } else if (bendIndex <= labelIndex) { - connection.labelIndex = labelIndex + 1; - } - - // save the new state - save(d, connection); - - d3.event.stopPropagation(); + // add it to the collection of points + bends.splice(bendIndex, 0, { + 'x': position[0], + 'y': position[1] }); - } + + var connection = { + id: d.id, + bends: bends + }; + + // update the label index if necessary + var labelIndex = d.component.labelIndex; + if (bends.length === 1) { + connection.labelIndex = 0; + } else if (bendIndex <= labelIndex) { + connection.labelIndex = labelIndex + 1; + } + + // save the new state + save(d, connection); + + d3.event.stopPropagation(); + }); // update connection which will establish appropriate start/end points among other things connection.call(updateConnections, true, false); @@ -339,9 +337,11 @@ nf.Connection = (function () { updated.classed('grouped', function (d) { var grouped = false; - // if there are more than one selected relationship, mark this as grouped - if (nf.Common.isDefinedAndNotNull(d.component.selectedRelationships) && d.component.selectedRelationships.length > 1) { - grouped = true; + if (d.accessPolicy.canRead) { + // if there are more than one selected relationship, mark this as grouped + if (nf.Common.isDefinedAndNotNull(d.component.selectedRelationships) && d.component.selectedRelationships.length > 1) { + grouped = true; + } } return grouped; @@ -349,9 +349,11 @@ nf.Connection = (function () { .classed('ghost', function (d) { var ghost = false; - // if the connection has a relationship that is unavailable, mark it a ghost relationship - if (hasUnavailableRelationship(d)) { - ghost = true; + if (d.accessPolicy.canRead) { + // if the connection has a relationship that is unavailable, mark it a ghost relationship + if (hasUnavailableRelationship(d)) { + ghost = true; + } } return ghost; @@ -363,7 +365,7 @@ nf.Connection = (function () { if (updatePath === true) { // calculate the start and end points - var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d.component); + var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d); var sourceData = d3.select('#id-' + sourceComponentId).datum(); var end; @@ -373,8 +375,8 @@ nf.Connection = (function () { endAnchor = d.bends[d.bends.length - 1]; } else { endAnchor = { - x: sourceData.component.position.x + (sourceData.dimensions.width / 2), - y: sourceData.component.position.y + (sourceData.dimensions.height / 2) + x: sourceData.position.x + (sourceData.dimensions.width / 2), + y: sourceData.position.y + (sourceData.dimensions.height / 2) }; } @@ -391,8 +393,8 @@ nf.Connection = (function () { // get the position on the new destination perimeter var newEnd = nf.CanvasUtils.getPerimeterPoint(endAnchor, { - 'x': newDestinationData.component.position.x, - 'y': newDestinationData.component.position.y, + 'x': newDestinationData.position.x, + 'y': newDestinationData.position.y, 'width': newDestinationData.dimensions.width, 'height': newDestinationData.dimensions.height }); @@ -402,13 +404,13 @@ nf.Connection = (function () { end.y = newEnd.y; } } else { - var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d.component); + var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d); var destinationData = d3.select('#id-' + destinationComponentId).datum(); // get the position on the destination perimeter end = nf.CanvasUtils.getPerimeterPoint(endAnchor, { - 'x': destinationData.component.position.x, - 'y': destinationData.component.position.y, + 'x': destinationData.position.x, + 'y': destinationData.position.y, 'width': destinationData.dimensions.width, 'height': destinationData.dimensions.height }); @@ -424,8 +426,8 @@ nf.Connection = (function () { // get the position on the source perimeter var start = nf.CanvasUtils.getPerimeterPoint(startAnchor, { - 'x': sourceData.component.position.x, - 'y': sourceData.component.position.y, + 'x': sourceData.position.x, + 'y': sourceData.position.y, 'width': sourceData.dimensions.width, 'height': sourceData.dimensions.height }); @@ -444,9 +446,11 @@ nf.Connection = (function () { 'marker-end': function () { var marker = 'normal'; - // if the connection has a relationship that is unavailable, mark it a ghost relationship - if (hasUnavailableRelationship(d)) { - marker = 'ghost'; + if (d.accessPolicy.canRead) { + // if the connection has a relationship that is unavailable, mark it a ghost relationship + if (hasUnavailableRelationship(d)) { + marker = 'ghost'; + } } return 'url(#' + marker + ')'; @@ -471,7 +475,7 @@ nf.Connection = (function () { // bends // ----- - if (nf.Common.isDFM()) { + if (d.accessPolicy.canWrite) { // ------------------ // bends - startpoint // ------------------ @@ -549,8 +553,8 @@ nf.Connection = (function () { d3.event.stopPropagation(); // if this is a self loop prevent removing the last two bends - var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d.component); - var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d.component); + var sourceComponentId = nf.CanvasUtils.getConnectionSourceComponentId(d); + var destinationComponentId = nf.CanvasUtils.getConnectionDestinationComponentId(d); if (sourceComponentId === destinationComponentId && d.component.bends.length <= 2) { nf.Dialog.showOkDialog({ dialogContent: 'Looping connections must have at least two bend points.', @@ -576,7 +580,7 @@ nf.Connection = (function () { } var connection = { - id: d.component.id, + id: d.id, bends: newBends }; @@ -640,224 +644,227 @@ nf.Connection = (function () { var labelCount = 0; - // ----------------------- - // connection label - from - // ----------------------- + if (d.accessPolicy.canRead) { - var connectionFrom = connectionLabelContainer.select('g.connection-from-container'); + // ----------------------- + // connection label - from + // ----------------------- - // determine if the connection require a from label - if (isGroup(d.component.source)) { - // see if the connection from label is already rendered - if (connectionFrom.empty()) { - connectionFrom = connectionLabelContainer.append('g') - .attr({ - 'class': 'connection-from-container' - }); - - connectionFrom.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('From'); - - connectionFrom.append('text') - .attr({ - 'class': 'connection-stats-value connection-from', - 'x': 33, - 'y': 10, - 'width': 130 - }); - - connectionFrom.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'connection-from-run-status', - 'width': 10, - 'height': 10, - 'x': 167, - 'y': 1 - }); - } - - // update the connection from positioning - connectionFrom.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; - }); - - // update the label text - connectionFrom.select('text.connection-from') - .each(function () { - var connectionFromLabel = d3.select(this); - - // reset the label name to handle any previous state - connectionFromLabel.text(null).selectAll('title').remove(); - - // apply ellipsis to the label as necessary - nf.CanvasUtils.ellipsis(connectionFromLabel, d.component.source.name); - }).append('title').text(function () { - return d.component.source.name; - }); - - // update the label run status - connectionFrom.select('image.connection-from-run-status').attr('xlink:href', function () { - if (d.component.source.exists === false) { - return 'images/portRemoved.png'; - } else if (d.component.source.running === true) { - return 'images/portRunning.png'; - } else { - return 'images/portStopped.png'; + var connectionFrom = connectionLabelContainer.select('g.connection-from-container'); + + // determine if the connection require a from label + if (isGroup(d.component.source)) { + // see if the connection from label is already rendered + if (connectionFrom.empty()) { + connectionFrom = connectionLabelContainer.append('g') + .attr({ + 'class': 'connection-from-container' + }); + + connectionFrom.append('text') + .attr({ + 'class': 'connection-stats-label', + 'x': 0, + 'y': 10 + }) + .text('From'); + + connectionFrom.append('text') + .attr({ + 'class': 'connection-stats-value connection-from', + 'x': 33, + 'y': 10, + 'width': 130 + }); + + connectionFrom.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'class': 'connection-from-run-status', + 'width': 10, + 'height': 10, + 'x': 167, + 'y': 1 + }); } - }); - } else { - // there is no connection from, but check if the name was previous - // rendered so it can be removed - if (!connectionFrom.empty()) { - connectionFrom.remove(); - } - } - - // --------------------- - // connection label - to - // --------------------- - - var connectionTo = connectionLabelContainer.select('g.connection-to-container'); - - // determine if the connection require a to label - if (isGroup(d.component.destination)) { - // see if the connection to label is already rendered - if (connectionTo.empty()) { - connectionTo = connectionLabelContainer.append('g') - .attr({ - 'class': 'connection-to-container' + + // update the connection from positioning + connectionFrom.attr('transform', function () { + var y = 5 + (15 * labelCount++); + return 'translate(5, ' + y + ')'; + }); + + // update the label text + connectionFrom.select('text.connection-from') + .each(function () { + var connectionFromLabel = d3.select(this); + + // reset the label name to handle any previous state + connectionFromLabel.text(null).selectAll('title').remove(); + + // apply ellipsis to the label as necessary + nf.CanvasUtils.ellipsis(connectionFromLabel, d.component.source.name); + }).append('title').text(function () { + return d.component.source.name; }); - - connectionTo.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('To'); - - connectionTo.append('text') - .attr({ - 'class': 'connection-stats-value connection-to', - 'x': 18, - 'y': 10, - 'width': 145 - }); - - connectionTo.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'class': 'connection-to-run-status', - 'width': 10, - 'height': 10, - 'x': 167, - 'y': 1 - }); - } - - // update the connection to positioning - connectionTo.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; - }); - - // update the label text - connectionTo.select('text.connection-to') - .each(function (d) { - var connectionToLabel = d3.select(this); - - // reset the label name to handle any previous state - connectionToLabel.text(null).selectAll('title').remove(); - - // apply ellipsis to the label as necessary - nf.CanvasUtils.ellipsis(connectionToLabel, d.component.destination.name); - }).append('title').text(function (d) { - return d.component.destination.name; - }); - - // update the label run status - connectionTo.select('image.connection-to-run-status').attr('xlink:href', function () { - if (d.component.destination.exists === false) { - return 'images/portRemoved.png'; - } else if (d.component.destination.running === true) { - return 'images/portRunning.png'; - } else { - return 'images/portStopped.png'; + + // update the label run status + connectionFrom.select('image.connection-from-run-status').attr('xlink:href', function () { + if (d.component.source.exists === false) { + return 'images/portRemoved.png'; + } else if (d.component.source.running === true) { + return 'images/portRunning.png'; + } else { + return 'images/portStopped.png'; + } + }); + } else { + // there is no connection from, but check if the name was previous + // rendered so it can be removed + if (!connectionFrom.empty()) { + connectionFrom.remove(); } - }); - } else { - // there is no connection to, but check if the name was previous - // rendered so it can be removed - if (!connectionTo.empty()) { - connectionTo.remove(); } - } - - // ----------------------- - // connection label - name - // ----------------------- - - // get the connection name - var connectionNameValue = nf.CanvasUtils.formatConnectionName(d.component); - var connectionName = connectionLabelContainer.select('g.connection-name-container'); - - // is there a name to render - if (!nf.Common.isBlank(connectionNameValue)) { - // see if the connection name label is already rendered - if (connectionName.empty()) { - connectionName = connectionLabelContainer.append('g') - .attr({ - 'class': 'connection-name-container' - }); - - connectionName.append('text') - .attr({ - 'class': 'connection-stats-label', - 'x': 0, - 'y': 10 - }) - .text('Name'); - - connectionName.append('text') - .attr({ - 'class': 'connection-stats-value connection-name', - 'x': 35, - 'y': 10, - 'width': 142 + + // --------------------- + // connection label - to + // --------------------- + + var connectionTo = connectionLabelContainer.select('g.connection-to-container'); + + // determine if the connection require a to label + if (isGroup(d.component.destination)) { + // see if the connection to label is already rendered + if (connectionTo.empty()) { + connectionTo = connectionLabelContainer.append('g') + .attr({ + 'class': 'connection-to-container' + }); + + connectionTo.append('text') + .attr({ + 'class': 'connection-stats-label', + 'x': 0, + 'y': 10 + }) + .text('To'); + + connectionTo.append('text') + .attr({ + 'class': 'connection-stats-value connection-to', + 'x': 18, + 'y': 10, + 'width': 145 + }); + + connectionTo.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'class': 'connection-to-run-status', + 'width': 10, + 'height': 10, + 'x': 167, + 'y': 1 + }); + } + + // update the connection to positioning + connectionTo.attr('transform', function () { + var y = 5 + (15 * labelCount++); + return 'translate(5, ' + y + ')'; + }); + + // update the label text + connectionTo.select('text.connection-to') + .each(function (d) { + var connectionToLabel = d3.select(this); + + // reset the label name to handle any previous state + connectionToLabel.text(null).selectAll('title').remove(); + + // apply ellipsis to the label as necessary + nf.CanvasUtils.ellipsis(connectionToLabel, d.component.destination.name); + }).append('title').text(function (d) { + return d.component.destination.name; }); + + // update the label run status + connectionTo.select('image.connection-to-run-status').attr('xlink:href', function () { + if (d.component.destination.exists === false) { + return 'images/portRemoved.png'; + } else if (d.component.destination.running === true) { + return 'images/portRunning.png'; + } else { + return 'images/portStopped.png'; + } + }); + } else { + // there is no connection to, but check if the name was previous + // rendered so it can be removed + if (!connectionTo.empty()) { + connectionTo.remove(); + } } - - // update the connection name positioning - connectionName.attr('transform', function () { - var y = 5 + (15 * labelCount++); - return 'translate(5, ' + y + ')'; - }); - - // update the connection name - connectionName.select('text.connection-name') - .each(function () { - var connectionToLabel = d3.select(this); - - // reset the label name to handle any previous state - connectionToLabel.text(null).selectAll('title').remove(); - - // apply ellipsis to the label as necessary - nf.CanvasUtils.ellipsis(connectionToLabel, connectionNameValue); - }).append('title').text(function () { - return connectionNameValue; - }); - } else { - // there is no connection name, but check if the name was previous - // rendered so it can be removed - if (!connectionName.empty()) { - connectionName.remove(); + + // ----------------------- + // connection label - name + // ----------------------- + + // get the connection name + var connectionNameValue = nf.CanvasUtils.formatConnectionName(d.component); + var connectionName = connectionLabelContainer.select('g.connection-name-container'); + + // is there a name to render + if (!nf.Common.isBlank(connectionNameValue)) { + // see if the connection name label is already rendered + if (connectionName.empty()) { + connectionName = connectionLabelContainer.append('g') + .attr({ + 'class': 'connection-name-container' + }); + + connectionName.append('text') + .attr({ + 'class': 'connection-stats-label', + 'x': 0, + 'y': 10 + }) + .text('Name'); + + connectionName.append('text') + .attr({ + 'class': 'connection-stats-value connection-name', + 'x': 35, + 'y': 10, + 'width': 142 + }); + } + + // update the connection name positioning + connectionName.attr('transform', function () { + var y = 5 + (15 * labelCount++); + return 'translate(5, ' + y + ')'; + }); + + // update the connection name + connectionName.select('text.connection-name') + .each(function () { + var connectionToLabel = d3.select(this); + + // reset the label name to handle any previous state + connectionToLabel.text(null).selectAll('title').remove(); + + // apply ellipsis to the label as necessary + nf.CanvasUtils.ellipsis(connectionToLabel, connectionNameValue); + }).append('title').text(function () { + return connectionNameValue; + }); + } else { + // there is no connection name, but check if the name was previous + // rendered so it can be removed + if (!connectionName.empty()) { + connectionName.remove(); + } } } @@ -939,16 +946,18 @@ nf.Connection = (function () { return 5 + (15 * labelCount) + 3; }); - // determine whether or not to show the expiration icon - connectionLabelContainer.select('g.expiration-icon') - .classed('hidden', function () { - return !isExpirationConfigured(d.component); - }) - .select('title').text(function () { - return 'Expires FlowFiles older than ' + d.component.flowFileExpiration; - }); + if (d.accessPolicy.canRead) { + // determine whether or not to show the expiration icon + connectionLabelContainer.select('g.expiration-icon') + .classed('hidden', function () { + return !isExpirationConfigured(d.component); + }) + .select('title').text(function () { + return 'Expires FlowFiles older than ' + d.component.flowFileExpiration; + }); + } - if (nf.Common.isDFM()) { + if (d.accessPolicy.canWrite) { // only support dragging the label when appropriate connectionLabelContainer.call(labelDrag); } @@ -1003,8 +1012,8 @@ nf.Connection = (function () { var revision = nf.Client.getRevision(); var entity = { - revision: revision, - connection: connection + 'revision': revision, + 'component': connection }; return $.ajax({ @@ -1018,7 +1027,7 @@ nf.Connection = (function () { nf.Client.setRevision(response.revision); // request was successful, update the entry - nf.Connection.set(response.connection); + nf.Connection.set(response); }).fail(function (xhr, status, error) { if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) { nf.Dialog.showOkDialog({ @@ -1035,7 +1044,7 @@ nf.Connection = (function () { var removeConnections = function (removed) { // consider reloading source/destination of connection being removed removed.each(function (d) { - nf.CanvasUtils.reloadConnectionSourceAndDestination(d.component.source.id, d.component.destination.id); + nf.CanvasUtils.reloadConnectionSourceAndDestination(d.sourceId, d.destinationId); }); // remove the connection @@ -1099,7 +1108,7 @@ nf.Connection = (function () { // only save the updated bends if necessary if (different) { save(connectionData, { - id: connectionData.component.id, + id: connectionData.id, bends: bends }).fail(function () { // restore the previous bend points @@ -1174,10 +1183,10 @@ nf.Connection = (function () { var connectionEntity = { 'revision': nf.Client.getRevision(), - 'connection': { - 'id': connectionData.component.id, + 'component': { + 'id': connectionData.id, 'destination': { - 'id': destinationData.component.id, + 'id': destinationData.id, 'groupId': nf.Canvas.getGroupId(), 'type': destinationType } @@ -1185,10 +1194,10 @@ nf.Connection = (function () { }; // if this is a self loop and there are less than 2 bends, add them - if (connectionData.bends.length < 2 && connectionData.component.source.id === destinationData.component.id) { + if (connectionData.bends.length < 2 && connectionData.component.source.id === destinationData.id) { var rightCenter = { - x: destinationData.component.position.x + (destinationData.dimensions.width), - y: destinationData.component.position.y + (destinationData.dimensions.height / 2) + x: destinationData.position.x + (destinationData.dimensions.width), + y: destinationData.position.y + (destinationData.dimensions.height / 2) }; var xOffset = nf.Connection.config.selfLoopXOffset; var yOffset = nf.Connection.config.selfLoopYOffset; @@ -1211,13 +1220,13 @@ nf.Connection = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - var updatedConnectionData = response.connection; + var updatedConnectionData = response.component; // update the revision nf.Client.setRevision(response.revision); // refresh to update the label - nf.Connection.set(updatedConnectionData); + nf.Connection.set(response); // reload the previous destination and the new source/destination nf.CanvasUtils.reloadConnectionSourceAndDestination(null, previousDestinationId); @@ -1344,7 +1353,7 @@ nf.Connection = (function () { // save the new label index save(d, { - id: d.component.id, + id: d.id, labelIndex: d.labelIndex }).fail(function () { // restore the previous label index @@ -1364,34 +1373,26 @@ nf.Connection = (function () { /** * Populates the graph with the specified connections. * - * @argument {object | array} connections The connections to add + * @argument {object | array} connectionEntities The connections to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (connections, selectAll) { + add: function (connectionEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; - var add = function (connection) { + var add = function (connectionEntity) { // add the connection - connectionMap.set(connection.id, { + connectionMap.set(connectionEntity.id, $.extend({ type: 'Connection', - component: connection, - bends: $.map(connection.bends, function (bend) { - return { - x: bend.x, - y: bend.y - }; - }), - labelIndex: connection.labelIndex - }); + }, connectionEntity)); }; // determine how to handle the specified connection - if ($.isArray(connections)) { - $.each(connections, function (_, connection) { - add(connection); + if ($.isArray(connectionEntities)) { + $.each(connectionEntities, function (_, connectionEntity) { + add(connectionEntity); }); } else { - add(connections); + add(connectionEntities); } // apply the selection and handle all new connection @@ -1408,34 +1409,27 @@ nf.Connection = (function () { /** * Sets the value of the specified connection. * - * @param {type} connection + * @param {type} connectionEntities */ - set: function (connection) { - var set = function (conn) { - if (connectionMap.has(conn.id)) { + set: function (connectionEntities) { + var set = function (connectionEntity) { + if (connectionMap.has(connectionEntity.id)) { // update the current entry - var connectionEntry = connectionMap.get(conn.id); - connectionEntry.component = conn; - connectionEntry.bends = $.map(conn.bends, function (bend) { - return { - x: bend.x, - y: bend.y - }; - }); - connectionEntry.labelIndex = conn.labelIndex; + var connectionEntry = connectionMap.get(connectionEntity.id); + $.extend(connectionEntry, connectionEntity); // update the connection in the UI - d3.select('#id-' + conn.id).call(updateConnections, true, true); + d3.select('#id-' + connectionEntity.id).call(updateConnections, true, true); } }; // determine how to handle the specified connection - if ($.isArray(connection)) { - $.each(connection, function (_, conn) { - set(conn); + if ($.isArray(connectionEntities)) { + $.each(connectionEntities, function (_, connectionEntity) { + set(connectionEntity); }); } else { - set(connection); + set(connectionEntities); } }, @@ -1518,7 +1512,7 @@ nf.Connection = (function () { url: connection.uri, dataType: 'json' }).done(function (response) { - nf.Connection.set(response.connection); + nf.Connection.set(response); }); } }, @@ -1532,11 +1526,9 @@ nf.Connection = (function () { getComponentConnections: function (id) { var connections = []; connectionMap.forEach(function (_, entry) { - var connection = entry.component; - // see if this component is the source or destination of this connection - if (nf.CanvasUtils.getConnectionSourceComponentId(connection) === id || nf.CanvasUtils.getConnectionDestinationComponentId(connection) === id) { - connections.push(connection); + if (nf.CanvasUtils.getConnectionSourceComponentId(entry) === id || nf.CanvasUtils.getConnectionDestinationComponentId(entry) === id) { + connections.push(entry); } }); return connections; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js index f841e51186..90863d580b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js @@ -38,6 +38,9 @@ nf.ContextMenu = (function () { if (selection.size() !== 1) { return false; } + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } var isConfigurableComponent = nf.CanvasUtils.isLabel(selection) || nf.CanvasUtils.isProcessGroup(selection); if (!isConfigurableComponent) { @@ -46,7 +49,7 @@ nf.ContextMenu = (function () { } } - return isConfigurableComponent && nf.Common.isDFM(); + return isConfigurableComponent; }; /** @@ -59,8 +62,11 @@ nf.ContextMenu = (function () { if (selection.size() !== 1) { return false; } + if (nf.CanvasUtils.canRead(selection) === false) { + return false; + } - if (nf.Common.isDFM()) { + if (nf.CanvasUtils.canModify(selection)) { if (nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isInputPort(selection) || nf.CanvasUtils.isOutputPort(selection) || nf.CanvasUtils.isRemoteProcessGroup(selection) || nf.CanvasUtils.isConnection(selection)) { return !nf.CanvasUtils.supportsModification(selection); } @@ -77,7 +83,11 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection of currently selected components */ var isDeletable = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.isDeletable(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.isDeletable(selection); }; /** @@ -86,7 +96,11 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection of currently selected components */ var isRunnable = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.areRunnable(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.areRunnable(selection); }; /** @@ -95,7 +109,11 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection of currently selected components */ var isStoppable = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.areStoppable(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.areStoppable(selection); }; /** @@ -141,7 +159,11 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection of currently selected components */ var isCopyable = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.isCopyable(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.isCopyable(selection); }; /** @@ -172,8 +194,11 @@ nf.ContextMenu = (function () { if (selection.size() !== 1) { return false; } + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } - return nf.Common.isDFM() && nf.CanvasUtils.isConnection(selection); + return nf.CanvasUtils.isConnection(selection); }; /** @@ -182,7 +207,11 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection */ var isColorable = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.isColorable(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.isColorable(selection); }; /** @@ -205,14 +234,16 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection */ var hasDownstream = function (selection) { - // ensure the correct number of components are selected - if (selection.size() !== 1) { - return false; - } - - return nf.CanvasUtils.isFunnel(selection) || nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isProcessGroup(selection) || - nf.CanvasUtils.isRemoteProcessGroup(selection) || nf.CanvasUtils.isInputPort(selection) || - (nf.CanvasUtils.isOutputPort(selection) && nf.Canvas.getParentGroupId() !== null); + // TODO + // // ensure the correct number of components are selected + // if (selection.size() !== 1) { + // return false; + // } + // + // return nf.CanvasUtils.isFunnel(selection) || nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isProcessGroup(selection) || + // nf.CanvasUtils.isRemoteProcessGroup(selection) || nf.CanvasUtils.isInputPort(selection) || + // (nf.CanvasUtils.isOutputPort(selection) && nf.Canvas.getParentGroupId() !== null); + return false; }; /** @@ -221,14 +252,16 @@ nf.ContextMenu = (function () { * @param {selection} selection The selection */ var hasUpstream = function (selection) { - // ensure the correct number of components are selected - if (selection.size() !== 1) { - return false; - } - - return nf.CanvasUtils.isFunnel(selection) || nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isProcessGroup(selection) || - nf.CanvasUtils.isRemoteProcessGroup(selection) || nf.CanvasUtils.isOutputPort(selection) || - (nf.CanvasUtils.isInputPort(selection) && nf.Canvas.getParentGroupId() !== null); + // TODO + // // ensure the correct number of components are selected + // if (selection.size() !== 1) { + // return false; + // } + // + // return nf.CanvasUtils.isFunnel(selection) || nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isProcessGroup(selection) || + // nf.CanvasUtils.isRemoteProcessGroup(selection) || nf.CanvasUtils.isOutputPort(selection) || + // (nf.CanvasUtils.isInputPort(selection) && nf.Canvas.getParentGroupId() !== null); + return false; }; /** @@ -241,9 +274,7 @@ nf.ContextMenu = (function () { if (selection.size() !== 1) { return false; } - - // ensure the user is DFM - if (nf.Common.isDFM() === false) { + if (nf.CanvasUtils.canModify(selection) === false) { return false; } @@ -304,7 +335,11 @@ nf.ContextMenu = (function () { * @param {selection} selection */ var canStartTransmission = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.canAllStartTransmitting(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.canAllStartTransmitting(selection); }; /** @@ -313,7 +348,11 @@ nf.ContextMenu = (function () { * @param {selection} selection */ var canStopTransmission = function (selection) { - return nf.Common.isDFM() && nf.CanvasUtils.canAllStopTransmitting(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return nf.CanvasUtils.canAllStopTransmitting(selection); }; /** @@ -322,7 +361,11 @@ nf.ContextMenu = (function () { * @param {selection} selection */ var canEmptyQueue = function (selection) { - return nf.Common.isDFM() && isConnection(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return isConnection(selection); }; /** @@ -331,7 +374,11 @@ nf.ContextMenu = (function () { * @param {selection} selection */ var canListQueue = function (selection) { - return nf.Common.isDFM() && isConnection(selection); + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + return isConnection(selection); }; /** @@ -340,6 +387,12 @@ nf.ContextMenu = (function () { * @param {type} selection */ var canMoveToParent = function (selection) { + if (nf.CanvasUtils.canModify(selection) === false) { + return false; + } + + // TODO - also check can modify in parent + return !selection.empty() && nf.CanvasUtils.isDisconnected(selection) && nf.Canvas.getParentGroupId() !== null; }; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js index d4dd1deb3b..ab3078f3be 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-draggable.js @@ -43,19 +43,17 @@ nf.Draggable = (function () { var updateComponentPosition = function(d) { var newPosition = { - 'x': d.component.position.x + delta.x, - 'y': d.component.position.y + delta.y + 'x': d.position.x + delta.x, + 'y': d.position.y + delta.y }; // build the entity var entity = { - 'revision': nf.Client.getRevision() - }; - - // use bracket notation to dynamic get the key based on the entity type - entity[nf[d.type].getEntityKey(d)] = { - 'id': d.component.id, - 'position': newPosition + 'revision': nf.Client.getRevision(), + 'component': { + 'id': d.id, + 'position': newPosition + } }; // update the component positioning @@ -70,13 +68,13 @@ nf.Draggable = (function () { // update the revision nf.Client.setRevision(response.revision); - // store the updated location - d.component.position = newPosition; + // update the component + nf[d.type].set(response); // resolve with an object so we can refresh when finished deferred.resolve({ type: d.type, - id: d.component.id + id: d.id }); }).fail(function (xhr, status, error) { if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) { @@ -95,12 +93,12 @@ nf.Draggable = (function () { var updateConnectionPosition = function(d) { // only update if necessary - if (d.component.bends.length === 0) { + if (d.bends.length === 0) { return null; } // calculate the new bend points - var newBends = $.map(d.component.bends, function (bend) { + var newBends = $.map(d.bends, function (bend) { return { x: bend.x + delta.x, y: bend.y + delta.y @@ -108,9 +106,9 @@ nf.Draggable = (function () { }); var entity = { - revision: revision, - connection: { - id: d.component.id, + 'revision': revision, + 'component': { + id: d.id, bends: newBends } }; @@ -127,19 +125,13 @@ nf.Draggable = (function () { // update the revision nf.Client.setRevision(response.revision); - // store the updated bend points - d.component.bends = response.connection.bends; - d.bends = $.map(d.component.bends, function (bend) { - return { - x: bend.x, - y: bend.y - }; - }); + // update the component + nf.Connection.set(response); // resolve with an object so we can refresh when finished deferred.resolve({ type: d.type, - id: d.component.id + id: d.id }); }).fail(function (xhr, status, error) { if (xhr.status === 400 || xhr.status === 404 || xhr.status === 409) { @@ -160,14 +152,14 @@ nf.Draggable = (function () { d3.selectAll('g.connection.selected').each(function (d) { var connectionUpdate = updateConnectionPosition(d); if (connectionUpdate !== null) { - updates.set(d.component.id, connectionUpdate); + updates.set(d.id, connectionUpdate); } }); // go through each selected component d3.selectAll('g.component.selected').each(function (d) { // consider any self looping connections - var connections = nf.Connection.getComponentConnections(d.component.id); + var connections = nf.Connection.getComponentConnections(d.id); $.each(connections, function(_, connection) { if (!updates.has(connection.id) && nf.CanvasUtils.getConnectionSourceComponentId(connection) === nf.CanvasUtils.getConnectionDestinationComponentId(connection)) { var connectionUpdate = updateConnectionPosition(nf.Connection.get(connection.id)); @@ -178,7 +170,7 @@ nf.Draggable = (function () { }); // consider the component itself - updates.set(d.component.id, updateComponentPosition(d)); + updates.set(d.id, updateComponentPosition(d)); }); // wait for all updates to complete @@ -240,14 +232,14 @@ nf.Draggable = (function () { // determine the appropriate bounding box var minX = null, maxX = null, minY = null, maxY = null; selection.each(function (d) { - if (minX === null || d.component.position.x < minX) { - minX = d.component.position.x; + if (minX === null || d.position.x < minX) { + minX = d.position.x; } - if (minY === null || d.component.position.y < minY) { - minY = d.component.position.y; + if (minY === null || d.position.y < minY) { + minY = d.position.y; } - var componentMaxX = d.component.position.x + d.dimensions.width; - var componentMaxY = d.component.position.y + d.dimensions.height; + var componentMaxX = d.position.x + d.dimensions.width; + var componentMaxY = d.position.y + d.dimensions.height; if (maxX === null || componentMaxX > maxX) { maxX = componentMaxX; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js index 555450e30d..d0422861cd 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-funnel.js @@ -45,7 +45,7 @@ nf.Funnel = (function () { */ var select = function () { return funnelContainer.selectAll('g.funnel').data(funnelMap.values(), function (d) { - return d.component.id; + return d.id; }); }; @@ -63,7 +63,7 @@ nf.Funnel = (function () { var funnel = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': 'funnel component' }) @@ -100,9 +100,9 @@ nf.Funnel = (function () { funnel.call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only support dragging and connecting when appropriate - if (nf.Common.isDFM()) { - funnel.call(nf.Draggable.activate).call(nf.Connectable.activate); - } + funnel.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).call(nf.Draggable.activate).call(nf.Connectable.activate); return funnel; }; @@ -142,28 +142,27 @@ nf.Funnel = (function () { /** * Populates the graph with the specified funnels. * - * @argument {object | array} funnels The funnels to add + * @argument {object | array} funnelEntities The funnels to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (funnels, selectAll) { + add: function (funnelEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; - var add = function (funnel) { + var add = function (funnelEntity) { // add the funnel - funnelMap.set(funnel.id, { + funnelMap.set(funnelEntity.id, $.extend({ type: 'Funnel', - component: funnel, dimensions: dimensions - }); + }, funnelEntity)); }; // determine how to handle the specified funnel status - if ($.isArray(funnels)) { - $.each(funnels, function (_, funnel) { - add(funnel); + if ($.isArray(funnelEntities)) { + $.each(funnelEntities, function (_, funnelEntity) { + add(funnelEntity); }); } else { - add(funnels); + add(funnelEntities); } // apply the selection and handle all new processors @@ -211,7 +210,7 @@ nf.Funnel = (function () { url: funnel.uri, dataType: 'json' }).done(function (response) { - nf.Funnel.set(response.funnel); + nf.Funnel.set(response); }); } }, @@ -230,37 +229,30 @@ nf.Funnel = (function () { * will set each funnel. If it is not an array, it will * attempt to set the specified funnel. * - * @param {object | array} funnels + * @param {object | array} funnelEntities */ - set: function (funnels) { - var set = function (funnel) { - if (funnelMap.has(funnel.id)) { + set: function (funnelEntities) { + var set = function (funnelEntity) { + if (funnelMap.has(funnelEntity.id)) { // update the current entry - var funnelEntry = funnelMap.get(funnel.id); - funnelEntry.component = funnel; - + var funnelEntry = funnelMap.get(funnelEntity.id); + $.extend(funnelEntry, funnelEntity); + // update the connection in the UI - d3.select('#id-' + funnel.id).call(updateFunnels); + d3.select('#id-' + funnelEntity.id).call(updateFunnels); } }; // determine how to handle the specified funnel status - if ($.isArray(funnels)) { - $.each(funnels, function (_, funnel) { - set(funnel); + if ($.isArray(funnelEntities)) { + $.each(funnelEntities, function (_, funnelEntity) { + set(funnelEntity); }); } else { - set(funnels); + set(funnelEntities); } }, - /** - * Returns the entity key when marshalling an entity of this type. - */ - getEntityKey: function (d) { - return 'funnel'; - }, - /** * Removes the specified funnel. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-go-to.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-go-to.js index f3d0738c2c..5bf3e9eaea 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-go-to.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-go-to.js @@ -156,7 +156,7 @@ nf.GoTo = (function () { var addDestinationInputPort = function (container, connection) { // get the remote process group return getProcessGroup(connection.destination.groupId).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; // process group var downstreamComponent = $('
').appendTo(container); @@ -263,7 +263,7 @@ nf.GoTo = (function () { var addSourceOutputPort = function (container, connection) { // get the remote process group return getProcessGroup(connection.source.groupId).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; // process group var sourceComponent = $('
').appendTo(container); @@ -364,7 +364,7 @@ nf.GoTo = (function () { // add the destination for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the source - if (connection.source.id === selectionData.component.id) { + if (connection.source.id === selectionData.id) { addConnection(connection); } }); @@ -403,7 +403,7 @@ nf.GoTo = (function () { // add the source for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the destination - if (connection.destination.id === selectionData.component.id) { + if (connection.destination.id === selectionData.id) { addConnection(connection); } }); @@ -442,7 +442,7 @@ nf.GoTo = (function () { // add the destination for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the source - if (connection.source.groupId === selectionData.component.id) { + if (connection.source.groupId === selectionData.id) { addConnection(connection); } }); @@ -481,7 +481,7 @@ nf.GoTo = (function () { // add the source for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the destination - if (connection.destination.groupId === selectionData.component.id) { + if (connection.destination.groupId === selectionData.id) { addConnection(connection); } }); @@ -520,7 +520,7 @@ nf.GoTo = (function () { // add the destination for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the source - if (connection.source.id === selectionData.component.id) { + if (connection.source.id === selectionData.id) { addConnection(connection); } }); @@ -562,7 +562,7 @@ nf.GoTo = (function () { // add the source for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the destination - if (connection.destination.id === selectionData.component.id) { + if (connection.destination.id === selectionData.id) { addConnection(connection); } }); @@ -604,7 +604,7 @@ nf.GoTo = (function () { // add the destination for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the source - if (connection.source.id === selectionData.component.id) { + if (connection.source.id === selectionData.id) { addConnection(connection); } }); @@ -643,7 +643,7 @@ nf.GoTo = (function () { // add the source for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the destination - if (connection.destination.id === selectionData.component.id) { + if (connection.destination.id === selectionData.id) { addConnection(connection); } }); @@ -679,7 +679,7 @@ nf.GoTo = (function () { // add the destination for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the source - if (connection.source.id === selectionData.component.id) { + if (connection.source.id === selectionData.id) { addConnection(connection); } }); @@ -715,7 +715,7 @@ nf.GoTo = (function () { // add the source for each connection $.each(connections, function (_, connection) { // only show connections for which this selection is the destination - if (connection.destination.id === selectionData.component.id) { + if (connection.destination.id === selectionData.id) { addConnection(connection); } }); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label-configuration.js index 6e9ee362a1..5524ec4f1a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label-configuration.js @@ -43,7 +43,7 @@ nf.LabelConfiguration = (function () { // build the label entity var labelEntity = { 'revision': nf.Client.getRevision(), - 'label': { + 'component': { 'id': labelId, 'label': labelValue, 'style': { @@ -64,7 +64,7 @@ nf.LabelConfiguration = (function () { nf.Client.setRevision(response.revision); // get the label out of the response - nf.Label.set(response.label); + nf.Label.set(response); }).fail(nf.Common.handleAjaxError); // reset and hide the dialog @@ -139,7 +139,7 @@ nf.LabelConfiguration = (function () { } // store the label uri - labelId = selectionData.component.id; + labelId = selectionData.id; // populate the dialog $('#label-value').val(labelValue); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js index 5629bbb933..809b90520f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-label.js @@ -53,9 +53,7 @@ nf.Label = (function () { * Selects the labels elements against the current label map. */ var select = function () { - return labelContainer.selectAll('g.label').data(labelMap.values(), function (d) { - return d.component.id; - }); + return labelContainer.selectAll('g.label').data(labelMap.values()); }; /** @@ -72,12 +70,12 @@ nf.Label = (function () { var label = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': 'label component' }) .classed('selected', selected) - .call(position); + .call(nf.CanvasUtils.position); // label border label.append('rect') @@ -110,30 +108,14 @@ nf.Label = (function () { label.call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only support dragging when appropriate - if (nf.Common.isDFM()) { - label.call(nf.Draggable.activate); - } + label.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).call(nf.Draggable.activate); // call update to trigger some rendering label.call(updateLabels); }; - /** - * Position the component accordingly. - * - * @param {selection} updated - */ - var position = function (updated) { - if (updated.empty()) { - return; - } - - // update the processors positioning - updated.attr('transform', function (d) { - return 'translate(' + d.component.position.x + ', ' + d.component.position.y + ')'; - }); - }; - /** * Updates the labels in the specified selection. * @@ -150,9 +132,11 @@ nf.Label = (function () { // determine all unique colors labelMap.forEach(function (id, d) { - var color = d.component.style['background-color']; - if (nf.Common.isDefinedAndNotNull(color)) { - colors.add(nf.Common.substringAfterLast(color, '#')); + if (d.accessPolicy.canRead) { + var color = d.component.style['background-color']; + if (nf.Common.isDefinedAndNotNull(color)) { + colors.add(nf.Common.substringAfterLast(color, '#')); + } } }); nf.Canvas.defineLabelColors(colors.values()); @@ -163,9 +147,11 @@ nf.Label = (function () { 'stroke': function (d) { var color = nf.Label.defaultColor(); - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; + } } return color; @@ -184,9 +170,11 @@ nf.Label = (function () { 'fill': function (d) { var color = nf.Label.defaultColor(); - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; + } } // get just the color code part @@ -206,68 +194,71 @@ nf.Label = (function () { updated.each(function (d) { var updatedLabel = d3.select(this); - // update the label - var label = updatedLabel.select('text.label-value'); + if (d.accessPolicy.canRead) { + // update the label + var label = updatedLabel.select('text.label-value'); - // udpate the font size - label.attr('font-size', function () { - var fontSize = '12px'; + // udpate the font size + label.attr('font-size', function () { + var fontSize = '12px'; - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['font-size'])) { - fontSize = d.component.style['font-size']; - } + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['font-size'])) { + fontSize = d.component.style['font-size']; + } - return fontSize; - }); - - // remove the previous label value - label.selectAll('tspan').remove(); - - // parse the lines in this label - var lines = []; - if (nf.Common.isDefinedAndNotNull(d.component.label)) { - lines = d.component.label.split('\n'); - } else { - lines.push(''); - } - - // add label value - $.each(lines, function (i, line) { - label.append('tspan') - .attr('x', '0.4em') - .attr('dy', '1.2em') - .text(function () { - return line; - }); - }); - - // ----------- - // labelpoints - // ----------- - - if (nf.Common.isDFM()) { - var pointData = [ - {x: d.dimensions.width, y: d.dimensions.height} - ]; - var points = updatedLabel.selectAll('rect.labelpoint').data(pointData); - - // create a point for the end - points.enter().append('rect') - .attr({ - 'class': 'labelpoint', - 'width': 10, - 'height': 10 - }) - .call(labelPointDrag); - - // update the midpoints - points.attr('transform', function (p) { - return 'translate(' + (p.x - 10) + ', ' + (p.y - 10) + ')'; + return fontSize; }); - // remove old items - points.exit().remove(); + // remove the previous label value + label.selectAll('tspan').remove(); + + // parse the lines in this label + var lines = []; + if (nf.Common.isDefinedAndNotNull(d.component.label)) { + lines = d.component.label.split('\n'); + } else { + lines.push(''); + } + + // add label value + $.each(lines, function (i, line) { + label.append('tspan') + .attr('x', '0.4em') + .attr('dy', '1.2em') + .text(function () { + return line; + }); + }); + + + // ----------- + // labelpoints + // ----------- + + if (d.accessPolicy.canWrite) { + var pointData = [ + {x: d.dimensions.width, y: d.dimensions.height} + ]; + var points = updatedLabel.selectAll('rect.labelpoint').data(pointData); + + // create a point for the end + points.enter().append('rect') + .attr({ + 'class': 'labelpoint', + 'width': 10, + 'height': 10 + }) + .call(labelPointDrag); + + // update the midpoints + points.attr('transform', function (p) { + return 'translate(' + (p.x - 10) + ', ' + (p.y - 10) + ')'; + }); + + // remove old items + points.exit().remove(); + } } }); }; @@ -334,24 +325,27 @@ nf.Label = (function () { // only save the updated bends if necessary if (different) { - var revision = nf.Client.getRevision(); + var labelEntity = { + 'revision': nf.Client.getRevision(), + 'component': { + 'id': labelData.id, + 'width': labelData.dimensions.width, + 'height': labelData.dimensions.height + } + } $.ajax({ type: 'PUT', url: labelData.component.uri, - data: { - 'version': revision.version, - 'clientId': revision.clientId, - 'width': labelData.dimensions.width, - 'height': labelData.dimensions.height - }, - dataType: 'json' + data: JSON.stringify(labelEntity), + dataType: 'json', + contentType: 'application/json' }).done(function (response) { // update the revision nf.Client.setRevision(response.revision); // request was successful, update the entry - nf.Label.set(response.label); + nf.Label.set(response); }).fail(function () { // determine the previous width var width = dimensions.width; @@ -384,43 +378,26 @@ nf.Label = (function () { /** * Populates the graph with the specified labels. * - * @argument {object | array} labels The labels to add + * @argument {object | array} labelEntities The labels to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (labels, selectAll) { + add: function (labelEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; - var add = function (label) { - // determine the width - var width = dimensions.width; - if (nf.Common.isDefinedAndNotNull(label.width)) { - width = label.width; - } - - // determine the height - var height = dimensions.height; - if (nf.Common.isDefinedAndNotNull(label.height)) { - height = label.height; - } - + var add = function (labelEntity) { // add the label - labelMap.set(label.id, { - type: 'Label', - component: label, - dimensions: { - width: width, - height: height - } - }); + labelMap.set(labelEntity.id, $.extend({ + type: 'Label' + }, labelEntity)); }; // determine how to handle the specified label status - if ($.isArray(labels)) { - $.each(labels, function (_, label) { - add(label); + if ($.isArray(labelEntities)) { + $.each(labelEntities, function (_, labelEntity) { + add(labelEntity); }); } else { - add(labels); + add(labelEntities); } // apply the selection and handle all new labels @@ -468,7 +445,7 @@ nf.Label = (function () { url: label.uri, dataType: 'json' }).done(function (response) { - nf.Label.set(response.label); + nf.Label.set(response); }); } }, @@ -479,7 +456,7 @@ nf.Label = (function () { * @param {string} id The id */ position: function (id) { - d3.select('#id-' + id).call(position); + d3.select('#id-' + id).call(nf.CanvasUtils.position); }, /** @@ -487,53 +464,30 @@ nf.Label = (function () { * will set each label. If it is not an array, it will * attempt to set the specified label. * - * @param {object | array} labels + * @param {object | array} labelEntities */ - set: function (labels) { - var set = function (label) { - if (labelMap.has(label.id)) { - // determine the width - var width = dimensions.width; - if (nf.Common.isDefinedAndNotNull(label.width)) { - width = label.width; - } - - // determine the height - var height = dimensions.height; - if (nf.Common.isDefinedAndNotNull(label.height)) { - height = label.height; - } - + set: function (labelEntities) { + var set = function (labelEntity) { + if (labelMap.has(labelEntity.id)) { // update the current entry - var labelEntry = labelMap.get(label.id); - labelEntry.component = label; - labelEntry.dimensions = { - width: width, - height: height - }; + var labelEntry = labelMap.get(labelEntity.id); + $.extend(labelEntry, labelEntity); // update the connection in the UI - d3.select('#id-' + label.id).call(updateLabels); + d3.select('#id-' + labelEntry.id).call(updateLabels); } }; // determine how to handle the specified label status - if ($.isArray(labels)) { - $.each(labels, function (_, label) { + if ($.isArray(labelEntities)) { + $.each(labelEntities, function (_, label) { set(label); }); } else { - set(labels); + set(labelEntities); } }, - /** - * Returns the entity key when marshalling an entity of this type. - */ - getEntityKey: function (d) { - return 'label'; - }, - /** * Removes the specified label. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-configuration.js index 41278b8489..a972e8ef75 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-configuration.js @@ -55,12 +55,10 @@ nf.PortConfiguration = (function () { // build the port entity var portEntity = { - 'revision': nf.Client.getRevision() + 'revision': nf.Client.getRevision(), + 'component': port }; - // use bracket notation to set the key based on the type - portEntity[nf[portData.type].getEntityKey(portData)] = port; - // update the selected component $.ajax({ type: 'PUT', @@ -72,15 +70,8 @@ nf.PortConfiguration = (function () { // update the revision nf.Client.setRevision(response.revision); - var port; - if (nf.Common.isDefinedAndNotNull(response.inputPort)) { - port = response.inputPort; - } else { - port = response.outputPort; - } - // refresh the port component - nf.Port.set(port); + nf.Port.set(response); // close the details panel $('#port-configuration').modal('hide'); @@ -166,7 +157,7 @@ nf.PortConfiguration = (function () { } // populate the port settings - $('#port-id').text(selectionData.component.id); + $('#port-id').text(selectionData.id); $('#port-name').val(selectionData.component.name); $('#port-enabled').removeClass('checkbox-unchecked checkbox-checked').addClass(portEnableStyle); $('#port-concurrent-tasks').val(selectionData.component.concurrentlySchedulableTaskCount); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-details.js index c5200448cd..1134fc1aba 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-details.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port-details.js @@ -55,7 +55,7 @@ nf.PortDetails = (function () { // populate the port settings nf.Common.populateField('read-only-port-name', selectionData.component.name); - nf.Common.populateField('read-only-port-id', selectionData.component.id); + nf.Common.populateField('read-only-port-id', selectionData.id); nf.Common.populateField('read-only-port-comments', selectionData.component.comments); // show the details diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js index 7b69c8b457..74c7a77bc1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-port.js @@ -51,9 +51,7 @@ nf.Port = (function () { * Selects the port elements against the current port map. */ var select = function () { - return portContainer.selectAll('g.input-port, g.output-port').data(portMap.values(), function (d) { - return d.component.id; - }); + return portContainer.selectAll('g.input-port, g.output-port').data(portMap.values()); }; /** @@ -70,10 +68,10 @@ nf.Port = (function () { var port = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': function (d) { - if (d.component.type === 'INPUT_PORT') { + if (d.portType === 'INPUT_PORT') { return 'input-port component'; } else { return 'output-port component'; @@ -142,7 +140,7 @@ nf.Port = (function () { .call(nf.CanvasUtils.disableImageHref) .attr({ 'xlink:href': function (d) { - if (d.component.type === 'INPUT_PORT') { + if (d.portTtype === 'INPUT_PORT') { return 'images/iconInputPort.png'; } else { return 'images/iconOutputPort.png'; @@ -151,7 +149,7 @@ nf.Port = (function () { 'width': 46, 'height': 31, 'x': function (d) { - if (d.component.type === 'INPUT_PORT') { + if (d.portType === 'INPUT_PORT') { return 0; } else { return 114; @@ -164,7 +162,7 @@ nf.Port = (function () { port.append('text') .attr({ 'x': function (d) { - if (d.component.type === 'INPUT_PORT') { + if (d.portType === 'INPUT_PORT') { return 52; } else { return 5; @@ -183,9 +181,9 @@ nf.Port = (function () { port.call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only activate dragging and connecting if appropriate - if (nf.Common.isDFM()) { - port.call(nf.Draggable.activate).call(nf.Connectable.activate); - } + port.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).call(nf.Draggable.activate).call(nf.Connectable.activate); // call update to trigger some rendering port.call(updatePorts); @@ -201,7 +199,7 @@ nf.Port = (function () { return; } - updated.each(function () { + updated.each(function (portData) { var port = d3.select(this); var details = port.select('g.port-details'); @@ -246,7 +244,7 @@ nf.Port = (function () { 'width': 16, 'height': 16, 'x': function (d) { - if (d.component.type === 'INPUT_PORT') { + if (d.portType === 'INPUT_PORT') { return 33; } else { return 107; @@ -279,83 +277,87 @@ nf.Port = (function () { }); } - // update the run status - details.select('image.port-run-status-icon') - .attr('xlink:href', function (d) { - var img = ''; - if (d.component.state === 'DISABLED') { - img = 'images/iconDisable.png'; - } else if (!nf.Common.isEmpty(d.component.validationErrors)) { - img = 'images/iconAlert.png'; - } else if (d.component.state === 'RUNNING') { - img = 'images/iconRun.png'; - } else if (d.component.state === 'STOPPED') { - img = 'images/iconStop.png'; - } - return img; - }) - .each(function (d) { - // remove the existing tip if necessary - var tip = d3.select('#run-status-tip-' + d.component.id); - if (!tip.empty()) { - tip.remove(); - } + if (portData.accessPolicy.canRead) { + // update the run status + details.select('image.port-run-status-icon') + .attr('xlink:href', function (d) { + var img = ''; + if (d.component.state === 'DISABLED') { + img = 'images/iconDisable.png'; + } else if (!nf.Common.isEmpty(d.component.validationErrors)) { + img = 'images/iconAlert.png'; + } else if (d.component.state === 'RUNNING') { + img = 'images/iconRun.png'; + } else if (d.component.state === 'STOPPED') { + img = 'images/iconStop.png'; + } + return img; + }) + .each(function (d) { + // remove the existing tip if necessary + var tip = d3.select('#run-status-tip-' + d.id); + if (!tip.empty()) { + tip.remove(); + } - // if there are validation errors generate a tooltip - if (!nf.Common.isEmpty(d.component.validationErrors)) { - tip = d3.select('#port-tooltips').append('div') - .attr('id', function () { - return 'run-status-tip-' + d.component.id; - }) - .attr('class', 'tooltip nifi-tooltip') - .html(function () { - var list = nf.Common.formatUnorderedList(d.component.validationErrors); - if (list === null || list.length === 0) { - return ''; - } else { - return $('
').append(list).html(); - } - }); + // if there are validation errors generate a tooltip + if (!nf.Common.isEmpty(d.component.validationErrors)) { + tip = d3.select('#port-tooltips').append('div') + .attr('id', function () { + return 'run-status-tip-' + d.id; + }) + .attr('class', 'tooltip nifi-tooltip') + .html(function () { + var list = nf.Common.formatUnorderedList(d.component.validationErrors); + if (list === null || list.length === 0) { + return ''; + } else { + return $('
').append(list).html(); + } + }); - // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); - } - }); + // add the tooltip + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); + } + }); - // update the port name - port.select('text.port-name') - .each(function (d) { - var portName = d3.select(this); - var name = d.component.name; - var words = name.split(/\s+/); + // update the port name + port.select('text.port-name') + .each(function (d) { + var portName = d3.select(this); + var name = d.component.name; + var words = name.split(/\s+/); - // reset the port name to handle any previous state - portName.text(null).selectAll('tspan, title').remove(); + // reset the port name to handle any previous state + portName.text(null).selectAll('tspan, title').remove(); - // handle based on the number of tokens in the port name - if (words.length === 1) { - // apply ellipsis to the port name as necessary - nf.CanvasUtils.ellipsis(portName, name); - } else { - nf.CanvasUtils.multilineEllipsis(portName, 2, name); - } - }).append('title').text(function (d) { - return d.component.name; - }); + // handle based on the number of tokens in the port name + if (words.length === 1) { + // apply ellipsis to the port name as necessary + nf.CanvasUtils.ellipsis(portName, name); + } else { + nf.CanvasUtils.multilineEllipsis(portName, 2, name); + } + }).append('title').text(function (d) { + return d.component.name; + }); + } // populate the stats port.call(updatePortStatus); } else { - // update the port name - port.select('text.port-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + if (portData.accessPolicy.canRead) { + // update the port name + port.select('text.port-name') + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); + } // remove tooltips if necessary port.call(removeTooltips); @@ -430,8 +432,8 @@ nf.Port = (function () { var removeTooltips = function (removed) { removed.each(function (d) { // remove any associated tooltips - $('#run-status-tip-' + d.component.id).remove(); - $('#bulletin-tip-' + d.component.id).remove(); + $('#run-status-tip-' + d.id).remove(); + $('#bulletin-tip-' + d.id).remove(); }); }; @@ -453,10 +455,10 @@ nf.Port = (function () { /** * Populates the graph with the specified ports. * - * @argument {object | array} ports The ports to add + * @argument {object | array} portNodes The ports to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (ports, selectAll) { + add: function (portEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; // determine the appropriate dimensions for this port @@ -465,25 +467,24 @@ nf.Port = (function () { dimensions = remotePortDimensions; } - var add = function (ports) { + var add = function (portEntity) { // add the port - portMap.set(ports.id, { + portMap.set(portEntity.id, $.extend({ type: 'Port', - component: ports, dimensions: dimensions, status: { activeThreadCount: 0 } - }); + }, portEntity)); }; // determine how to handle the specified port status - if ($.isArray(ports)) { - $.each(ports, function (_, port) { - add(port); + if ($.isArray(portEntities)) { + $.each(portEntities, function (_, portNode) { + add(portNode); }); } else { - add(ports); + add(portEntities); } // apply the selection and handle all new ports @@ -539,9 +540,9 @@ nf.Port = (function () { dataType: 'json' }).done(function (response) { if (nf.Common.isDefinedAndNotNull(response.inputPort)) { - nf.Port.set(response.inputPort); + nf.Port.set(response); } else { - nf.Port.set(response.outputPort); + nf.Port.set(response); } }); } @@ -561,27 +562,27 @@ nf.Port = (function () { * will set each port. If it is not an array, it will * attempt to set the specified port. * - * @param {object | array} ports + * @param {object | array} portEntities */ - set: function (ports) { - var set = function (port) { - if (portMap.has(port.id)) { + set: function (portEntities) { + var set = function (portEntity) { + if (portMap.has(portEntity.id)) { // update the current entry - var portEntry = portMap.get(port.id); - portEntry.component = port; + var portEntry = portMap.get(portEntity.id); + $.extend(portEntry, portEntity); // update the connection in the UI - d3.select('#id-' + port.id).call(updatePorts); + d3.select('#id-' + portEntry.id).call(updatePorts); } }; // determine how to handle the specified ports - if ($.isArray(ports)) { - $.each(ports, function (_, port) { + if ($.isArray(portEntities)) { + $.each(portEntities, function (_, port) { set(port); }); } else { - set(ports); + set(portEntities); } }, @@ -607,13 +608,6 @@ nf.Port = (function () { d3.selectAll('g.input-port.visible, g.output-port.visible').call(updatePortStatus); }, - /** - * Returns the entity key when marshalling an entity of this type. - */ - getEntityKey: function (d) { - return d.component.type === 'INPUT_PORT' ? 'inputPort' : 'outputPort'; - }, - /** * Removes the specified port. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js index b72deb2c67..3b6cd1408d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-configuration.js @@ -37,7 +37,7 @@ nf.ProcessGroupConfiguration = (function () { // build the entity var entity = { 'revision': nf.Client.getRevision(), - 'processGroup': { + 'component': { 'id': processGroupId, 'name': $('#process-group-name').val(), 'comments': $('#process-group-comments').val() @@ -52,12 +52,12 @@ nf.ProcessGroupConfiguration = (function () { dataType: 'json', contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processGroup)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); // refresh the process group - nf.ProcessGroup.set(response.processGroup); + nf.ProcessGroup.set(response); // close the details panel $('#process-group-configuration').modal('hide'); @@ -104,7 +104,7 @@ nf.ProcessGroupConfiguration = (function () { var selectionData = selection.datum(); // populate the process group settings - $('#process-group-id').text(selectionData.component.id); + $('#process-group-id').text(selectionData.id); $('#process-group-name').val(selectionData.component.name); $('#process-group-comments').val(selectionData.component.comments); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-details.js index 473ca9c640..7796901033 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-details.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group-details.js @@ -54,7 +54,7 @@ nf.ProcessGroupDetails = (function () { var selectionData = selection.datum(); // populate the port settings - nf.Common.populateField('read-only-process-group-id', selectionData.component.id); + nf.Common.populateField('read-only-process-group-id', selectionData.id); nf.Common.populateField('read-only-process-group-name', selectionData.component.name); nf.Common.populateField('read-only-process-group-comments', selectionData.component.comments); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js index bde0f41d87..5af7a45389 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-process-group.js @@ -59,9 +59,7 @@ nf.ProcessGroup = (function () { * Selects the process group elements against the current process group map. */ var select = function () { - return processGroupContainer.selectAll('g.process-group').data(processGroupMap.values(), function (d) { - return d.component.id; - }); + return processGroupContainer.selectAll('g.process-group').data(processGroupMap.values()); }; /** @@ -78,7 +76,7 @@ nf.ProcessGroup = (function () { var processGroup = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': 'process-group component' }) @@ -152,45 +150,48 @@ nf.ProcessGroup = (function () { // always support selecting and navigation processGroup.on('dblclick', function (d) { // enter this group on double click - nf.CanvasUtils.enterGroup(d.component.id); + nf.CanvasUtils.enterGroup(d.id); }) .call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only support dragging, connection, and drag and drop if appropriate if (nf.Common.isDFM()) { - processGroup - // Using mouseover/out to workaround chrome issue #122746 - .on('mouseover.drop', function (d) { - // get the target and ensure its not already been marked for drop - var target = d3.select(this); - if (!target.classed('drop')) { - var targetData = target.datum(); - - // see if there is a selection being dragged - var drag = d3.select('rect.drag-selection'); - if (!drag.empty()) { - // filter the current selection by this group - var selection = nf.CanvasUtils.getSelection().filter(function(d) { - return targetData.component.id === d.component.id; - }); - - // ensure this group isn't in the selection - if (selection.empty()) { - // mark that we are hovering over a drop area if appropriate - target.classed('drop', function () { - // get the current selection and ensure its disconnected - return nf.CanvasUtils.isDisconnected(nf.CanvasUtils.getSelection()); - }); - } - } + processGroup.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }) + .on('mouseover.drop', function (d) { + // Using mouseover/out to workaround chrome issue #122746 + + // get the target and ensure its not already been marked for drop + var target = d3.select(this); + if (!target.classed('drop')) { + var targetData = target.datum(); + + // see if there is a selection being dragged + var drag = d3.select('rect.drag-selection'); + if (!drag.empty()) { + // filter the current selection by this group + var selection = nf.CanvasUtils.getSelection().filter(function(d) { + return targetData.id === d.id; + }); + + // ensure this group isn't in the selection + if (selection.empty()) { + // mark that we are hovering over a drop area if appropriate + target.classed('drop', function () { + // get the current selection and ensure its disconnected + return nf.CanvasUtils.isDisconnected(nf.CanvasUtils.getSelection()); + }); } - }) - .on('mouseout.drop', function (d) { - // mark that we are no longer hovering over a drop area unconditionally - d3.select(this).classed('drop', false); - }) - .call(nf.Draggable.activate) - .call(nf.Connectable.activate); + } + } + }) + .on('mouseout.drop', function (d) { + // mark that we are no longer hovering over a drop area unconditionally + d3.select(this).classed('drop', false); + }) + .call(nf.Draggable.activate) + .call(nf.Connectable.activate); } // call update to trigger some rendering @@ -210,7 +211,7 @@ nf.ProcessGroup = (function () { return; } - updated.each(function () { + updated.each(function (processGroupData) { var processGroup = d3.select(this); var details = processGroup.select('g.process-group-details'); @@ -261,150 +262,152 @@ nf.ProcessGroup = (function () { // contents // -------- - // input ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconInputPortSmall.png', - 'width': 16, - 'height': 16, - 'x': 10, - 'y': 25 - }); + if (processGroupData.accessPolicy.canRead) { + // input ports icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconInputPortSmall.png', + 'width': 16, + 'height': 16, + 'x': 10, + 'y': 25 + }); - // input ports count - details.append('text') - .attr({ - 'x': 29, - 'y': 37, - 'class': 'process-group-input-port-count process-group-contents-count' - }); + // input ports count + details.append('text') + .attr({ + 'x': 29, + 'y': 37, + 'class': 'process-group-input-port-count process-group-contents-count' + }); - // output ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconOutputPortSmall.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-output-port' - }); + // output ports icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconOutputPortSmall.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-output-port' + }); - // output ports count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-output-port-count process-group-contents-count' - }); + // output ports count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-output-port-count process-group-contents-count' + }); - // transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionActive.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-transmitting' - }); + // transmitting icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconTransmissionActive.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-transmitting' + }); - // transmitting count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-transmitting-count process-group-contents-count' - }); + // transmitting count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-transmitting-count process-group-contents-count' + }); - // not transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionInactive.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-not-transmitting' - }); + // not transmitting icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconTransmissionInactive.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-not-transmitting' + }); - // not transmitting count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-not-transmitting-count process-group-contents-count' - }); + // not transmitting count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-not-transmitting-count process-group-contents-count' + }); - // running icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconRun.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-running' - }); + // running icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconRun.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-running' + }); - // running count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-running-count process-group-contents-count' - }); + // running count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-running-count process-group-contents-count' + }); - // stopped icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconStop.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-stopped' - }); + // stopped icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconStop.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-stopped' + }); - // stopped count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-stopped-count process-group-contents-count' - }); + // stopped count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-stopped-count process-group-contents-count' + }); - // invalid icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconAlert.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-invalid' - }); + // invalid icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconAlert.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-invalid' + }); - // invalid count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-invalid-count process-group-contents-count' - }); + // invalid count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-invalid-count process-group-contents-count' + }); - // disabled icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconDisable.png', - 'width': 16, - 'height': 16, - 'y': 25, - 'class': 'process-group-disabled' - }); + // disabled icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconDisable.png', + 'width': 16, + 'height': 16, + 'y': 25, + 'class': 'process-group-disabled' + }); - // disabled count - details.append('text') - .attr({ - 'y': 37, - 'class': 'process-group-disabled-count process-group-contents-count' - }); + // disabled count + details.append('text') + .attr({ + 'y': 37, + 'class': 'process-group-disabled-count process-group-contents-count' + }); + } // ----- // stats @@ -600,157 +603,159 @@ nf.ProcessGroup = (function () { }); } - // update the input ports - var inputPortCount = details.select('text.process-group-input-port-count') - .text(function (d) { - return d.component.inputPortCount; - }); + if (processGroupData.accessPolicy.canRead) { + // update the input ports + var inputPortCount = details.select('text.process-group-input-port-count') + .text(function (d) { + return d.component.inputPortCount; + }); - // update the output ports - var outputPort = details.select('image.process-group-output-port') - .attr('x', function () { - var inputPortCountX = parseInt(inputPortCount.attr('x'), 10); - return inputPortCountX + inputPortCount.node().getComputedTextLength() + CONTENTS_SPACER; - }); - details.select('text.process-group-output-port-count') - .attr('x', function () { - var outputPortImageX = parseInt(outputPort.attr('x'), 10); - var outputPortImageWidth = parseInt(outputPort.attr('width'), 10); - return outputPortImageX + outputPortImageWidth + CONTENTS_SPACER; - }) - .text(function (d) { - return d.component.outputPortCount; - }); + // update the output ports + var outputPort = details.select('image.process-group-output-port') + .attr('x', function () { + var inputPortCountX = parseInt(inputPortCount.attr('x'), 10); + return inputPortCountX + inputPortCount.node().getComputedTextLength() + CONTENTS_SPACER; + }); + details.select('text.process-group-output-port-count') + .attr('x', function () { + var outputPortImageX = parseInt(outputPort.attr('x'), 10); + var outputPortImageWidth = parseInt(outputPort.attr('width'), 10); + return outputPortImageX + outputPortImageWidth + CONTENTS_SPACER; + }) + .text(function (d) { + return d.component.outputPortCount; + }); - // get the container to help right align - var container = details.select('rect.process-group-contents-container'); + // get the container to help right align + var container = details.select('rect.process-group-contents-container'); - // update disabled - var disabledCount = details.select('text.process-group-disabled-count') - .text(function (d) { - return d.component.disabledCount; - }) - .attr('x', function () { - var containerX = parseInt(container.attr('x'), 10); - var containerWidth = parseInt(container.attr('width'), 10); - return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var disabled = details.select('image.process-group-disabled') - .attr('x', function () { - var disabledCountX = parseInt(disabledCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return disabledCountX - width - CONTENTS_SPACER; - }); + // update disabled + var disabledCount = details.select('text.process-group-disabled-count') + .text(function (d) { + return d.component.disabledCount; + }) + .attr('x', function () { + var containerX = parseInt(container.attr('x'), 10); + var containerWidth = parseInt(container.attr('width'), 10); + return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var disabled = details.select('image.process-group-disabled') + .attr('x', function () { + var disabledCountX = parseInt(disabledCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return disabledCountX - width - CONTENTS_SPACER; + }); - // update invalid - var invalidCount = details.select('text.process-group-invalid-count') - .text(function (d) { - return d.component.invalidCount; - }) - .attr('x', function () { - var disabledX = parseInt(disabled.attr('x'), 10); - return disabledX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var invalid = details.select('image.process-group-invalid') - .attr('x', function () { - var invalidCountX = parseInt(invalidCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return invalidCountX - width - CONTENTS_SPACER; - }); + // update invalid + var invalidCount = details.select('text.process-group-invalid-count') + .text(function (d) { + return d.component.invalidCount; + }) + .attr('x', function () { + var disabledX = parseInt(disabled.attr('x'), 10); + return disabledX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var invalid = details.select('image.process-group-invalid') + .attr('x', function () { + var invalidCountX = parseInt(invalidCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return invalidCountX - width - CONTENTS_SPACER; + }); - // update stopped - var stoppedCount = details.select('text.process-group-stopped-count') - .text(function (d) { - return d.component.stoppedCount; - }) - .attr('x', function () { - var invalidX = parseInt(invalid.attr('x'), 10); - return invalidX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var stopped = details.select('image.process-group-stopped') - .attr('x', function () { - var stoppedCountX = parseInt(stoppedCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return stoppedCountX - width - CONTENTS_SPACER; - }); + // update stopped + var stoppedCount = details.select('text.process-group-stopped-count') + .text(function (d) { + return d.component.stoppedCount; + }) + .attr('x', function () { + var invalidX = parseInt(invalid.attr('x'), 10); + return invalidX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var stopped = details.select('image.process-group-stopped') + .attr('x', function () { + var stoppedCountX = parseInt(stoppedCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return stoppedCountX - width - CONTENTS_SPACER; + }); - // update running - var runningCount = details.select('text.process-group-running-count') - .text(function (d) { - return d.component.runningCount; - }) - .attr('x', function () { - var stoppedX = parseInt(stopped.attr('x'), 10); - return stoppedX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var running = details.select('image.process-group-running') - .attr('x', function () { - var runningCountX = parseInt(runningCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return runningCountX - width - CONTENTS_SPACER; - }); + // update running + var runningCount = details.select('text.process-group-running-count') + .text(function (d) { + return d.component.runningCount; + }) + .attr('x', function () { + var stoppedX = parseInt(stopped.attr('x'), 10); + return stoppedX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var running = details.select('image.process-group-running') + .attr('x', function () { + var runningCountX = parseInt(runningCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return runningCountX - width - CONTENTS_SPACER; + }); - // update not transmitting - var notTransmittingCount = details.select('text.process-group-not-transmitting-count') - .text(function (d) { - return d.component.inactiveRemotePortCount; - }) - .attr('x', function () { - var runningX = parseInt(running.attr('x'), 10); - return runningX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var notTransmitting = details.select('image.process-group-not-transmitting') - .attr('x', function () { - var notTransmittingCountX = parseInt(notTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return notTransmittingCountX - width - CONTENTS_SPACER; - }); + // update not transmitting + var notTransmittingCount = details.select('text.process-group-not-transmitting-count') + .text(function (d) { + return d.component.inactiveRemotePortCount; + }) + .attr('x', function () { + var runningX = parseInt(running.attr('x'), 10); + return runningX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var notTransmitting = details.select('image.process-group-not-transmitting') + .attr('x', function () { + var notTransmittingCountX = parseInt(notTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return notTransmittingCountX - width - CONTENTS_SPACER; + }); - // update transmitting - var transmittingCount = details.select('text.process-group-transmitting-count') - .text(function (d) { - return d.component.activeRemotePortCount; - }) - .attr('x', function () { - var notTransmittingX = parseInt(notTransmitting.attr('x'), 10); - return notTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - details.select('image.process-group-transmitting') - .attr('x', function () { - var transmittingCountX = parseInt(transmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return transmittingCountX - width - CONTENTS_SPACER; - }); + // update transmitting + var transmittingCount = details.select('text.process-group-transmitting-count') + .text(function (d) { + return d.component.activeRemotePortCount; + }) + .attr('x', function () { + var notTransmittingX = parseInt(notTransmitting.attr('x'), 10); + return notTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + details.select('image.process-group-transmitting') + .attr('x', function () { + var transmittingCountX = parseInt(transmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return transmittingCountX - width - CONTENTS_SPACER; + }); - // update the process group comments - details.select('text.process-group-comments') - .each(function (d) { - var processGroupComments = d3.select(this); + // update the process group comments + details.select('text.process-group-comments') + .each(function (d) { + var processGroupComments = d3.select(this); - // reset the process group name to handle any previous state - processGroupComments.text(null).selectAll('tspan, title').remove(); + // reset the process group name to handle any previous state + processGroupComments.text(null).selectAll('tspan, title').remove(); - // apply ellipsis to the port name as necessary - nf.CanvasUtils.multilineEllipsis(processGroupComments, 2, getProcessGroupComments(d)); - }).classed('unset', function (d) { - return nf.Common.isBlank(d.component.comments); - }).append('title').text(function (d) { - return getProcessGroupComments(d); - }); + // apply ellipsis to the port name as necessary + nf.CanvasUtils.multilineEllipsis(processGroupComments, 2, getProcessGroupComments(d)); + }).classed('unset', function (d) { + return nf.Common.isBlank(d.component.comments); + }).append('title').text(function (d) { + return getProcessGroupComments(d); + }); - // update the process group name - processGroup.select('text.process-group-name') - .each(function (d) { - var processGroupName = d3.select(this); + // update the process group name + processGroup.select('text.process-group-name') + .each(function (d) { + var processGroupName = d3.select(this); - // reset the process group name to handle any previous state - processGroupName.text(null).selectAll('title').remove(); + // reset the process group name to handle any previous state + processGroupName.text(null).selectAll('title').remove(); - // apply ellipsis to the process group name as necessary - nf.CanvasUtils.ellipsis(processGroupName, d.component.name); - }).append('title').text(function (d) { - return d.component.name; - }); + // apply ellipsis to the process group name as necessary + nf.CanvasUtils.ellipsis(processGroupName, d.component.name); + }).append('title').text(function (d) { + return d.component.name; + }); + } // hide the preview processGroup.select('image.process-group-preview').style('display', 'none'); @@ -758,16 +763,18 @@ nf.ProcessGroup = (function () { // populate the stats processGroup.call(updateProcessGroupStatus); } else { - // update the process group name - processGroup.select('text.process-group-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + if (processGroupData.accessPolicy.canRead) { + // update the process group name + processGroup.select('text.process-group-name') + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); + } // show the preview processGroup.select('image.process-group-preview').style('display', 'block'); @@ -876,7 +883,7 @@ nf.ProcessGroup = (function () { var removeTooltips = function (removed) { removed.each(function (d) { // remove any associated tooltips - $('#bulletin-tip-' + d.component.id).remove(); + $('#bulletin-tip-' + d.id).remove(); }); }; @@ -898,28 +905,27 @@ nf.ProcessGroup = (function () { /** * Populates the graph with the specified process groups. * - * @argument {object | array} processGroups The process groups to add + * @argument {object | array} processGroupEntities The process groups to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (processGroups, selectAll) { + add: function (processGroupEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; - var add = function (processGroup) { + var add = function (processGroupEntity) { // add the process group - processGroupMap.set(processGroup.id, { + processGroupMap.set(processGroupEntity.id, $.extend({ type: 'ProcessGroup', - component: processGroup, dimensions: dimensions - }); + }, processGroupEntity)); }; // determine how to handle the specified process groups - if ($.isArray(processGroups)) { - $.each(processGroups, function (_, processGroup) { - add(processGroup); + if ($.isArray(processGroupEntities)) { + $.each(processGroupEntities, function (_, processGroupEntity) { + add(processGroupEntity); }); } else { - add(processGroups); + add(processGroupEntities); } // apply the selection and handle all new process group @@ -974,7 +980,7 @@ nf.ProcessGroup = (function () { url: processGroup.uri, dataType: 'json' }).done(function (response) { - nf.ProcessGroup.set(response.processGroup); + nf.ProcessGroup.set(response); }); } }, @@ -993,27 +999,27 @@ nf.ProcessGroup = (function () { * will set each process group. If it is not an array, it will * attempt to set the specified process group. * - * @param {object | array} processGroups + * @param {object | array} processGroupEntities */ - set: function (processGroups) { - var set = function (processGroup) { - if (processGroupMap.has(processGroup.id)) { + set: function (processGroupEntities) { + var set = function (processGroupEntity) { + if (processGroupMap.has(processGroupEntity.id)) { // update the current entry - var processGroupEntry = processGroupMap.get(processGroup.id); - processGroupEntry.component = processGroup; - + var processGroupEntry = processGroupMap.get(processGroupEntity.id); + $.extend(processGroupEntry, processGroupEntity); + // update the process group in the UI - d3.select('#id-' + processGroup.id).call(updateProcessGroups); + d3.select('#id-' + processGroupEntry.id).call(updateProcessGroups); } }; // determine how to handle the specified process group - if ($.isArray(processGroups)) { - $.each(processGroups, function (_, processGroup) { - set(processGroup); + if ($.isArray(processGroupEntities)) { + $.each(processGroupEntities, function (_, processGroupEntity) { + set(processGroupEntity); }); } else { - set(processGroups); + set(processGroupEntities); } }, @@ -1039,13 +1045,6 @@ nf.ProcessGroup = (function () { d3.selectAll('g.process-group.visible').call(updateProcessGroupStatus); }, - /** - * Returns the entity key when marshalling an entity of this type. - */ - getEntityKey: function (d) { - return 'processGroup'; - }, - /** * Removes the specified process group. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js index 12714801ee..b6b7f348ff 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js @@ -303,7 +303,7 @@ nf.ProcessorConfiguration = (function () { // create the processor entity var processorEntity = {}; processorEntity['revision'] = nf.Client.getRevision(); - processorEntity['processor'] = processorDto; + processorEntity['component'] = processorDto; // return the marshaled details return processorEntity; @@ -340,7 +340,7 @@ nf.ProcessorConfiguration = (function () { */ var validateDetails = function (details) { var errors = []; - var processor = details['processor']; + var processor = details['component']; var config = processor['config']; // ensure numeric fields are specified correctly @@ -377,8 +377,10 @@ nf.ProcessorConfiguration = (function () { var reloadProcessorConnections = function (processor) { var connections = nf.Connection.getComponentConnections(processor.id); $.each(connections, function (_, connection) { - if (connection.source.id === processor.id) { - nf.Connection.reload(connection); + if (connection.accessPolicy.canRead) { + if (connection.sourceId === processor.id) { + nf.Connection.reload(connection); + } } }); }; @@ -435,7 +437,7 @@ nf.ProcessorConfiguration = (function () { processData: false, contentType: 'application/json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processor)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // update the revision nf.Client.setRevision(response.revision); } @@ -592,7 +594,7 @@ nf.ProcessorConfiguration = (function () { // once everything is loaded, show the dialog $.when.apply(window, requests).done(function (processorResponse, historyResponse) { // get the updated processor - processor = processorResponse[0].processor; + processor = processorResponse[0].component; // get the processor history var processorHistory = historyResponse[0].componentHistory; @@ -717,7 +719,7 @@ nf.ProcessorConfiguration = (function () { // save the processor saveProcessor(processor).done(function (response) { // set the new processor state based on the response - nf.Processor.set(response.processor); + nf.Processor.set(response); // reload the processor's outgoing connections reloadProcessorConnections(processor); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js index e46b462bc8..dbe52464a5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor.js @@ -47,9 +47,7 @@ nf.Processor = (function () { * Selects the processor elements against the current processor map. */ var select = function () { - return processorContainer.selectAll('g.processor').data(processorMap.values(), function (d) { - return d.component.id; - }); + return processorContainer.selectAll('g.processor').data(processorMap.values()); }; // renders the processors @@ -61,7 +59,7 @@ nf.Processor = (function () { var processor = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': 'processor component' }) @@ -138,9 +136,9 @@ nf.Processor = (function () { processor.call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only activate dragging and connecting if appropriate - if (nf.Common.isDFM()) { - processor.call(nf.Draggable.activate).call(nf.Connectable.activate); - } + processor.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).call(nf.Draggable.activate).call(nf.Connectable.activate); // call update to trigger some rendering processor.call(updateProcessors); @@ -156,7 +154,7 @@ nf.Processor = (function () { return; } - updated.each(function () { + updated.each(function (processorData) { var processor = d3.select(this); var details = processor.select('g.processor-details'); @@ -176,28 +174,30 @@ nf.Processor = (function () { 'y': 5 }); - // processor type - details.append('text') - .attr({ - 'x': 25, - 'y': 30, - 'width': 246, - 'height': 16, - 'font-size': '8pt', - 'font-weight': 'normal', - 'fill': 'black' - }) - .each(function (d) { - var processorType = d3.select(this); + if (processorData.accessPolicy.canRead) { + // processor type + details.append('text') + .attr({ + 'x': 25, + 'y': 30, + 'width': 246, + 'height': 16, + 'font-size': '8pt', + 'font-weight': 'normal', + 'fill': 'black' + }) + .each(function (d) { + var processorType = d3.select(this); - // reset the processor type to handle any previous state - processorType.text(null).selectAll('title').remove(); + // reset the processor type to handle any previous state + processorType.text(null).selectAll('title').remove(); - // apply ellipsis to the processor type as necessary - nf.CanvasUtils.ellipsis(processorType, nf.Common.substringAfterLast(d.component.type, '.')); - }).append('title').text(function (d) { - return nf.Common.substringAfterLast(d.component.type, '.'); - }); + // apply ellipsis to the processor type as necessary + nf.CanvasUtils.ellipsis(processorType, nf.Common.substringAfterLast(d.component.type, '.')); + }).append('title').text(function (d) { + return nf.Common.substringAfterLast(d.component.type, '.'); + }); + } // ----- // stats @@ -412,62 +412,64 @@ nf.Processor = (function () { }); } - // update the run status - details.select('image.run-status-icon') - .attr('xlink:href', function (d) { - var img = ''; - if (d.component.state === 'DISABLED') { - img = 'images/iconDisable.png'; - } else if (!nf.Common.isEmpty(d.component.validationErrors)) { - img = 'images/iconAlert.png'; - } else if (d.component.state === 'RUNNING') { - img = 'images/iconRun.png'; - } else if (d.component.state === 'STOPPED') { - img = 'images/iconStop.png'; - } - return img; - }) - .each(function (d) { - // remove the existing tip if necessary - var tip = d3.select('#run-status-tip-' + d.component.id); - if (!tip.empty()) { - tip.remove(); - } + if (processorData.accessPolicy.canRead) { + // update the run status + details.select('image.run-status-icon') + .attr('xlink:href', function (d) { + var img = ''; + if (d.component.state === 'DISABLED') { + img = 'images/iconDisable.png'; + } else if (!nf.Common.isEmpty(d.component.validationErrors)) { + img = 'images/iconAlert.png'; + } else if (d.component.state === 'RUNNING') { + img = 'images/iconRun.png'; + } else if (d.component.state === 'STOPPED') { + img = 'images/iconStop.png'; + } + return img; + }) + .each(function (d) { + // remove the existing tip if necessary + var tip = d3.select('#run-status-tip-' + d.id); + if (!tip.empty()) { + tip.remove(); + } - // if there are validation errors generate a tooltip - if (!nf.Common.isEmpty(d.component.validationErrors)) { - tip = d3.select('#processor-tooltips').append('div') - .attr('id', function () { - return 'run-status-tip-' + d.component.id; - }) - .attr('class', 'tooltip nifi-tooltip') - .html(function () { - var list = nf.Common.formatUnorderedList(d.component.validationErrors); - if (list === null || list.length === 0) { - return ''; - } else { - return $('
').append(list).html(); - } - }); + // if there are validation errors generate a tooltip + if (!nf.Common.isEmpty(d.component.validationErrors)) { + tip = d3.select('#processor-tooltips').append('div') + .attr('id', function () { + return 'run-status-tip-' + d.id; + }) + .attr('class', 'tooltip nifi-tooltip') + .html(function () { + var list = nf.Common.formatUnorderedList(d.component.validationErrors); + if (list === null || list.length === 0) { + return ''; + } else { + return $('
').append(list).html(); + } + }); - // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); - } - }); + // add the tooltip + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); + } + }); - // update the processor name - processor.select('text.processor-name') - .each(function (d) { - var processorName = d3.select(this); + // update the processor name + processor.select('text.processor-name') + .each(function (d) { + var processorName = d3.select(this); - // reset the processor name to handle any previous state - processorName.text(null).selectAll('title').remove(); + // reset the processor name to handle any previous state + processorName.text(null).selectAll('title').remove(); - // apply ellipsis to the processor name as necessary - nf.CanvasUtils.ellipsis(processorName, d.component.name); - }).append('title').text(function (d) { - return d.component.name; - }); + // apply ellipsis to the processor name as necessary + nf.CanvasUtils.ellipsis(processorName, d.component.name); + }).append('title').text(function (d) { + return d.component.name; + }); + } // hide the preview processor.select('image.processor-stats-preview').style('display', 'none'); @@ -475,16 +477,18 @@ nf.Processor = (function () { // populate the stats processor.call(updateProcessorStatus); } else { - // update the processor name - processor.select('text.processor-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + if (processorData.accessPolicy.canRead) { + // update the processor name + processor.select('text.processor-name') + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); + } // show the preview processor.select('image.processor-stats-preview').style('display', 'block'); @@ -509,9 +513,11 @@ nf.Processor = (function () { // determine all unique colors processorMap.forEach(function (id, d) { - var color = d.component.style['background-color']; - if (nf.Common.isDefinedAndNotNull(color)) { - colors.add(nf.Common.substringAfterLast(color, '#')); + if (d.accessPolicy.canRead) { + var color = d.component.style['background-color']; + if (nf.Common.isDefinedAndNotNull(color)) { + colors.add(nf.Common.substringAfterLast(color, '#')); + } } }); nf.Canvas.defineProcessorColors(colors.values()); @@ -521,9 +527,11 @@ nf.Processor = (function () { .attr('stroke', function (d) { var color = nf.Processor.defaultColor(); - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; + } } return color; @@ -533,9 +541,11 @@ nf.Processor = (function () { .attr('fill', function (d) { var color = nf.Processor.defaultColor(); - // use the specified color if appropriate - if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { - color = d.component.style['background-color']; + if (d.accessPolicy.canRead) { + // use the specified color if appropriate + if (nf.Common.isDefinedAndNotNull(d.component.style['background-color'])) { + color = d.component.style['background-color']; + } } // get just the color code part @@ -635,8 +645,8 @@ nf.Processor = (function () { var removeTooltips = function (removed) { removed.each(function (d) { // remove any associated tooltips - $('#run-status-tip-' + d.component.id).remove(); - $('#bulletin-tip-' + d.component.id).remove(); + $('#run-status-tip-' + d.id).remove(); + $('#bulletin-tip-' + d.id).remove(); }); }; @@ -658,28 +668,27 @@ nf.Processor = (function () { /** * Populates the graph with the specified processors. * - * @argument {object | array} processors The processors to add + * @argument {object | array} processorEntities The processors to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (processors, selectAll) { + add: function (processorNodeEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; - var add = function (processor) { + var add = function (processorEntity) { // add the processor - processorMap.set(processor.id, { + processorMap.set(processorEntity.id, $.extend({ type: 'Processor', - component: processor, dimensions: dimensions - }); + }, processorEntity)); }; // determine how to handle the specified processor - if ($.isArray(processors)) { - $.each(processors, function (_, processor) { - add(processor); + if ($.isArray(processorNodeEntities)) { + $.each(processorNodeEntities, function (_, processorEntity) { + add(processorEntity); }); } else { - add(processors); + add(processorNodeEntities); } // apply the selection and handle all new processors @@ -743,7 +752,7 @@ nf.Processor = (function () { url: processor.uri, dataType: 'json' }).done(function (response) { - nf.Processor.set(response.processor); + nf.Processor.set(response); }); } }, @@ -753,27 +762,27 @@ nf.Processor = (function () { * will set each processor. If it is not an array, it will * attempt to set the specified processor. * - * @param {object | array} processors + * @param {object | array} processorEntities */ - set: function (processors) { - var set = function (processor) { - if (processorMap.has(processor.id)) { + set: function (processorEntities) { + var set = function (processorEntity) { + if (processorMap.has(processorEntity.id)) { // update the current entry - var processorEntry = processorMap.get(processor.id); - processorEntry.component = processor; - + var processorEntry = processorMap.get(processorEntity.id); + $.extend(processorEntry, processorEntity); + // update the processor in the UI - d3.select('#id-' + processor.id).call(updateProcessors); + d3.select('#id-' + processorEntry.id).call(updateProcessors); } }; // determine how to handle the specified processor - if ($.isArray(processors)) { - $.each(processors, function (_, processor) { - set(processor); + if ($.isArray(processorEntities)) { + $.each(processorEntities, function (_, processorEntity) { + set(processorEntity); }); } else { - set(processors); + set(processorEntities); } }, @@ -824,13 +833,6 @@ nf.Processor = (function () { d3.selectAll('g.processor.visible').call(updateProcessorStatus); }, - /** - * Returns the entity key when marshalling an entity of this type. - */ - getEntityKey: function (d) { - return 'processor'; - }, - /** * Returns the default color that should be used when drawing a processor. */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-queue-listing.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-queue-listing.js index 5f9de0cac2..6a8277b381 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-queue-listing.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-queue-listing.js @@ -380,7 +380,7 @@ nf.QueueListing = (function () { // issue the request to list the flow files $.ajax({ type: 'POST', - url: '../nifi-api/flowfile-queues/' + connection.component.id + '/listing-requests', + url: '../nifi-api/flowfile-queues/' + connection.id + '/listing-requests', dataType: 'json', contentType: 'application/json' }).done(function(response) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js index 738b5b04eb..f539b66b4d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js @@ -32,8 +32,8 @@ nf.RemoteProcessGroupConfiguration = (function () { // create the remote process group details var remoteProcessGroupEntity = { - revision: nf.Client.getRevision(), - remoteProcessGroup: { + 'revision': nf.Client.getRevision(), + 'component': { id: remoteProcessGroupId, communicationsTimeout: $('#remote-process-group-timeout').val(), yieldDuration: $('#remote-process-group-yield-duration').val() @@ -52,7 +52,7 @@ nf.RemoteProcessGroupConfiguration = (function () { nf.Client.setRevision(response.revision); // refresh the remote process group component - nf.RemoteProcessGroup.set(response.remoteProcessGroup); + nf.RemoteProcessGroup.set(response); // close the details panel $('#remote-process-group-configuration').modal('hide'); @@ -113,7 +113,7 @@ nf.RemoteProcessGroupConfiguration = (function () { var selectionData = selection.datum(); // populate the port settings - $('#remote-process-group-id').text(selectionData.component.id); + $('#remote-process-group-id').text(selectionData.id); $('#remote-process-group-name').text(selectionData.component.name); $('#remote-process-group-url').text(selectionData.component.targetUri); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js index b74628a614..8ec7c89d7a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js @@ -58,7 +58,7 @@ nf.RemoteProcessGroupDetails = (function () { var selectionData = selection.datum(); // populate the port settings - nf.Common.populateField('read-only-remote-process-group-id', selectionData.component.id); + nf.Common.populateField('read-only-remote-process-group-id', selectionData.id); nf.Common.populateField('read-only-remote-process-group-name', selectionData.component.name); nf.Common.populateField('read-only-remote-process-group-url', selectionData.component.targetUri); nf.Common.populateField('read-only-remote-process-group-timeout', selectionData.component.communicationsTimeout); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js index ef51f466d7..4a0789ebd6 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js @@ -40,8 +40,8 @@ nf.RemoteProcessGroupPorts = (function () { // create the remote process group details var remoteProcessGroupPortEntity = { - revision: nf.Client.getRevision(), - remoteProcessGroupPort: { + 'revision': nf.Client.getRevision(), + 'remoteProcessGroupPort': { id: remotePortId, useCompression: $('#remote-port-use-compression').hasClass('checkbox-checked'), concurrentlySchedulableTaskCount: remotePortConcurrentTasks @@ -259,8 +259,8 @@ nf.RemoteProcessGroupPorts = (function () { // create the remote process group details var remoteProcessGroupPortEntity = { - revision: nf.Client.getRevision(), - remoteProcessGroupPort: { + 'revision': nf.Client.getRevision(), + 'remoteProcessGroupPort': { id: port.id, transmitting: isTransmitting } @@ -460,7 +460,7 @@ nf.RemoteProcessGroupPorts = (function () { var remoteProcessGroup = response.remoteProcessGroup; // set the model locally - nf.RemoteProcessGroup.set(remoteProcessGroup); + nf.RemoteProcessGroup.set(response); // populate the port settings $('#remote-process-group-ports-id').text(remoteProcessGroup.id); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js index dd7454be3f..27fa46170d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js @@ -59,9 +59,7 @@ nf.RemoteProcessGroup = (function () { * Selects the remote process group elements against the current remote process group map. */ var select = function () { - return remoteProcessGroupContainer.selectAll('g.remote-process-group').data(remoteProcessGroupMap.values(), function (d) { - return d.component.id; - }); + return remoteProcessGroupContainer.selectAll('g.remote-process-group').data(remoteProcessGroupMap.values()); }; /** @@ -78,7 +76,7 @@ nf.RemoteProcessGroup = (function () { var remoteProcessGroup = entered.append('g') .attr({ 'id': function (d) { - return 'id-' + d.component.id; + return 'id-' + d.id; }, 'class': 'remote-process-group component' }) @@ -153,9 +151,9 @@ nf.RemoteProcessGroup = (function () { remoteProcessGroup.call(nf.Selectable.activate).call(nf.ContextMenu.activate); // only support dragging and connecting when appropriate - if (nf.Common.isDFM()) { - remoteProcessGroup.call(nf.Draggable.activate).call(nf.Connectable.activate); - } + remoteProcessGroup.filter(function (d) { + return d.accessPolicy.canWrite && d.accessPolicy.canRead; + }).call(nf.Draggable.activate).call(nf.Connectable.activate); // call update to trigger some rendering remoteProcessGroup.call(updateRemoteProcessGroups); @@ -174,7 +172,7 @@ nf.RemoteProcessGroup = (function () { return; } - updated.each(function () { + updated.each(function (remoteProcessGroupData) { var remoteProcessGroup = d3.select(this); var details = remoteProcessGroup.select('g.remote-process-group-details'); @@ -205,28 +203,30 @@ nf.RemoteProcessGroup = (function () { 'y': 23 }); - // remote process group uri - details.append('text') - .attr({ - 'x': 25, - 'y': 32, - 'width': 305, - 'height': 12, - 'font-size': '8pt', - 'fill': '#91b9ce', - 'class': 'remote-process-group-uri' - }) - .each(function (d) { - var remoteProcessGroupUri = d3.select(this); + if (remoteProcessGroupData.accessPolicy.canRead) { + // remote process group uri + details.append('text') + .attr({ + 'x': 25, + 'y': 32, + 'width': 305, + 'height': 12, + 'font-size': '8pt', + 'fill': '#91b9ce', + 'class': 'remote-process-group-uri' + }) + .each(function (d) { + var remoteProcessGroupUri = d3.select(this); - // reset the remote process group name to handle any previous state - remoteProcessGroupUri.text(null).selectAll('title').remove(); + // reset the remote process group name to handle any previous state + remoteProcessGroupUri.text(null).selectAll('title').remove(); - // apply ellipsis to the remote process group name as necessary - nf.CanvasUtils.ellipsis(remoteProcessGroupUri, d.component.targetUri); - }).append('title').text(function (d) { - return d.component.name; - }); + // apply ellipsis to the remote process group name as necessary + nf.CanvasUtils.ellipsis(remoteProcessGroupUri, d.component.targetUri); + }).append('title').text(function (d) { + return d.component.name; + }); + } // ---------------- // stats background @@ -282,116 +282,118 @@ nf.RemoteProcessGroup = (function () { // contents // -------- - // input ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconInputPortSmall.png', - 'width': 16, - 'height': 16, - 'x': 10, - 'y': 41 - }); + if (remoteProcessGroupData.accessPolicy.canRead) { + // input ports icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconInputPortSmall.png', + 'width': 16, + 'height': 16, + 'x': 10, + 'y': 41 + }); - // input ports count - details.append('text') - .attr({ - 'x': 30, - 'y': 53, - 'class': 'remote-process-group-input-port-count process-group-contents-count' - }); + // input ports count + details.append('text') + .attr({ + 'x': 30, + 'y': 53, + 'class': 'remote-process-group-input-port-count process-group-contents-count' + }); - // input transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionActive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-input-transmitting' - }); + // input transmitting icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconTransmissionActive.png', + 'width': 16, + 'height': 16, + 'y': 41, + 'class': 'remote-process-group-input-transmitting' + }); - // input transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-input-transmitting-count process-group-contents-count' - }); + // input transmitting count + details.append('text') + .attr({ + 'y': 53, + 'class': 'remote-process-group-input-transmitting-count process-group-contents-count' + }); - // input not transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionInactive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-input-not-transmitting' - }); + // input not transmitting icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconTransmissionInactive.png', + 'width': 16, + 'height': 16, + 'y': 41, + 'class': 'remote-process-group-input-not-transmitting' + }); - // input not transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-input-not-transmitting-count process-group-contents-count' - }); + // input not transmitting count + details.append('text') + .attr({ + 'y': 53, + 'class': 'remote-process-group-input-not-transmitting-count process-group-contents-count' + }); - // output ports icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconOutputPortSmall.png', - 'width': 16, - 'height': 16, - 'x': 186, - 'y': 41, - 'class': 'remote-process-group-output-port' - }); + // output ports icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconOutputPortSmall.png', + 'width': 16, + 'height': 16, + 'x': 186, + 'y': 41, + 'class': 'remote-process-group-output-port' + }); - // output ports count - details.append('text') - .attr({ - 'x': 206, - 'y': 53, - 'class': 'remote-process-group-output-port-count process-group-contents-count' - }); + // output ports count + details.append('text') + .attr({ + 'x': 206, + 'y': 53, + 'class': 'remote-process-group-output-port-count process-group-contents-count' + }); - // output transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionActive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-output-transmitting' - }); + // output transmitting icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconTransmissionActive.png', + 'width': 16, + 'height': 16, + 'y': 41, + 'class': 'remote-process-group-output-transmitting' + }); - // output transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-output-transmitting-count process-group-contents-count' - }); + // output transmitting count + details.append('text') + .attr({ + 'y': 53, + 'class': 'remote-process-group-output-transmitting-count process-group-contents-count' + }); - // output not transmitting icon - details.append('image') - .call(nf.CanvasUtils.disableImageHref) - .attr({ - 'xlink:href': 'images/iconTransmissionInactive.png', - 'width': 16, - 'height': 16, - 'y': 41, - 'class': 'remote-process-group-output-not-transmitting' - }); + // output not transmitting icon + details.append('image') + .call(nf.CanvasUtils.disableImageHref) + .attr({ + 'xlink:href': 'images/iconTransmissionInactive.png', + 'width': 16, + 'height': 16, + 'y': 41, + 'class': 'remote-process-group-output-not-transmitting' + }); - // output not transmitting count - details.append('text') - .attr({ - 'y': 53, - 'class': 'remote-process-group-output-not-transmitting-count process-group-contents-count' - }); + // output not transmitting count + details.append('text') + .attr({ + 'y': 53, + 'class': 'remote-process-group-output-not-transmitting-count process-group-contents-count' + }); + } // ----- // stats @@ -545,179 +547,181 @@ nf.RemoteProcessGroup = (function () { }); } - // update the process groups transmission status - details.select('image.remote-process-group-transmission-secure') - .attr('xlink:href', function (d) { - var img = ''; - if (d.component.targetSecure === true) { - img = 'images/iconSecure.png'; - } else { - img = 'images/iconNotSecure.png'; - } - return img; - }) - .each(function (d) { - // remove the existing tip if necessary - var tip = d3.select('#transmission-secure-' + d.component.id); - if (!tip.empty()) { - tip.remove(); - } + if (remoteProcessGroupData.accessPolicy.canRead) { + // update the process groups transmission status + details.select('image.remote-process-group-transmission-secure') + .attr('xlink:href', function (d) { + var img = ''; + if (d.component.targetSecure === true) { + img = 'images/iconSecure.png'; + } else { + img = 'images/iconNotSecure.png'; + } + return img; + }) + .each(function (d) { + // remove the existing tip if necessary + var tip = d3.select('#transmission-secure-' + d.id); + if (!tip.empty()) { + tip.remove(); + } - tip = d3.select('#remote-process-group-tooltips').append('div') - .attr('id', function () { - return 'transmission-secure-' + d.component.id; - }) - .attr('class', 'tooltip nifi-tooltip') - .text(function () { - if (d.component.targetSecure === true) { - return 'Site-to-Site is secure.'; - } else { - return 'Site-to-Site is NOT secure.'; - } - }); + tip = d3.select('#remote-process-group-tooltips').append('div') + .attr('id', function () { + return 'transmission-secure-' + d.id; + }) + .attr('class', 'tooltip nifi-tooltip') + .text(function () { + if (d.component.targetSecure === true) { + return 'Site-to-Site is secure.'; + } else { + return 'Site-to-Site is NOT secure.'; + } + }); - // add the tooltip - nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); - }); + // add the tooltip + nf.CanvasUtils.canvasTooltip(tip, d3.select(this)); + }); - // ---------------------- - // update the input ports - // ---------------------- + // ---------------------- + // update the input ports + // ---------------------- - // input port count - details.select('text.remote-process-group-input-port-count') - .text(function (d) { - return d.component.inputPortCount; - }); + // input port count + details.select('text.remote-process-group-input-port-count') + .text(function (d) { + return d.component.inputPortCount; + }); - // get the input port container to help right align - var inputContainer = details.select('rect.remote-process-group-input-container'); + // get the input port container to help right align + var inputContainer = details.select('rect.remote-process-group-input-container'); - // update input not transmitting - var inputNotTransmittingCount = details.select('text.remote-process-group-input-not-transmitting-count') - .text(function (d) { - return d.component.inactiveRemoteInputPortCount; - }) - .attr('x', function () { - var containerX = parseInt(inputContainer.attr('x'), 10); - var containerWidth = parseInt(inputContainer.attr('width'), 10); - return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var inputNotTransmitting = details.select('image.remote-process-group-input-not-transmitting') - .attr('x', function () { - var inputNotTransmittingCountX = parseInt(inputNotTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return inputNotTransmittingCountX - width - CONTENTS_SPACER; - }); + // update input not transmitting + var inputNotTransmittingCount = details.select('text.remote-process-group-input-not-transmitting-count') + .text(function (d) { + return d.component.inactiveRemoteInputPortCount; + }) + .attr('x', function () { + var containerX = parseInt(inputContainer.attr('x'), 10); + var containerWidth = parseInt(inputContainer.attr('width'), 10); + return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var inputNotTransmitting = details.select('image.remote-process-group-input-not-transmitting') + .attr('x', function () { + var inputNotTransmittingCountX = parseInt(inputNotTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return inputNotTransmittingCountX - width - CONTENTS_SPACER; + }); - // update input transmitting - var inputTransmittingCount = details.select('text.remote-process-group-input-transmitting-count') - .text(function (d) { - return d.component.activeRemoteInputPortCount; - }) - .attr('x', function () { - var inputNotTransmittingX = parseInt(inputNotTransmitting.attr('x'), 10); - return inputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - details.select('image.remote-process-group-input-transmitting') - .attr('x', function () { - var inputTransmittingCountX = parseInt(inputTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return inputTransmittingCountX - width - CONTENTS_SPACER; - }); + // update input transmitting + var inputTransmittingCount = details.select('text.remote-process-group-input-transmitting-count') + .text(function (d) { + return d.component.activeRemoteInputPortCount; + }) + .attr('x', function () { + var inputNotTransmittingX = parseInt(inputNotTransmitting.attr('x'), 10); + return inputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + details.select('image.remote-process-group-input-transmitting') + .attr('x', function () { + var inputTransmittingCountX = parseInt(inputTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return inputTransmittingCountX - width - CONTENTS_SPACER; + }); - // ----------------------- - // update the output ports - // ----------------------- + // ----------------------- + // update the output ports + // ----------------------- - // output port count - details.select('text.remote-process-group-output-port-count') - .text(function (d) { - return d.component.outputPortCount; - }); + // output port count + details.select('text.remote-process-group-output-port-count') + .text(function (d) { + return d.component.outputPortCount; + }); - // get the output port container to help right align - var outputContainer = details.select('rect.remote-process-group-output-container'); + // get the output port container to help right align + var outputContainer = details.select('rect.remote-process-group-output-container'); - // update input not transmitting - var outputNotTransmittingCount = details.select('text.remote-process-group-output-not-transmitting-count') - .text(function (d) { - return d.component.inactiveRemoteOutputPortCount; - }) - .attr('x', function () { - var containerX = parseInt(outputContainer.attr('x'), 10); - var containerWidth = parseInt(outputContainer.attr('width'), 10); - return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; - }); - var outputNotTransmitting = details.select('image.remote-process-group-output-not-transmitting') - .attr('x', function () { - var outputNotTransmittingCountX = parseInt(outputNotTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return outputNotTransmittingCountX - width - CONTENTS_SPACER; - }); + // update input not transmitting + var outputNotTransmittingCount = details.select('text.remote-process-group-output-not-transmitting-count') + .text(function (d) { + return d.component.inactiveRemoteOutputPortCount; + }) + .attr('x', function () { + var containerX = parseInt(outputContainer.attr('x'), 10); + var containerWidth = parseInt(outputContainer.attr('width'), 10); + return containerX + containerWidth - this.getComputedTextLength() - CONTENTS_SPACER; + }); + var outputNotTransmitting = details.select('image.remote-process-group-output-not-transmitting') + .attr('x', function () { + var outputNotTransmittingCountX = parseInt(outputNotTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return outputNotTransmittingCountX - width - CONTENTS_SPACER; + }); - // update output transmitting - var outputTransmittingCount = details.select('text.remote-process-group-output-transmitting-count') - .text(function (d) { - return d.component.activeRemoteOutputPortCount; - }) - .attr('x', function () { - var outputNotTransmittingX = parseInt(outputNotTransmitting.attr('x'), 10); - return outputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; - }); - details.select('image.remote-process-group-output-transmitting') - .attr('x', function () { - var outputTransmittingCountX = parseInt(outputTransmittingCount.attr('x'), 10); - var width = parseInt(d3.select(this).attr('width'), 10); - return outputTransmittingCountX - width - CONTENTS_SPACER; - }); + // update output transmitting + var outputTransmittingCount = details.select('text.remote-process-group-output-transmitting-count') + .text(function (d) { + return d.component.activeRemoteOutputPortCount; + }) + .attr('x', function () { + var outputNotTransmittingX = parseInt(outputNotTransmitting.attr('x'), 10); + return outputNotTransmittingX - this.getComputedTextLength() - CONTENTS_SPACER; + }); + details.select('image.remote-process-group-output-transmitting') + .attr('x', function () { + var outputTransmittingCountX = parseInt(outputTransmittingCount.attr('x'), 10); + var width = parseInt(d3.select(this).attr('width'), 10); + return outputTransmittingCountX - width - CONTENTS_SPACER; + }); - // --------------- - // update comments - // --------------- + // --------------- + // update comments + // --------------- - // update the process group comments - details.select('text.remote-process-group-comments') - .each(function (d) { - var remoteProcessGroupComments = d3.select(this); + // update the process group comments + details.select('text.remote-process-group-comments') + .each(function (d) { + var remoteProcessGroupComments = d3.select(this); - // reset the processor name to handle any previous state - remoteProcessGroupComments.text(null).selectAll('tspan, title').remove(); + // reset the processor name to handle any previous state + remoteProcessGroupComments.text(null).selectAll('tspan, title').remove(); - // apply ellipsis to the port name as necessary - nf.CanvasUtils.multilineEllipsis(remoteProcessGroupComments, 2, getProcessGroupComments(d)); - }).classed('unset', function (d) { - return nf.Common.isBlank(d.component.comments); - }).append('title').text(function (d) { - return getProcessGroupComments(d); - }); + // apply ellipsis to the port name as necessary + nf.CanvasUtils.multilineEllipsis(remoteProcessGroupComments, 2, getProcessGroupComments(d)); + }).classed('unset', function (d) { + return nf.Common.isBlank(d.component.comments); + }).append('title').text(function (d) { + return getProcessGroupComments(d); + }); - // -------------- - // last refreshed - // -------------- + // -------------- + // last refreshed + // -------------- - details.select('text.remote-process-group-last-refresh') - .text(function (d) { - if (nf.Common.isDefinedAndNotNull(d.component.flowRefreshed)) { - return d.component.flowRefreshed; - } else { - return 'Remote flow not current'; - } - }); + details.select('text.remote-process-group-last-refresh') + .text(function (d) { + if (nf.Common.isDefinedAndNotNull(d.component.flowRefreshed)) { + return d.component.flowRefreshed; + } else { + return 'Remote flow not current'; + } + }); - // update the process group name - remoteProcessGroup.select('text.remote-process-group-name') - .each(function (d) { - var remoteProcessGroupName = d3.select(this); + // update the process group name + remoteProcessGroup.select('text.remote-process-group-name') + .each(function (d) { + var remoteProcessGroupName = d3.select(this); - // reset the remote process group name to handle any previous state - remoteProcessGroupName.text(null).selectAll('title').remove(); + // reset the remote process group name to handle any previous state + remoteProcessGroupName.text(null).selectAll('title').remove(); - // apply ellipsis to the remote process group name as necessary - nf.CanvasUtils.ellipsis(remoteProcessGroupName, d.component.name); - }).append('title').text(function (d) { - return d.component.name; - }); + // apply ellipsis to the remote process group name as necessary + nf.CanvasUtils.ellipsis(remoteProcessGroupName, d.component.name); + }).append('title').text(function (d) { + return d.component.name; + }); + } // show the preview remoteProcessGroup.select('image.remote-process-group-preview').style('display', 'none'); @@ -725,16 +729,18 @@ nf.RemoteProcessGroup = (function () { // populate the stats remoteProcessGroup.call(updateProcessGroupStatus); } else { - // update the process group name - remoteProcessGroup.select('text.remote-process-group-name') - .text(function (d) { - var name = d.component.name; - if (name.length > PREVIEW_NAME_LENGTH) { - return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); - } else { - return name; - } - }); + if (remoteProcessGroupData.accessPolicy.canRead) { + // update the process group name + remoteProcessGroup.select('text.remote-process-group-name') + .text(function (d) { + var name = d.component.name; + if (name.length > PREVIEW_NAME_LENGTH) { + return name.substring(0, PREVIEW_NAME_LENGTH) + String.fromCharCode(8230); + } else { + return name; + } + }); + } // show the preview remoteProcessGroup.select('image.remote-process-group-preview').style('display', 'block'); @@ -784,22 +790,25 @@ nf.RemoteProcessGroup = (function () { // authorization issues // -------------------- + // TODO - only consider state from the status // update the process groups transmission status updated.select('image.remote-process-group-transmission-status') .attr('xlink:href', function (d) { var img = ''; if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.authorizationIssues)) { img = 'images/iconAlert.png'; - } else if (d.component.transmitting === true) { - img = 'images/iconTransmissionActive.png'; - } else { - img = 'images/iconTransmissionInactive.png'; + } else if (d.accessPolicy.canRead) { + if (d.component.transmitting === true) { + img = 'images/iconTransmissionActive.png'; + } else { + img = 'images/iconTransmissionInactive.png'; + } } return img; }) .each(function (d) { // remove the existing tip if necessary - var tip = d3.select('#authorization-issues-' + d.component.id); + var tip = d3.select('#authorization-issues-' + d.id); if (!tip.empty()) { tip.remove(); } @@ -808,7 +817,7 @@ nf.RemoteProcessGroup = (function () { if (nf.Common.isDefinedAndNotNull(d.status) && !nf.Common.isEmpty(d.status.authorizationIssues)) { tip = d3.select('#remote-process-group-tooltips').append('div') .attr('id', function () { - return 'authorization-issues-' + d.component.id; + return 'authorization-issues-' + d.id; }) .attr('class', 'tooltip nifi-tooltip') .html(function () { @@ -868,9 +877,9 @@ nf.RemoteProcessGroup = (function () { var removeTooltips = function (removed) { removed.each(function (d) { // remove any associated tooltips - $('#bulletin-tip-' + d.component.id).remove(); - $('#authorization-issues-' + d.component.id).remove(); - $('#transmission-secure-' + d.component.id).remove(); + $('#bulletin-tip-' + d.id).remove(); + $('#authorization-issues-' + d.id).remove(); + $('#transmission-secure-' + d.id).remove(); }); }; @@ -892,28 +901,27 @@ nf.RemoteProcessGroup = (function () { /** * Populates the graph with the specified remote process groups. * - * @argument {object | array} remoteProcessGroups The remote process groups to add + * @argument {object | array} remoteProcessGroupEntities The remote process groups to add * @argument {boolean} selectAll Whether or not to select the new contents */ - add: function (remoteProcessGroups, selectAll) { + add: function (remoteProcessGroupEntities, selectAll) { selectAll = nf.Common.isDefinedAndNotNull(selectAll) ? selectAll : false; - var add = function (remoteProcessGroup) { + var add = function (remoteProcessGroupEntity) { // add the remote process group - remoteProcessGroupMap.set(remoteProcessGroup.id, { + remoteProcessGroupMap.set(remoteProcessGroupEntity.id, $.extend({ type: 'RemoteProcessGroup', - component: remoteProcessGroup, dimensions: dimensions - }); + }, remoteProcessGroupEntity)); }; // determine how to handle the specified remote process groups - if ($.isArray(remoteProcessGroups)) { - $.each(remoteProcessGroups, function (_, remoteProcessGroup) { - add(remoteProcessGroup); + if ($.isArray(remoteProcessGroupEntities)) { + $.each(remoteProcessGroupEntities, function (_, remoteProcessGroupEntity) { + add(remoteProcessGroupEntity); }); } else { - add(remoteProcessGroups); + add(remoteProcessGroupEntities); } // apply the selection and handle all new remote process groups @@ -968,7 +976,7 @@ nf.RemoteProcessGroup = (function () { url: remoteProcessGroup.uri, dataType: 'json' }).done(function (response) { - nf.RemoteProcessGroup.set(response.remoteProcessGroup); + nf.RemoteProcessGroup.set(response); // reload the group's connections var connections = nf.Connection.getComponentConnections(remoteProcessGroup.id); @@ -993,27 +1001,27 @@ nf.RemoteProcessGroup = (function () { * will set each remote process group. If it is not an array, it will * attempt to set the specified remote process group. * - * @param {object | array} remoteProcessGroups + * @param {object | array} remoteProcessGroupEntities */ - set: function (remoteProcessGroups) { - var set = function (remoteProcessGroup) { - if (remoteProcessGroupMap.has(remoteProcessGroup.id)) { + set: function (remoteProcessGroupEntities) { + var set = function (remoteProcessGroupEntity) { + if (remoteProcessGroupMap.has(remoteProcessGroupEntity.id)) { // update the current entry - var remoteProcessGroupEntry = remoteProcessGroupMap.get(remoteProcessGroup.id); - remoteProcessGroupEntry.component = remoteProcessGroup; - + var remoteProcessGroupEntry = remoteProcessGroupMap.get(remoteProcessGroupEntity.id); + $.extend(remoteProcessGroupEntry, remoteProcessGroupEntity); + // update the remote process group in the UI - d3.select('#id-' + remoteProcessGroup.id).call(updateRemoteProcessGroups); + d3.select('#id-' + remoteProcessGroupEntry.id).call(updateRemoteProcessGroups); } }; // determine how to handle the specified remote process group - if ($.isArray(remoteProcessGroups)) { - $.each(remoteProcessGroups, function (_, remoteProcessGroup) { - set(remoteProcessGroup); + if ($.isArray(remoteProcessGroupEntities)) { + $.each(remoteProcessGroupEntities, function (_, remoteProcessGroupEntity) { + set(remoteProcessGroupEntity); }); } else { - set(remoteProcessGroups); + set(remoteProcessGroupEntities); } }, @@ -1039,13 +1047,6 @@ nf.RemoteProcessGroup = (function () { d3.selectAll('g.remote-process-group.visible').call(updateProcessGroupStatus); }, - /** - * Returns the entity key when marshalling an entity of this type. - */ - getEntityKey: function (d) { - return 'remoteProcessGroup'; - }, - /** * Removes the specified process group. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-snippet.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-snippet.js index ecea569c15..c2d82b7f57 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-snippet.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-snippet.js @@ -51,21 +51,21 @@ nf.Snippet = (function () { var selected = d3.select(this); if (nf.CanvasUtils.isProcessor(selected)) { - snippet.processors.push(d.component.id); + snippet.processors.push(d.id); } else if (nf.CanvasUtils.isFunnel(selected)) { - snippet.funnels.push(d.component.id); + snippet.funnels.push(d.id); } else if (nf.CanvasUtils.isLabel(selected)) { - snippet.labels.push(d.component.id); + snippet.labels.push(d.id); } else if (nf.CanvasUtils.isInputPort(selected)) { - snippet.inputPorts.push(d.component.id); + snippet.inputPorts.push(d.id); } else if (nf.CanvasUtils.isOutputPort(selected)) { - snippet.outputPorts.push(d.component.id); + snippet.outputPorts.push(d.id); } else if (nf.CanvasUtils.isProcessGroup(selected)) { - snippet.processGroups.push(d.component.id); + snippet.processGroups.push(d.id); } else if (nf.CanvasUtils.isRemoteProcessGroup(selected)) { - snippet.remoteProcessGroups.push(d.component.id); + snippet.remoteProcessGroups.push(d.id); } else if (nf.CanvasUtils.isConnection(selected)) { - snippet.connections.push(d.component.id); + snippet.connections.push(d.id); } }); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js index f9702ef743..fb80e4835f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js @@ -51,7 +51,7 @@ nf.ConnectionDetails = (function () { url: '../nifi-api/processors/' + encodeURIComponent(source.id), dataType: 'json' }).done(function (response) { - var processor = response.processor; + var processor = response.component; var processorName = $('
').text(processor.name); var processorType = $('
').text(nf.Common.substringAfterLast(processor.type, '.')); @@ -94,7 +94,7 @@ nf.ConnectionDetails = (function () { }, dataType: 'json' }).done(function (response) { - var remoteProcessGroup = response.remoteProcessGroup; + var remoteProcessGroup = response.component; // populate source port details $('#read-only-connection-source-label').text('From output'); @@ -128,7 +128,7 @@ nf.ConnectionDetails = (function () { }, dataType: 'json' }).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; // populate source port details $('#read-only-connection-source-label').text('From output'); @@ -176,7 +176,7 @@ nf.ConnectionDetails = (function () { url: '../nifi-api/processors/' + encodeURIComponent(destination.id), dataType: 'json' }).done(function (response) { - var processor = response.processor; + var processor = response.component; var processorName = $('
').text(processor.name); var processorType = $('
').text(nf.Common.substringAfterLast(processor.type, '.')); @@ -224,7 +224,7 @@ nf.ConnectionDetails = (function () { }, dataType: 'json' }).done(function (response) { - var remoteProcessGroup = response.remoteProcessGroup; + var remoteProcessGroup = response.component; // populate source port details $('#read-only-connection-target-label').text('To input'); @@ -258,7 +258,7 @@ nf.ConnectionDetails = (function () { }, dataType: 'json' }).done(function (response) { - var processGroup = response.processGroup; + var processGroup = response.component; // populate destination port details $('#read-only-connection-target-label').text('To input'); @@ -384,8 +384,8 @@ nf.ConnectionDetails = (function () { var connectionResponse = connectionResult[0]; if (nf.Common.isDefinedAndNotNull(groupResponse.processGroup) && nf.Common.isDefinedAndNotNull(connectionResponse.connection)) { - var processGroup = groupResponse.processGroup; - var connection = connectionResponse.connection; + var processGroup = groupResponse.component; + var connection = connectionResponse.component; // process the source var connectionSource = initializeConnectionSource(processGroup.id, processGroup.name, connection.source); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js index 29579ddc22..5dc69e7302 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js @@ -143,9 +143,9 @@ nf.ProcessorDetails = (function () { url: '../nifi-api/processors/' + encodeURIComponent(processorId), dataType: 'json' }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processor)) { + if (nf.Common.isDefinedAndNotNull(response.component)) { // get the processor details - var details = response.processor; + var details = response.component; // record the processor details $('#processor-details').data('processorDetails', details); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html index 5bfa3cba5c..c152f12209 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html @@ -19,7 +19,7 @@ limitations under the License.
- + »