You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2018/01/08 18:14:25 UTC

[37/50] nifi git commit: NIFI-4436: - Code clean up. - Improved error handling. - Minor UX improvements. - Adding message to indicate that variables do not support sensitive values. - Preventing a user from changing the flow version to the current versio

NIFI-4436:
- Code clean up.
- Improved error handling.
- Minor UX improvements.
- Adding message to indicate that variables do not support sensitive values.
- Preventing a user from changing the flow version to the current version.
- Only presenting buckets a user has appropriate permissions to.
- Adding basic auditing to the version control actions.


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/db2cc9fe
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/db2cc9fe
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/db2cc9fe

Branch: refs/heads/master
Commit: db2cc9fec1ca3ad4382f8dee25ce9790ad53c1f7
Parents: 014c542
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Dec 6 10:47:28 2017 -0500
Committer: Bryan Bende <bb...@apache.org>
Committed: Mon Jan 8 12:44:55 2018 -0500

----------------------------------------------------------------------
 .../java/org/apache/nifi/action/Operation.java  |  44 ++++---
 .../nifi/admin/dao/impl/StandardActionDAO.java  |   4 +-
 .../nifi/web/api/entity/BucketEntity.java       |  18 +++
 .../nifi/web/api/entity/RegistriesEntity.java   |   4 +-
 .../web/api/entity/RegistryClientEntity.java    |  38 ++++++
 .../web/api/entity/RegistryClientsEntity.java   |  41 +++++++
 .../nifi/web/api/entity/RegistryEntity.java     |  13 +--
 .../apache/nifi/audit/ProcessGroupAuditor.java  | 117 +++++++++++++++----
 .../org/apache/nifi/web/NiFiServiceFacade.java  |  27 ++---
 .../nifi/web/StandardNiFiServiceFacade.java     |  87 ++++++--------
 .../apache/nifi/web/api/ControllerResource.java |  62 +++++-----
 .../org/apache/nifi/web/api/FlowResource.java   |   3 +-
 .../apache/nifi/web/api/VersionsResource.java   |  13 ++-
 .../org/apache/nifi/web/api/dto/DtoFactory.java |   4 +-
 .../apache/nifi/web/api/dto/EntityFactory.java  |  42 +++++++
 .../apache/nifi/web/dao/ProcessGroupDAO.java    |   8 +-
 .../nifi/web/dao/impl/FlowRegistryDAO.java      |   7 +-
 .../web/dao/impl/StandardProcessGroupDAO.java   |  10 +-
 .../partials/canvas/variable-configuration.jsp  |   1 +
 .../main/webapp/WEB-INF/partials/ok-dialog.jsp  |   2 +-
 .../nifi-web-ui/src/main/webapp/css/dialog.css  |   7 ++
 .../webapp/js/jquery/modal/jquery.modal.css     |   9 ++
 .../src/main/webapp/js/nf/canvas/nf-actions.js  |   2 +-
 .../main/webapp/js/nf/canvas/nf-flow-version.js | 110 ++++++++++++-----
 .../webapp/js/nf/canvas/nf-process-group.js     |  32 +++--
 25 files changed, 502 insertions(+), 203 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-api/src/main/java/org/apache/nifi/action/Operation.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/action/Operation.java b/nifi-api/src/main/java/org/apache/nifi/action/Operation.java
index 0d5072c..99b9495 100644
--- a/nifi-api/src/main/java/org/apache/nifi/action/Operation.java
+++ b/nifi-api/src/main/java/org/apache/nifi/action/Operation.java
@@ -21,18 +21,34 @@ package org.apache.nifi.action;
  */
 public enum Operation {
 
-    Add,
-    Remove,
-    Paste,
-    Configure,
-    Move,
-    Disconnect,
-    Connect,
-    Start,
-    Stop,
-    Enable,
-    Disable,
-    Batch,
-    Purge,
-    ClearState;
+    Add("Add"),
+    Remove("Remove"),
+    Paste("Paste"),
+    Configure("Configure"),
+    Move("Move"),
+    Disconnect("Disconnect"),
+    Connect("Connect"),
+    Start("Start"),
+    Stop("Stop"),
+    Enable("Enable"),
+    Disable("Disable"),
+    Batch("Batch"),
+    Purge("Purge"),
+    ClearState("Clear State"),
+    StartVersionControl("Start Version Control"),
+    StopVersionControl("Stop Version Control"),
+    CommitLocalChanges("Commit Local Changes"),
+    RevertLocalChanges("Revert Local Changes"),
+    ChangeVersion("Change Version");
+
+    private final String label;
+
+    Operation(String label) {
+        this.label = label;
+    }
+
+    @Override
+    public String toString() {
+        return label;
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
index df1774c..1b79b18 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
@@ -219,8 +219,8 @@ public class StandardActionDAO implements ActionDAO {
             statement.setString(1, StringUtils.left(action.getUserIdentity(), 4096));
             statement.setString(2, action.getSourceId());
             statement.setString(3, StringUtils.left(action.getSourceName(), 1000));
-            statement.setString(4, action.getSourceType().toString());
-            statement.setString(5, action.getOperation().toString());
+            statement.setString(4, action.getSourceType().name());
+            statement.setString(5, action.getOperation().name());
             statement.setTimestamp(6, new java.sql.Timestamp(action.getTimestamp().getTime()));
 
             // insert the action

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/BucketEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/BucketEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/BucketEntity.java
index 3d99308..486fdf7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/BucketEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/BucketEntity.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.web.api.entity;
 
 import org.apache.nifi.web.api.dto.BucketDTO;
+import org.apache.nifi.web.api.dto.PermissionsDTO;
 
 import javax.xml.bind.annotation.XmlRootElement;
 
@@ -26,8 +27,17 @@ import javax.xml.bind.annotation.XmlRootElement;
 @XmlRootElement(name = "bucketEntity")
 public class BucketEntity extends Entity {
 
+    private String id;
     private BucketDTO bucket;
+    private PermissionsDTO permissions;
 
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
 
     public BucketDTO getBucket() {
         return bucket;
@@ -36,4 +46,12 @@ public class BucketEntity extends Entity {
     public void setBucket(BucketDTO bucket) {
         this.bucket = bucket;
     }
+
+    public PermissionsDTO getPermissions() {
+        return permissions;
+    }
+
+    public void setPermissions(PermissionsDTO permissions) {
+        this.permissions = permissions;
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistriesEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistriesEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistriesEntity.java
index 6705c7a..26754bd 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistriesEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistriesEntity.java
@@ -22,13 +22,13 @@ import java.util.Set;
 /**
  * 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 set of RegistryEntity's.
  */
-@XmlRootElement(name = "registriesEntity")
+@XmlRootElement(name = "registryClientsEntity")
 public class RegistriesEntity extends Entity {
 
     private Set<RegistryEntity> registries;
 
     /**
-     * @return collection of LabelEntity's that are being serialized
+     * @return collection of RegistryEntity's that are being serialized
      */
     public Set<RegistryEntity> getRegistries() {
         return registries;

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientEntity.java
new file mode 100644
index 0000000..3b16067
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientEntity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.RegistryDTO;
+
+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 RegistryDTO.
+ */
+@XmlRootElement(name = "registryClientEntity")
+public class RegistryClientEntity extends ComponentEntity {
+
+    private RegistryDTO component;
+
+    public RegistryDTO getComponent() {
+        return component;
+    }
+
+    public void setComponent(RegistryDTO component) {
+        this.component = component;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientsEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientsEntity.java
new file mode 100644
index 0000000..9d6b849
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryClientsEntity.java
@@ -0,0 +1,41 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlRootElement;
+import java.util.Set;
+
+/**
+ * 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 set of RegistryClientEntity's.
+ */
+@XmlRootElement(name = "registryClientsEntity")
+public class RegistryClientsEntity extends Entity {
+
+    private Set<RegistryClientEntity> registries;
+
+    /**
+     * @return collection of RegistryClientEntity's that are being serialized
+     */
+    public Set<RegistryClientEntity> getRegistries() {
+        return registries;
+    }
+
+    public void setRegistries(Set<RegistryClientEntity> registries) {
+        this.registries = registries;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryEntity.java
index 5968579..33ac3b1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/RegistryEntity.java
@@ -24,16 +24,15 @@ 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 RegistryDTO.
  */
 @XmlRootElement(name = "registryEntity")
-public class RegistryEntity extends ComponentEntity {
+public class RegistryEntity {
 
-    private RegistryDTO component;
+    private RegistryDTO registry;
 
-
-    public RegistryDTO getComponent() {
-        return component;
+    public RegistryDTO getRegistry() {
+        return registry;
     }
 
-    public void setComponent(RegistryDTO component) {
-        this.component = component;
+    public void setRegistry(RegistryDTO registry) {
+        this.registry = registry;
     }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java
----------------------------------------------------------------------
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 22ad122..363e049 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
@@ -28,7 +28,10 @@ import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.controller.ScheduledState;
 import org.apache.nifi.controller.service.ControllerServiceState;
 import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.registry.flow.VersionControlInformation;
 import org.apache.nifi.web.api.dto.ProcessGroupDTO;
+import org.apache.nifi.web.api.dto.VariableRegistryDTO;
+import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
 import org.apache.nifi.web.dao.ProcessGroupDAO;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
@@ -39,6 +42,7 @@ import org.slf4j.LoggerFactory;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
+import java.util.concurrent.Future;
 
 /**
  * Audits process group creation/removal and configuration changes.
@@ -173,10 +177,13 @@ public class ProcessGroupAuditor extends NiFiAuditor {
      * @throws Throwable ex
      */
     @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
-        + "execution(void scheduleComponents(java.lang.String, org.apache.nifi.controller.ScheduledState, java.util.Set)) && "
+        + "execution(java.util.concurrent.Future<Void> scheduleComponents(java.lang.String, org.apache.nifi.controller.ScheduledState, java.util.Set)) && "
         + "args(groupId, state)")
-    public void scheduleComponentsAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ScheduledState state) throws Throwable {
+    public Future<Void> scheduleComponentsAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ScheduledState state) throws Throwable {
         final Operation operation;
+
+        final Future<Void> result = (Future<Void>) proceedingJoinPoint.proceed();
+
         // determine the running state
         if (ScheduledState.RUNNING.equals(state)) {
             operation = Operation.Start;
@@ -184,7 +191,9 @@ public class ProcessGroupAuditor extends NiFiAuditor {
             operation = Operation.Stop;
         }
 
-        saveUpdateAction(proceedingJoinPoint, groupId, operation);
+        saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, operation);
+
+        return result;
     }
 
 
@@ -193,51 +202,117 @@ public class ProcessGroupAuditor extends NiFiAuditor {
      *
      * @param proceedingJoinPoint join point
      * @param groupId group id
-     * @param state controller serivce state state
+     * @param state controller service state
      * @throws Throwable ex
      */
     @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
-        + "execution(java.util.concurrent.Future activateControllerServices(java.lang.String, org.apache.nifi.controller.service.ControllerServiceState, java.util.Set)) && "
+        + "execution(java.util.concurrent.Future<Void> activateControllerServices(java.lang.String, org.apache.nifi.controller.service.ControllerServiceState, java.util.Set)) && "
         + "args(groupId, state)")
-    public void activateControllerServicesAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ControllerServiceState state) throws Throwable {
+    public Future<Void> activateControllerServicesAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ControllerServiceState state) throws Throwable {
+        final Operation operation;
+
+        final Future<Void> result = (Future<Void>) proceedingJoinPoint.proceed();
 
         // determine the service state
-        final Operation operation;
         if (ControllerServiceState.ENABLED.equals(state)) {
             operation = Operation.Enable;
         } else {
             operation = Operation.Disable;
         }
 
-        saveUpdateAction(proceedingJoinPoint, groupId, operation);
+        saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, operation);
+
+        return result;
     }
 
     /**
      * Audits the update of process group variable registry.
      *
      * @param proceedingJoinPoint join point
-     * @param groupId group id
+     * @param user the user performing the action
+     * @param variableRegistry variable registry
      * @throws Throwable ex
      */
     @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
-        + "execution(org.apache.nifi.groups.ProcessGroup updateVariableRegistry(org.apache.nifi.web.api.dto.VariableRegistryDTO)) && "
-        + "args(groupId)")
-    public void updateVariableRegistryAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId) throws Throwable {
-        final Operation operation = Operation.Configure;
-        saveUpdateAction(proceedingJoinPoint, groupId, operation);
+        + "execution(org.apache.nifi.groups.ProcessGroup updateVariableRegistry(org.apache.nifi.authorization.user.NiFiUser, org.apache.nifi.web.api.dto.VariableRegistryDTO)) && "
+        + "args(user, variableRegistry)")
+    public ProcessGroup updateVariableRegistryAdvice(final ProceedingJoinPoint proceedingJoinPoint, final NiFiUser user, final VariableRegistryDTO variableRegistry) throws Throwable {
+        final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
+
+        saveUpdateAction(user, variableRegistry.getProcessGroupId(), Operation.Configure);
+
+        return updatedProcessGroup;
     }
 
+    @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+            + "execution(org.apache.nifi.groups.ProcessGroup updateProcessGroupFlow(..))")
+    public ProcessGroup updateProcessGroupFlowAdvice(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+        final Object[] args = proceedingJoinPoint.getArgs();
+        final String groupId = (String) args[0];
+        final NiFiUser user = (NiFiUser) args[1];
 
+        final ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
+        final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
+        final VersionControlInformation vci = processGroup.getVersionControlInformation();
 
-    private void saveUpdateAction(final ProceedingJoinPoint proceedingJoinPoint, final String groupId, final Operation operation) throws Throwable {
-        ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
-        ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
+        final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
+        final VersionControlInformation updatedVci = updatedProcessGroup.getVersionControlInformation();
 
-        // perform the action
-        proceedingJoinPoint.proceed();
+        final Operation operation;
+        if (vci == null) {
+            operation = Operation.StartVersionControl;
+        } else {
+            if (updatedVci == null) {
+                operation = Operation.StopVersionControl;
+            } else if (vci.getVersion() == updatedVci.getVersion()) {
+                operation = Operation.RevertLocalChanges;
+            } else {
+                operation = Operation.ChangeVersion;
+            }
+        }
 
-        // get the current user
-        NiFiUser user = NiFiUserUtils.getNiFiUser();
+        saveUpdateAction(user, groupId, operation);
+
+        return updatedProcessGroup;
+    }
+
+    @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+            + "execution(org.apache.nifi.groups.ProcessGroup updateVersionControlInformation(..))")
+    public ProcessGroup updateVersionControlInformationAdvice(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+        final VersionControlInformationDTO vciDto = (VersionControlInformationDTO) proceedingJoinPoint.getArgs()[0];
+
+        final ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
+        final ProcessGroup processGroup = processGroupDAO.getProcessGroup(vciDto.getGroupId());
+        final VersionControlInformation vci = processGroup.getVersionControlInformation();
+
+        final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
+
+        final Operation operation;
+        if (vci == null) {
+            operation = Operation.StartVersionControl;
+        } else {
+            operation = Operation.CommitLocalChanges;
+        }
+
+        saveUpdateAction(NiFiUserUtils.getNiFiUser(), vciDto.getGroupId(), operation);
+
+        return updatedProcessGroup;
+    }
+
+    @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+            + "execution(org.apache.nifi.groups.ProcessGroup disconnectVersionControl(java.lang.String)) && "
+            + "args(groupId)")
+    public ProcessGroup disconnectVersionControlAdvice(final ProceedingJoinPoint proceedingJoinPoint, final String groupId) throws Throwable {
+        final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
+
+        saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, Operation.StopVersionControl);
+
+        return updatedProcessGroup;
+    }
+
+    private void saveUpdateAction(final NiFiUser user, final String groupId, final Operation operation) throws Throwable {
+        ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
+        ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
 
         // if the user was starting/stopping this process group
         FlowChangeAction action = new FlowChangeAction();

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
----------------------------------------------------------------------
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 be77d10..78335f4 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
@@ -16,14 +16,6 @@
  */
 package org.apache.nifi.web;
 
-import java.io.IOException;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-
 import org.apache.nifi.authorization.AuthorizeAccess;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.user.NiFiUser;
@@ -106,6 +98,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
 import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
 import org.apache.nifi.web.api.entity.ProcessorEntity;
 import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
+import org.apache.nifi.web.api.entity.RegistryClientEntity;
 import org.apache.nifi.web.api.entity.RegistryEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
@@ -124,6 +117,14 @@ import org.apache.nifi.web.api.entity.VersionControlInformationEntity;
 import org.apache.nifi.web.api.entity.VersionedFlowEntity;
 import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataEntity;
 
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+
 /**
  * Defines the NiFiServiceFacade interface.
  */
@@ -1929,7 +1930,7 @@ public interface NiFiServiceFacade {
      * @param registryDTO The registry DTO
      * @return The reporting task DTO
      */
-    RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO);
+    RegistryClientEntity createRegistryClient(Revision revision, RegistryDTO registryDTO);
 
     /**
      * Gets a registry with the specified id.
@@ -1937,14 +1938,14 @@ public interface NiFiServiceFacade {
      * @param registryId id
      * @return entity
      */
-    RegistryEntity getRegistryClient(String registryId);
+    RegistryClientEntity getRegistryClient(String registryId);
 
     /**
      * Returns all registry clients.
      *
      * @return registry clients
      */
-    Set<RegistryEntity> getRegistryClients();
+    Set<RegistryClientEntity> getRegistryClients();
 
     /**
      * Gets all registries for the current user.
@@ -1991,7 +1992,7 @@ public interface NiFiServiceFacade {
      * @param registryDTO the registry dto
      * @return the updated registry registry entity
      */
-    RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO);
+    RegistryClientEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO);
 
     /**
      * Deletes the specified registry using the specified revision.
@@ -2000,7 +2001,7 @@ public interface NiFiServiceFacade {
      * @param registryId id
      * @return the deleted registry entity
      */
-    RegistryEntity deleteRegistryClient(Revision revision, String registryId);
+    RegistryClientEntity deleteRegistryClient(Revision revision, String registryId);
 
     /**
      * Verifies the specified registry can be removed.

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
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 4adb85b..ae89ef0 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
@@ -220,6 +220,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
 import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
 import org.apache.nifi.web.api.entity.ProcessorEntity;
 import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
+import org.apache.nifi.web.api.entity.RegistryClientEntity;
 import org.apache.nifi.web.api.entity.RegistryEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
@@ -927,7 +928,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(variableRegistryDto.getProcessGroupId());
         final RevisionUpdate<VariableRegistryDTO> snapshot = updateComponent(user, revision,
             processGroupNode,
-            () -> processGroupDAO.updateVariableRegistry(variableRegistryDto),
+            () -> processGroupDAO.updateVariableRegistry(user, variableRegistryDto),
             processGroup -> dtoFactory.createVariableRegistryDto(processGroup, revisionManager));
 
         final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode);
@@ -2301,10 +2302,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
 
 
     @Override
-    public RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) {
+    public RegistryClientEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) {
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
-        // read lock on the containing group
         // request claim for component to be created... revision already verified (version == 0)
         final RevisionClaim claim = new StandardRevisionClaim(revision);
 
@@ -2321,52 +2321,25 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         });
 
         final FlowRegistry registry = revisionUpdate.getComponent();
-        return createRegistryEntity(registry);
+        return createRegistryClientEntity(registry);
     }
 
     @Override
-    public RegistryEntity getRegistryClient(final String registryId) {
+    public RegistryClientEntity getRegistryClient(final String registryId) {
         final FlowRegistry registry = registryDAO.getFlowRegistry(registryId);
-        return createRegistryEntity(registry);
+        return createRegistryClientEntity(registry);
     }
 
-    private RegistryEntity createRegistryEntity(final FlowRegistry flowRegistry) {
+    private RegistryClientEntity createRegistryClientEntity(final FlowRegistry flowRegistry) {
         if (flowRegistry == null) {
             return null;
         }
 
+        final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(flowRegistry.getIdentifier()));
+        final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getController());
         final RegistryDTO dto = dtoFactory.createRegistryDto(flowRegistry);
-        final Revision revision = revisionManager.getRevision(dto.getId());
-
-        final RegistryEntity entity = new RegistryEntity();
-        entity.setComponent(dto);
-        entity.setRevision(dtoFactory.createRevisionDTO(revision));
-        entity.setId(dto.getId());
 
-        // User who created it can read/write it.
-        final PermissionsDTO permissions = new PermissionsDTO();
-        permissions.setCanRead(true);
-        permissions.setCanWrite(true);
-        entity.setPermissions(permissions);
-
-        return entity;
-    }
-
-    private BucketEntity createBucketEntity(final Bucket bucket) {
-        if (bucket == null) {
-            return null;
-        }
-
-        final BucketDTO dto = new BucketDTO();
-        dto.setId(bucket.getIdentifier());
-        dto.setName(bucket.getName());
-        dto.setDescription(bucket.getDescription());
-        dto.setCreated(bucket.getCreatedTimestamp());
-
-        final BucketEntity entity = new BucketEntity();
-        entity.setBucket(dto);
-
-        return entity;
+        return entityFactory.createRegistryClientEntity(dto, revision, permissions);
     }
 
     private VersionedFlowEntity createVersionedFlowEntity(final String registryId, final VersionedFlow versionedFlow) {
@@ -2400,23 +2373,40 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     }
 
     @Override
-    public Set<RegistryEntity> getRegistryClients() {
+    public Set<RegistryClientEntity> getRegistryClients() {
         return registryDAO.getFlowRegistries().stream()
-            .map(this::createRegistryEntity)
+            .map(this::createRegistryClientEntity)
             .collect(Collectors.toSet());
     }
 
     @Override
     public Set<RegistryEntity> getRegistriesForUser(final NiFiUser user) {
         return registryDAO.getFlowRegistriesForUser(user).stream()
-                .map(this::createRegistryEntity)
+                .map(flowRegistry -> entityFactory.createRegistryEntity(dtoFactory.createRegistryDto(flowRegistry)))
                 .collect(Collectors.toSet());
     }
 
     @Override
     public Set<BucketEntity> getBucketsForUser(final String registryId, final NiFiUser user) {
         return registryDAO.getBucketsForUser(registryId, user).stream()
-                .map(this::createBucketEntity)
+                .map(bucket -> {
+                    if (bucket == null) {
+                        return null;
+                    }
+
+                    final BucketDTO dto = new BucketDTO();
+                    dto.setId(bucket.getIdentifier());
+                    dto.setName(bucket.getName());
+                    dto.setDescription(bucket.getDescription());
+                    dto.setCreated(bucket.getCreatedTimestamp());
+
+                    final Set<String> authorizedActions = bucket.getAuthorizedActions();
+                    final PermissionsDTO permissions = new PermissionsDTO();
+                    permissions.setCanRead(authorizedActions.contains("read"));
+                    permissions.setCanWrite(authorizedActions.contains("write"));
+
+                    return entityFactory.createBucketEntity(dto, permissions);
+                })
                 .collect(Collectors.toSet());
     }
 
@@ -2435,7 +2425,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     }
 
     @Override
-    public RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) {
+    public RegistryClientEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) {
         final RevisionClaim revisionClaim = new StandardRevisionClaim(revision);
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
@@ -2454,7 +2444,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         });
 
         final FlowRegistry updatedReg = revisionUpdate.getComponent();
-        return createRegistryEntity(updatedReg);
+        return createRegistryClientEntity(updatedReg);
     }
 
     @Override
@@ -2463,7 +2453,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     }
 
     @Override
-    public RegistryEntity deleteRegistryClient(final Revision revision, final String registryId) {
+    public RegistryClientEntity deleteRegistryClient(final Revision revision, final String registryId) {
         final RevisionClaim claim = new StandardRevisionClaim(revision);
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
@@ -2473,7 +2463,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
             return reg;
         });
 
-        return createRegistryEntity(registry);
+        return createRegistryClientEntity(registry);
     }
 
     @Override
@@ -3695,10 +3685,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
             // add first snapshot to the flow in the registry
             registeredSnapshot = registerVersionedFlowSnapshot(registryId, registeredFlow, versionedProcessGroup, versionedFlowDto.getComments(), expectedVersion);
         } catch (final NiFiRegistryException e) {
-            throw new IllegalArgumentException(e);
+            throw new IllegalArgumentException(e.getLocalizedMessage());
         } catch (final IOException ioe) {
-            // will result in a 500: Internal Server Error
-            throw new RuntimeException("Failed to communicate with Flow Registry when attempting to " + action);
+            throw new IllegalStateException("Failed to communicate with Flow Registry when attempting to " + action);
         }
 
         final Bucket bucket = registeredSnapshot.getBucket();
@@ -4105,7 +4094,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(groupId);
         final RevisionUpdate<ProcessGroupDTO> snapshot = updateComponent(user, revision,
             processGroupNode,
-            () -> processGroupDAO.updateProcessGroupFlow(groupId, proposedFlowSnapshot, versionControlInfo, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows),
+            () -> processGroupDAO.updateProcessGroupFlow(groupId, user, proposedFlowSnapshot, versionControlInfo, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows),
             processGroup -> dtoFactory.createProcessGroupDto(processGroup));
 
         final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode);

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
----------------------------------------------------------------------
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 356d231..04c0efa 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
@@ -46,8 +46,8 @@ import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.Entity;
 import org.apache.nifi.web.api.entity.HistoryEntity;
 import org.apache.nifi.web.api.entity.NodeEntity;
-import org.apache.nifi.web.api.entity.RegistriesEntity;
-import org.apache.nifi.web.api.entity.RegistryEntity;
+import org.apache.nifi.web.api.entity.RegistryClientsEntity;
+import org.apache.nifi.web.api.entity.RegistryClientEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
 import org.apache.nifi.web.api.request.ClientIdParameter;
 import org.apache.nifi.web.api.request.DateTimeParameter;
@@ -91,12 +91,12 @@ public class ControllerResource extends ApplicationResource {
     /**
      * Populate the uri's for the specified registry.
      *
-     * @param registryEntity registry
+     * @param registryClientEntity registry
      * @return dtos
      */
-    public RegistryEntity populateRemainingRegistryEntityContent(final RegistryEntity registryEntity) {
-        registryEntity.setUri(generateResourceUri("controller", "registry-clients", registryEntity.getId()));
-        return registryEntity;
+    public RegistryClientEntity populateRemainingRegistryEntityContent(final RegistryClientEntity registryClientEntity) {
+        registryClientEntity.setUri(generateResourceUri("controller", "registry-clients", registryClientEntity.getId()));
+        return registryClientEntity;
     }
 
     /**
@@ -316,7 +316,7 @@ public class ControllerResource extends ApplicationResource {
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
     @Path("registry-clients")
-    @ApiOperation(value = "Gets the listing of available registry clients", response = RegistriesEntity.class, authorizations = {
+    @ApiOperation(value = "Gets the listing of available registry clients", response = RegistryClientsEntity.class, authorizations = {
             @Authorization(value = "Read - /flow")
     })
     @ApiResponses(value = {
@@ -333,10 +333,10 @@ public class ControllerResource extends ApplicationResource {
             return replicate(HttpMethod.GET);
         }
 
-        final Set<RegistryEntity> registries = serviceFacade.getRegistryClients();
+        final Set<RegistryClientEntity> registries = serviceFacade.getRegistryClients();
         registries.forEach(registry -> populateRemainingRegistryEntityContent(registry));
 
-        final RegistriesEntity registryEntities = new RegistriesEntity();
+        final RegistryClientsEntity registryEntities = new RegistryClientsEntity();
         registryEntities.setRegistries(registries);
 
         return generateOkResponse(registryEntities).build();
@@ -346,8 +346,8 @@ public class ControllerResource extends ApplicationResource {
      * Creates a new Registry.
      *
      * @param httpServletRequest  request
-     * @param requestRegistryEntity A registryEntity.
-     * @return A registryEntity.
+     * @param requestRegistryClientEntity A registryClientEntity.
+     * @return A registryClientEntity.
      */
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
@@ -355,7 +355,7 @@ public class ControllerResource extends ApplicationResource {
     @Path("registry-clients")
     @ApiOperation(
             value = "Creates a new registry client",
-            response = RegistryEntity.class,
+            response = RegistryClientEntity.class,
             authorizations = {
                     @Authorization(value = "Write - /controller")
             }
@@ -373,28 +373,28 @@ public class ControllerResource extends ApplicationResource {
             @ApiParam(
                     value = "The registry configuration details.",
                     required = true
-            ) final RegistryEntity requestRegistryEntity) {
+            ) final RegistryClientEntity requestRegistryClientEntity) {
 
-        if (requestRegistryEntity == null || requestRegistryEntity.getComponent() == null) {
+        if (requestRegistryClientEntity == null || requestRegistryClientEntity.getComponent() == null) {
             throw new IllegalArgumentException("Registry details must be specified.");
         }
 
-        if (requestRegistryEntity.getRevision() == null || (requestRegistryEntity.getRevision().getVersion() == null || requestRegistryEntity.getRevision().getVersion() != 0)) {
+        if (requestRegistryClientEntity.getRevision() == null || (requestRegistryClientEntity.getRevision().getVersion() == null || requestRegistryClientEntity.getRevision().getVersion() != 0)) {
             throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Registry.");
         }
 
-        final RegistryDTO requestReportingTask = requestRegistryEntity.getComponent();
+        final RegistryDTO requestReportingTask = requestRegistryClientEntity.getComponent();
         if (requestReportingTask.getId() != null) {
             throw new IllegalArgumentException("Registry ID cannot be specified.");
         }
 
         if (isReplicateRequest()) {
-            return replicate(HttpMethod.POST, requestRegistryEntity);
+            return replicate(HttpMethod.POST, requestRegistryClientEntity);
         }
 
         return withWriteLock(
                 serviceFacade,
-                requestRegistryEntity,
+                requestRegistryClientEntity,
                 lookup -> {
                     authorizeController(RequestAction.WRITE);
                 },
@@ -407,7 +407,7 @@ public class ControllerResource extends ApplicationResource {
 
                     // create the reporting task and generate the json
                     final Revision revision = getRevision(registryEntity, registry.getId());
-                    final RegistryEntity entity = serviceFacade.createRegistryClient(revision, registry);
+                    final RegistryClientEntity entity = serviceFacade.createRegistryClient(revision, registry);
                     populateRemainingRegistryEntityContent(entity);
 
                     // build the response
@@ -420,7 +420,7 @@ public class ControllerResource extends ApplicationResource {
      * Retrieves the specified registry.
      *
      * @param id The id of the registry to retrieve
-     * @return A registryEntity.
+     * @return A registryClientEntity.
      */
     @GET
     @Consumes(MediaType.WILDCARD)
@@ -428,7 +428,7 @@ public class ControllerResource extends ApplicationResource {
     @Path("/registry-clients/{id}")
     @ApiOperation(
             value = "Gets a registry client",
-            response = RegistryEntity.class,
+            response = RegistryClientEntity.class,
             authorizations = {
                     @Authorization(value = "Read - /controller")
             }
@@ -442,7 +442,7 @@ public class ControllerResource extends ApplicationResource {
                     @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 getRegistry(
+    public Response getRegistryClient(
             @ApiParam(
                     value = "The registry id.",
                     required = true
@@ -457,7 +457,7 @@ public class ControllerResource extends ApplicationResource {
         authorizeController(RequestAction.READ);
 
         // get the registry
-        final RegistryEntity entity = serviceFacade.getRegistryClient(id);
+        final RegistryClientEntity entity = serviceFacade.getRegistryClient(id);
         populateRemainingRegistryEntityContent(entity);
 
         return generateOkResponse(entity).build();
@@ -477,7 +477,7 @@ public class ControllerResource extends ApplicationResource {
     @Path("/registry-clients/{id}")
     @ApiOperation(
             value = "Updates a registry client",
-            response = RegistryEntity.class,
+            response = RegistryClientEntity.class,
             authorizations = {
                     @Authorization(value = "Write - /controller")
             }
@@ -501,7 +501,7 @@ public class ControllerResource extends ApplicationResource {
             @ApiParam(
                     value = "The registry configuration details.",
                     required = true
-            ) final RegistryEntity requestRegsitryEntity) {
+            ) final RegistryClientEntity requestRegsitryEntity) {
 
         if (requestRegsitryEntity == null || requestRegsitryEntity.getComponent() == null) {
             throw new IllegalArgumentException("Registry details must be specified.");
@@ -536,7 +536,7 @@ public class ControllerResource extends ApplicationResource {
                     final RegistryDTO registry = registryEntity.getComponent();
 
                     // update the controller service
-                    final RegistryEntity entity = serviceFacade.updateRegistryClient(revision, registry);
+                    final RegistryClientEntity entity = serviceFacade.updateRegistryClient(revision, registry);
                     populateRemainingRegistryEntityContent(entity);
 
                     return generateOkResponse(entity).build();
@@ -562,7 +562,7 @@ public class ControllerResource extends ApplicationResource {
     @Path("/registry-clients/{id}")
     @ApiOperation(
             value = "Deletes a registry client",
-            response = RegistryEntity.class,
+            response = RegistryClientEntity.class,
             authorizations = {
                     @Authorization(value = "Write - /controller")
             }
@@ -598,14 +598,14 @@ public class ControllerResource extends ApplicationResource {
             return replicate(HttpMethod.DELETE);
         }
 
-        final RegistryEntity requestRegistryEntity = new RegistryEntity();
-        requestRegistryEntity.setId(id);
+        final RegistryClientEntity requestRegistryClientEntity = new RegistryClientEntity();
+        requestRegistryClientEntity.setId(id);
 
         // handle expects request (usually from the cluster manager)
         final Revision requestRevision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
         return withWriteLock(
                 serviceFacade,
-                requestRegistryEntity,
+                requestRegistryClientEntity,
                 requestRevision,
                 lookup -> {
                     authorizeController(RequestAction.WRITE);
@@ -613,7 +613,7 @@ public class ControllerResource extends ApplicationResource {
                 () -> serviceFacade.verifyDeleteRegistry(id),
                 (revision, registryEntity) -> {
                     // delete the specified registry
-                    final RegistryEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId());
+                    final RegistryClientEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId());
                     return generateOkResponse(entity).build();
                 }
         );

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
----------------------------------------------------------------------
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 0ae5864..dad8039 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
@@ -88,6 +88,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
 import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
 import org.apache.nifi.web.api.entity.ProcessorTypesEntity;
 import org.apache.nifi.web.api.entity.RegistriesEntity;
+import org.apache.nifi.web.api.entity.RegistryClientsEntity;
 import org.apache.nifi.web.api.entity.RegistryEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
@@ -1316,7 +1317,7 @@ public class FlowResource extends ApplicationResource {
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
     @Path("registries")
-    @ApiOperation(value = "Gets the listing of available registries", response = RegistriesEntity.class, authorizations = {
+    @ApiOperation(value = "Gets the listing of available registries", response = RegistryClientsEntity.class, authorizations = {
             @Authorization(value = "Read - /flow")
     })
     @ApiResponses(value = {

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java
index 6dd641b..5dc7325 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/VersionsResource.java
@@ -183,7 +183,7 @@ public class VersionsResource extends ApplicationResource {
         @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 createVersionControlRequest(
-            @ApiParam(value = "The versioned flow details.", required = true) final CreateActiveRequestEntity requestEntity) throws InterruptedException {
+            @ApiParam(value = "The versioned flow details.", required = true) final CreateActiveRequestEntity requestEntity) {
 
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST);
@@ -412,7 +412,7 @@ public class VersionsResource extends ApplicationResource {
     })
     public Response saveToFlowRegistry(
         @ApiParam("The process group id.") @PathParam("id") final String groupId,
-        @ApiParam(value = "The versioned flow details.", required = true) final StartVersionControlRequestEntity requestEntity) throws IOException {
+        @ApiParam(value = "The versioned flow details.", required = true) final StartVersionControlRequestEntity requestEntity) {
 
         // Verify the request
         final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();
@@ -569,8 +569,9 @@ public class VersionsResource extends ApplicationResource {
         return requestId;
     }
 
-    private void replicateVersionControlMapping(final VersionControlComponentMappingEntity mappingEntity, final StartVersionControlRequestEntity requestEntity, final URI requestUri,
-        final String groupId) {
+    private void replicateVersionControlMapping(final VersionControlComponentMappingEntity mappingEntity, final StartVersionControlRequestEntity requestEntity,
+                                                final URI requestUri, final String groupId) {
+
         final Map<String, String> headers = new HashMap<>();
         headers.put("content-type", MediaType.APPLICATION_JSON);
 
@@ -652,7 +653,7 @@ public class VersionsResource extends ApplicationResource {
                 value = "If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response.",
                 required = false)
         @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
-        @ApiParam("The process group id.") @PathParam("id") final String groupId) throws IOException {
+        @ApiParam("The process group id.") @PathParam("id") final String groupId) {
 
         if (isReplicateRequest()) {
             return replicate(HttpMethod.DELETE);
@@ -705,7 +706,7 @@ public class VersionsResource extends ApplicationResource {
         @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 updateFlowVersion(@ApiParam("The process group id.") @PathParam("id") final String groupId,
-        @ApiParam(value = "The controller service configuration details.", required = true) final VersionedFlowSnapshotEntity requestEntity) throws IOException, LifecycleManagementException {
+        @ApiParam(value = "The controller service configuration details.", required = true) final VersionedFlowSnapshotEntity requestEntity) {
 
         // Verify the request
         final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
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 7a1442d..ca781a4 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
@@ -272,10 +272,10 @@ public final class DtoFactory {
         actionDto.setId(action.getId());
         actionDto.setSourceId(action.getSourceId());
         actionDto.setSourceName(action.getSourceName());
-        actionDto.setSourceType(action.getSourceType().name());
+        actionDto.setSourceType(action.getSourceType().toString());
         actionDto.setTimestamp(action.getTimestamp());
         actionDto.setUserIdentity(action.getUserIdentity());
-        actionDto.setOperation(action.getOperation().name());
+        actionDto.setOperation(action.getOperation().toString());
         actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails()));
         actionDto.setComponentDetails(createComponentDetailsDto(action.getComponentDetails()));
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/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-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
index 1e6167c..34f4997 100644
--- 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
@@ -35,6 +35,7 @@ import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity;
 import org.apache.nifi.web.api.entity.ActionEntity;
 import org.apache.nifi.web.api.entity.AffectedComponentEntity;
 import org.apache.nifi.web.api.entity.AllowableValueEntity;
+import org.apache.nifi.web.api.entity.BucketEntity;
 import org.apache.nifi.web.api.entity.BulletinEntity;
 import org.apache.nifi.web.api.entity.ComponentReferenceEntity;
 import org.apache.nifi.web.api.entity.ConnectionEntity;
@@ -56,6 +57,8 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
 import org.apache.nifi.web.api.entity.ProcessorEntity;
 import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
 import org.apache.nifi.web.api.entity.ProcessorStatusSnapshotEntity;
+import org.apache.nifi.web.api.entity.RegistryClientEntity;
+import org.apache.nifi.web.api.entity.RegistryEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
@@ -546,4 +549,43 @@ public final class EntityFactory {
         entity.setProcessGroupRevision(processGroupRevision);
         return entity;
     }
+
+    public RegistryClientEntity createRegistryClientEntity(final RegistryDTO dto, final RevisionDTO revision, final PermissionsDTO permissions) {
+        final RegistryClientEntity entity = new RegistryClientEntity();
+        entity.setRevision(revision);
+        entity.setPermissions(permissions);
+
+        if (dto != null) {
+            entity.setId(dto.getId());
+
+            if (permissions != null && permissions.getCanRead()) {
+                entity.setComponent(dto);
+            }
+        }
+
+        return entity;
+    }
+
+    public RegistryEntity createRegistryEntity(final RegistryDTO dto) {
+        final RegistryEntity entity = new RegistryEntity();
+
+        if (dto != null) {
+            entity.setRegistry(dto);
+        }
+
+        return entity;
+    }
+
+    public BucketEntity createBucketEntity(final BucketDTO dto, final PermissionsDTO permissions) {
+        final BucketEntity entity = new BucketEntity();
+        entity.setId(dto.getId());
+        entity.setPermissions(permissions);
+
+        if (permissions != null && permissions.getCanRead()) {
+            entity.setBucket(dto);
+        }
+
+        return entity;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
index 9259bf4..459acfc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ProcessGroupDAO.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.web.dao;
 
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.controller.ScheduledState;
 import org.apache.nifi.controller.service.ControllerServiceState;
 import org.apache.nifi.groups.ProcessGroup;
@@ -118,8 +119,8 @@ public interface ProcessGroupDAO {
      *            update the contents of that Process Group
      * @return the process group
      */
-    ProcessGroup updateProcessGroupFlow(String groupId, VersionedFlowSnapshot proposedSnapshot, VersionControlInformationDTO versionControlInformation, String componentIdSeed,
-        boolean verifyNotModified, boolean updateSettings, boolean updateDescendantVersionedFlows);
+    ProcessGroup updateProcessGroupFlow(String groupId, NiFiUser user, VersionedFlowSnapshot proposedSnapshot, VersionControlInformationDTO versionControlInformation, String componentIdSeed,
+                                        boolean verifyNotModified, boolean updateSettings, boolean updateDescendantVersionedFlows);
 
     /**
      * Applies the given Version Control Information to the Process Group
@@ -141,10 +142,11 @@ public interface ProcessGroupDAO {
     /**
      * Updates the specified variable registry
      *
+     * @param user the user performing the update
      * @param variableRegistry the Variable Registry
      * @return the Process Group that was updated
      */
-    ProcessGroup updateVariableRegistry(VariableRegistryDTO variableRegistry);
+    ProcessGroup updateVariableRegistry(NiFiUser user, VariableRegistryDTO variableRegistry);
 
     /**
      * Verifies that the specified updates to a current Process Group can be applied at this time

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/FlowRegistryDAO.java
----------------------------------------------------------------------
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/FlowRegistryDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/FlowRegistryDAO.java
index 4f5af74..7d3b567 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/FlowRegistryDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/FlowRegistryDAO.java
@@ -17,11 +17,6 @@
 
 package org.apache.nifi.web.dao.impl;
 
-import java.io.IOException;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.registry.bucket.Bucket;
 import org.apache.nifi.registry.client.NiFiRegistryException;
@@ -36,6 +31,7 @@ import org.apache.nifi.web.dao.RegistryDAO;
 
 import java.io.IOException;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.stream.Collectors;
 
 public class FlowRegistryDAO implements RegistryDAO {
@@ -65,7 +61,6 @@ public class FlowRegistryDAO implements RegistryDAO {
 
     @Override
     public Set<FlowRegistry> getFlowRegistriesForUser(final NiFiUser user) {
-        // TODO - implement to be user specific
         return getFlowRegistries();
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
----------------------------------------------------------------------
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/StandardProcessGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
index 1aaf4cc..d25f294 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.web.dao.impl;
 
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Port;
 import org.apache.nifi.connectable.Position;
@@ -143,7 +144,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
     }
 
     @Override
-    public CompletableFuture<Void> scheduleComponents(final String groupId, final ScheduledState state, final Set<String> componentIds) {
+    public Future<Void> scheduleComponents(final String groupId, final ScheduledState state, final Set<String> componentIds) {
         final ProcessGroup group = locateProcessGroup(flowController, groupId);
 
         CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
@@ -275,8 +276,9 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
     }
 
     @Override
-    public ProcessGroup updateProcessGroupFlow(final String groupId, final VersionedFlowSnapshot proposedSnapshot, final VersionControlInformationDTO versionControlInformation,
-        final String componentIdSeed, final boolean verifyNotModified, final boolean updateSettings, final boolean updateDescendantVersionedFlows) {
+    public ProcessGroup updateProcessGroupFlow(final String groupId, final NiFiUser user, final VersionedFlowSnapshot proposedSnapshot, final VersionControlInformationDTO versionControlInformation,
+                                               final String componentIdSeed, final boolean verifyNotModified, final boolean updateSettings, final boolean updateDescendantVersionedFlows) {
+
         final ProcessGroup group = locateProcessGroup(flowController, groupId);
         group.updateFlow(proposedSnapshot, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows);
 
@@ -291,7 +293,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
     }
 
     @Override
-    public ProcessGroup updateVariableRegistry(final VariableRegistryDTO variableRegistry) {
+    public ProcessGroup updateVariableRegistry(final NiFiUser user, final VariableRegistryDTO variableRegistry) {
         final ProcessGroup group = locateProcessGroup(flowController, variableRegistry.getProcessGroupId());
         if (group == null) {
             throw new ResourceNotFoundException("Could not find Process Group with ID " + variableRegistry.getProcessGroupId());

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
index f26c2eb..4bbd9c8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/variable-configuration.jsp
@@ -80,6 +80,7 @@
             </div>
         </div>
     </div>
+    <div id="variable-message">Variables do not support sensitive values and will be included when versioning a Process Group.</div>
 </div>
 <div id="new-variable-dialog" class="dialog cancellable small-dialog hidden">
     <div class="dialog-content">

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/ok-dialog.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/ok-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/ok-dialog.jsp
index 92a3d4a..826a1ff 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/ok-dialog.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/ok-dialog.jsp
@@ -15,7 +15,7 @@
   limitations under the License.
 --%>
 <%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
-<div id="nf-ok-dialog" class="hidden small-dialog">
+<div id="nf-ok-dialog" class="hidden medium-short-dialog">
     <div class="dialog-content">
         <div id="nf-ok-dialog-content"></div>
     </div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
index 9acbdde..710c0fb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
@@ -323,6 +323,13 @@ div.slick-cell div.overridden {
     text-decoration: line-through;
 }
 
+#variable-message {
+    position: absolute;
+    top: 550px;
+    left: 20px;
+    font-size: 13px;
+}
+
 /*
     Registry configuration dialog
  */

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.css
index d998436..32aa8f3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/modal/jquery.modal.css
@@ -43,6 +43,15 @@
     min-width: 470px;
 }
 
+.medium-short-dialog {
+    max-height: 32%;
+    max-width: 34%;
+    min-height: 250px;
+    min-width: 440px;
+    font-size: 13px;
+    line-height: 1.3;
+}
+
 .large-dialog {
     max-height: 72%;
     max-width: 55%;

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
----------------------------------------------------------------------
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 725b6a1..8a17291 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
@@ -920,7 +920,7 @@
         'delete': function (selection) {
             if (nfCommon.isUndefined(selection) || selection.empty()) {
                 nfDialog.showOkDialog({
-                    headerText: 'Reload',
+                    headerText: 'Delete Components',
                     dialogContent: 'No eligible components are selected. Please select the components to be deleted.'
                 });
             } else {

http://git-wip-us.apache.org/repos/asf/nifi/blob/db2cc9fe/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
index 9ef210e..f1b9a45 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-flow-version.js
@@ -180,9 +180,11 @@
      * @param registryCombo
      * @param bucketCombo
      * @param flowCombo
+     * @param selectBucket
+     * @param bucketCheck
      * @returns {deferred}
      */
-    var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket) {
+    var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket, bucketCheck) {
         return $.ajax({
             type: 'GET',
             url: '../nifi-api/flow/registries',
@@ -192,11 +194,11 @@
 
             if (nfCommon.isDefinedAndNotNull(registriesResponse.registries) && registriesResponse.registries.length > 0) {
                 registriesResponse.registries.sort(function (a, b) {
-                    return a.component.name > b.component.name;
+                    return a.registry.name > b.registry.name;
                 });
 
                 $.each(registriesResponse.registries, function (_, registryEntity) {
-                    var registry = registryEntity.component;
+                    var registry = registryEntity.registry;
                     registries.push({
                         text: registry.name,
                         value: registry.id,
@@ -216,7 +218,7 @@
             registryCombo.combo({
                 options: registries,
                 select: function (selectedOption) {
-                    selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket)
+                    selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket, bucketCheck)
                 }
             });
         }).fail(nfErrorHandler.handleAjaxError);
@@ -229,9 +231,10 @@
      * @param bucketCombo
      * @param flowCombo
      * @param selectBucket
+     * @param bucketCheck
      * @returns {*}
      */
-    var loadBuckets = function (registryIdentifier, bucketCombo, flowCombo, selectBucket) {
+    var loadBuckets = function (registryIdentifier, bucketCombo, flowCombo, selectBucket, bucketCheck) {
         return $.ajax({
             type: 'GET',
             url: '../nifi-api/flow/registries/' + encodeURIComponent(registryIdentifier) + '/buckets',
@@ -241,18 +244,33 @@
 
             if (nfCommon.isDefinedAndNotNull(response.buckets) && response.buckets.length > 0) {
                 response.buckets.sort(function (a, b) {
+                    if (a.permissions.canRead === false && b.permissions.canRead === false) {
+                        return 0;
+                    } else if (a.permissions.canRead === false) {
+                        return -1;
+                    } else if (b.permissions.canRead === false) {
+                        return 1;
+                    }
+
                     return a.bucket.name > b.bucket.name;
                 });
 
                 $.each(response.buckets, function (_, bucketEntity) {
-                    var bucket = bucketEntity.bucket;
-                    buckets.push({
-                        text: bucket.name,
-                        value: bucket.id,
-                        description: nfCommon.escapeHtml(bucket.description)
-                    });
+                    if (bucketEntity.permissions.canRead === true) {
+                        var bucket = bucketEntity.bucket;
+
+                        if (bucketCheck(bucketEntity)) {
+                            buckets.push({
+                                text: bucket.name,
+                                value: bucket.id,
+                                description: nfCommon.escapeHtml(bucket.description)
+                            });
+                        }
+                    }
                 });
-            } else {
+            }
+
+            if (buckets.length === 0) {
                 buckets.push({
                     text: 'No available buckets',
                     value: null,
@@ -285,8 +303,9 @@
      * @param bucketCombo
      * @param flowCombo
      * @param selectBucket
+     * @param bucketCheck
      */
-    var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket) {
+    var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket, bucketCheck) {
         var showNoBucketsAvailable = function () {
             bucketCombo.combo('destroy').combo({
                 options: [{
@@ -333,7 +352,7 @@
                 clearFlowVersionsGrid();
             }
 
-            loadBuckets(selectedOption.value, bucketCombo, flowCombo, selectBucket).fail(function () {
+            loadBuckets(selectedOption.value, bucketCombo, flowCombo, selectBucket, bucketCheck).fail(function () {
                 showNoBucketsAvailable();
             });
         }
@@ -744,7 +763,9 @@
             }]
         }).show();
 
-        loadRegistries($('#import-flow-version-dialog'), registryCombo, bucketCombo, flowCombo, selectBucketImportVersion).done(function () {
+        loadRegistries($('#import-flow-version-dialog'), registryCombo, bucketCombo, flowCombo, selectBucketImportVersion, function (bucketEntity) {
+            return true;
+        }).done(function () {
             // show the import dialog
             $('#import-flow-version-dialog').modal('setHeaderText', 'Import Version').modal('setButtonModel', [{
                 buttonText: 'Import',
@@ -904,23 +925,35 @@
      * @param selectedBucket
      */
     var selectBucketImportVersion = function (selectedBucket) {
-        // mark the flows as loading
-        $('#import-flow-version-name-combo').combo('destroy').combo({
-            options: [{
-                text: 'Loading flows...',
-                value: null,
-                optionClass: 'unset',
-                disabled: true
-            }]
-        });
-
         // clear the flow versions grid
         clearFlowVersionsGrid();
 
-        var selectedRegistry = $('#import-flow-version-registry-combo').combo('getSelectedOption');
+        if (nfCommon.isDefinedAndNotNull(selectedBucket.value)) {
+            // mark the flows as loading
+            $('#import-flow-version-name-combo').combo('destroy').combo({
+                options: [{
+                    text: 'Loading flows...',
+                    value: null,
+                    optionClass: 'unset',
+                    disabled: true
+                }]
+            });
+
+            var selectedRegistry = $('#import-flow-version-registry-combo').combo('getSelectedOption');
 
-        // load the flows for the currently selected registry and bucket
-        loadFlows(selectedRegistry.value, selectedBucket.value, selectVersionedFlow);
+            // load the flows for the currently selected registry and bucket
+            loadFlows(selectedRegistry.value, selectedBucket.value, selectVersionedFlow);
+        } else {
+            // mark no flows available
+            $('#import-flow-version-name-combo').combo('destroy').combo({
+                options: [{
+                    text: 'No available flows',
+                    value: null,
+                    optionClass: 'unset',
+                    disabled: true
+                }]
+            });
+        }
     };
 
     /**
@@ -988,7 +1021,22 @@
         var importFlowVersionGrid = $('#import-flow-version-table').data('gridInstance');
         if (nfCommon.isDefinedAndNotNull(importFlowVersionGrid)) {
             var selected = importFlowVersionGrid.getSelectedRows();
-            return selected.length !== 1;
+
+            // if the version label is visible, this is a change version request so disable when
+            // the version that represents the current version is selected
+            if ($('#import-flow-version-label').is(':visible')) {
+                if (selected.length === 1) {
+                    var selectedFlow = importFlowVersionGrid.getDataItem(selected[0]);
+
+                    var currentVersion = parseInt($('#import-flow-version-label').text(), 10);
+                    return currentVersion === selectedFlow.version;
+                } else {
+                    return true;
+                }
+            } else {
+                // if importing, enable when a single row is selecting
+                return selected.length !== 1;
+            }
         } else {
             return true;
         }
@@ -1731,7 +1779,9 @@
                         // reposition the version label
                         $('#save-flow-version-label').css('margin-top', '0');
 
-                        loadRegistries($('#save-flow-version-dialog'), registryCombo, bucketCombo, null, selectBucketSaveFlowVersion).done(function () {
+                        loadRegistries($('#save-flow-version-dialog'), registryCombo, bucketCombo, null, selectBucketSaveFlowVersion, function (bucketEntity) {
+                            return bucketEntity.permissions.canWrite === true;
+                        }).done(function () {
                             deferred.resolve();
                         }).fail(function () {
                             deferred.reject();