nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From marka...@apache.org
Subject [4/9] nifi git commit: NIFI-2095: - Adding a page for managing users and groups. - Adding a page for managing access policies. - Renaming accessPolicy in entity to permissions to avoid confusion with the accessPolicy model. - Adding an Authorizable for a
Date Tue, 12 Jul 2016 21:00:07 GMT
http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestDataTransferResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestDataTransferResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestDataTransferResource.java
new file mode 100644
index 0000000..c23cc7d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestDataTransferResource.java
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.api;
+
+import org.apache.nifi.authorization.resource.ResourceType;
+import org.apache.nifi.remote.HttpRemoteSiteListener;
+import org.apache.nifi.remote.Peer;
+import org.apache.nifi.remote.RootGroupPort;
+import org.apache.nifi.remote.VersionNegotiator;
+import org.apache.nifi.remote.exception.HandshakeException;
+import org.apache.nifi.remote.io.http.HttpServerCommunicationsSession;
+import org.apache.nifi.remote.protocol.ResponseCode;
+import org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol;
+import org.apache.nifi.remote.protocol.http.HttpHeaders;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.api.entity.TransactionResultEntity;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+
+public class TestDataTransferResource {
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        final URL resource = TestDataTransferResource.class.getResource("/site-to-site/nifi.properties");
+        final String propertiesFile = resource.toURI().getPath();
+        System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, propertiesFile);
+    }
+
+    private HttpServletRequest createCommonHttpServletRequest() {
+        final HttpServletRequest req = mock(HttpServletRequest.class);
+        doReturn("1").when(req).getHeader(eq(HttpHeaders.PROTOCOL_VERSION));
+        return req;
+    }
+
+    @Test
+    public void testCreateTransactionPortNotFound() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+        final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
+
+        doThrow(new HandshakeException(ResponseCode.UNKNOWN_PORT, "Not found.")).when(serverProtocol).handshake(any());
+
+        final ServletContext context = null;
+        final UriInfo uriInfo = null;
+        final InputStream inputStream = null;
+
+        final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(404, response.getStatus());
+        assertEquals(ResponseCode.UNKNOWN_PORT.getCode(), resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testCreateTransactionPortNotInValidState() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+        final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
+
+        doThrow(new HandshakeException(ResponseCode.PORT_NOT_IN_VALID_STATE, "Not in valid state.")).when(serverProtocol).handshake(any());
+
+        final ServletContext context = null;
+        final UriInfo uriInfo = null;
+        final InputStream inputStream = null;
+
+        final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(503, response.getStatus());
+        assertEquals(ResponseCode.PORT_NOT_IN_VALID_STATE.getCode(), resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testCreateTransactionUnauthorized() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+        final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
+
+        doThrow(new HandshakeException(ResponseCode.UNAUTHORIZED, "Unauthorized.")).when(serverProtocol).handshake(any());
+
+        final ServletContext context = null;
+        final UriInfo uriInfo = null;
+        final InputStream inputStream = null;
+
+        final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(401, response.getStatus());
+        assertEquals(ResponseCode.UNAUTHORIZED.getCode(), resultEntity.getResponseCode());
+    }
+
+    private UriInfo mockUriInfo(final String locationUriStr) throws URISyntaxException {
+        final UriInfo uriInfo = mock(UriInfo.class);
+        final UriBuilder uriBuilder = mock(UriBuilder.class);
+
+        final URI locationUri = new URI(locationUriStr);
+        doReturn(uriBuilder).when(uriInfo).getBaseUriBuilder();
+        doReturn(uriBuilder).when(uriBuilder).path(any(String.class));
+        doReturn(locationUri).when(uriBuilder).build();
+        return uriInfo;
+    }
+
+    @Test
+    public void testCreateTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+
+        final String locationUriStr = "http://localhost:8080/nifi-api/data-transfer/input-ports/port-id/transactions/transaction-id";
+
+        final ServletContext context = null;
+        final UriInfo uriInfo = mockUriInfo(locationUriStr);
+        final InputStream inputStream = null;
+
+       final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(201, response.getStatus());
+        assertEquals(ResponseCode.PROPERTIES_OK.getCode(), resultEntity.getResponseCode());
+        assertEquals(locationUriStr, response.getMetadata().getFirst(HttpHeaders.LOCATION_HEADER_NAME).toString());
+    }
+
+    @Test
+    public void testExtendTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+
+        final String locationUriStr = "http://localhost:8080/nifi-api/data-transfer/input-ports/port-id/transactions/transaction-id";
+
+        final ServletContext context = null;
+        final HttpServletResponse res = null;
+        final UriInfo uriInfo = mockUriInfo(locationUriStr);
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.extendPortTransactionTTL("input-ports", "port-id", transactionId, req, res, context, uriInfo, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(ResponseCode.CONTINUE_TRANSACTION.getCode(), resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testReceiveFlowFiles() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+        final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
+
+        final RootGroupPort port = mock(RootGroupPort.class);
+        doReturn(port).when(serverProtocol).getPort();
+        doAnswer(invocation -> {
+            Peer peer = (Peer) invocation.getArguments()[0];
+            ((HttpServerCommunicationsSession)peer.getCommunicationsSession()).setChecksum("server-checksum");
+            return 7;
+        }).when(port).receiveFlowFiles(any(Peer.class), any());
+
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.receiveFlowFiles("port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        final Object entity = response.getEntity();
+
+        assertEquals(202, response.getStatus());
+        assertEquals("server-checksum", entity);
+    }
+
+    @Test
+    public void testReceiveZeroFlowFiles() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+        final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
+
+        final RootGroupPort port = mock(RootGroupPort.class);
+        doReturn(port).when(serverProtocol).getPort();
+        doAnswer(invocation -> 0).when(port).receiveFlowFiles(any(Peer.class), any());
+
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.receiveFlowFiles("port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        assertEquals(400, response.getStatus());
+    }
+
+    @Test
+    public void testCommitInputPortTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.commitInputPortTransaction(ResponseCode.CONFIRM_TRANSACTION.getCode(), "port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(ResponseCode.CONFIRM_TRANSACTION.getCode(), resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testTransferFlowFiles() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+
+        final ServletContext context = null;
+        final HttpServletResponse res = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.transferFlowFiles("port-id", transactionId, req, res, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        final Object entity = response.getEntity();
+
+        assertEquals(202, response.getStatus());
+        assertTrue(entity instanceof StreamingOutput);
+    }
+
+    @Test
+    public void testCommitOutputPortTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.commitOutputPortTransaction(ResponseCode.CONFIRM_TRANSACTION.getCode(),
+                "client-checksum", "port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(ResponseCode.CONFIRM_TRANSACTION.getCode(), resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testCommitOutputPortTransactionBadChecksum() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final DataTransferResource resource = getDataTransferResource();
+        final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
+
+        doThrow(new HandshakeException(ResponseCode.BAD_CHECKSUM, "Bad checksum.")).when(serverProtocol).commitTransferTransaction(any(), any());
+
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.commitOutputPortTransaction(ResponseCode.CONFIRM_TRANSACTION.getCode(),
+                "client-checksum", "port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
+
+        assertEquals(400, response.getStatus());
+        assertEquals(ResponseCode.BAD_CHECKSUM.getCode(), resultEntity.getResponseCode());
+    }
+
+    private DataTransferResource getDataTransferResource() {
+        final HttpFlowFileServerProtocol serverProtocol = mock(HttpFlowFileServerProtocol.class);
+        final DataTransferResource resource = new DataTransferResource() {
+            @Override
+            protected void authorizeDataTransfer(ResourceType resourceType, String identifier) {
+            }
+
+            @Override
+            HttpFlowFileServerProtocol getHttpFlowFileServerProtocol(VersionNegotiator versionNegotiator) {
+                return serverProtocol;
+            }
+        };
+        resource.setProperties(NiFiProperties.getInstance());
+        return resource;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
index 79cb623..8b65c3a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
@@ -16,14 +16,7 @@
  */
 package org.apache.nifi.web.api;
 
-import org.apache.nifi.remote.HttpRemoteSiteListener;
-import org.apache.nifi.remote.Peer;
-import org.apache.nifi.remote.RootGroupPort;
-import org.apache.nifi.remote.VersionNegotiator;
-import org.apache.nifi.remote.exception.HandshakeException;
-import org.apache.nifi.remote.io.http.HttpServerCommunicationsSession;
 import org.apache.nifi.remote.protocol.ResponseCode;
-import org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol;
 import org.apache.nifi.remote.protocol.http.HttpHeaders;
 import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.web.NiFiServiceFacade;
@@ -31,32 +24,18 @@ import org.apache.nifi.web.api.dto.ControllerDTO;
 import org.apache.nifi.web.api.entity.ControllerEntity;
 import org.apache.nifi.web.api.entity.PeersEntity;
 import org.apache.nifi.web.api.entity.TransactionResultEntity;
-import org.apache.nifi.web.api.request.ClientIdParameter;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.StreamingOutput;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.net.URL;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 
 public class TestSiteToSiteResource {
 
@@ -78,12 +57,10 @@ public class TestSiteToSiteResource {
         controller.setRemoteSiteHttpListeningPort(8080);
         controller.setRemoteSiteListeningPort(9990);
 
-        doReturn(controller).when(serviceFacade).getController();
+        doReturn(controller).when(serviceFacade).getSiteToSiteDetails();
 
-        final SiteToSiteResource resource = new SiteToSiteResource();
-        resource.setProperties(NiFiProperties.getInstance());
-        resource.setServiceFacade(serviceFacade);
-        final Response response = resource.getSiteToSite(req);
+        final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade);
+        final Response response = resource.getSiteToSiteDetails(req);
 
         ControllerEntity resultEntity = (ControllerEntity)response.getEntity();
 
@@ -105,12 +82,10 @@ public class TestSiteToSiteResource {
         controller.setRemoteSiteHttpListeningPort(8080);
         controller.setRemoteSiteListeningPort(9990);
 
-        doReturn(controller).when(serviceFacade).getController();
+        doReturn(controller).when(serviceFacade).getSiteToSiteDetails();
 
-        final SiteToSiteResource resource = new SiteToSiteResource();
-        resource.setProperties(NiFiProperties.getInstance());
-        resource.setServiceFacade(serviceFacade);
-        final Response response = resource.getSiteToSite(req);
+        final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade);
+        final Response response = resource.getSiteToSiteDetails(req);
 
         ControllerEntity resultEntity = (ControllerEntity)response.getEntity();
 
@@ -131,11 +106,9 @@ public class TestSiteToSiteResource {
 
         final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
 
-        final SiteToSiteResource resource = new SiteToSiteResource();
-        resource.setProperties(NiFiProperties.getInstance());
-        resource.setServiceFacade(serviceFacade);
+        final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade);
 
-        final Response response = resource.getPeers(null, req);
+        final Response response = resource.getPeers(req);
 
         PeersEntity resultEntity = (PeersEntity) response.getEntity();
 
@@ -150,11 +123,9 @@ public class TestSiteToSiteResource {
 
         final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
 
-        final SiteToSiteResource resource = new SiteToSiteResource();
-        resource.setProperties(NiFiProperties.getInstance());
-        resource.setServiceFacade(serviceFacade);
+        final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade);
 
-        final Response response = resource.getPeers(null, req);
+        final Response response = resource.getPeers(req);
 
         TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
         assertEquals(400, response.getStatus());
@@ -168,11 +139,9 @@ public class TestSiteToSiteResource {
 
         final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
 
-        final SiteToSiteResource resource = new SiteToSiteResource();
-        resource.setProperties(NiFiProperties.getInstance());
-        resource.setServiceFacade(serviceFacade);
+        final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade);
 
-        final Response response = resource.getPeers(null, req);
+        final Response response = resource.getPeers(req);
 
         PeersEntity resultEntity = (PeersEntity) response.getEntity();
 
@@ -181,336 +150,14 @@ public class TestSiteToSiteResource {
         assertEquals(new Integer(1), response.getMetadata().getFirst(HttpHeaders.PROTOCOL_VERSION));
     }
 
-    @Test
-    public void testCreateTransactionPortNotFound() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        final HttpFlowFileServerProtocol serverProtocol = mockHttpFlowFileServerProtocol(resource);
-
-        doThrow(new HandshakeException(ResponseCode.UNKNOWN_PORT, "Not found.")).when(serverProtocol).handshake(any());
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final UriInfo uriInfo = null;
-        final InputStream inputStream = null;
-
-        final Response response = resource.createPortTransaction(clientId, "input-ports", "port-id", req, context, uriInfo, inputStream);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(404, response.getStatus());
-        assertEquals(ResponseCode.UNKNOWN_PORT.getCode(), resultEntity.getResponseCode());
-    }
-
-    @Test
-    public void testCreateTransactionPortNotInValidState() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        final HttpFlowFileServerProtocol serverProtocol = mockHttpFlowFileServerProtocol(resource);
-
-        doThrow(new HandshakeException(ResponseCode.PORT_NOT_IN_VALID_STATE, "Not in valid state.")).when(serverProtocol).handshake(any());
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final UriInfo uriInfo = null;
-        final InputStream inputStream = null;
-
-        final Response response = resource.createPortTransaction(clientId, "input-ports", "port-id", req, context, uriInfo, inputStream);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(503, response.getStatus());
-        assertEquals(ResponseCode.PORT_NOT_IN_VALID_STATE.getCode(), resultEntity.getResponseCode());
-    }
-
-    @Test
-    public void testCreateTransactionUnauthorized() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        final HttpFlowFileServerProtocol serverProtocol = mockHttpFlowFileServerProtocol(resource);
-
-        doThrow(new HandshakeException(ResponseCode.UNAUTHORIZED, "Unauthorized.")).when(serverProtocol).handshake(any());
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final UriInfo uriInfo = null;
-        final InputStream inputStream = null;
-
-        final Response response = resource.createPortTransaction(clientId, "input-ports", "port-id", req, context, uriInfo, inputStream);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(401, response.getStatus());
-        assertEquals(ResponseCode.UNAUTHORIZED.getCode(), resultEntity.getResponseCode());
-    }
-
-    private UriInfo mockUriInfo(final String locationUriStr) throws URISyntaxException {
-        final UriInfo uriInfo = mock(UriInfo.class);
-        final UriBuilder uriBuilder = mock(UriBuilder.class);
-
-        final URI locationUri = new URI(locationUriStr);
-        doReturn(uriBuilder).when(uriInfo).getBaseUriBuilder();
-        doReturn(uriBuilder).when(uriBuilder).path(any(String.class));
-        doReturn(locationUri).when(uriBuilder).build();
-        return uriInfo;
-    }
-
-    @Test
-    public void testCreateTransaction() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        mockHttpFlowFileServerProtocol(resource);
-
-        final String locationUriStr = "http://localhost:8080/nifi-api/site-to-site/input-ports/port-id/transactions/transaction-id";
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final UriInfo uriInfo = mockUriInfo(locationUriStr);
-        final InputStream inputStream = null;
-
-       final Response response = resource.createPortTransaction(clientId, "input-ports", "port-id", req, context, uriInfo, inputStream);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(201, response.getStatus());
-        assertEquals(ResponseCode.PROPERTIES_OK.getCode(), resultEntity.getResponseCode());
-        assertEquals(locationUriStr, response.getMetadata().getFirst(HttpHeaders.LOCATION_HEADER_NAME).toString());
-    }
-
-    @Test
-    public void testExtendTransaction() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        mockHttpFlowFileServerProtocol(resource);
-
-        final String locationUriStr = "http://localhost:8080/nifi-api/site-to-site/input-ports/port-id/transactions/transaction-id";
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final HttpServletResponse res = null;
-        final UriInfo uriInfo = mockUriInfo(locationUriStr);
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.extendPortTransactionTTL(clientId, "input-ports", "port-id", transactionId, req, res, context, uriInfo, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(200, response.getStatus());
-        assertEquals(ResponseCode.CONTINUE_TRANSACTION.getCode(), resultEntity.getResponseCode());
-    }
-
-    @Test
-    public void testReceiveFlowFiles() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        final HttpFlowFileServerProtocol serverProtocol = mockHttpFlowFileServerProtocol(resource);
-
-        final RootGroupPort port = mock(RootGroupPort.class);
-        doReturn(port).when(serverProtocol).getPort();
-        doAnswer(invocation -> {
-            Peer peer = (Peer) invocation.getArguments()[0];
-            ((HttpServerCommunicationsSession)peer.getCommunicationsSession()).setChecksum("server-checksum");
-            return 7;
-        }).when(port).receiveFlowFiles(any(Peer.class), any());
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.receiveFlowFiles(clientId, "port-id", transactionId, req, context, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        final Object entity = response.getEntity();
-
-        assertEquals(202, response.getStatus());
-        assertEquals("server-checksum", entity);
-    }
-
-    @Test
-    public void testReceiveZeroFlowFiles() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        final HttpFlowFileServerProtocol serverProtocol = mockHttpFlowFileServerProtocol(resource);
-
-        final RootGroupPort port = mock(RootGroupPort.class);
-        doReturn(port).when(serverProtocol).getPort();
-        doAnswer(invocation -> 0).when(port).receiveFlowFiles(any(Peer.class), any());
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.receiveFlowFiles(clientId, "port-id", transactionId, req, context, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        assertEquals(400, response.getStatus());
-    }
-
-    @Test
-    public void testCommitInputPortTransaction() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        mockHttpFlowFileServerProtocol(resource);
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.commitInputPortTransaction(clientId, ResponseCode.CONFIRM_TRANSACTION.getCode(), "port-id", transactionId, req, context, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(200, response.getStatus());
-        assertEquals(ResponseCode.CONFIRM_TRANSACTION.getCode(), resultEntity.getResponseCode());
-    }
-
-    @Test
-    public void testTransferFlowFiles() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        mockHttpFlowFileServerProtocol(resource);
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final HttpServletResponse res = null;
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.transferFlowFiles(clientId, "port-id", transactionId, req, res, context, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        final Object entity = response.getEntity();
-
-        assertEquals(202, response.getStatus());
-        assertTrue(entity instanceof StreamingOutput);
-    }
-
-    @Test
-    public void testCommitOutputPortTransaction() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        mockHttpFlowFileServerProtocol(resource);
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.commitOutputPortTransaction(clientId, ResponseCode.CONFIRM_TRANSACTION.getCode(),
-                "client-checksum", "port-id", transactionId, req, context, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(200, response.getStatus());
-        assertEquals(ResponseCode.CONFIRM_TRANSACTION.getCode(), resultEntity.getResponseCode());
-    }
-
-    @Test
-    public void testCommitOutputPortTransactionBadChecksum() throws Exception {
-        final HttpServletRequest req = createCommonHttpServletRequest();
-
-        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
-
-        final SiteToSiteResource resource = spySiteToSiteResource(serviceFacade);
-
-        final HttpFlowFileServerProtocol serverProtocol = mockHttpFlowFileServerProtocol(resource);
-        doThrow(new HandshakeException(ResponseCode.BAD_CHECKSUM, "Bad checksum.")).when(serverProtocol).commitTransferTransaction(any(), any());
-
-        final ClientIdParameter clientId = new ClientIdParameter("client-id");
-        final ServletContext context = null;
-        final InputStream inputStream = null;
-
-        final HttpRemoteSiteListener transactionManager = HttpRemoteSiteListener.getInstance();
-        final String transactionId = transactionManager.createTransaction();
-
-        final Response response = resource.commitOutputPortTransaction(clientId, ResponseCode.CONFIRM_TRANSACTION.getCode(),
-                "client-checksum", "port-id", transactionId, req, context, inputStream);
-
-        transactionManager.cancelTransaction(transactionId);
-
-        TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
-
-        assertEquals(400, response.getStatus());
-        assertEquals(ResponseCode.BAD_CHECKSUM.getCode(), resultEntity.getResponseCode());
-    }
-
-    private HttpFlowFileServerProtocol mockHttpFlowFileServerProtocol(SiteToSiteResource resource) {
-        final HttpFlowFileServerProtocol serverProtocol = mock(HttpFlowFileServerProtocol.class);
-        doReturn(serverProtocol).when(resource).getHttpFlowFileServerProtocol(any(VersionNegotiator.class));
-        return serverProtocol;
-    }
-
-    private SiteToSiteResource spySiteToSiteResource(NiFiServiceFacade serviceFacade) {
-        final SiteToSiteResource resource = spy(SiteToSiteResource.class);
+    private SiteToSiteResource getSiteToSiteResource(final NiFiServiceFacade serviceFacade) {
+        final SiteToSiteResource resource = new SiteToSiteResource() {
+            @Override
+            protected void authorizeSiteToSite() {
+            }
+        };
         resource.setProperties(NiFiProperties.getInstance());
         resource.setServiceFacade(serviceFacade);
         return resource;
     }
-
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
index 1b65f0b..c09bd8a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml
@@ -32,6 +32,7 @@
         <counters.filter>counters.properties</counters.filter>
         <cluster.filter>cluster.properties</cluster.filter>
         <templates.filter>templates.properties</templates.filter>
+        <users.filter>users.properties</users.filter>
         <bulletin.board.filter>bulletin-board.properties</bulletin.board.filter>
         <login.filter>login.properties</login.filter>
         <provenance.filter>provenance.properties</provenance.filter>
@@ -61,6 +62,7 @@
             <filter>src/main/resources/filters/${counters.filter}</filter>
             <filter>src/main/resources/filters/${cluster.filter}</filter>
             <filter>src/main/resources/filters/${templates.filter}</filter>
+            <filter>src/main/resources/filters/${users.filter}</filter>
             <filter>src/main/resources/filters/${bulletin.board.filter}</filter>
             <filter>src/main/resources/filters/${login.filter}</filter>
             <filter>src/main/resources/filters/${provenance.filter}</filter>
@@ -96,6 +98,7 @@
                                 **/counters.jsp,
                                 **/cluster.jsp,
                                 **/templates.jsp,
+                                **/users.jsp,
                                 **/bulletin-board.jsp,
                                 **/login.jsp
                             </excludes>
@@ -209,6 +212,14 @@
                             <directory>src/main/webapp/WEB-INF/pages</directory>
                             <targetPath>WEB-INF/pages</targetPath>
                             <includes>
+                                <include>users.jsp</include>
+                            </includes>
+                            <filtering>true</filtering>
+                        </resource>
+                        <resource>
+                            <directory>src/main/webapp/WEB-INF/pages</directory>
+                            <targetPath>WEB-INF/pages</targetPath>
+                            <includes>
                                 <include>templates.jsp</include>
                             </includes>
                             <filtering>true</filtering>
@@ -247,7 +258,6 @@
                 <configuration>
                     <installDirectory>${frontend.working.dir}</installDirectory>
                 </configuration>
-
                 <executions>
                     <execution>
                         <id>install-node-and-npm</id>
@@ -297,6 +307,7 @@
                 <counters.filter>counters-min.properties</counters.filter>
                 <cluster.filter>cluster-min.properties</cluster.filter>
                 <templates.filter>templates-min.properties</templates.filter>
+                <users.filter>users-min.properties</users.filter>
                 <bulletin.board.filter>bulletin-board-min.properties</bulletin.board.filter>
                 <login.filter>login-min.properties</login.filter>
                 <provenance.filter>provenance-min.properties</provenance.filter>
@@ -346,7 +357,7 @@
                                                 <include>${staging.dir}/js/nf/canvas/nf-processor-configuration.js</include>
                                                 <include>${staging.dir}/js/nf/nf-processor-details.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-process-group-configuration.js</include>
-                                                <include>${staging.dir}/js/nf/canvas/nf-process-group-details.js</include>
+                                                <include>${staging.dir}/js/nf/canvas/nf-policy-management.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-remote-process-group-configuration.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-remote-process-group-details.js</include>
                                                 <include>${staging.dir}/js/nf/canvas/nf-remote-process-group-ports.js</include>
@@ -466,6 +477,20 @@
                                         </aggregation>
                                         <aggregation>
                                             <insertNewLine>true</insertNewLine>
+                                            <output>${project.build.directory}/${project.build.finalName}/js/nf/users/nf-users-all.js</output>
+                                            <includes>
+                                                <include>${staging.dir}/js/nf/nf-client.js</include>
+                                                <include>${staging.dir}/js/nf/nf-common.js</include>
+                                                <include>${staging.dir}/js/nf/nf-universal-capture.js</include>
+                                                <include>${staging.dir}/js/nf/nf-dialog.js</include>
+                                                <include>${staging.dir}/js/nf/nf-storage.js</include>
+                                                <include>${staging.dir}/js/nf/nf-ajax-setup.js</include>
+                                                <include>${staging.dir}/js/nf/users/nf-users.js</include>
+                                                <include>${staging.dir}/js/nf/users/nf-users-table.js</include>
+                                            </includes>
+                                        </aggregation>
+                                        <aggregation>
+                                            <insertNewLine>true</insertNewLine>
                                             <output>${project.build.directory}/${project.build.finalName}/js/nf/templates/nf-templates-all.js</output>
                                             <includes>
                                                 <include>${staging.dir}/js/nf/nf-client.js</include>
@@ -531,7 +556,7 @@
                                                 <include>${staging.dir}/css/processor-configuration.css</include>
                                                 <include>${staging.dir}/css/processor-details.css</include>
                                                 <include>${staging.dir}/css/process-group-configuration.css</include>
-                                                <include>${staging.dir}/css/process-group-details.css</include>
+                                                <include>${staging.dir}/css/policy-management.css</include>
                                                 <include>${staging.dir}/css/remote-process-group-configuration.css</include>
                                                 <include>${staging.dir}/css/port-configuration.css</include>
                                                 <include>${staging.dir}/css/port-details.css</include>
@@ -611,6 +636,16 @@
                                         </aggregation>
                                         <aggregation>
                                             <insertNewLine>true</insertNewLine>
+                                            <output>${project.build.directory}/${project.build.finalName}/css/nf-users-all.css</output>
+                                            <includes>
+                                                <include>${staging.dir}/css/main.css</include>
+                                                <include>${staging.dir}/css/banner.css</include>
+                                                <include>${staging.dir}/css/dialog.css</include>
+                                                <include>${staging.dir}/css/users.css</include>
+                                            </includes>
+                                        </aggregation>
+                                        <aggregation>
+                                            <insertNewLine>true</insertNewLine>
                                             <output>${project.build.directory}/${project.build.finalName}/css/nf-templates-all.css</output>
                                             <includes>
                                                 <include>${staging.dir}/css/main.css</include>
@@ -673,6 +708,8 @@
                                 css/nf-counters-all.css.gz,
                                 css/nf-cluster-all.css,
                                 css/nf-cluster-all.css.gz,
+                                css/nf-users-all.css,
+                                css/nf-users-all.css.gz,
                                 css/nf-templates-all.css,
                                 css/nf-templates-all.css.gz,
                                 css/nf-bulletin-board-all.css,
@@ -712,6 +749,8 @@
                                 js/nf/counters/nf-counters-all.js.gz,
                                 js/nf/cluster/nf-cluster-all.js,
                                 js/nf/cluster/nf-cluster-all.js.gz,
+                                js/nf/users/nf-users-all.js,
+                                js/nf/users/nf-users-all.js.gz,
                                 js/nf/templates/nf-templates-all.js,
                                 js/nf/templates/nf-templates-all.js.gz,
                                 js/nf/bulletin-board/nf-bulletin-board-all.js,

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/bulletin-board.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/bulletin-board.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/bulletin-board.properties
index a4afc92..72f99a5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/bulletin-board.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/bulletin-board.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.bulletin.board.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.bulletin.board.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
index f3d3941..0f219d4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/canvas.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-client.js?${project.version}"></script>\n\
+nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-client.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-canvas-utils.js?${project.version}"></script>\n\
@@ -32,7 +31,7 @@ nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?
 <script type="text/javascript" src="js/nf/canvas/nf-processor-configuration.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-processor-details.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-process-group-configuration.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/canvas/nf-process-group-details.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/canvas/nf-policy-management.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-remote-process-group-configuration.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-remote-process-group-details.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/canvas/nf-remote-process-group-ports.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/cluster.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/cluster.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/cluster.properties
index 0fb872c..9061e02 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/cluster.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/cluster.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.cluster.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.cluster.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/counters.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/counters.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/counters.properties
index 4c947b4..4414909 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/counters.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/counters.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.counters.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.counters.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/history.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/history.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/history.properties
index 6cee206..e532204 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/history.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/history.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.history.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.history.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/provenance.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/provenance.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/provenance.properties
index a87195c..8536bf9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/provenance.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/provenance.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.provenance.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.provenance.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/summary.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/summary.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/summary.properties
index 33e1a5a..52dfe49 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/summary.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/summary.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.summary.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.summary.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/templates.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/templates.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/templates.properties
index c0cee4c..7ad302c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/templates.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/templates.properties
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-nf.templates.script.tags=<script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>\n\
-<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+nf.templates.script.tags=<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
 <script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users-min.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users-min.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users-min.properties
new file mode 100644
index 0000000..9375334
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users-min.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nf.users.script.tags=<script type="text/javascript" src="js/nf/users/nf-users-all.js?${project.version}"></script>
+nf.users.style.tags=<link rel="stylesheet" href="css/nf-users-all.css?${project.version}" type="text/css" />\n\
+<link rel="stylesheet" href="css/message-pane.css?${project.version}" type="text/css" />
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users.properties
new file mode 100644
index 0000000..b2dee8e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/resources/filters/users.properties
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nf.users.script.tags=<script type="text/javascript" src="js/nf/nf-client.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/nf-common.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/nf-universal-capture.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/nf-dialog.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/nf-storage.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/nf-ajax-setup.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/users/nf-users.js?${project.version}"></script>\n\
+<script type="text/javascript" src="js/nf/users/nf-users-table.js?${project.version}"></script>
+nf.users.style.tags=<link rel="stylesheet" href="css/reset.css?${project.version}" type="text/css" />\n\
+<link rel="stylesheet" href="css/main.css?${project.version}" type="text/css" />\n\
+<link rel="stylesheet" href="css/banner.css?${project.version}" type="text/css" />\n\
+<link rel="stylesheet" href="css/dialog.css?${project.version}" type="text/css" />\n\
+<link rel="stylesheet" href="css/message-pane.css?${project.version}" type="text/css" />\n\
+<link rel="stylesheet" href="css/users.css?${project.version}" type="text/css" />
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
index 39fdffd..44f284a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/canvas.jsp
@@ -95,6 +95,7 @@
         <jsp:include page="/WEB-INF/partials/ok-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/yes-no-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/status-history-dialog.jsp"/>
+        <jsp:include page="/WEB-INF/partials/canvas/search-users-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/disable-controller-service-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/enable-controller-service-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/new-controller-service-dialog.jsp"/>
@@ -123,6 +124,7 @@
         <jsp:include page="/WEB-INF/partials/canvas/processor-configuration.jsp"/>
         <jsp:include page="/WEB-INF/partials/processor-details.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/process-group-configuration.jsp"/>
+        <jsp:include page="/WEB-INF/partials/canvas/policy-management.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/process-group-details.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/remote-process-group-configuration.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/remote-process-group-details.jsp"/>

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
new file mode 100644
index 0000000..473f538
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp
@@ -0,0 +1,70 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>NiFi Users</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <link rel="shortcut icon" href="images/nifi16.ico"/>
+        <link rel="stylesheet" href="css/reset.css" type="text/css" />
+        ${nf.users.style.tags}
+        <link rel="stylesheet" href="js/jquery/tabbs/jquery.tabbs.css?${project.version}" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/combo/jquery.combo.css?${project.version}" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/modal/jquery.modal.css?${project.version}" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/ui-smoothness/jquery-ui-1.10.4.min.css" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
+        <link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
+        <link rel="stylesheet" href="fonts/flowfont/flowfont.css" type="text/css" />
+        <link rel="stylesheet" href="assets/font-awesome/css/font-awesome.min.css" type="text/css" />
+        <script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
+        <script type="text/javascript" src="js/jquery/ui-smoothness/jquery-ui-1.10.4.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.center.js"></script>
+        <script type="text/javascript" src="js/jquery/tabbs/jquery.tabbs.js?${project.version}"></script>
+        <script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>
+        <script type="text/javascript" src="js/jquery/propertytable/jquery.propertytable.js?${project.version}"></script>
+        <script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>
+        <script type="text/javascript" src="js/jquery/jquery.ellipsis.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.each.js"></script>
+        <script type="text/javascript" src="js/jquery/qtip2/jquery.qtip.min.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.event.drag-2.2.min.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellrangeselector.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.cellselectionmodel.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.rowselectionmodel.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/plugins/slick.autotooltips.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/slick.formatters.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/slick.editors.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/slick.dataview.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/slick.core.js"></script>
+        <script type="text/javascript" src="js/jquery/slickgrid/slick.grid.js"></script>
+        <script type="text/javascript" src="js/nf/nf-namespace.js?${project.version}"></script>
+        <script type="text/javascript" src="js/nf/nf-ng-namespace.js?${project.version}"></script>
+        ${nf.users.script.tags}
+        <script type="text/javascript" src="js/jquery/nfeditor/languages/nfel.js?${project.version}"></script>
+        <script type="text/javascript" src="js/jquery/nfeditor/jquery.nfeditor.js?${project.version}"></script>
+    </head>
+    <body ng-controller="ngSummaryAppCtrl">
+        <jsp:include page="/WEB-INF/partials/message-pane.jsp"/>
+        <jsp:include page="/WEB-INF/partials/banners-utility.jsp"/>
+        <jsp:include page="/WEB-INF/partials/ok-dialog.jsp"/>
+        <jsp:include page="/WEB-INF/partials/users/user-dialog.jsp"/>
+        <jsp:include page="/WEB-INF/partials/users/user-delete-dialog.jsp"/>
+        <jsp:include page="/WEB-INF/partials/users/users-content.jsp"/>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/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 7d3bcc0..d4d7aed 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
@@ -147,12 +147,19 @@
                             <i class="fa fa-history"></i>Flow Configuration History
                         </a>
                     </md-menu-item>
+                    <md-menu-divider></md-menu-divider>
                     <md-menu-item layout-align="space-around center">
                         <a id="users-link" layout="row"
                            ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.users.shell.launch();"
-                           ng-class="{disabled: !appCtrl.nf.Common.canAccessTenants()}">
+                           ng-class="{disabled: !appCtrl.nf.Common.canModifyTenants()}">
                             <i class="fa fa-users"></i>Users
-                            <div id="has-pending-accounts" class="hidden"></div>
+                        </a>
+                    </md-menu-item>
+                    <md-menu-item layout-align="space-around center">
+                        <a id="policies-link" layout="row"
+                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.policies.shell.launch();"
+                           ng-class="{disabled: !(appCtrl.nf.Common.canAccessTenants() && appCtrl.nf.Common.canModifyPolicies())}">
+                            <i class="fa fa-key"></i>Policies
                         </a>
                     </md-menu-item>
                     <md-menu-divider></md-menu-divider>

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/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 b2b2606..a15dee1 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
@@ -99,6 +99,12 @@
                                 ng-disabled="false">
                             <div class="graph-control-action-icon fa fa-gear"></div></button>
                     </div>
+                    <div class="button-spacer-small">&nbsp;</div>
+                    <div id="operate-policy" class="action-button" title="Access Policies">
+                        <button ng-click="appCtrl.nf.Actions['managePolicies'](appCtrl.nf.CanvasUtils.getSelection());"
+                                ng-disabled="appCtrl.nf.CanvasUtils.getSelection().size() > 1">
+                            <div class="graph-control-action-icon fa fa-key"></div></button>
+                    </div>
                     <div class="button-spacer-large">&nbsp;</div>
                     <div id="operate-enable" class="action-button" title="Enable">
                         <button ng-click="appCtrl.nf.Actions['enable'](appCtrl.nf.CanvasUtils.getSelection());"

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
new file mode 100644
index 0000000..926b6f1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
@@ -0,0 +1,92 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="policy-management">
+    <div id="policy-management-header-text">Access Policies</div>
+    <div id="policy-controls-container">
+        <span id="selected-policy-action" class="hidden"></span>
+        <span id="selected-policy-type" class="hidden"></span>
+        <div id="policy-message-container">
+            <div id="policy-message"></div>
+            <div id="new-policy-message" class="hidden"><span id="create-policy-link" class="link">Create</span> a new policy.</div>
+            <div id="override-policy-message" class="hidden"><span id="override-policy-link" class="link">Override</span> this policy.</div>
+            <div class="clear"></div>
+        </div>
+        <div id="global-policy-controls" class="hidden policy-controls">
+            <div id="policy-type-list"></div>
+            <div id="controller-policy-target"></div>
+            <div class="clear"></div>
+        </div>
+        <div id="component-policy-controls" class="hidden policy-controls">
+            <div id="policy-selected-component-container" class="hidden policy-selected-component-container">
+                <div class="policy-selected-component-type-icon">
+                    <i class="icon icon-drop" ng-class="appCtrl.serviceProvider.graphControlsCtrl.getContextIcon()"></i>
+                </div>
+                <div class="policy-selected-component-details-container">
+                    <div class="policy-selected-component-name">{{appCtrl.serviceProvider.graphControlsCtrl.getContextName()}}</div>
+                    <div class="policy-selected-component-type" ng-class="appCtrl.serviceProvider.graphControlsCtrl.hide()">{{appCtrl.serviceProvider.graphControlsCtrl.getContextType()}}</div>
+                </div>
+                <div class="clear"></div>
+            </div>
+            <div id="policy-selected-template-container" class="hidden policy-selected-component-container">
+                <div class="policy-selected-component-type-icon">
+                    <i class="icon icon-template"></i>
+                </div>
+                <div class="policy-selected-component-details-container">
+                    <div class="policy-selected-component-name"></div>
+                    <div class="policy-selected-component-type">Template</div>
+                </div>
+                <div class="clear"></div>
+            </div>
+            <div id="policy-selected-controller-service-container" class="hidden policy-selected-component-container">
+                <div class="policy-selected-component-type-icon">
+                    <i class="icon icon-drop"></i>
+                </div>
+                <div class="policy-selected-component-details-container">
+                    <div class="policy-selected-component-name"></div>
+                    <div class="policy-selected-component-type">Controller Service</div>
+                </div>
+                <div class="clear"></div>
+            </div>
+            <div id="policy-selected-reporting-task-container" class="hidden policy-selected-component-container">
+                <div class="policy-selected-component-type-icon">
+                    <i class="icon icon-drop"></i>
+                </div>
+                <div class="policy-selected-component-details-container">
+                    <div class="policy-selected-component-name"></div>
+                    <div class="policy-selected-component-type">Reporting Task</div>
+                </div>
+                <div class="clear"></div>
+            </div>
+            <div id="selected-policy-component-id" class="hidden"></div>
+            <div id="selected-policy-component-type" class="hidden"></div>
+            <div id="component-policy-target"></div>
+            <div class="clear"></div>
+        </div>
+        <button id="delete-policy-button" class="fa fa-trash policy-button"></button>
+        <button id="new-policy-user-button" class="fa fa-user-plus policy-button"></button>
+        <div class="clear"></div>
+    </div>
+    <div id="policy-table"></div>
+    <div id="policy-refresh-container">
+        <button id="policy-refresh-button" class="refresh-button pointer fa fa-refresh" title="Refresh"></button>
+        <div class="last-refreshed-container">
+            Last updated:&nbsp;<span id="policy-last-refreshed" class="last-refreshed"></span>
+        </div>
+        <div id="policy-loading-container" class="loading-container"></div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
new file mode 100644
index 0000000..03c62ca
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
@@ -0,0 +1,23 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="search-users-dialog" class="hidden">
+    <div class="dialog-content">
+        <input id="search-users-field" type="text" placeholder="User Identity"/>
+    </div>
+</div>
+<div id="search-users-results"></div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/e0c96794/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-delete-dialog.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-delete-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-delete-dialog.jsp
new file mode 100644
index 0000000..ef30baf
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-delete-dialog.jsp
@@ -0,0 +1,21 @@
+<%--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="user-delete-dialog" class="hidden">
+    <div class="dialog-content">
+        <input type="hidden" id="user-id-delete-dialog"/>
+        Are you sure you want to delete the user account for '<span id="user-identity-delete-dialog"></span>'?
+    </div>
+</div>
\ No newline at end of file


Mime
View raw message