Repository: nifi
Updated Branches:
  refs/heads/master c27763a12 -> 69586d8bd


http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.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/FlowFileQueueResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
index cea97da..e5c10ba 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowFileQueueResource.java
@@ -24,6 +24,7 @@ import com.wordnik.swagger.annotations.ApiResponses;
 import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.ConnectionAuthorizable;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
@@ -120,7 +121,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/flowfiles/{flowfile-uuid}")
+    @Path("{id}/flowfiles/{flowfile-uuid}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Gets a FlowFile from a Connection.",
@@ -142,7 +143,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The flowfile uuid.",
                 required = true
@@ -170,11 +171,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
             }
         }
 
-        // authorize access
-        serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = 
lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
-        });
+        // NOTE - deferred authorization so we can consider flowfile 
attributes in the access decision
 
         // get the flowfile
         final FlowFileDTO flowfileDto = 
serviceFacade.getFlowFile(connectionId, flowFileUuid);
@@ -200,7 +197,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.WILDCARD)
-    @Path("{connection-id}/flowfiles/{flowfile-uuid}/content")
+    @Path("{id}/flowfiles/{flowfile-uuid}/content")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Gets the content for a FlowFile in a Connection.",
@@ -227,7 +224,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The flowfile uuid.",
                 required = true
@@ -255,11 +252,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
             }
         }
 
-        // authorize access
-        serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = 
lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
-        });
+        // NOTE - deferred authorization so we can consider flowfile 
attributes in the access decision
 
         // get the uri of the request
         final String uri = generateResourceUri("flowfile-queues", 
connectionId, "flowfiles", flowFileUuid, "content");
@@ -300,7 +293,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @POST
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/listing-requests")
+    @Path("{id}/listing-requests")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Lists the contents of the queue in this connection.",
@@ -325,7 +318,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String id) {
+            @PathParam("id") final String id) {
 
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST);
@@ -336,8 +329,9 @@ public class FlowFileQueueResource extends 
ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = 
lookup.getConnection(id).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = 
lookup.getConnection(id);
+                final Authorizable dataAuthorizable = 
lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.READ, 
NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {
@@ -371,7 +365,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/listing-requests/{listing-request-id}")
+    @Path("{id}/listing-requests/{listing-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Gets the current status of a listing request for the 
specified connection.",
@@ -394,7 +388,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The listing request id.",
                 required = true
@@ -407,8 +401,9 @@ public class FlowFileQueueResource extends 
ApplicationResource {
 
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = 
lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
+            final ConnectionAuthorizable connAuth = 
lookup.getConnection(connectionId);
+            final Authorizable dataAuthorizable = 
lookup.getData(connAuth.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, 
NiFiUserUtils.getNiFiUser());
         });
 
         // get the listing request
@@ -433,7 +428,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @DELETE
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/listing-requests/{listing-request-id}")
+    @Path("{id}/listing-requests/{listing-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Cancels and/or removes a request to list the contents of this 
connection.",
@@ -457,7 +452,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                 value = "The connection id.",
                 required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                 value = "The listing request id.",
                 required = true
@@ -473,8 +468,9 @@ public class FlowFileQueueResource extends 
ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = 
lookup.getConnection(connectionId).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = 
lookup.getConnection(connectionId);
+                final Authorizable dataAuthorizable = 
lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.READ, 
NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {
@@ -507,7 +503,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @POST
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/drop-requests")
+    @Path("{id}/drop-requests")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
         value = "Creates a request to drop the contents of the queue in this 
connection.",
@@ -532,7 +528,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
             value = "The connection id.",
             required = true
         )
-        @PathParam("connection-id") final String id) {
+        @PathParam("id") final String id) {
 
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST);
@@ -543,8 +539,9 @@ public class FlowFileQueueResource extends 
ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = 
lookup.getConnection(id).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = 
lookup.getConnection(id);
+                final Authorizable dataAuthorizable = 
lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {
@@ -577,7 +574,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/drop-requests/{drop-request-id}")
+    @Path("{id}/drop-requests/{drop-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
             value = "Gets the current status of a drop request for the 
specified connection.",
@@ -600,7 +597,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                     value = "The connection id.",
                     required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                     value = "The drop request id.",
                     required = true
@@ -613,8 +610,9 @@ public class FlowFileQueueResource extends 
ApplicationResource {
 
         // authorize access
         serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable connection = 
lookup.getConnection(connectionId).getAuthorizable();
-            connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
+            final ConnectionAuthorizable connAuth = 
lookup.getConnection(connectionId);
+            final Authorizable dataAuthorizable = 
lookup.getData(connAuth.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
         });
 
         // get the drop request
@@ -639,7 +637,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
     @DELETE
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("{connection-id}/drop-requests/{drop-request-id}")
+    @Path("{id}/drop-requests/{drop-request-id}")
     // TODO - @PreAuthorize("hasRole('ROLE_DFM')")
     @ApiOperation(
             value = "Cancels and/or removes a request to drop the contents of 
this connection.",
@@ -663,7 +661,7 @@ public class FlowFileQueueResource extends 
ApplicationResource {
                     value = "The connection id.",
                     required = true
             )
-            @PathParam("connection-id") final String connectionId,
+            @PathParam("id") final String connectionId,
             @ApiParam(
                     value = "The drop request id.",
                     required = true
@@ -679,8 +677,9 @@ public class FlowFileQueueResource extends 
ApplicationResource {
         if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
             // authorize access
             serviceFacade.authorizeAccess(lookup -> {
-                final Authorizable connection = 
lookup.getConnection(connectionId).getAuthorizable();
-                connection.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
+                final ConnectionAuthorizable connAuth = 
lookup.getConnection(connectionId);
+                final Authorizable dataAuthorizable = 
lookup.getData(connAuth.getSource().getIdentifier());
+                dataAuthorizable.authorize(authorizer, RequestAction.WRITE, 
NiFiUserUtils.getNiFiUser());
             });
         }
         if (validationPhase) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 8299181..aa9a8ac 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -30,7 +30,6 @@ import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
-import org.apache.nifi.authorization.user.StandardNiFiUser;
 import org.apache.nifi.cluster.coordination.ClusterCoordinator;
 import org.apache.nifi.cluster.protocol.NodeIdentifier;
 import org.apache.nifi.components.PropertyDescriptor;
@@ -69,8 +68,8 @@ import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.processor.DataUnit;
 import org.apache.nifi.processor.Processor;
 import org.apache.nifi.processor.Relationship;
-import org.apache.nifi.provenance.ProvenanceRepository;
 import org.apache.nifi.provenance.ProvenanceEventRecord;
+import org.apache.nifi.provenance.ProvenanceRepository;
 import org.apache.nifi.provenance.SearchableFields;
 import org.apache.nifi.provenance.lineage.ComputeLineageSubmission;
 import org.apache.nifi.provenance.search.Query;
@@ -109,7 +108,6 @@ import 
org.apache.nifi.web.api.dto.search.ComponentSearchResultDTO;
 import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
 import org.apache.nifi.web.api.dto.status.ControllerStatusDTO;
 import org.apache.nifi.web.api.dto.status.StatusHistoryDTO;
-import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -767,7 +765,7 @@ public class ControllerFacade implements Authorizable {
         // add each processor
         for (final ProcessorNode processor : root.findAllProcessors()) {
             
resources.add(ResourceFactory.getComponentResource(ResourceType.Processor, 
processor.getIdentifier(), processor.getName()));
-            
resources.add(ResourceFactory.getProvenanceEventResource(processor.getResource()));
+            
resources.add(ResourceFactory.getDataResource(processor.getResource()));
         }
 
         // add each label
@@ -778,25 +776,25 @@ public class ControllerFacade implements Authorizable {
         // add each process group
         for (final ProcessGroup processGroup : root.findAllProcessGroups()) {
             
resources.add(ResourceFactory.getComponentResource(ResourceType.ProcessGroup, 
processGroup.getIdentifier(), processGroup.getName()));
-            
resources.add(ResourceFactory.getProvenanceEventResource(processGroup.getResource()));
+            
resources.add(ResourceFactory.getDataResource(processGroup.getResource()));
         }
 
         // add each remote process group
         for (final RemoteProcessGroup remoteProcessGroup : 
root.findAllRemoteProcessGroups()) {
             
resources.add(ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup,
 remoteProcessGroup.getIdentifier(), remoteProcessGroup.getName()));
-            
resources.add(ResourceFactory.getProvenanceEventResource(remoteProcessGroup.getResource()));
+            
resources.add(ResourceFactory.getDataResource(remoteProcessGroup.getResource()));
         }
 
         // add each input port
         for (final Port inputPort : root.findAllInputPorts()) {
             
resources.add(ResourceFactory.getComponentResource(ResourceType.InputPort, 
inputPort.getIdentifier(), inputPort.getName()));
-            
resources.add(ResourceFactory.getProvenanceEventResource(inputPort.getResource()));
+            
resources.add(ResourceFactory.getDataResource(inputPort.getResource()));
         }
 
         // add each output port
         for (final Port outputPort : root.findAllOutputPorts()) {
             
resources.add(ResourceFactory.getComponentResource(ResourceType.OutputPort, 
outputPort.getIdentifier(), outputPort.getName()));
-            
resources.add(ResourceFactory.getProvenanceEventResource(outputPort.getResource()));
+            
resources.add(ResourceFactory.getDataResource(outputPort.getResource()));
         }
 
         // add each controller service
@@ -1087,7 +1085,7 @@ public class ControllerFacade implements Authorizable {
             final NiFiUser user = NiFiUserUtils.getNiFiUser();
 
             // get the event in order to get the filename
-            final ProvenanceEventRecord event = 
flowController.getProvenanceRepository().getEvent(eventId, 
NiFiUserUtils.getNiFiUser());
+            final ProvenanceEventRecord event = 
flowController.getProvenanceRepository().getEvent(eventId);
             if (event == null) {
                 throw new ResourceNotFoundException("Unable to find the 
specified event.");
             }
@@ -1101,7 +1099,8 @@ public class ControllerFacade implements Authorizable {
             }
 
             // authorize the event
-            authorizeEvent(event.getComponentId(), attributes);
+            final Authorizable dataAuthorizable = 
flowController.createDataAuthorizable(event.getComponentId());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, user, 
attributes);
 
             // get the filename and fall back to the identifier (should never 
happen)
             String filename = attributes.get(CoreAttributes.FILENAME.key());
@@ -1137,7 +1136,7 @@ public class ControllerFacade implements Authorizable {
             }
 
             // lookup the original event
-            final ProvenanceEventRecord originalEvent = 
flowController.getProvenanceRepository().getEvent(eventId, 
NiFiUserUtils.getNiFiUser());
+            final ProvenanceEventRecord originalEvent = 
flowController.getProvenanceRepository().getEvent(eventId);
             if (originalEvent == null) {
                 throw new ResourceNotFoundException("Unable to find the 
specified event.");
             }
@@ -1156,67 +1155,6 @@ public class ControllerFacade implements Authorizable {
     }
 
     /**
-     * Authorizes access to a provenance event generated by the specified 
component and containing the specified eventAttributes.
-     *
-     * @param componentId component id
-     * @param eventAttributes event attributes
-     */
-    private AuthorizationResult checkAuthorizationForEvent(final String 
componentId, final Map<String, String> eventAttributes) {
-        AuthorizationResult result = null;
-
-        // calculate the dn chain
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final List<String> dnChain = 
ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-        for (final String identity : dnChain) {
-            final Authorizable eventAuthorizable = 
flowController.createProvenanceAuthorizable(componentId);
-            final String clientAddress = user.getIdentity().equals(identity) ? 
user.getClientAddress() : null;
-            final NiFiUser chainUser = new StandardNiFiUser(identity, 
clientAddress) {
-                @Override
-                public boolean isAnonymous() {
-                    // allow current user to drive anonymous flag as anonymous 
users are never chained... supports single user case
-                    return user.isAnonymous();
-                }
-            };
-
-            result = eventAuthorizable.checkAuthorization(authorizer, 
RequestAction.READ, chainUser, eventAttributes);
-            if (!Result.Approved.equals(result.getResult())) {
-                break;
-            }
-        }
-
-        if (result == null) {
-            result = AuthorizationResult.denied();
-        }
-
-        return result;
-    }
-
-    /**
-     * Authorizes access to a provenance event generated by the specified 
component and containing the specified eventAttributes.
-     *
-     * @param componentId component id
-     * @param eventAttributes event attributes
-     */
-    private void authorizeEvent(final String componentId, final Map<String, 
String> eventAttributes) {
-        // calculate the dn chain
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final List<String> dnChain = 
ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-        for (final String identity : dnChain) {
-            final Authorizable eventAuthorizable = 
flowController.createProvenanceAuthorizable(componentId);
-            final String clientAddress = user.getIdentity().equals(identity) ? 
user.getClientAddress() : null;
-            final NiFiUser chainUser = new StandardNiFiUser(identity, 
clientAddress) {
-                @Override
-                public boolean isAnonymous() {
-                    // allow current user to drive anonymous flag as anonymous 
users are never chained... supports single user case
-                    return user.isAnonymous();
-                }
-            };
-
-            eventAuthorizable.authorize(authorizer, RequestAction.READ, 
chainUser, eventAttributes);
-        }
-    }
-
-    /**
      * Authorizes access to replay a specified provenance event.
      *
      * @param componentId component id
@@ -1229,16 +1167,17 @@ public class ControllerFacade implements Authorizable {
             return AuthorizationResult.denied();
         }
 
-        final AuthorizationResult result = 
checkAuthorizationForEvent(componentId, eventAttributes);
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+        final Authorizable dataAuthorizable = 
flowController.createDataAuthorizable(componentId);
+
+        // ensure we can read the data
+        final AuthorizationResult result = 
dataAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, 
eventAttributes);
         if (!Result.Approved.equals(result.getResult())) {
             return result;
         }
 
-        // authorize write permissions for the queue
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final ProcessGroup rootGroup = 
flowController.getGroup(flowController.getRootGroupId());
-        final Connection connection = rootGroup.findConnection(connectionId);
-        return connection.checkAuthorization(authorizer, RequestAction.WRITE, 
user);
+        // ensure we can write the data
+        return dataAuthorizable.checkAuthorization(authorizer, 
RequestAction.WRITE, user, eventAttributes);
     }
 
     /**
@@ -1254,13 +1193,12 @@ public class ControllerFacade implements Authorizable {
             throw new AccessDeniedException("The connection id is unknown.");
         }
 
-        authorizeEvent(componentId, eventAttributes);
-
-        // authorize write permissions for the queue
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        final ProcessGroup rootGroup = 
flowController.getGroup(flowController.getRootGroupId());
-        final Connection connection = rootGroup.findConnection(connectionId);
-        connection.authorize(authorizer, RequestAction.WRITE, user);
+        final Authorizable dataAuthorizable = 
flowController.createDataAuthorizable(componentId);
+
+        // ensure we can read and write the data
+        dataAuthorizable.authorize(authorizer, RequestAction.READ, user, 
eventAttributes);
+        dataAuthorizable.authorize(authorizer, RequestAction.WRITE, user, 
eventAttributes);
     }
 
     /**
@@ -1271,14 +1209,15 @@ public class ControllerFacade implements Authorizable {
      */
     public ProvenanceEventDTO getProvenanceEvent(final Long eventId) {
         try {
-            final ProvenanceEventRecord event = 
flowController.getProvenanceRepository().getEvent(eventId, 
NiFiUserUtils.getNiFiUser());
+            final ProvenanceEventRecord event = 
flowController.getProvenanceRepository().getEvent(eventId);
             if (event == null) {
                 throw new ResourceNotFoundException("Unable to find the 
specified event.");
             }
 
             // get the flowfile attributes and authorize the event
             final Map<String, String> attributes = event.getAttributes();
-            authorizeEvent(event.getComponentId(), attributes);
+            final Authorizable dataAuthorizable = 
flowController.createDataAuthorizable(event.getComponentId());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, 
NiFiUserUtils.getNiFiUser(), attributes);
 
             // convert the event
             return createProvenanceEventDto(event);
@@ -1293,8 +1232,8 @@ public class ControllerFacade implements Authorizable {
      * @param componentId component id
      * @return authorizable
      */
-    public Authorizable getProvenanceEventAuthorizable(final String 
componentId) {
-        return flowController.createProvenanceAuthorizable(componentId);
+    public Authorizable getDataAuthorizable(final String componentId) {
+        return flowController.createDataAuthorizable(componentId);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.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/AccessPolicyDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
index d3f8965..05b7fd7 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
@@ -46,7 +46,18 @@ public interface AccessPolicyDAO {
     AccessPolicy getAccessPolicy(String accessPolicyId);
 
     /**
-     * Gets the access policy according to the action and authorizable.
+     * Gets the access policy according to the action and authorizable. Will 
return null
+     * if no policy exists for the specific resource.
+     *
+     * @param requestAction action
+     * @param resource resource
+     * @return access policy
+     */
+    AccessPolicy getAccessPolicy(RequestAction requestAction, String resource);
+
+    /**
+     * Gets the access policy according to the action and authorizable. Will 
return the
+     * effective policy if no policy exists for the specific authorizable.
      *
      * @param requestAction action
      * @param authorizable authorizable

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.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/StandardConnectionDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
index a337854..16cf03f 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectionDAO.java
@@ -16,16 +16,11 @@
  */
 package org.apache.nifi.web.dao.impl;
 
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authorization.AccessDeniedException;
-import org.apache.nifi.authorization.AuthorizationResult;
-import org.apache.nifi.authorization.AuthorizationResult.Result;
 import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
-import org.apache.nifi.authorization.UserContextKeys;
+import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
-import org.apache.nifi.authorization.user.StandardNiFiUser;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.ConnectableType;
 import org.apache.nifi.connectable.Connection;
@@ -50,7 +45,6 @@ import org.apache.nifi.web.api.dto.ConnectableDTO;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
 import org.apache.nifi.web.api.dto.PositionDTO;
 import org.apache.nifi.web.dao.ConnectionDAO;
-import org.apache.nifi.web.security.ProxiedEntitiesUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,7 +54,6 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -139,6 +132,11 @@ public class StandardConnectionDAO extends ComponentDAO 
implements ConnectionDAO
                 throw new ResourceNotFoundException(String.format("The 
FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
             }
 
+            // get the attributes and ensure appropriate access
+            final Map<String, String> attributes = flowFile.getAttributes();
+            final Authorizable dataAuthorizable = 
flowController.createDataAuthorizable(connection.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, 
NiFiUserUtils.getNiFiUser(), attributes);
+
             return flowFile;
         } catch (final IOException ioe) {
             logger.error(String.format("Unable to get the flowfile (%s) at 
this time.", flowFileUuid), ioe);
@@ -597,26 +595,10 @@ public class StandardConnectionDAO extends ComponentDAO 
implements ConnectionDAO
                 throw new ResourceNotFoundException(String.format("The 
FlowFile with UUID %s is no longer in the active queue.", flowFileUuid));
             }
 
+            // get the attributes and ensure appropriate access
             final Map<String, String> attributes = flowFile.getAttributes();
-
-            // calculate the dn chain
-            final List<String> dnChain = 
ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-            dnChain.forEach(identity -> {
-                // build the request
-                final Map<String,String> userContext;
-                if (!StringUtils.isBlank(user.getClientAddress())) {
-                    userContext = new HashMap<>();
-                    userContext.put(UserContextKeys.CLIENT_ADDRESS.name(), 
user.getClientAddress());
-                } else {
-                    userContext = null;
-                }
-
-                final NiFiUser chainUser = new StandardNiFiUser(identity, 
user.getClientAddress());
-                final AuthorizationResult result = 
connection.checkAuthorization(authorizer, RequestAction.WRITE, chainUser, 
attributes);
-                if (!Result.Approved.equals(result.getResult())) {
-                    throw new AccessDeniedException(result.getExplanation());
-                }
-            });
+            final Authorizable dataAuthorizable = 
flowController.createDataAuthorizable(connection.getSource().getIdentifier());
+            dataAuthorizable.authorize(authorizer, RequestAction.READ, user, 
attributes);
 
             // get the filename and fall back to the identifier (should never 
happen)
             String filename = attributes.get(CoreAttributes.FILENAME.key());

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.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/StandardPolicyBasedAuthorizerDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
index 7488fe1..41051e1 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
@@ -180,6 +180,11 @@ public class StandardPolicyBasedAuthorizerDAO implements 
AccessPolicyDAO, UserGr
     }
 
     @Override
+    public AccessPolicy getAccessPolicy(final RequestAction requestAction, 
final String resource) {
+        return findAccessPolicy(requestAction, resource);
+    }
+
+    @Override
     public AccessPolicy getAccessPolicy(final RequestAction requestAction, 
final Authorizable authorizable) {
         final String resource = authorizable.getResource().getIdentifier();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
index 605e98b..0ff9fed 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java
@@ -16,17 +16,19 @@
  */
 package org.apache.nifi.web.security;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  *
  */
@@ -72,34 +74,11 @@ public class ProxiedEntitiesUtils {
      */
     public static String buildProxiedEntitiesChainString(final NiFiUser user) {
         // calculate the dn chain
-        final List<String> proxyChain = buildProxiedEntitiesChain(user);
+        final List<String> proxyChain = 
NiFiUserUtils.buildProxiedEntitiesChain(user);
         return formatProxyDn(StringUtils.join(proxyChain, "><"));
     }
 
     /**
-     * Builds the proxy chain for the specified user.
-     *
-     * @param user The current user
-     * @return The proxy chain for that user in List form
-     */
-    public static List<String> buildProxiedEntitiesChain(final NiFiUser user) {
-        // calculate the dn chain
-        final List<String> proxyChain = new ArrayList<>();
-
-        // build the dn chain
-        NiFiUser chainedUser = user;
-        do {
-            // add the entry for this user
-            proxyChain.add(chainedUser.getIdentity());
-
-            // go to the next user in the chain
-            chainedUser = chainedUser.getChain();
-        } while (chainedUser != null);
-
-        return proxyChain;
-    }
-
-    /**
      * Builds the proxy chain from the specified request and user.
      *
      * @param request the request

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
index 1c16d13..fbc0de5 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/login.css
@@ -68,7 +68,7 @@
 */
 
 body.login-body input, body.login-body textarea {
-    width: 400px;
+    width: 412px;
 }
 
 div.login-container {

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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 4057334..aee9aaf 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
@@ -999,8 +999,9 @@ nf.Actions = (function () {
                         
$('#drop-request-status-message').text(dropRequest.state);
 
                         // update the current number of enqueued flowfiles
-                        if (nf.Common.isDefinedAndNotNull(connection.status) 
&& nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
+                        if 
(nf.Common.isDefinedAndNotNull(dropRequest.currentCount)) {
                             connection.status.queued = dropRequest.current;
+                            connection.status.aggregateSnapshot.queued = 
dropRequest.current;
                             nf.Connection.refresh(connection.id);
                         }
 
@@ -1028,13 +1029,19 @@ nf.Actions = (function () {
                         }).done(function (response) {
                             dropRequest = response.dropRequest;
                             processDropRequest(nextDelay);
-                        }).fail(completeDropRequest);
+                        }).fail(function (xhr, status, error) {
+                            if (xhr.status === 403) {
+                                nf.Common.handleAjaxError(xhr, status, error);
+                            } else {
+                                completeDropRequest()
+                            }
+                        });
                     };
 
                     // issue the request to delete the flow files
                     $.ajax({
                         type: 'POST',
-                        url: '../nifi-api/flowfile-queues/' + connection.id + 
'/drop-requests',
+                        url: '../nifi-api/flowfile-queues/' + 
encodeURIComponent(connection.id) + '/drop-requests',
                         dataType: 'json',
                         contentType: 'application/json'
                     }).done(function (response) {
@@ -1047,7 +1054,13 @@ nf.Actions = (function () {
                         // process the drop request
                         dropRequest = response.dropRequest;
                         processDropRequest(1);
-                    }).fail(completeDropRequest);
+                    }).fail(function (xhr, status, error) {
+                        if (xhr.status === 403) {
+                            nf.Common.handleAjaxError(xhr, status, error);
+                        } else {
+                            completeDropRequest()
+                        }
+                    });
                 }
             });
         },

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/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 2282fe2..326f1a1 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
@@ -316,10 +316,6 @@ nf.ContextMenu = (function () {
      * @param {selection} selection
      */
     var canEmptyQueue = function (selection) {
-        if (nf.CanvasUtils.canModify(selection) === false) {
-            return false;
-        }
-        
         return isConnection(selection);
     };
 
@@ -329,10 +325,6 @@ nf.ContextMenu = (function () {
      * @param {selection} selection
      */
     var canListQueue = function (selection) {
-        if (nf.CanvasUtils.canModify(selection) === false) {
-            return false;
-        }
-        
         return isConnection(selection);
     };
     

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
index 4ba2bcd..c207e80 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
@@ -308,17 +308,13 @@ nf.PolicyManagement = (function () {
                 value: 'write-component',
                 description: 'Allows users to modify component configuration 
details'
             }, {
-                text: 'view the provenance events',
-                value: 'read-provenance-events',
-                description: 'Allows users to access provenance events and 
content for this component'
+                text: 'view the data',
+                value: 'read-data',
+                description: 'Allows users to view metadata and content for 
this component through provenance data and flowfile queues in outbound 
connections'
             }, {
-                text: 'view the policies',
-                value: 'read-policies',
-                description: 'Allows users to view the list of users who can 
view/modify this component'
-            }, {
-                text: 'modify the policies',
-                value: 'write-policies',
-                description: 'Allows users to modify the list of users who can 
view/modify this component'
+                text: 'modify the data',
+                value: 'write-data',
+                description: 'Allows users to empty flowfile queues in 
outbound connections and submit replays'
             }, {
                 text: 'receive data via site-to-site',
                 value: 'write-receive-data',
@@ -329,6 +325,14 @@ nf.PolicyManagement = (function () {
                 value: 'write-send-data',
                 description: 'Allows this port to send data to these NiFi 
instances',
                 disabled: true
+            }, {
+                text: 'view the policies',
+                value: 'read-policies',
+                description: 'Allows users to view the list of users who can 
view/modify this component'
+            }, {
+                text: 'modify the policies',
+                value: 'write-policies',
+                description: 'Allows users to modify the list of users who can 
view/modify this component'
             }],
             select: function (option) {
                 if (initialized) {
@@ -338,9 +342,12 @@ nf.PolicyManagement = (function () {
                         $('#selected-policy-action').text('read');
                     } else if (option.value === 'write-component') {
                         $('#selected-policy-action').text('write');
-                    } else if (option.value === 'read-provenance-events') {
+                    } else if (option.value === 'read-data') {
                         $('#selected-policy-action').text('read');
-                        resource = ('provenance-events/' + resource);
+                        resource = ('data/' + resource);
+                    } else if (option.value === 'write-data') {
+                        $('#selected-policy-action').text('write');
+                        resource = ('data/' + resource);
                     } else if (option.value === 'read-policies') {
                         $('#selected-policy-action').text('read');
                         resource = ('policies/' + resource);
@@ -380,7 +387,11 @@ nf.PolicyManagement = (function () {
         var actionFormatter = function (row, cell, value, columnDef, 
dataContext) {
             var markup = '';
 
-            markup += '<div title="Remove" class="pointer delete-user fa 
fa-trash"></div>';
+            // see if the user has permissions for the current policy
+            var currentEntity = $('#policy-table').data('policy');
+            if (currentEntity.permissions.canWrite === true) {
+                markup += '<div title="Remove" class="pointer delete-user fa 
fa-trash"></div>';
+            }
 
             return markup;
         };
@@ -538,7 +549,11 @@ nf.PolicyManagement = (function () {
                 dataType: 'json'
             }).done(function () {
                 loadPolicy();
-            }).fail(nf.Common.handleAjaxError);
+            }).fail(function (xhr, status, error) {
+                nf.Common.handleAjaxError(xhr, status, error);
+                resetPolicy();
+                loadPolicy();
+            });
         } else {
             nf.Dialog.showOkDialog({
                 headerText: 'Update Policy',
@@ -600,6 +615,7 @@ nf.PolicyManagement = (function () {
 
         // re-sort and clear selection after updating
         policyData.reSort();
+        policyGrid.invalidate();
         policyGrid.getSelectionModel().setSelectedRows([]);
     };
 
@@ -634,20 +650,21 @@ nf.PolicyManagement = (function () {
 
         // store the current policy version
         $('#policy-table').data('policy', policyEntity);
-        
-        // allow removal and modification as the policy is not inherited
-        $('#new-policy-user-button').prop('disabled', false);
+
+        // allow modification if allowed
+        $('#new-policy-user-button').prop('disabled', 
policyEntity.permissions.canWrite === false);
 
         // see if the policy is for this resource
         if (resourceAndAction.resource === policy.resource) {
             // allow remove when policy is not inherited
-            $('#delete-policy-button').prop('disabled', false);
+            $('#delete-policy-button').prop('disabled', 
policyEntity.permissions.canWrite === false);
         } else {
             $('#policy-message').text('Showing effective policy inherited from 
' + convertToHumanReadableResource(policy.resource) + '. ');
-            $('#new-policy-message').hide();
+
+            // policy is inherited, we do not know if the user has permissions 
to modify the desired policy... show button and let server decide
             $('#override-policy-message').show();
 
-            // require non inherited policy for removal
+            // to not support policy deletion
             $('#delete-policy-button').prop('disabled', true);
         }
 
@@ -660,7 +677,6 @@ nf.PolicyManagement = (function () {
      */
     var loadPolicy = function () {
         var resourceAndAction = getSelectedResourceAndAction();
-
         return $.Deferred(function (deferred) {
             $.ajax({
                 type: 'GET',
@@ -673,7 +689,7 @@ nf.PolicyManagement = (function () {
                 $('#policy-last-refreshed').text(policyEntity.generated);
 
                 // ensure appropriate actions for the loaded policy
-                if (policyEntity.permissions.canRead === true && 
policyEntity.permissions.canWrite === true) {
+                if (policyEntity.permissions.canRead === true) {
                     var policy = policyEntity.component;
 
                     $('#policy-message').text(policy.resource);
@@ -684,9 +700,10 @@ nf.PolicyManagement = (function () {
                     // reset the policy
                     resetPolicy();
 
-                    // show an appropriate message
-                    $('#policy-message').text('No policy for the specified 
resource and not authorized to access the inherited policy. ');
-                    $('#new-policy-message').hide();
+                    // since we cannot read, the policy may be inherited or 
not... we cannot tell
+                    $('#policy-message').text('Not authorized to view the 
policy.');
+
+                    // allow option to override because we don't know if it's 
supported or not
                     $('#override-policy-message').show();
                 }
 
@@ -698,8 +715,9 @@ nf.PolicyManagement = (function () {
 
                     // show an appropriate message
                     $('#policy-message').text('No policy for the specified 
resource.');
+
+                    // we don't know if the user has permissions to the 
desired policy... show create button and allow the server to decide
                     $('#new-policy-message').show();
-                    $('#override-policy-message').hide();
 
                     deferred.resolve();
                 } else if (xhr.status === 403) {
@@ -708,8 +726,6 @@ nf.PolicyManagement = (function () {
 
                     // show an appropriate message
                     $('#policy-message').text('Not authorized to access the 
policy for the specified resource.');
-                    $('#new-policy-message').hide();
-                    $('#override-policy-message').hide();
 
                     deferred.resolve();
                 } else {
@@ -747,7 +763,19 @@ nf.PolicyManagement = (function () {
             dataType: 'json',
             contentType: 'application/json'
         }).done(function (policyEntity) {
-            populatePolicy(policyEntity);
+            // ensure appropriate actions for the loaded policy
+            if (policyEntity.permissions.canRead === true) {
+                var policy = policyEntity.component;
+
+                $('#policy-message').text(policy.resource);
+
+                // populate the policy details
+                populatePolicy(policyEntity);
+            } else {
+                // the request succeeded but we don't have access to the 
policy... reset/reload the policy
+                resetPolicy();
+                loadPolicy();
+            }
         }).fail(nf.Common.handleAjaxError);
     };
 
@@ -792,7 +820,7 @@ nf.PolicyManagement = (function () {
                 contentType: 'application/json'
             }).done(function (policyEntity) {
                 // ensure appropriate actions for the loaded policy
-                if (policyEntity.permissions.canRead === true && 
policyEntity.permissions.canWrite === true) {
+                if (policyEntity.permissions.canRead === true) {
                     var policy = policyEntity.component;
 
                     $('#policy-message').text(policy.resource);
@@ -800,15 +828,15 @@ nf.PolicyManagement = (function () {
                     // populate the policy details
                     populatePolicy(policyEntity);
                 } else {
-                    // reset the policy
+                    // the request succeeded but we don't have access to the 
policy... reset/reload the policy
                     resetPolicy();
-
-                    // show an appropriate message
-                    $('#policy-message').text('No policy for the specified 
resource and not authorized to access the inherited policy. ');
-                    $('#new-policy-message').hide();
-                    $('#override-policy-message').show();
+                    loadPolicy();
                 }
-            }).fail(nf.Common.handleAjaxError);
+            }).fail(function (xhr, status, error) {
+                nf.Common.handleAjaxError(xhr, status, error)
+                resetPolicy();
+                loadPolicy();
+            });
         } else {
             nf.Dialog.showOkDialog({
                 headerText: 'Update Policy',
@@ -872,35 +900,6 @@ nf.PolicyManagement = (function () {
         $('div.policy-selected-component-container').hide();
     };
 
-    /**
-     * Populates the initial policy resource.
-     *
-     * @param resource
-     */
-    var populateComponentResource = function (resource) {
-        // record the initial resource type
-        $('#selected-policy-component-type').text(resource);
-
-        var policyTarget = 
$('#component-policy-target').combo('getSelectedOption').value;
-        if (policyTarget === 'read-component') {
-            $('#selected-policy-action').text('read');
-        } else if (policyTarget === 'write-component') {
-            $('#selected-policy-action').text('write');
-        } else if (policyTarget === 'read-provenance-events') {
-            $('#selected-policy-action').text('read');
-            resource = ('provenance-events/' + resource);
-        } else if (policyTarget === 'read-policies') {
-            $('#selected-policy-action').text('read');
-            resource = ('policies/' + resource);
-        } else if (policyTarget === 'write-policies') {
-            $('#selected-policy-action').text('write');
-            resource = ('policies/' + resource);
-        }
-
-        // update the policy type
-        $('#selected-policy-type').text(resource);
-    };
-    
     return {
         /**
          * Initializes the settings page.
@@ -909,6 +908,13 @@ nf.PolicyManagement = (function () {
             initAddTenantToPolicyDialog();
             initPolicyTable();
 
+            $('#policy-refresh-button').on('click', function () {
+                loadPolicy();
+            });
+
+            // reset the policy to initialize
+            resetPolicy();
+
             // mark as initialized
             initialized = true;
         },
@@ -940,7 +946,7 @@ nf.PolicyManagement = (function () {
             $('#global-policy-controls').hide();
 
             // update the visibility
-            if (d.permissions.canRead) {
+            if (d.permissions.canRead === true) {
                 $('#policy-selected-controller-service-container 
div.policy-selected-component-name').text(d.component.name);
             } else {
                 $('#policy-selected-controller-service-container 
div.policy-selected-component-name').text(d.id);
@@ -949,7 +955,17 @@ nf.PolicyManagement = (function () {
 
             // populate the initial resource
             $('#selected-policy-component-id').text(d.id);
-            populateComponentResource('controller-services');
+            $('#selected-policy-component-type').text('controller-services');
+            $('#component-policy-target')
+                .combo('setOptionEnabled', {
+                    value: 'write-receive-data'
+                }, false)
+                .combo('setOptionEnabled', {
+                    value: 'write-send-data'
+                }, false)
+                .combo('setSelectedOption', {
+                    value: 'read-component'
+                });
 
             return loadPolicy().always(showPolicy);
         },
@@ -968,7 +984,7 @@ nf.PolicyManagement = (function () {
             $('#global-policy-controls').hide();
 
             // update the visibility
-            if (d.permissions.canRead) {
+            if (d.permissions.canRead === true) {
                 $('#policy-selected-reporting-task-container 
div.policy-selected-component-name').text(d.component.name);
             } else {
                 $('#policy-selected-reporting-task-container 
div.policy-selected-component-name').text(d.id);
@@ -977,7 +993,17 @@ nf.PolicyManagement = (function () {
             
             // populate the initial resource
             $('#selected-policy-component-id').text(d.id);
-            populateComponentResource('reporting-tasks');
+            $('#selected-policy-component-type').text('reporting-tasks');
+            $('#component-policy-target')
+                .combo('setOptionEnabled', {
+                    value: 'write-receive-data'
+                }, false)
+                .combo('setOptionEnabled', {
+                    value: 'write-send-data'
+                }, false)
+                .combo('setSelectedOption', {
+                    value: 'read-component'
+                });
 
             return loadPolicy().always(showPolicy);
         },
@@ -996,7 +1022,7 @@ nf.PolicyManagement = (function () {
             $('#global-policy-controls').hide();
 
             // update the visibility
-            if (d.permissions.canRead) {
+            if (d.permissions.canRead === true) {
                 $('#policy-selected-template-container 
div.policy-selected-component-name').text(d.template.name);
             } else {
                 $('#policy-selected-template-container 
div.policy-selected-component-name').text(d.id);
@@ -1005,7 +1031,17 @@ nf.PolicyManagement = (function () {
 
             // populate the initial resource
             $('#selected-policy-component-id').text(d.id);
-            populateComponentResource('templates');
+            $('#selected-policy-component-type').text('templates');
+            $('#component-policy-target')
+                .combo('setOptionEnabled', {
+                    value: 'write-receive-data'
+                }, false)
+                .combo('setOptionEnabled', {
+                    value: 'write-send-data'
+                }, false)
+                .combo('setSelectedOption', {
+                    value: 'read-component'
+                });
 
             return loadPolicy().always(showPolicy);
         },
@@ -1028,6 +1064,15 @@ nf.PolicyManagement = (function () {
             if (selection.empty()) {
                 
$('#selected-policy-component-id').text(nf.Canvas.getGroupId());
                 resource = 'process-groups';
+
+                // disable site to site option
+                $('#component-policy-target')
+                    .combo('setOptionEnabled', {
+                        value: 'write-receive-data'
+                    }, false)
+                    .combo('setOptionEnabled', {
+                        value: 'write-send-data'
+                    }, false);
             } else {
                 var d = selection.datum();
                 $('#selected-policy-component-id').text(d.id);
@@ -1059,7 +1104,10 @@ nf.PolicyManagement = (function () {
             }
 
             // populate the initial resource
-            populateComponentResource(resource);
+            $('#selected-policy-component-type').text(resource);
+            $('#component-policy-target').combo('setSelectedOption', {
+                value: 'read-component'
+            });
 
             return loadPolicy().always(showPolicy);
         },

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
 
b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
index e01c2b1..7e8b9a6 100644
--- 
a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
+++ 
b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/main/java/org/apache/nifi/provenance/PersistentProvenanceRepository.java
@@ -411,7 +411,7 @@ public class PersistentProvenanceRepository implements 
ProvenanceRepository {
 
         final Authorizable eventAuthorizable;
         try {
-            eventAuthorizable = 
resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+            eventAuthorizable = 
resourceFactory.createDataAuthorizable(event.getComponentId());
         } catch (final ResourceNotFoundException rnfe) {
             return false;
         }
@@ -425,7 +425,7 @@ public class PersistentProvenanceRepository implements 
ProvenanceRepository {
             return;
         }
 
-        final Authorizable eventAuthorizable = 
resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+        final Authorizable eventAuthorizable = 
resourceFactory.createDataAuthorizable(event.getComponentId());
         eventAuthorizable.authorize(authorizer, RequestAction.READ, user, 
event.getAttributes());
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/69586d8b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
 
b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
index b65d99d..10026cf 100644
--- 
a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
+++ 
b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/main/java/org/apache/nifi/provenance/VolatileProvenanceRepository.java
@@ -243,7 +243,7 @@ public class VolatileProvenanceRepository implements 
ProvenanceRepository {
 
         final Authorizable eventAuthorizable;
         try {
-            eventAuthorizable = 
resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+            eventAuthorizable = 
resourceFactory.createDataAuthorizable(event.getComponentId());
         } catch (final ResourceNotFoundException rnfe) {
             return false;
         }
@@ -257,7 +257,7 @@ public class VolatileProvenanceRepository implements 
ProvenanceRepository {
             return;
         }
 
-        final Authorizable eventAuthorizable = 
resourceFactory.createProvenanceAuthorizable(event.getComponentId());
+        final Authorizable eventAuthorizable = 
resourceFactory.createDataAuthorizable(event.getComponentId());
         eventAuthorizable.authorize(authorizer, RequestAction.READ, user, 
event.getAttributes());
     }
 

Reply via email to