Repository: nifi
Updated Branches:
  refs/heads/master d42ea467c -> 4dd50c80a


http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.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/StandardSnippetDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
index fa3da71..f41e7f9 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
@@ -16,11 +16,7 @@
  */
 package org.apache.nifi.web.dao.impl;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
+import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.controller.ProcessorNode;
@@ -41,7 +37,11 @@ import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.dto.SnippetDTO;
 import org.apache.nifi.web.dao.SnippetDAO;
 import org.apache.nifi.web.util.SnippetUtils;
-import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 
 public class StandardSnippetDAO implements SnippetDAO {
 
@@ -119,7 +119,6 @@ public class StandardSnippetDAO implements SnippetDAO {
         final StandardSnippet snippet = new StandardSnippet();
         snippet.setId(snippetDTO.getId());
         snippet.setParentGroupId(snippetDTO.getParentGroupId());
-        snippet.setLinked(snippetDTO.isLinked());
         snippet.addProcessors(mapDtoToRevision(snippetDTO.getProcessors()));
         
snippet.addProcessGroups(mapDtoToRevision(snippetDTO.getProcessGroups()));
         
snippet.addRemoteProcessGroups(mapDtoToRevision(snippetDTO.getRemoteProcessGroups()));
@@ -146,39 +145,31 @@ public class StandardSnippetDAO implements SnippetDAO {
     }
 
     @Override
-    public void verifyDelete(String snippetId) {
-        final StandardSnippet snippet = locateSnippet(snippetId);
-
-        // only need to check if the snippet is linked
-        if (snippet.isLinked()) {
-            // ensure the parent group exist
-            final ProcessGroup processGroup = 
flowController.getGroup(snippet.getParentGroupId());
-            if (processGroup == null) {
-                throw new IllegalArgumentException("The specified parent 
process group could not be found.");
-            }
+    public void verifyDeleteSnippetComponents(String snippetId) {
+        final Snippet snippet = locateSnippet(snippetId);
 
-            // verify the processGroup can remove the snippet
-            processGroup.verifyCanDelete(snippet);
+        // ensure the parent group exist
+        final ProcessGroup processGroup = 
flowController.getGroup(snippet.getParentGroupId());
+        if (processGroup == null) {
+            throw new IllegalArgumentException("The specified parent process 
group could not be found.");
         }
+
+        // verify the processGroup can remove the snippet
+        processGroup.verifyCanDelete(snippet);
     }
 
     @Override
-    public void deleteSnippet(String snippetId) {
-        final StandardSnippet snippet = locateSnippet(snippetId);
-
-        // if the snippet is linked, remove the contents
-        if (snippet.isLinked()) {
-            final ProcessGroup processGroup = 
flowController.getGroup(snippet.getParentGroupId());
-            if (processGroup == null) {
-                throw new IllegalArgumentException("The specified parent 
process group could not be found.");
-            }
+    public void deleteSnippetComponents(String snippetId) {
+        final Snippet snippet = locateSnippet(snippetId);
 
-            // remove the underlying components
-            processGroup.remove(snippet);
+        // remove the contents
+        final ProcessGroup processGroup = 
flowController.getGroup(snippet.getParentGroupId());
+        if (processGroup == null) {
+            throw new IllegalArgumentException("The specified parent process 
group could not be found.");
         }
 
-        // delete the snippet itself
-        flowController.getSnippetManager().removeSnippet(snippet);
+        // remove the underlying components
+        processGroup.remove(snippet);
     }
 
     @Override
@@ -192,11 +183,18 @@ public class StandardSnippetDAO implements SnippetDAO {
     }
 
     @Override
-    public void verifyUpdate(SnippetDTO snippetDTO) {
-        final StandardSnippet snippet = locateSnippet(snippetDTO.getId());
+    public void dropSnippet(String snippetId) {
+        // drop the snippet itself
+        final StandardSnippet snippet = locateSnippet(snippetId);
+        flowController.getSnippetManager().removeSnippet(snippet);
+    }
+
+    @Override
+    public void verifyUpdateSnippetComponent(SnippetDTO snippetDTO) {
+        final Snippet snippet = locateSnippet(snippetDTO.getId());
 
-        // if attempting to move the snippet contents
-        if (snippetDTO.getParentGroupId() != null) {
+        // if the group is changing move it
+        if (snippetDTO.getParentGroupId() != null && 
snippet.getParentGroupId() != snippetDTO.getParentGroupId()) {
             // get the current process group
             final ProcessGroup processGroup = 
flowController.getGroup(snippet.getParentGroupId());
             if (processGroup == null) {
@@ -209,35 +207,17 @@ public class StandardSnippetDAO implements SnippetDAO {
                 throw new IllegalArgumentException("The new process group 
could not be found.");
             }
 
-            boolean verificationRequired = false;
-
-            // verify if necessary
-            if (snippetDTO.isLinked() != null) {
-                if (snippetDTO.isLinked()) {
-                    verificationRequired = true;
-                }
-            } else if (snippet.isLinked()) {
-                verificationRequired = true;
-            }
-
-            // perform the verification if necessary
-            if (verificationRequired) {
-                processGroup.verifyCanMove(snippet, newProcessGroup);
-            }
+            // perform the verification
+            processGroup.verifyCanMove(snippet, newProcessGroup);
         }
     }
 
     @Override
-    public Snippet updateSnippet(final SnippetDTO snippetDTO) {
+    public Snippet updateSnippetComponents(final SnippetDTO snippetDTO) {
         final StandardSnippet snippet = locateSnippet(snippetDTO.getId());
 
-        // update whether this snippet is linked to the data flow
-        if (snippetDTO.isLinked() != null) {
-            snippet.setLinked(snippetDTO.isLinked());
-        }
-
-        // if the group is changing and its linked to the data flow move it
-        if (snippetDTO.getParentGroupId() != null && snippet.isLinked()) {
+        // if the group is changing move it
+        if (snippetDTO.getParentGroupId() != null && 
snippet.getParentGroupId() != snippetDTO.getParentGroupId()) {
             final ProcessGroup currentProcessGroup = 
flowController.getGroup(snippet.getParentGroupId());
             if (currentProcessGroup == null) {
                 throw new IllegalArgumentException("The current process group 
could not be found.");

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
----------------------------------------------------------------------
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 08ce354..99dfe6f 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
@@ -183,6 +183,7 @@
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="controllerResource" 
class="org.apache.nifi.web.api.ControllerResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
@@ -195,20 +196,29 @@
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
     </bean>
+    <bean id="snippetResource" class="org.apache.nifi.web.api.SnippetResource" 
scope="singleton">
+        <property name="serviceFacade" ref="serviceFacade"/>
+        <property name="properties" ref="nifiProperties"/>
+        <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
+    </bean>
     <bean id="templateResource" 
class="org.apache.nifi.web.api.TemplateResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="controllerServiceResource" 
class="org.apache.nifi.web.api.ControllerServiceResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="reportingTaskResource" 
class="org.apache.nifi.web.api.ReportingTaskResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="processGroupResource" 
class="org.apache.nifi.web.api.ProcessGroupResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
@@ -223,41 +233,49 @@
         <property name="connectionResource" ref="connectionResource"/>
         <property name="templateResource" ref="templateResource"/>
         <property name="controllerServiceResource" 
ref="controllerServiceResource"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="processorResource" 
class="org.apache.nifi.web.api.ProcessorResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="connectionResource" 
class="org.apache.nifi.web.api.ConnectionResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="flowfileQueueResource" 
class="org.apache.nifi.web.api.FlowFileQueueResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="remoteProcessGroupResource" 
class="org.apache.nifi.web.api.RemoteProcessGroupResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="inputPortResource" 
class="org.apache.nifi.web.api.InputPortResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="outputPortResource" 
class="org.apache.nifi.web.api.OutputPortResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="labelResource" class="org.apache.nifi.web.api.LabelResource" 
scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="funnelResource" class="org.apache.nifi.web.api.FunnelResource" 
scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
@@ -284,6 +302,7 @@
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>
         <property name="clusterManager" ref="clusterManager"/>
+        <property name="authorizer" ref="authorizer"/>
     </bean>
     <bean id="accessResource" class="org.apache.nifi.web.api.AccessResource" 
scope="singleton">
         <property name="properties" ref="nifiProperties"/>

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/DfmAccessControlTest.java
----------------------------------------------------------------------
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 ecbb374..83033f1 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
@@ -361,7 +361,6 @@ public class DfmAccessControlTest {
 
         // get a processor and update its configuration state
         ProcessGroupDTO processGroup = getRandomProcessGroup();
-        processGroup.setRunning(Boolean.FALSE);
 
         // create the revision
         final RevisionDTO revision = new RevisionDTO();

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
index b21ac8e..01cff66 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
@@ -550,16 +550,16 @@ public class NaiveRevisionManager implements 
RevisionManager {
         public boolean releaseClaimIfCurrentThread(final Revision revision) {
             threadLock.writeLock().lock();
             try {
-                if (revision != null && !getRevision().equals(revision)) {
-                    throw new InvalidRevisionException("Cannot release claim 
because the provided Revision is not valid");
-                }
-
                 final LockStamp stamp = lockStamp.get();
                 if (stamp == null) {
                     logger.debug("Cannot cancel claim for {} because there is 
no claim held", getRevision());
                     return false;
                 }
 
+                if (revision != null && !getRevision().equals(revision)) {
+                    throw new InvalidRevisionException("Cannot release claim 
because the provided Revision is not valid");
+                }
+
                 if (stamp.isObtainedByCurrentThread()) {
                     releaseClaim();
                     logger.debug("Successfully canceled claim for {}", 
getRevision());

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
index 492dc21..206b37e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
@@ -21,34 +21,42 @@
         <div id="component-container">
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.processor}}"
                     id="processor-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.processorComponent);">
                 <i class="icon icon-processor"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.inputPort}}"
                     id="port-in-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.inputPortComponent);">
                 <i class="icon icon-port-in"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.outputPort}}"
                     id="port-out-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.outputPortComponent);">
                 <i class="icon icon-port-out"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.processGroup}}"
                     id="group-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.groupComponent);">
                 <i class="icon icon-group"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.remoteProcessGroup}}"
 hide
                     show-gt-sm id="group-remote-component" 
class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.remoteGroupComponent);">
                 <i class="icon icon-group-remote"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.funnel}}"
                     id="funnel-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.funnelComponent);">
                 <i class="icon icon-funnel"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.template}}"
                     id="template-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.templateComponent);">
                 <i class="icon icon-template"></i></button>
             <button 
title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.label}}"
                     id="label-component" class="component-button"
+                    ng-disabled="!appCtrl.nf.Canvas.canWrite();"
                     
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.labelComponent);">
                 <i class="icon icon-label"></i></button>
         </div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/navigation.jsp
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/navigation.jsp
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/navigation.jsp
index f6190b2..23a514a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/navigation.jsp
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/navigation.jsp
@@ -85,43 +85,43 @@
                 <div>
                     <div id="operate-enable" class="action-button" 
title="Enable">
                         <button 
ng-click="appCtrl.nf.Actions['enable'](appCtrl.nf.CanvasUtils.getSelection());"
-                                
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().empty() || 
!appCtrl.nf.CanvasUtils.canEnable(appCtrl.nf.CanvasUtils.getSelection());">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.canEnable(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon fa 
fa-flash"></i></button>
                     </div>
                     <div class="button-spacer-small">&nbsp;</div>
                     <div id="operate-disable" class="action-button" 
title="Disable">
                         <button 
ng-click="appCtrl.nf.Actions['disable'](appCtrl.nf.CanvasUtils.getSelection());"
-                                
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().empty() || 
!appCtrl.nf.CanvasUtils.canDisable(appCtrl.nf.CanvasUtils.getSelection());">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.canDisable(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon icon 
icon-enable-false"></i></button>
                     </div>
                     <div class="button-spacer-large">&nbsp;</div>
                     <div id="operate-start" class="action-button" 
title="Start">
                         <button 
ng-click="appCtrl.nf.Actions['start'](appCtrl.nf.CanvasUtils.getSelection());"
-                                ng-disabled="!appCtrl.nf.Common.isDFM();">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.getSelection().empty() && 
!appCtrl.nf.CanvasUtils.canModify(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon fa 
fa-play"></i></button>
                     </div>
                     <div class="button-spacer-small">&nbsp;</div>
                     <div id="operate-stop" class="action-button" title="Stop">
                         <button 
ng-click="appCtrl.nf.Actions['stop'](appCtrl.nf.CanvasUtils.getSelection());"
-                                ng-disabled="!appCtrl.nf.Common.isDFM();">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.getSelection().empty() && 
!appCtrl.nf.CanvasUtils.canModify(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon fa 
fa-stop"></i></button>
                     </div>
                     <div class="button-spacer-large">&nbsp;</div>
                     <div id="operate-template" class="action-button" 
title="Create Template">
                         <button 
ng-click="appCtrl.nf.Actions['template'](appCtrl.nf.CanvasUtils.getSelection());"
-                                ng-disabled="!appCtrl.nf.Common.isDFM();">
+                                ng-disabled="!(appCtrl.nf.Canvas.canWrite() && 
(appCtrl.nf.CanvasUtils.getSelection().empty() || 
appCtrl.nf.CanvasUtils.canRead(appCtrl.nf.CanvasUtils.getSelection())));">
                             <i class="graph-control-action-icon icon 
icon-template"></i></button>
                     </div>
                     <div class="button-spacer-large">&nbsp;</div>
                     <div id="operate-copy" class="action-button" title="Copy">
                         <button 
ng-click="appCtrl.nf.Actions['copy'](appCtrl.nf.CanvasUtils.getSelection());"
-                                
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().empty() || 
!appCtrl.nf.CanvasUtils.isCopyable(appCtrl.nf.CanvasUtils.getSelection());">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.isCopyable(appCtrl.nf.CanvasUtils.getSelection())
 || !appCtrl.nf.CanvasUtils.canRead(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon fa 
fa-copy"></i></button>
                     </div>
                     <div class="button-spacer-small">&nbsp;</div>
                     <div id="operate-paste" class="action-button" 
title="Paste">
                         <button 
ng-click="appCtrl.nf.Actions['paste'](appCtrl.nf.CanvasUtils.getSelection());"
-                                ng-disabled="!appCtrl.nf.Clipboard.isCopied() 
|| !appCtrl.nf.CanvasUtils.canModify(appCtrl.nf.CanvasUtils.getSelection());">
+                                ng-disabled="!appCtrl.nf.Clipboard.isCopied()">
                             <i class="graph-control-action-icon fa 
fa-paste"></i></button>
                     </div>
                     <div class="clear"></div>
@@ -129,19 +129,19 @@
                 <div style="margin-top: 5px;">
                     <div id="operate-group" class="action-button" 
title="Group">
                         <button 
ng-click="appCtrl.nf.Actions['group'](appCtrl.nf.CanvasUtils.getSelection());"
-                                
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().empty() || 
!appCtrl.nf.CanvasUtils.isDisconnected(appCtrl.nf.CanvasUtils.getSelection());">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.isDisconnected(appCtrl.nf.CanvasUtils.getSelection())
 || !appCtrl.nf.CanvasUtils.canModify(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon icon 
icon-group"></i></button>
                     </div>
                     <div class="button-spacer-large">&nbsp;</div>
                     <div id="operate-color" class="action-button" title="Fill 
Color">
                         <button 
ng-click="appCtrl.nf.Actions['fillColor'](appCtrl.nf.CanvasUtils.getSelection());"
-                                
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().empty() || 
!appCtrl.nf.CanvasUtils.isColorable(appCtrl.nf.CanvasUtils.getSelection());">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.isColorable(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon fa 
fa-paint-brush"></i></button>
                     </div>
                     <div class="button-spacer-large">&nbsp;</div>
                     <div id="operate-delete" class="action-button" 
title="Delete">
                         <button 
ng-click="appCtrl.nf.Actions['delete'](appCtrl.nf.CanvasUtils.getSelection());"
-                                
ng-disabled="appCtrl.nf.CanvasUtils.getSelection().empty();">
+                                
ng-disabled="!appCtrl.nf.CanvasUtils.areDeletable(appCtrl.nf.CanvasUtils.getSelection());">
                             <i class="graph-control-action-icon fa 
fa-trash"></i><span>Delete</span></button>
                     </div>
                     <div class="clear"></div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
index 4c1335a..4d943c5 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/navigation.css
@@ -74,6 +74,7 @@ div.graph-control {
 div.graph-control button {
     height: 24px;
     width: 24px;
+    line-height: 19px;
     border-radius: 2px;
     border: 1px solid #CCDADB; /*tint link-color 80%*/
     background-color: rgba(249, 250, 251, 0.97);

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/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
----------------------------------------------------------------------
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 3c0b5e4..2087034 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,21 @@ nf.ng.BreadcrumbsCtrl = function (serviceProvider, 
$sanitize) {
         /**
          * Generate the breadcrumbs.
          *
-         * @param {object} breadcrumb  The breadcrumb
+         * @param {object} breadcrumbEntity  The breadcrumb
          */
-        generateBreadcrumbs: function(breadcrumb) {
+        generateBreadcrumbs: function(breadcrumbEntity) {
+            var label = breadcrumbEntity.id;
+            if (breadcrumbEntity.accessPolicy.canRead) {
+                label = breadcrumbEntity.breadcrumb.name;
+            }
+            
             //explicitly sanitize processGroup.name
-            breadcrumb.name = $sanitize(breadcrumb.name);
-            this.breadcrumbs.unshift(breadcrumb);
+            this.breadcrumbs.unshift($.extend({
+                'label': $sanitize(label)
+            }, breadcrumbEntity));
 
-            if (nf.Common.isDefinedAndNotNull(breadcrumb.parentBreadcrumb)) {
-                this.generateBreadcrumbs(breadcrumb.parentBreadcrumb);
+            if 
(nf.Common.isDefinedAndNotNull(breadcrumbEntity.parentBreadcrumb)) {
+                this.generateBreadcrumbs(breadcrumbEntity.parentBreadcrumb);
             }
         },
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/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 d83aba8..2e5bd14 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
@@ -157,7 +157,9 @@ nf.Actions = (function () {
                             // reload the group's connections
                             var connections = 
nf.Connection.getComponentConnections(remoteProcessGroup.id);
                             $.each(connections, function (_, connection) {
-                                nf.Connection.reload(connection.component);
+                                if (connection.accessPolicy.canRead) {
+                                    nf.Connection.reload(connection.component);
+                                }
                             });
                         }
                     });
@@ -487,13 +489,11 @@ nf.Actions = (function () {
             if (selection.empty()) {
                 // build the entity
                 var entity = {
-                    'component': {
-                        'id': nf.Canvas.getGroupId(),
-                        'running': true
-                    }
+                    'id': nf.Canvas.getGroupId(),
+                    'state': 'RUNNING'
                 };
 
-                updateResource(config.urls.api + '/process-groups/' + 
encodeURIComponent(nf.Canvas.getGroupId()), entity).done(updateProcessGroup);
+                updateResource(config.urls.api + '/flow/process-groups/' + 
encodeURIComponent(nf.Canvas.getGroupId()), entity).done(updateProcessGroup);
             } else {
                 var componentsToStart = selection.filter(function (d) {
                     return nf.CanvasUtils.isRunnable(d3.select(this));
@@ -535,7 +535,9 @@ nf.Actions = (function () {
                                 // reload the group's connections
                                 var connections = 
nf.Connection.getComponentConnections(response.id);
                                 $.each(connections, function (_, connection) {
-                                    nf.Connection.reload(connection);
+                                    if (connection.accessPolicy.canRead) {
+                                        
nf.Connection.reload(connection.component);
+                                    }
                                 });
                             } else {
                                 nf[d.type].set(response);
@@ -562,13 +564,11 @@ nf.Actions = (function () {
             if (selection.empty()) {
                 // build the entity
                 var entity = {
-                    'component': {
-                        'id': nf.Canvas.getGroupId(),
-                        'running': false
-                    }
+                    'id': nf.Canvas.getGroupId(),
+                    'state': 'STOPPED'
                 };
 
-                updateResource(config.urls.api + '/process-groups/' + 
encodeURIComponent(nf.Canvas.getGroupId()), entity).done(updateProcessGroup);
+                updateResource(config.urls.api + '/flow/process-groups/' + 
encodeURIComponent(nf.Canvas.getGroupId()), entity).done(updateProcessGroup);
             } else {
                 var componentsToStop = selection.filter(function (d) {
                     return nf.CanvasUtils.isStoppable(d3.select(this));
@@ -610,7 +610,9 @@ nf.Actions = (function () {
                                 // reload the group's connections
                                 var connections = 
nf.Connection.getComponentConnections(response.id);
                                 $.each(connections, function (_, connection) {
-                                    nf.Connection.reload(connection);
+                                    if (connection.accessPolicy.canRead) {
+                                        
nf.Connection.reload(connection.component);
+                                    }
                                 });
                             } else {
                                 nf[d.type].set(response);
@@ -826,10 +828,10 @@ nf.Actions = (function () {
                     }).fail(nf.Common.handleAjaxError);
                 } else {
                     // create a snippet for the specified component and link 
to the data flow
-                    var snippetDetails = nf.Snippet.marshal(selection, true);
-                    nf.Snippet.create(snippetDetails).done(function 
(snippetEntity) {
+                    var snippet = nf.Snippet.marshal(selection);
+                    nf.Snippet.create(snippet).done(function (response) {
                         // remove the snippet, effectively removing the 
components
-                        nf.Snippet.remove(snippetEntity).done(function () {
+                        nf.Snippet.remove(response.snippet.id).done(function 
() {
                             var components = d3.map();
 
                             // add the id to the type's array
@@ -870,18 +872,10 @@ nf.Actions = (function () {
 
                             // refresh the birdseye
                             nf.Birdseye.refresh();
+                            
                             // inform Angular app values have changed
                             nf.ng.Bridge.digest();
-                        }).fail(function (xhr, status, error) {
-                            // unable to actually remove the components so 
attempt to
-                            // unlink and remove just the snippet - if 
unlinking fails
-                            // just ignore
-                            nf.Snippet.unlink(snippetEntity).done(function 
(unlinkedSnippetEntity) {
-                                nf.Snippet.remove(unlinkedSnippetEntity);
-                            });
-
-                            nf.Common.handleAjaxError(xhr, status, error);
-                        });
+                        }).fail(nf.Common.handleAjaxError);
                     }).fail(nf.Common.handleAjaxError);
                 }
             }
@@ -1222,14 +1216,14 @@ nf.Actions = (function () {
                             var templateDescription = 
$('#new-template-description').val();
 
                             // create a snippet
-                            var snippetDetails = nf.Snippet.marshal(selection, 
false);
+                            var snippet = nf.Snippet.marshal(selection);
 
                             // create the snippet
-                            nf.Snippet.create(snippetDetails).done(function 
(snippetEntity) {
+                            nf.Snippet.create(snippet).done(function 
(response) {
                                 var createSnippetEntity = {
                                     'name': templateName,
                                     'description': templateDescription,
-                                    'snippetId': snippetEntity.id
+                                    'snippetId': response.snippet.id
                                 };
 
                                 // create the template
@@ -1246,9 +1240,6 @@ nf.Actions = (function () {
                                         overlayBackground: false
                                     });
                                 }).always(function () {
-                                    // remove the snippet
-                                    nf.Snippet.remove(snippetEntity);
-
                                     // clear the template dialog fields
                                     $('#new-template-name').val('');
                                     $('#new-template-description').val('');
@@ -1284,7 +1275,7 @@ nf.Actions = (function () {
 
             // copy the snippet details
             nf.Clipboard.copy({
-                snippet: nf.Snippet.marshal(selection, false),
+                snippet: nf.Snippet.marshal(selection),
                 origin: origin
             });
         },
@@ -1323,7 +1314,7 @@ nf.Actions = (function () {
                     };
 
                     // create a snippet from the details
-                    nf.Snippet.create(data['snippet']).done(function 
(snippetEntity) {
+                    nf.Snippet.create(data['snippet']).done(function 
(createResponse) {
                         // determine the origin of the bounding box of the copy
                         var origin = pasteLocation;
                         var snippetOrigin = data['origin'];
@@ -1336,7 +1327,7 @@ nf.Actions = (function () {
                         }
 
                         // copy the snippet to the new location
-                        nf.Snippet.copy(snippetEntity.id, 
origin).done(function (copyResponse) {
+                        nf.Snippet.copy(createResponse.snippet.id, 
origin).done(function (copyResponse) {
                             var snippetFlow = copyResponse.flow;
 
                             // update the graph accordingly
@@ -1349,9 +1340,6 @@ nf.Actions = (function () {
 
                             // refresh the birdseye/toolbar
                             nf.Birdseye.refresh();
-
-                            // remove the original snippet
-                            nf.Snippet.remove(snippetEntity).fail(reject);
                         }).fail(function () {
                             // an error occured while performing the copy 
operation, reload the
                             // graph in case it was a partial success

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
----------------------------------------------------------------------
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 93f3cff..bfa567d 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
@@ -55,11 +55,11 @@ nf.CanvasUtils = (function () {
         return $.Deferred(function (deferred) {
             // ensure the current selection is eligible for move into the 
specified group
             nf.CanvasUtils.eligibleForMove(components, groupId).done(function 
() {
-                // create a snippet for the specified components and link to 
the data flow
-                var snippetDetails = nf.Snippet.marshal(components, true);
-                nf.Snippet.create(snippetDetails).done(function 
(snippetEntity) {
+                // create a snippet for the specified components
+                var snippet = nf.Snippet.marshal(components);
+                nf.Snippet.create(snippet).done(function (response) {
                     // move the snippet into the target
-                    nf.Snippet.move(snippetEntity, groupId).done(function () {
+                    nf.Snippet.move(response.snippet.id, 
groupId).done(function () {
                         var componentMap = d3.map();
 
                         // add the id to the type's array
@@ -85,12 +85,6 @@ nf.CanvasUtils = (function () {
                         deferred.resolve();
                     }).fail(nf.Common.handleAjaxError).fail(function () {
                         deferred.reject();
-                    }).always(function () {
-                        // unable to acutally move the components so attempt to
-                        // unlink and remove just the snippet
-                        nf.Snippet.unlink(snippetEntity).done(function 
(unlinkedSnippetEntity) {
-                            nf.Snippet.remove(unlinkedSnippetEntity);
-                        });
                     });
                 }).fail(nf.Common.handleAjaxError).fail(function () {
                     deferred.reject();
@@ -240,6 +234,7 @@ nf.CanvasUtils = (function () {
         getSelection: function () {
             return d3.selectAll('g.component.selected, g.connection.selected');
         },
+
         /**
          * Centers the specified bounding box.
          * 
@@ -558,10 +553,12 @@ nf.CanvasUtils = (function () {
             
             // determine if the current selection is entirely processors or 
labels
             var selectedProcessors = selection.filter(function(d) {
-                return nf.CanvasUtils.isProcessor(d3.select(this));
+                var processor = d3.select(this);
+                return nf.CanvasUtils.isProcessor(processor) && 
nf.CanvasUtils.canModify(processor);
             });
             var selectedLabels = selection.filter(function(d) {
-                return nf.CanvasUtils.isLabel(d3.select(this));
+                var label = d3.select(this);
+                return nf.CanvasUtils.isLabel(label) && 
nf.CanvasUtils.canModify(label);
             });
 
             var allProcessors = selectedProcessors.size() === selection.size();
@@ -753,7 +750,7 @@ nf.CanvasUtils = (function () {
                 return false;
             }
 
-            return !nf.CanvasUtils.filterEnable(selection).empty();
+            return nf.CanvasUtils.filterEnable(selection).size() === 
selection.size();
         },
 
         /**
@@ -783,7 +780,7 @@ nf.CanvasUtils = (function () {
                 return false;
             }
 
-            return !nf.CanvasUtils.filterDisable(selection).empty();
+            return nf.CanvasUtils.filterDisable(selection).size() === 
selection.size();
         },
 
 
@@ -844,13 +841,33 @@ nf.CanvasUtils = (function () {
         canStopTransmitting: function (selection) {
             return nf.CanvasUtils.isRemoteProcessGroup(selection);
         },
-        
+
         /**
          * Determines whether the components in the specified selection are 
deletable.
          *
          * @argument {selection} selection      The selection
          * @return {boolean}            Whether the selection is deletable
          */
+        areDeletable: function (selection) {
+            if (selection.empty()) {
+                return false;
+            }
+
+            var isDeletable = true;
+            selection.each(function () {
+                if (!nf.CanvasUtils.isDeletable(d3.select(this))) {
+                    isDeletable = false;
+                }
+            });
+            return isDeletable;
+        },
+
+        /**
+         * Determines whether the component in the specified selection is 
deletable.
+         *
+         * @argument {selection} selection      The selection
+         * @return {boolean}            Whether the selection is deletable
+         */
         isDeletable: function (selection) {
             if (selection.empty()) {
                 return false;
@@ -895,6 +912,11 @@ nf.CanvasUtils = (function () {
          * @argument {selection} selection      The selection
          */
         supportsModification: function (selection) {
+            if (selection.size() !== 1) {
+                return false;
+            }
+
+            // get the selection data
             var selectionData = selection.datum();
 
             // check access policies first
@@ -1301,6 +1323,11 @@ nf.CanvasUtils = (function () {
          * @argument {selection} selection          The selection
          */
         isDisconnected: function (selection) {
+            // if nothing is selected return
+            if (selection.empty()) {
+                return false;
+            }
+            
             var connections = d3.map();
             var components = d3.map();
             var isDisconnected = true;

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
----------------------------------------------------------------------
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 27c7e45..e2d029a 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
@@ -111,6 +111,7 @@ nf.Canvas = (function () {
     var polling = false;
     var groupId = 'root';
     var groupName = null;
+    var accessPolicy = null;
     var parentGroupId = null;
     var secureSiteToSite = false;
     var clustered = false;
@@ -621,6 +622,9 @@ nf.Canvas = (function () {
             // set the group details
             nf.Canvas.setGroupId(processGroupFlow.id);
 
+            // update the access policies
+            accessPolicy = flowResponse.accessPolicy;
+            
             // update the breadcrumbs
             
nf.ng.Bridge.get('appCtrl.serviceProvider.breadcrumbsCtrl').resetBreadcrumbs();
             
nf.ng.Bridge.get('appCtrl.serviceProvider.breadcrumbsCtrl').generateBreadcrumbs(processGroupFlow.breadcrumb);
@@ -941,6 +945,19 @@ nf.Canvas = (function () {
             return parentGroupId;
         },
 
+        /**
+         * Whether the current user can write in this group.
+         * 
+         * @returns {boolean}   can write
+         */
+        canWrite: function () {
+            if (accessPolicy === null) {
+                return false;
+            } else {
+                return accessPolicy.canWrite === true;
+            }
+        },
+
         View: (function () {
 
             /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-context-menu.js
----------------------------------------------------------------------
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 a809f52..b5b1156 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
@@ -87,7 +87,7 @@ nf.ContextMenu = (function () {
             return false;
         }
         
-        return nf.CanvasUtils.isDeletable(selection);
+        return nf.CanvasUtils.areDeletable(selection);
     };
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
----------------------------------------------------------------------
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 e2ea1da..49efc33 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
@@ -378,7 +378,7 @@ nf.ProcessorConfiguration = (function () {
         $.each(connections, function (_, connection) {
             if (connection.accessPolicy.canRead) {
                 if (connection.sourceId === processor.id) {
-                    nf.Connection.reload(connection);
+                    nf.Connection.reload(connection.component);
                 }
             }
         });

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group.js
----------------------------------------------------------------------
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 cde1456..466c435 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
@@ -942,7 +942,9 @@ nf.RemoteProcessGroup = (function () {
                     // reload the group's connections
                     var connections = 
nf.Connection.getComponentConnections(remoteProcessGroup.id);
                     $.each(connections, function (_, connection) {
-                        nf.Connection.reload(connection);
+                        if (connection.accessPolicy.canRead) {
+                            nf.Connection.reload(connection.component);
+                        }
                     });
                 });
             }

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-snippet.js
----------------------------------------------------------------------
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 f523d03..4275b36 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
@@ -21,6 +21,7 @@ nf.Snippet = (function () {
 
     var config = {
         urls: {
+            snippets: '../nifi-api/snippets',
             processGroups: '../nifi-api/process-groups'
         }
     };
@@ -30,12 +31,10 @@ nf.Snippet = (function () {
          * Marshals snippet from the specified selection.
          * 
          * @argument {selection} selection      The selection to marshal
-         * @argument {boolean} linked   Whether this snippet should be linked 
to the flow
          */
-        marshal: function (selection, linked) {
+        marshal: function (selection) {
             var snippet = {
                 parentGroupId: nf.Canvas.getGroupId(),
-                linked: nf.Common.isDefinedAndNotNull(linked) ? linked : false,
                 processors: {},
                 funnels: {},
                 inputPorts: {},
@@ -84,7 +83,7 @@ nf.Snippet = (function () {
 
             return $.ajax({
                 type: 'POST',
-                url: config.urls.processGroups + '/' + 
encodeURIComponent(nf.Canvas.getGroupId()) + '/snippets',
+                url: config.urls.snippets,
                 data: JSON.stringify(snippetEntity),
                 dataType: 'json',
                 contentType: 'application/json'
@@ -116,88 +115,36 @@ nf.Snippet = (function () {
         /**
          * Removes the specified snippet.
          * 
-         * @argument {string} snippetEntity         The snippet entity
+         * @argument {string} snippetId         The snippet id
          */
-        remove: function (snippetEntity) {
-            var revision = nf.Client.getRevision(snippetEntity);
-
+        remove: function (snippetId) {
             return $.ajax({
                 type: 'DELETE',
-                url: config.urls.processGroups + '/' + 
encodeURIComponent(nf.Canvas.getGroupId()) + '/snippets/' + 
encodeURIComponent(snippetEntity.id) + '?' + $.param({
-                    version: revision.version,
-                    clientId: revision.clientId
-                })
+                url: config.urls.snippets + '/' + encodeURIComponent(snippetId)
             });
         },
         
         /**
          * Moves the snippet into the specified group.
          * 
-         * @argument {object} snippetEntity         The snippet entity
+         * @argument {string} snippetId         The snippet id
          * @argument {string} newGroupId        The new group id
          */
-        move: function (snippetEntity, newGroupId) {
+        move: function (snippetId, newGroupId) {
             var moveSnippetEntity = {
-                'revision': nf.Client.getRevision(snippetEntity),
                 'snippet': {
-                    'id': snippetEntity.id,
+                    'id': snippetId,
                     'parentGroupId': newGroupId
                 }
             };
 
             return $.ajax({
                 type: 'PUT',
-                url: config.urls.processGroups + '/' + 
encodeURIComponent(nf.Canvas.getGroupId()) + '/snippets/' + 
encodeURIComponent(snippetEntity.id),
+                url: config.urls.snippets + '/' + 
encodeURIComponent(snippetId),
                 data: JSON.stringify(moveSnippetEntity),
                 dataType: 'json',
                 contentType: 'application/json'
             });
-        },
-        
-        /**
-         * Unlinks the snippet from the actual data flow.
-         * 
-         * @argument {object} snippetEntity       The snippet enmtity
-         */
-        unlink: function (snippetEntity) {
-            var unlinkSnippetEntity = {
-                'revision': nf.Client.getRevision(snippetEntity),
-                'snippet': {
-                    'id': snippetEntity.id,
-                    'linked': false
-                }
-            };
-
-            return $.ajax({
-                type: 'PUT',
-                url: config.urls.processGroups + '/' + 
encodeURIComponent(nf.Canvas.getGroupId()) + '/snippets/' + 
encodeURIComponent(snippetEntity.id),
-                data: JSON.stringify(unlinkSnippetEntity),
-                dataType: 'json',
-                contentType: 'application/json'
-            });
-        },
-        
-        /**
-         * Links the snippet from the actual data flow.
-         * 
-         * @argument {object} snippetEntity         The snippet entity
-         */
-        link: function (snippetEntity) {
-            var linkSnippetEntity = {
-                'revision': nf.Client.getRevision(snippetEntity),
-                'snippet': {
-                    'id': snippetEntity.id,
-                    'linked': true
-                }
-            };
-
-            return $.ajax({
-                type: 'PUT',
-                url: config.urls.processGroups + '/' + 
encodeURIComponent(nf.Canvas.getGroupId()) + '/snippets/' + 
encodeURIComponent(snippetEntity.id),
-                data: JSON.stringify(linkSnippetEntity),
-                dataType: 'json',
-                contentType: 'application/json'
-            });
         }
     };
 }());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-connection-details.js
----------------------------------------------------------------------
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 fb80e48..e655964 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
@@ -383,7 +383,7 @@ nf.ConnectionDetails = (function () {
                 var groupResponse = groupResult[0];
                 var connectionResponse = connectionResult[0];
 
-                if (nf.Common.isDefinedAndNotNull(groupResponse.processGroup) 
&& nf.Common.isDefinedAndNotNull(connectionResponse.connection)) {
+                if (nf.Common.isDefinedAndNotNull(groupResponse.component) && 
nf.Common.isDefinedAndNotNull(connectionResponse.component)) {
                     var processGroup = groupResponse.component;
                     var connection = connectionResponse.component;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-processor-details.js
----------------------------------------------------------------------
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 5dc69e7..ee6e2ab 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
@@ -211,7 +211,7 @@ nf.ProcessorDetails = (function () {
             // show the dialog once we have the processor and its history
             $.when(getProcessor, getProcessorHistory).done(function 
(processorResponse, historyResponse) {
                 var processorResponse = processorResponse[0];
-                var processor = processorResponse.processor;
+                var processor = processorResponse.component;
                 var historyResponse = historyResponse[0];
                 var history = historyResponse.componentHistory;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/4dd50c80/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/views/nf-ng-breadcrumbs-directive-view.html
----------------------------------------------------------------------
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 c152f12..10d36f1 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
@@ -25,7 +25,7 @@ limitations under the License.
                 <span class="link"
                       ng-class="(highlightCrumbId === crumb.id) ? 'link-bold' 
: ''"
                       ng-click="clickFunc(crumb.id)">
-                    {{crumb.name}}
+                    {{crumb.label}}
                 </span>
             </span>
         </div>

Reply via email to