You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2016/07/01 20:41:49 UTC

[1/5] nifi git commit: NIFI-1781: - Updating UI according to permissions through out the application. - Shuffling provenance events, template, and cluster search REST APIs according to resources being authorized. - Moving template upload controls. - Remo

Repository: nifi
Updated Branches:
  refs/heads/master 8eb0a3882 -> ce5330330


http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
index 04a2204..5d1d76a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js
@@ -26,7 +26,7 @@ nf.ProvenanceLineage = (function () {
         sliderTickCount: 75,
         urls: {
             lineage: '../nifi-api/provenance/lineage',
-            events: '../nifi-api/provenance/events/'
+            events: '../nifi-api/provenance-events/'
         }
     };
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
index f024866..9f739a3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-table.js
@@ -33,9 +33,10 @@ nf.ProvenanceTable = (function () {
         },
         urls: {
             searchOptions: '../nifi-api/provenance/search-options',
-            replays: '../nifi-api/provenance/replays',
+            replays: '../nifi-api/provenance-events/replays',
             provenance: '../nifi-api/provenance',
-            cluster: '../nifi-api/controller/cluster',
+            provenanceEvents: '../nifi-api/provenance-events',
+            clusterSearch: '../nifi-api/flow/cluster/search-results',
             d3Script: 'js/d3/d3.min.js',
             lineageScript: 'js/nf/provenance/nf-provenance-lineage.js',
             uiExtensionToken: '../nifi-api/access/ui-extension-token',
@@ -57,7 +58,7 @@ nf.ProvenanceTable = (function () {
         var eventId = $('#provenance-event-id').text();
 
         // build the url
-        var dataUri = config.urls.provenance + '/events/' + encodeURIComponent(eventId) + '/content/' + encodeURIComponent(direction);
+        var dataUri = config.urls.provenanceEvents + '/' + encodeURIComponent(eventId) + '/content/' + encodeURIComponent(direction);
 
         // perform the request once we've received a token
         nf.Common.getAccessToken(config.urls.downloadToken).done(function (downloadToken) {
@@ -98,7 +99,7 @@ nf.ProvenanceTable = (function () {
         var eventId = $('#provenance-event-id').text();
 
         // build the uri to the data
-        var dataUri = controllerUri + 'provenance/events/' + encodeURIComponent(eventId) + '/content/' + encodeURIComponent(direction);
+        var dataUri = config.urls.provenanceEvents + '/' + encodeURIComponent(eventId) + '/content/' + encodeURIComponent(direction);
 
         // generate tokens as necessary
         var getAccessTokens = $.Deferred(function (deferred) {
@@ -258,38 +259,35 @@ nf.ProvenanceTable = (function () {
         }
 
         // handle the replay and downloading
-        if (nf.Common.isDFM()) {
-            // replay
-            $('#replay-content').on('click', function () {
-                var replayEntity = {
-                    'eventId': $('#provenance-event-id').text()
-                };
+        $('#replay-content').on('click', function () {
+            var replayEntity = {
+                'eventId': $('#provenance-event-id').text()
+            };
 
-                // conditionally include the cluster node id
-                var clusterNodeId = $('#provenance-event-cluster-node-id').text();
-                if (!nf.Common.isBlank(clusterNodeId)) {
-                    replayEntity['clusterNodeId'] = clusterNodeId;
-                }
+            // conditionally include the cluster node id
+            var clusterNodeId = $('#provenance-event-cluster-node-id').text();
+            if (!nf.Common.isBlank(clusterNodeId)) {
+                replayEntity['clusterNodeId'] = clusterNodeId;
+            }
 
-                $.ajax({
-                    type: 'POST',
-                    url: config.urls.replays,
-                    data: JSON.stringify(replayEntity),
-                    dataType: 'json',
-                    contentType: 'application/json'
-                }).done(function (response) {
-                    nf.Dialog.showOkDialog({
-                        headerText: 'Provenance',
-                        dialogContent: 'Successfully submitted replay request.'
-                    });
-                }).fail(nf.Common.handleAjaxError);
+            $.ajax({
+                type: 'POST',
+                url: config.urls.replays,
+                data: JSON.stringify(replayEntity),
+                dataType: 'json',
+                contentType: 'application/json'
+            }).done(function (response) {
+                nf.Dialog.showOkDialog({
+                    headerText: 'Provenance',
+                    dialogContent: 'Successfully submitted replay request.'
+                });
+            }).fail(nf.Common.handleAjaxError);
 
-                $('#event-details-dialog').modal('hide');
-            });
+            $('#event-details-dialog').modal('hide');
+        });
 
-            // show the replay panel
-            $('#replay-details').show();
-        }
+        // show the replay panel
+        $('#replay-details').show();
     };
 
     /**
@@ -323,11 +321,10 @@ nf.ProvenanceTable = (function () {
             // get the nodes in the cluster
             $.ajax({
                 type: 'GET',
-                url: config.urls.cluster,
+                url: config.urls.clusterSearch,
                 dataType: 'json'
             }).done(function (response) {
-                var cluster = response.cluster;
-                var nodes = cluster.nodes;
+                var nodeResults = response.nodeResults;
 
                 // create the searchable options
                 var searchableOptions = [{
@@ -336,17 +333,17 @@ nf.ProvenanceTable = (function () {
                 }];
 
                 // sort the nodes
-                nodes.sort(function (a, b) {
-                    var compA = (a.address + ':' + a.apiPort).toUpperCase();
-                    var compB = (b.address + ':' + b.apiPort).toUpperCase();
+                nodeResults.sort(function (a, b) {
+                    var compA = a.address.toUpperCase();
+                    var compB = b.address.toUpperCase();
                     return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
                 });
 
                 // add each node
-                $.each(nodes, function (_, node) {
+                $.each(nodeResults, function (_, nodeResult) {
                     searchableOptions.push({
-                        text: node.address + ':' + node.apiPort,
-                        value: node.nodeId
+                        text: nodeResult.address,
+                        value: nodeResult.id
                     });
                 });
 
@@ -1430,15 +1427,13 @@ nf.ProvenanceTable = (function () {
                 $('#output-content-view').hide();
             }
 
-            if (nf.Common.isDFM()) {
-                if (event.replayAvailable === true) {
-                    $('#replay-content, #replay-content-connection').show();
-                    formatContentValue($('#replay-connection-id'), event.sourceConnectionIdentifier);
-                    $('#replay-content-message').hide();
-                } else {
-                    $('#replay-content, #replay-content-connection').hide();
-                    $('#replay-content-message').text(event.replayExplanation).show();
-                }
+            if (event.replayAvailable === true) {
+                $('#replay-content, #replay-content-connection').show();
+                formatContentValue($('#replay-connection-id'), event.sourceConnectionIdentifier);
+                $('#replay-content-message').hide();
+            } else {
+                $('#replay-content, #replay-content-connection').hide();
+                $('#replay-content-message').text(event.replayExplanation).show();
             }
 
             // show the dialog

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js
index a04aad7..fe16705 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance.js
@@ -32,7 +32,7 @@ nf.Provenance = (function () {
             flowConfig: '../nifi-api/flow/config',
             banners: '../nifi-api/flow/banners',
             about: '../nifi-api/flow/about',
-            authorities: '../nifi-api/flow/authorities'
+            currentUser: '../nifi-api/flow/current-user'
         }
     };
 
@@ -81,27 +81,16 @@ nf.Provenance = (function () {
     };
 
     /**
-     * Loads the current users authorities.
+     * Loads the current user.
      */
-    var loadAuthorities = function () {
-        return $.Deferred(function (deferred) {
-            $.ajax({
-                type: 'GET',
-                url: config.urls.authorities,
-                dataType: 'json'
-            }).done(function (response) {
-                if (nf.Common.isDefinedAndNotNull(response.authorities)) {
-                    // record the users authorities
-                    nf.Common.setAuthorities(response.authorities);
-                    deferred.resolve(response);
-                } else {
-                    deferred.reject();
-                }
-            }).fail(function (xhr, status, error) {
-                nf.Common.handleAjaxError(xhr, status, error);
-                deferred.reject();
-            });
-        }).promise();
+    var loadCurrentUser = function () {
+        return $.ajax({
+            type: 'GET',
+            url: config.urls.currentUser,
+            dataType: 'json'
+        }).done(function (currentUser) {
+            nf.Common.setCurrentUser(currentUser);
+        }).fail(nf.Common.handleAjaxError);
     };
 
     /**
@@ -170,8 +159,8 @@ nf.Provenance = (function () {
         init: function () {
             nf.Storage.init();
             
-            // load the users authorities and detect if the NiFi is clustered
-            $.when(loadAbout(), loadAuthorities(), detectedCluster()).done(function () {
+            // load the user and detect if the NiFi is clustered
+            $.when(loadAbout(), loadCurrentUser(), detectedCluster()).done(function () {
                 // create the provenance table
                 nf.ProvenanceTable.init(isClustered).done(function () {
                     var searchTerms = {};

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-cluster-search.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-cluster-search.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-cluster-search.js
index 8162c2c..eedeed2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-cluster-search.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/summary/nf-cluster-search.js
@@ -21,7 +21,7 @@ nf.ClusterSearch = (function () {
     var config = {
         search: 'Search nodes',
         urls: {
-            clusterSearch: '../nifi-api/controller/cluster/search-results'
+            clusterSearch: '../nifi-api/flow/cluster/search-results'
         }
     };
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js
index 81b80b7..5477a31 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates-table.js
@@ -28,17 +28,12 @@ nf.TemplatesTable = (function () {
             filterList: 'templates-filter-list'
         },
         urls: {
-            api: '../nifi-api',
+            templates: '../nifi-api/flow/templates',
             downloadToken: '../nifi-api/access/download-token'
         }
     };
 
     /**
-     * the current group id
-     */
-    var groupId;
-
-    /**
      * Sorts the specified data using the specified sort details.
      * 
      * @param {object} sortDetails
@@ -52,8 +47,8 @@ nf.TemplatesTable = (function () {
                 var bDate = nf.Common.parseDateTime(b[sortDetails.columnId]);
                 return aDate.getTime() - bDate.getTime();
             } else {
-                var aString = nf.Common.isDefinedAndNotNull(a[sortDetails.columnId]) ? a[sortDetails.columnId] : '';
-                var bString = nf.Common.isDefinedAndNotNull(b[sortDetails.columnId]) ? b[sortDetails.columnId] : '';
+                var aString = nf.Common.isDefinedAndNotNull(a.template[sortDetails.columnId]) ? a.template[sortDetails.columnId] : '';
+                var bString = nf.Common.isDefinedAndNotNull(b.template[sortDetails.columnId]) ? b.template[sortDetails.columnId] : '';
                 return aString === bString ? 0 : aString > bString ? 1 : -1;
             }
         };
@@ -65,15 +60,15 @@ nf.TemplatesTable = (function () {
     /**
      * Prompts the user before attempting to delete the specified template.
      * 
-     * @argument {object} template     The template
+     * @argument {object} templateEntity     The template
      */
-    var promptToDeleteTemplate = function (template) {
+    var promptToDeleteTemplate = function (templateEntity) {
         // prompt for deletion
         nf.Dialog.showYesNoDialog({
             headerText: 'Delete Template',
-            dialogContent: 'Delete template \'' + nf.Common.escapeHtml(template.name) + '\'?',
+            dialogContent: 'Delete template \'' + nf.Common.escapeHtml(templateEntity.template.name) + '\'?',
             yesHandler: function () {
-                deleteTemplate(template);
+                deleteTemplate(templateEntity);
             }
         });
     };
@@ -81,17 +76,17 @@ nf.TemplatesTable = (function () {
     /**
      * Deletes the template with the specified id.
      * 
-     * @argument {string} template     The template
+     * @argument {string} templateEntity     The template
      */
-    var deleteTemplate = function (template) {
+    var deleteTemplate = function (templateEntity) {
         $.ajax({
             type: 'DELETE',
-            url: template.uri,
+            url: templateEntity.template.uri,
             dataType: 'json'
         }).done(function () {
             var templatesGrid = $('#templates-table').data('gridInstance');
             var templatesData = templatesGrid.getData();
-            templatesData.deleteItem(template.id);
+            templatesData.deleteItem(templateEntity.id);
             
             // update the total number of templates
             $('#total-templates').text(templatesData.getItems().length);
@@ -153,15 +148,15 @@ nf.TemplatesTable = (function () {
         }
 
         // perform the filter
-        return item[args.property].search(filterExp) >= 0;
+        return item.template[args.property].search(filterExp) >= 0;
     };
 
     /**
      * Downloads the specified template.
      *
-     * @param {object} template     The template
+     * @param {object} templateEntity     The template
      */
-    var downloadTemplate = function (template) {
+    var downloadTemplate = function (templateEntity) {
         nf.Common.getAccessToken(config.urls.downloadToken).done(function (downloadToken) {
             var parameters = {};
 
@@ -172,9 +167,9 @@ nf.TemplatesTable = (function () {
 
             // open the url
             if ($.isEmptyObject(parameters)) {
-                window.open(template.uri + '/download');
+                window.open(templateEntity.template.uri + '/download');
             } else {
-                window.open(template.uri + '/download' + '?' + $.param(parameters));
+                window.open(templateEntity.template.uri + '/download' + '?' + $.param(parameters));
             }
         }).fail(function () {
             nf.Dialog.showOkDialog({
@@ -216,22 +211,48 @@ nf.TemplatesTable = (function () {
                 }
             });
 
-            // enable template uploading if DFM
-            if (nf.Common.isDFM()) {
-                $('#upload-template-container').show();
-            }
+            var timestampFormatter = function (row, cell, value, columnDef, dataContext) {
+                if (!dataContext.accessPolicy.canRead) {
+                    return '';
+                }
 
-            // function for formatting the last accessed time
-            var valueFormatter = function (row, cell, value, columnDef, dataContext) {
-                return nf.Common.formatValue(value);
+                return dataContext.template.timestamp;
+            };
+
+            var nameFormatter = function (row, cell, value, columnDef, dataContext) {
+                if (!dataContext.accessPolicy.canRead) {
+                    return '<span class="blank">' + dataContext.id + '</span>';
+                }
+
+                return dataContext.template.name;
+            };
+
+            var descriptionFormatter = function (row, cell, value, columnDef, dataContext) {
+                if (!dataContext.accessPolicy.canRead) {
+                    return '';
+                }
+
+                return nf.Common.formatValue(dataContext.template.description);
+            };
+
+            var groupIdFormatter = function (row, cell, value, columnDef, dataContext) {
+                if (!dataContext.accessPolicy.canRead) {
+                    return '';
+                }
+
+                return dataContext.template.groupId;
             };
 
             // function for formatting the actions column
             var actionFormatter = function (row, cell, value, columnDef, dataContext) {
-                var markup = '<div title="Download" class="pointer export-template icon icon-template-save" style="margin-top: 2px;"></div>';
+                var markup = '';
+
+                if (dataContext.accessPolicy.canRead === true) {
+                    markup += '<div title="Download" class="pointer export-template icon icon-template-save" style="margin-top: 2px;"></div>';
+                }
 
                 // all DFMs to remove templates
-                if (nf.Common.isDFM()) {
+                if (dataContext.accessPolicy.canWrite === true) {
                     markup += '<div title="Remove Template" class="pointer prompt-to-delete-template fa fa-trash" style="margin-top: 2px; margin-left: 3px;"></div>';
                 }
                 return markup;
@@ -239,9 +260,10 @@ nf.TemplatesTable = (function () {
 
             // initialize the templates table
             var templatesColumns = [
-                {id: 'timestamp', name: 'Date/Time', field: 'timestamp', sortable: true, defaultSortAsc: false, resizable: false, formatter: valueFormatter, width: 225, maxWidth: 225},
-                {id: 'name', name: 'Name', field: 'name', sortable: true, resizable: true},
-                {id: 'description', name: 'Description', field: 'description', sortable: true, resizable: true, formatter: valueFormatter},
+                {id: 'timestamp', name: 'Date/Time', sortable: true, defaultSortAsc: false, resizable: false, formatter: timestampFormatter, width: 225, maxWidth: 225},
+                {id: 'name', name: 'Name', sortable: true, resizable: true, formatter: nameFormatter},
+                {id: 'description', name: 'Description', sortable: true, resizable: true, formatter: descriptionFormatter},
+                {id: 'groupId', name: 'Process Group Id', sortable: true, resizable: true, formatter: groupIdFormatter},
                 {id: 'actions', name: '&nbsp;', sortable: false, resizable: false, formatter: actionFormatter, width: 100, maxWidth: 100}
             ];
             var templatesOptions = {
@@ -277,7 +299,7 @@ nf.TemplatesTable = (function () {
             templatesGrid.setSortColumn('timestamp', false);
             templatesGrid.onSort.subscribe(function (e, args) {
                 sort({
-                    columnId: args.sortCol.field,
+                    columnId: args.sortCol.id,
                     sortAsc: args.sortAsc
                 }, templatesData);
             });
@@ -333,17 +355,9 @@ nf.TemplatesTable = (function () {
          * Load the processor templates table.
          */
         loadTemplatesTable: function () {
-            groupId = $('#template-group-id').text();
-            if (nf.Common.isUndefined(groupId) || nf.Common.isNull(groupId)) {
-                nf.Dialog.showOkDialog({
-                    headerText: 'Load Templates',
-                    content: 'Group id not specified.'
-                });
-            }
-
             return $.ajax({
                 type: 'GET',
-                url: config.urls.api + '/process-groups/' + encodeURIComponent(groupId) + '/templates',
+                url: config.urls.templates,
                 data: {
                     verbose: false
                 },

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js
index 86d9934..678c25f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/templates/nf-templates.js
@@ -31,37 +31,21 @@ nf.Templates = (function () {
         urls: {
             banners: '../nifi-api/flow/banners',
             about: '../nifi-api/flow/about',
-            authorities: '../nifi-api/flow/authorities'
+            currentUser: '../nifi-api/flow/current-user'
         }
     };
 
     /**
-     * the current group id
+     * Loads the current users.
      */
-    var groupId;
-
-    /**
-     * Loads the current users authorities.
-     */
-    var loadAuthorities = function () {
-        return $.Deferred(function (deferred) {
-            $.ajax({
-                type: 'GET',
-                url: config.urls.authorities,
-                dataType: 'json'
-            }).done(function (response) {
-                if (nf.Common.isDefinedAndNotNull(response.authorities)) {
-                    // record the users authorities
-                    nf.Common.setAuthorities(response.authorities);
-                    deferred.resolve();
-                } else {
-                    deferred.reject();
-                }
-            }).fail(function (xhr, status, error) {
-                nf.Common.handleAjaxError(xhr, status, error);
-                deferred.reject();
-            });
-        }).promise();
+    var loadCurrentUser = function () {
+        return $.ajax({
+            type: 'GET',
+            url: config.urls.currentUser,
+            dataType: 'json'
+        }).done(function (currentUser) {
+            nf.Common.setCurrentUser(currentUser);
+        }).fail(nf.Common.handleAjaxError);
     };
 
     /**
@@ -73,81 +57,6 @@ nf.Templates = (function () {
             nf.TemplatesTable.loadTemplatesTable();
         });
 
-        // add a handler for the change file input chain event
-        $('#template-file-field').on('change', function (e) {
-            var filename = $(this).val();
-            if (!nf.Common.isBlank(filename)) {
-                filename = filename.replace(/^.*[\\\/]/, '');
-            }
-
-            // set the filename
-            $('#selected-template-name').text(filename);
-
-            // update the container visibility
-            $('#select-template-container').hide();
-            $('#submit-template-container').show();
-        });
-
-        // handles any uploading error - could be an error response or a successful response with an encoded error
-        var handleError = function (error) {
-            // show any errors
-            $('#upload-template-status').removeClass('import-status').addClass('import-status-error').text(error);
-
-            // clear the form
-            $('#cancel-upload-template-button').click();
-        };
-
-        // initialize the form
-        var templateForm = $('#template-upload-form').ajaxForm({
-            url: '../nifi-api/process-groups/' + encodeURIComponent(groupId) + '/templates/upload',
-            dataType: 'xml',
-            success: function (response, statusText, xhr, form) {
-                // see if the import was successful
-                if (response.documentElement.tagName === 'templateEntity') {
-                    // reset the status message
-                    $('#upload-template-status').removeClass('import-status-error').addClass('import-status');
-
-                    // clear the form
-                    $('#cancel-upload-template-button').click();
-
-                    // reload the templates table
-                    nf.TemplatesTable.loadTemplatesTable();
-                } else {
-                    // import failed
-                    var status = 'Unable to import template. Please check the log for errors.';
-                    if (response.documentElement.tagName === 'errorResponse') {
-                        // if a more specific error was given, use it
-                        var errorMessage = response.documentElement.getAttribute('statusText');
-                        if (!nf.Common.isBlank(errorMessage)) {
-                            status = errorMessage;
-                        }
-                    }
-                    handleError(status);
-                }
-            },
-            error: function (xhr, statusText, error) {
-                handleError(error);
-            }
-        });
-
-        // add a handler for the upload button
-        $('#upload-template-button').click(function () {
-            templateForm.submit();
-        });
-
-        // add a handler for the cancel upload button
-        $('#cancel-upload-template-button').click(function () {
-            // set the filename
-            $('#selected-template-name').text('');
-
-            // reset the form to ensure that the change fire will fire
-            templateForm.resetForm();
-
-            // update the container visibility
-            $('#select-template-container').show();
-            $('#submit-template-container').hide();
-        });
-
         // get the banners if we're not in the shell
         return $.Deferred(function (deferred) {
             if (top === window) {
@@ -204,17 +113,8 @@ nf.Templates = (function () {
         init: function () {
             nf.Storage.init();
 
-            // ensure the group id is specified
-            groupId = $('#template-group-id').text();
-            if (nf.Common.isUndefined(groupId) || nf.Common.isNull(groupId)) {
-                nf.Dialog.showOkDialog({
-                    headerText: 'Load Templates',
-                    content: 'Group id not specified.'
-                });
-            }
-            
-            // load the users authorities
-            loadAuthorities().done(function () {
+            // load the current user
+            loadCurrentUser().done(function () {
 
                 // create the templates table
                 nf.TemplatesTable.init();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 adb335c..3b827eb 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
@@ -16,51 +16,6 @@
  */
 package org.apache.nifi.provenance;
 
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexNotFoundException;
@@ -111,6 +66,51 @@ import org.apache.nifi.web.ResourceNotFoundException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
 public class PersistentProvenanceRepository implements ProvenanceEventRepository {
 
     public static final String DEPRECATED_CLASS_NAME = "nifi.controller.repository.provenance.PersistentProvenanceRepository";
@@ -416,7 +416,7 @@ public class PersistentProvenanceRepository implements ProvenanceEventRepository
             return false;
         }
 
-        final AuthorizationResult result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user);
+        final AuthorizationResult result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, event.getAttributes());
         return Result.Approved.equals(result.getResult());
     }
 
@@ -426,7 +426,7 @@ public class PersistentProvenanceRepository implements ProvenanceEventRepository
         }
 
         final Authorizable eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
-        eventAuthorizable.authorize(authorizer, RequestAction.READ, user);
+        eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
     }
 
     private List<ProvenanceEventRecord> filterUnauthorizedEvents(final List<ProvenanceEventRecord> events, final NiFiUser user) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/test/java/org/apache/nifi/provenance/TestPersistentProvenanceRepository.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/test/java/org/apache/nifi/provenance/TestPersistentProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/test/java/org/apache/nifi/provenance/TestPersistentProvenanceRepository.java
index 5417669..835e06e 100644
--- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/test/java/org/apache/nifi/provenance/TestPersistentProvenanceRepository.java
+++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-persistent-provenance-repository/src/test/java/org/apache/nifi/provenance/TestPersistentProvenanceRepository.java
@@ -16,33 +16,6 @@
  */
 package org.apache.nifi.provenance;
 
-import static org.apache.nifi.provenance.TestUtil.createFlowFile;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.stream.Collectors;
-import java.util.zip.GZIPOutputStream;
-
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.core.SimpleAnalyzer;
 import org.apache.lucene.document.Document;
@@ -85,6 +58,33 @@ import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+import java.util.zip.GZIPOutputStream;
+
+import static org.apache.nifi.provenance.TestUtil.createFlowFile;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
 public class TestPersistentProvenanceRepository {
 
     @Rule
@@ -1735,11 +1735,6 @@ public class TestPersistentProvenanceRepository {
             }
 
             @Override
-            public String getUserName() {
-                return "Unit Test";
-            }
-
-            @Override
             public NiFiUser getChain() {
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 888f55a..ce53393 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
@@ -16,27 +16,6 @@
  */
 package org.apache.nifi.provenance;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.regex.Pattern;
-
 import org.apache.nifi.authorization.AccessDeniedException;
 import org.apache.nifi.authorization.AuthorizationResult;
 import org.apache.nifi.authorization.AuthorizationResult.Result;
@@ -64,6 +43,27 @@ import org.apache.nifi.util.RingBuffer.ForEachEvaluator;
 import org.apache.nifi.util.RingBuffer.IterationDirection;
 import org.apache.nifi.web.ResourceNotFoundException;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.regex.Pattern;
+
 public class VolatileProvenanceRepository implements ProvenanceEventRepository {
 
     // properties
@@ -246,7 +246,7 @@ public class VolatileProvenanceRepository implements ProvenanceEventRepository {
             return false;
         }
 
-        final AuthorizationResult result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user);
+        final AuthorizationResult result = eventAuthorizable.checkAuthorization(authorizer, RequestAction.READ, user, event.getAttributes());
         return Result.Approved.equals(result.getResult());
     }
 
@@ -256,7 +256,7 @@ public class VolatileProvenanceRepository implements ProvenanceEventRepository {
         }
 
         final Authorizable eventAuthorizable = resourceFactory.createProvenanceAuthorizable(event.getComponentId());
-        eventAuthorizable.authorize(authorizer, RequestAction.READ, user);
+        eventAuthorizable.authorize(authorizer, RequestAction.READ, user, event.getAttributes());
     }
 
     private Filter<ProvenanceEventRecord> createFilter(final Query query, final NiFiUser user) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/test/java/org/apache/nifi/provenance/TestVolatileProvenanceRepository.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/test/java/org/apache/nifi/provenance/TestVolatileProvenanceRepository.java b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/test/java/org/apache/nifi/provenance/TestVolatileProvenanceRepository.java
index d35ceac..7a7a334 100644
--- a/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/test/java/org/apache/nifi/provenance/TestVolatileProvenanceRepository.java
+++ b/nifi-nar-bundles/nifi-provenance-repository-bundle/nifi-volatile-provenance-repository/src/test/java/org/apache/nifi/provenance/TestVolatileProvenanceRepository.java
@@ -16,7 +16,14 @@
  */
 package org.apache.nifi.provenance;
 
-import static org.junit.Assert.assertEquals;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.provenance.search.Query;
+import org.apache.nifi.provenance.search.QuerySubmission;
+import org.apache.nifi.provenance.search.SearchTerms;
+import org.apache.nifi.util.NiFiProperties;
+import org.junit.BeforeClass;
+import org.junit.Test;
 
 import java.io.IOException;
 import java.util.HashMap;
@@ -26,15 +33,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
-import org.apache.nifi.authorization.user.NiFiUser;
-import org.apache.nifi.flowfile.FlowFile;
-import org.apache.nifi.provenance.search.Query;
-import org.apache.nifi.provenance.search.QuerySubmission;
-import org.apache.nifi.provenance.search.SearchTerms;
-import org.apache.nifi.util.NiFiProperties;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
 
 public class TestVolatileProvenanceRepository {
 
@@ -184,11 +183,6 @@ public class TestVolatileProvenanceRepository {
             }
 
             @Override
-            public String getUserName() {
-                return "Unit Test";
-            }
-
-            @Override
             public NiFiUser getChain() {
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/processors/script/ExecuteScriptGroovyTest.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/processors/script/ExecuteScriptGroovyTest.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/processors/script/ExecuteScriptGroovyTest.groovy
index e7e9d48..86f119a 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/processors/script/ExecuteScriptGroovyTest.groovy
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/processors/script/ExecuteScriptGroovyTest.groovy
@@ -69,9 +69,9 @@ class ExecuteScriptGroovyTest extends BaseScriptTest {
         runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION + "groovy/testAddTimeAndThreadAttribute.groovy")
         runner.setProperty(ExecuteScript.MODULES, TEST_RESOURCE_LOCATION + "groovy")
 
-        // Override context value
+        // Override userContext value
         runner.processContext.maxConcurrentTasks = poolSize
-        logger.info("Overrode context max concurrent tasks to ${runner.processContext.maxConcurrentTasks}")
+        logger.info("Overrode userContext max concurrent tasks to ${runner.processContext.maxConcurrentTasks}")
     }
 
     @Test


[3/5] nifi git commit: NIFI-1781: - Updating UI according to permissions through out the application. - Shuffling provenance events, template, and cluster search REST APIs according to resources being authorized. - Moving template upload controls. - Remo

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
index 5c9bd9a..cc7d5aa 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java
@@ -16,29 +16,13 @@
  */
 package org.apache.nifi.web.api;
 
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
+import com.sun.jersey.api.core.ResourceContext;
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AccessDeniedException;
 import org.apache.nifi.authorization.AuthorizationRequest;
@@ -46,20 +30,25 @@ import org.apache.nifi.authorization.AuthorizationResult;
 import org.apache.nifi.authorization.AuthorizationResult.Result;
 import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.cluster.coordination.node.NodeConnectionState;
 import org.apache.nifi.cluster.manager.NodeResponse;
 import org.apache.nifi.controller.ScheduledState;
 import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.IllegalClusterResourceRequestException;
 import org.apache.nifi.web.NiFiServiceFacade;
 import org.apache.nifi.web.Revision;
 import org.apache.nifi.web.api.dto.AboutDTO;
 import org.apache.nifi.web.api.dto.BannerDTO;
 import org.apache.nifi.web.api.dto.BulletinBoardDTO;
 import org.apache.nifi.web.api.dto.BulletinQueryDTO;
+import org.apache.nifi.web.api.dto.ClusterDTO;
+import org.apache.nifi.web.api.dto.NodeDTO;
 import org.apache.nifi.web.api.dto.ProcessGroupDTO;
 import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.dto.action.ActionDTO;
@@ -67,6 +56,7 @@ import org.apache.nifi.web.api.dto.action.HistoryDTO;
 import org.apache.nifi.web.api.dto.action.HistoryQueryDTO;
 import org.apache.nifi.web.api.dto.flow.FlowDTO;
 import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO;
+import org.apache.nifi.web.api.dto.search.NodeSearchResultDTO;
 import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
 import org.apache.nifi.web.api.dto.status.ConnectionStatusDTO;
 import org.apache.nifi.web.api.dto.status.ControllerStatusDTO;
@@ -79,19 +69,19 @@ import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO;
 import org.apache.nifi.web.api.dto.status.StatusHistoryDTO;
 import org.apache.nifi.web.api.entity.AboutEntity;
 import org.apache.nifi.web.api.entity.ActionEntity;
-import org.apache.nifi.web.api.entity.AuthorityEntity;
 import org.apache.nifi.web.api.entity.BannerEntity;
 import org.apache.nifi.web.api.entity.BulletinBoardEntity;
+import org.apache.nifi.web.api.entity.ClusterSearchResultsEntity;
 import org.apache.nifi.web.api.entity.ComponentHistoryEntity;
 import org.apache.nifi.web.api.entity.ConnectionStatusEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceTypesEntity;
 import org.apache.nifi.web.api.entity.ControllerServicesEntity;
 import org.apache.nifi.web.api.entity.ControllerStatusEntity;
+import org.apache.nifi.web.api.entity.CurrentUserEntity;
 import org.apache.nifi.web.api.entity.Entity;
 import org.apache.nifi.web.api.entity.FlowConfigurationEntity;
 import org.apache.nifi.web.api.entity.HistoryEntity;
-import org.apache.nifi.web.api.entity.IdentityEntity;
 import org.apache.nifi.web.api.entity.PortStatusEntity;
 import org.apache.nifi.web.api.entity.PrioritizerTypesEntity;
 import org.apache.nifi.web.api.entity.ProcessGroupEntity;
@@ -106,19 +96,37 @@ import org.apache.nifi.web.api.entity.ReportingTasksEntity;
 import org.apache.nifi.web.api.entity.ScheduleComponentsEntity;
 import org.apache.nifi.web.api.entity.SearchResultsEntity;
 import org.apache.nifi.web.api.entity.StatusHistoryEntity;
+import org.apache.nifi.web.api.entity.TemplateEntity;
+import org.apache.nifi.web.api.entity.TemplatesEntity;
 import org.apache.nifi.web.api.request.BulletinBoardPatternParameter;
 import org.apache.nifi.web.api.request.ClientIdParameter;
 import org.apache.nifi.web.api.request.DateTimeParameter;
 import org.apache.nifi.web.api.request.IntegerParameter;
 import org.apache.nifi.web.api.request.LongParameter;
 
-import com.sun.jersey.api.core.ResourceContext;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiParam;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
-import com.wordnik.swagger.annotations.Authorization;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * RESTful endpoint for managing a Flow.
@@ -215,6 +223,21 @@ public class FlowResource extends ApplicationResource {
         }
     }
 
+    private boolean isAuthorized(final RequestAction action, final Resource resource) {
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+
+        final AuthorizationRequest request = new AuthorizationRequest.Builder()
+                .resource(resource)
+                .identity(user.getIdentity())
+                .anonymous(user.isAnonymous())
+                .accessAttempt(false)
+                .action(action)
+                .build();
+
+        final AuthorizationResult result = authorizer.authorize(request);
+        return Result.Approved.equals(result.getResult());
+    }
+
     // ----
     // flow
     // ----
@@ -299,12 +322,12 @@ public class FlowResource extends ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
-    @Path("identity")
+    @Path("current-user")
     @ApiOperation(
             value = "Retrieves the user identity of the user making the request",
-            response = IdentityEntity.class
+            response = CurrentUserEntity.class
     )
-    public Response getIdentity() {
+    public Response getCurrentUser() {
 
         authorizeFlow(RequestAction.READ);
 
@@ -315,59 +338,7 @@ public class FlowResource extends ApplicationResource {
         }
 
         // create the response entity
-        IdentityEntity entity = new IdentityEntity();
-        entity.setUserId(user.getIdentity());
-        entity.setIdentity(user.getUserName());
-        entity.setAnonymous(user.isAnonymous());
-
-        // generate the response
-        return clusterContext(generateOkResponse(entity)).build();
-    }
-
-    /**x
-     * Retrieves the user details, including the authorities, about the user making the request.
-     *
-     * @return A authoritiesEntity.
-     */
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("authorities")
-    // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN', 'ROLE_PROXY', 'ROLE_NIFI', 'ROLE_PROVENANCE')")
-    @ApiOperation(
-            value = "Retrieves the user details, including the authorities, about the user making the request",
-            response = AuthorityEntity.class,
-            authorizations = {
-                    @Authorization(value = "Read Only", type = "ROLE_MONITOR"),
-                    @Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
-                    @Authorization(value = "Administrator", type = "ROLE_ADMIN"),
-                    @Authorization(value = "Proxy", type = "ROLE_PROXY"),
-                    @Authorization(value = "NiFi", type = "ROLE_NIFI"),
-                    @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
-            }
-    )
-    @ApiResponses(
-            value = {
-                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
-                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-            }
-    )
-    public Response getAuthorities() {
-        // TODO - remove this method once authorities are completely removed
-        authorizeFlow(RequestAction.READ);
-
-        // note that the cluster manager will handle this request directly
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        if (user == null) {
-            throw new WebApplicationException(new Throwable("Unable to access details for current user."));
-        }
-
-        // create the response entity
-        AuthorityEntity entity = new AuthorityEntity();
-        entity.setUserId(user.getIdentity());
-        entity.setAuthorities(new HashSet<>(Arrays.asList("ROLE_MONITOR", "ROLE_DFM", "ROLE_ADMIN", "ROLE_PROXY", "ROLE_NIFI", "ROLE_PROVENANCE")));
+        final CurrentUserEntity entity = serviceFacade.getCurrentUser();
 
         // generate the response
         return clusterContext(generateOkResponse(entity)).build();
@@ -1081,7 +1052,7 @@ public class FlowResource extends ApplicationResource {
     // --------------
 
     /**
-     * Retrieves all the of templates in this NiFi.
+     * Retrieves all the of bulletins in this NiFi.
      *
      * @param after Supporting querying for bulletins after a particular
      *            bulletin id.
@@ -1960,7 +1931,7 @@ public class FlowResource extends ApplicationResource {
      * formatted as 'MM/dd/yyyy HH:mm:ss'. This parameter is optional and must
      * be specified in the timezone of the server. The server's timezone can be
      * determined by inspecting the result of a status or history request.
-     * @param userName The user name of the user who's actions are being
+     * @param userIdentity The user name of the user who's actions are being
      * queried. This parameter is optional.
      * @param sourceId The id of the source being queried (usually a processor
      * id). This parameter is optional.
@@ -2023,7 +1994,7 @@ public class FlowResource extends ApplicationResource {
                     value = "Include actions performed by this user.",
                     required = false
             )
-            @QueryParam("userName") String userName,
+            @QueryParam("userIdentity") String userIdentity,
             @ApiParam(
                     value = "Include actions on this component.",
                     required = false
@@ -2082,8 +2053,8 @@ public class FlowResource extends ApplicationResource {
         }
 
         // optionally set the user id
-        if (userName != null) {
-            query.setUserName(userName);
+        if (userIdentity != null) {
+            query.setUserIdentity(userIdentity);
         }
 
         // optionally set the processor id
@@ -2210,6 +2181,138 @@ public class FlowResource extends ApplicationResource {
         return generateOkResponse(entity).build();
     }
 
+    // ---------
+    // templates
+    // ---------
+
+    /**
+     * Retrieves all the of templates in this NiFi.
+     *
+     * @return A templatesEntity.
+     */
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("templates")
+    // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+    @ApiOperation(
+            value = "Gets all templates",
+            response = TemplatesEntity.class,
+            authorizations = {
+                    @Authorization(value = "Read Only", type = "ROLE_MONITOR"),
+                    @Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
+                    @Authorization(value = "Administrator", type = "ROLE_ADMIN")
+            }
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response getTemplates() {
+
+        if (isReplicateRequest()) {
+            return replicate(HttpMethod.GET);
+        }
+
+        // authorize access
+        authorizeFlow(RequestAction.READ);
+
+        // get all the templates
+        final Set<TemplateEntity> templates = serviceFacade.getTemplates();
+        templateResource.populateRemainingTemplateEntitiesContent(templates);
+
+        // create the response entity
+        final TemplatesEntity entity = new TemplatesEntity();
+        entity.setTemplates(templates);
+        entity.setGenerated(new Date());
+
+        // generate the response
+        return clusterContext(generateOkResponse(entity)).build();
+    }
+
+    // --------------------
+    // search cluster nodes
+    // --------------------
+
+    /**
+     * Searches the cluster for a node with a given address.
+     *
+     * @param value Search value that will be matched against a node's address
+     * @return Nodes that match the specified criteria
+     */
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("cluster/search-results")
+    // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+    @ApiOperation(
+            value = "Searches the cluster for a node with the specified address",
+            response = ClusterSearchResultsEntity.class,
+            authorizations = {
+                    @Authorization(value = "Read Only", type = "ROLE_MONITOR"),
+                    @Authorization(value = "DFM", type = "ROLE_DFM"),
+                    @Authorization(value = "Admin", type = "ROLE_ADMIN")
+            }
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response searchCluster(
+            @ApiParam(
+                    value = "Node address to search for.",
+                    required = true
+            )
+            @QueryParam("q") @DefaultValue(StringUtils.EMPTY) String value) {
+
+        authorizeFlow(RequestAction.READ);
+
+        // ensure connected to the cluster
+        if (!isConnectedToCluster()) {
+            throw new IllegalClusterResourceRequestException("Only a node connected to a cluster can process the request.");
+        }
+
+        final List<NodeSearchResultDTO> nodeMatches = new ArrayList<>();
+
+        // get the nodes in the cluster
+        final ClusterDTO cluster = serviceFacade.getCluster();
+
+        // check each to see if it matches the search term
+        for (NodeDTO node : cluster.getNodes()) {
+            // ensure the node is connected
+            if (!NodeConnectionState.CONNECTED.name().equals(node.getStatus())) {
+                continue;
+            }
+
+            // determine the current nodes address
+            final String address = node.getAddress() + ":" + node.getApiPort();
+
+            // count the node if there is no search or it matches the address
+            if (StringUtils.isBlank(value) || StringUtils.containsIgnoreCase(address, value)) {
+                final NodeSearchResultDTO nodeMatch = new NodeSearchResultDTO();
+                nodeMatch.setId(node.getNodeId());
+                nodeMatch.setAddress(address);
+                nodeMatches.add(nodeMatch);
+            }
+        }
+
+        // build the response
+        ClusterSearchResultsEntity results = new ClusterSearchResultsEntity();
+        results.setNodeResults(nodeMatches);
+
+        // generate an 200 - OK response
+        return noCache(Response.ok(results)).build();
+    }
+
     // setters
     public void setServiceFacade(NiFiServiceFacade serviceFacade) {
         this.serviceFacade = serviceFacade;

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.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/ProcessGroupResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
index 48c241c..0a94fea 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProcessGroupResource.java
@@ -16,36 +16,14 @@
  */
 package org.apache.nifi.web.api;
 
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.transform.stream.StreamSource;
-
+import com.sun.jersey.api.core.ResourceContext;
+import com.sun.jersey.multipart.FormDataParam;
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
@@ -82,20 +60,38 @@ import org.apache.nifi.web.api.entity.ProcessorsEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupsEntity;
 import org.apache.nifi.web.api.entity.TemplateEntity;
-import org.apache.nifi.web.api.entity.TemplatesEntity;
 import org.apache.nifi.web.api.request.ClientIdParameter;
 import org.apache.nifi.web.api.request.LongParameter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.sun.jersey.api.core.ResourceContext;
-import com.sun.jersey.multipart.FormDataParam;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiParam;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
-import com.wordnik.swagger.annotations.Authorization;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * RESTful endpoint for managing a Group.
@@ -1848,62 +1844,6 @@ public class ProcessGroupResource extends ApplicationResource {
     }
 
     /**
-     * Retrieves all the of templates in this NiFi.
-     *
-     * @return A templatesEntity.
-     */
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("{id}/templates")
-    // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
-    @ApiOperation(
-        value = "Gets all templates",
-        response = TemplatesEntity.class,
-        authorizations = {
-            @Authorization(value = "Read Only", type = "ROLE_MONITOR"),
-            @Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
-            @Authorization(value = "Administrator", type = "ROLE_ADMIN")
-        }
-    )
-    @ApiResponses(
-        value = {
-            @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-            @ApiResponse(code = 401, message = "Client could not be authenticated."),
-            @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-            @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-        }
-    )
-    public Response getTemplates(
-        @ApiParam(
-            value = "The process group id.",
-            required = true
-        )
-        @PathParam("id") final String groupId) {
-
-        if (isReplicateRequest()) {
-            return replicate(HttpMethod.GET);
-        }
-
-        // authorize access
-        serviceFacade.authorizeAccess(lookup -> {
-            final Authorizable processGroup = lookup.getProcessGroup(groupId);
-            processGroup.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
-        });
-
-        // get all the templates
-        final Set<TemplateDTO> templates = templateResource.populateRemainingTemplatesContent(serviceFacade.getTemplates());
-
-        // create the response entity
-        final TemplatesEntity entity = new TemplatesEntity();
-        entity.setTemplates(templates);
-        entity.setGenerated(new Date());
-
-        // generate the response
-        return clusterContext(generateOkResponse(entity)).build();
-    }
-
-    /**
      * Creates a new template based off of the specified template.
      *
      * @param httpServletRequest request

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceEventResource.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/ProvenanceEventResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceEventResource.java
new file mode 100644
index 0000000..8c3a5d6
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceEventResource.java
@@ -0,0 +1,391 @@
+/*
+ * 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 com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import com.wordnik.swagger.annotations.Authorization;
+import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
+import org.apache.nifi.controller.repository.claim.ContentDirection;
+import org.apache.nifi.stream.io.StreamUtils;
+import org.apache.nifi.web.DownloadableContent;
+import org.apache.nifi.web.NiFiServiceFacade;
+import org.apache.nifi.web.api.dto.provenance.ProvenanceDTO;
+import org.apache.nifi.web.api.dto.provenance.ProvenanceEventDTO;
+import org.apache.nifi.web.api.dto.provenance.lineage.LineageDTO;
+import org.apache.nifi.web.api.entity.ProvenanceEventEntity;
+import org.apache.nifi.web.api.entity.SubmitReplayRequestEntity;
+import org.apache.nifi.web.api.request.LongParameter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+
+
+/**
+ * RESTful endpoint for querying data provenance.
+ */
+@Path("/provenance-events")
+@Api(
+    value = "/provenance-events",
+    description = "Endpoint for accessing data flow provenance."
+)
+public class ProvenanceEventResource extends ApplicationResource {
+
+    private NiFiServiceFacade serviceFacade;
+
+    /**
+     * Populates the uri for the specified provenance.
+     */
+    private ProvenanceDTO populateRemainingProvenanceContent(ProvenanceDTO provenance) {
+        provenance.setUri(generateResourceUri("provenance", provenance.getId()));
+        return provenance;
+    }
+
+    /**
+     * Populates the uri for the specified lineage.
+     */
+    private LineageDTO populateRemainingLineageContent(LineageDTO lineage) {
+        lineage.setUri(generateResourceUri("provenance", "lineage", lineage.getId()));
+        return lineage;
+    }
+
+    /**
+     * Gets the content for the input of the specified event.
+     *
+     * @param clusterNodeId The id of the node within the cluster this content is on. Required if clustered.
+     * @param id The id of the provenance event associated with this content.
+     * @return The content stream
+     */
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.WILDCARD)
+    @Path("{id}/content/input")
+    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
+    @ApiOperation(
+            value = "Gets the input content for a provenance event",
+            authorizations = {
+                @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
+            }
+    )
+    @ApiResponses(
+            value = {
+                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                @ApiResponse(code = 404, message = "The specified resource could not be found."),
+                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response getInputContent(
+            @ApiParam(
+                    value = "The id of the node where the content exists if clustered.",
+                    required = false
+            )
+            @QueryParam("clusterNodeId") final String clusterNodeId,
+            @ApiParam(
+                    value = "The provenance event id.",
+                    required = true
+            )
+            @PathParam("id") final LongParameter id) {
+
+        // ensure proper input
+        if (id == null) {
+            throw new IllegalArgumentException("The event id must be specified.");
+        }
+
+        // replicate if cluster manager
+        if (isReplicateRequest()) {
+            // determine where this request should be sent
+            if (clusterNodeId == null) {
+                throw new IllegalArgumentException("The id of the node in the cluster is required.");
+            } else {
+                return replicate(HttpMethod.GET, clusterNodeId);
+            }
+        }
+
+        // get the uri of the request
+        final String uri = generateResourceUri("provenance", "events", String.valueOf(id.getLong()), "content", "input");
+
+        // get an input stream to the content
+        final DownloadableContent content = serviceFacade.getContent(id.getLong(), uri, ContentDirection.INPUT);
+
+        // generate a streaming response
+        final StreamingOutput response = new StreamingOutput() {
+            @Override
+            public void write(OutputStream output) throws IOException, WebApplicationException {
+                try (InputStream is = content.getContent()) {
+                    // stream the content to the response
+                    StreamUtils.copy(is, output);
+
+                    // flush the response
+                    output.flush();
+                }
+            }
+        };
+
+        // use the appropriate content type
+        String contentType = content.getType();
+        if (contentType == null) {
+            contentType = MediaType.APPLICATION_OCTET_STREAM;
+        }
+
+        return generateOkResponse(response).type(contentType).header("Content-Disposition", String.format("attachment; filename=\"%s\"", content.getFilename())).build();
+    }
+
+    /**
+     * Gets the content for the output of the specified event.
+     *
+     * @param clusterNodeId The id of the node within the cluster this content is on. Required if clustered.
+     * @param id The id of the provenance event associated with this content.
+     * @return The content stream
+     */
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.WILDCARD)
+    @Path("{id}/content/output")
+    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
+    @ApiOperation(
+            value = "Gets the output content for a provenance event",
+            authorizations = {
+                @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
+            }
+    )
+    @ApiResponses(
+            value = {
+                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                @ApiResponse(code = 404, message = "The specified resource could not be found."),
+                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response getOutputContent(
+            @ApiParam(
+                    value = "The id of the node where the content exists if clustered.",
+                    required = false
+            )
+            @QueryParam("clusterNodeId") final String clusterNodeId,
+            @ApiParam(
+                    value = "The provenance event id.",
+                    required = true
+            )
+            @PathParam("id") final LongParameter id) {
+
+        // ensure proper input
+        if (id == null) {
+            throw new IllegalArgumentException("The event id must be specified.");
+        }
+
+        // replicate if cluster manager
+        if (isReplicateRequest()) {
+            // determine where this request should be sent
+            if (clusterNodeId == null) {
+                throw new IllegalArgumentException("The id of the node in the cluster is required.");
+            } else {
+                return replicate(HttpMethod.GET, clusterNodeId);
+            }
+        }
+
+        // get the uri of the request
+        final String uri = generateResourceUri("provenance", "events", String.valueOf(id.getLong()), "content", "output");
+
+        // get an input stream to the content
+        final DownloadableContent content = serviceFacade.getContent(id.getLong(), uri, ContentDirection.OUTPUT);
+
+        // generate a streaming response
+        final StreamingOutput response = new StreamingOutput() {
+            @Override
+            public void write(OutputStream output) throws IOException, WebApplicationException {
+                try (InputStream is = content.getContent()) {
+                    // stream the content to the response
+                    StreamUtils.copy(is, output);
+
+                    // flush the response
+                    output.flush();
+                }
+            }
+        };
+
+        // use the appropriate content type
+        String contentType = content.getType();
+        if (contentType == null) {
+            contentType = MediaType.APPLICATION_OCTET_STREAM;
+        }
+
+        return generateOkResponse(response).type(contentType).header("Content-Disposition", String.format("attachment; filename=\"%s\"", content.getFilename())).build();
+    }
+
+    /**
+     * Gets the details for a provenance event.
+     *
+     * @param id The id of the event
+     * @param clusterNodeId The id of node in the cluster that the event/flowfile originated from. This is only required when clustered.
+     * @return A provenanceEventEntity
+     */
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{id}")
+    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
+    @ApiOperation(
+            value = "Gets a provenance event",
+            response = ProvenanceEventEntity.class,
+            authorizations = {
+                @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
+            }
+    )
+    @ApiResponses(
+            value = {
+                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                @ApiResponse(code = 404, message = "The specified resource could not be found."),
+                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response getProvenanceEvent(
+            @ApiParam(
+                    value = "The id of the node where this event exists if clustered.",
+                    required = false
+            )
+            @QueryParam("clusterNodeId") final String clusterNodeId,
+            @ApiParam(
+                    value = "The provenence event id.",
+                    required = true
+            )
+            @PathParam("id") final LongParameter id) {
+
+        // ensure the id is specified
+        if (id == null) {
+            throw new IllegalArgumentException("Provenance event id must be specified.");
+        }
+
+        // replicate if cluster manager
+        if (isReplicateRequest()) {
+            // since we're cluster we must specify the cluster node identifier
+            if (clusterNodeId == null) {
+                throw new IllegalArgumentException("The cluster node identifier must be specified.");
+            }
+
+            return replicate(HttpMethod.GET, clusterNodeId);
+        }
+
+        // get the provenance event
+        final ProvenanceEventDTO event = serviceFacade.getProvenanceEvent(id.getLong());
+
+        // create a response entity
+        final ProvenanceEventEntity entity = new ProvenanceEventEntity();
+        entity.setProvenanceEvent(event);
+
+        // generate the response
+        return clusterContext(generateOkResponse(entity)).build();
+    }
+
+    /**
+     * Creates a new replay request for the content associated with the specified provenance event id.
+     *
+     * @param httpServletRequest request
+     * @param replayRequestEntity The replay request
+     * @return A provenanceEventEntity
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("replays")
+    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE') and hasRole('ROLE_DFM')")
+    @ApiOperation(
+            value = "Replays content from a provenance event",
+            response = ProvenanceEventEntity.class,
+            authorizations = {
+                    @Authorization(value = "Provenance and Data Flow Manager", type = "ROLE_PROVENANCE and ROLE_DFM")
+            }
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
+                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
+                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
+                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
+                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
+            }
+    )
+    public Response submitReplay(
+            @Context final HttpServletRequest httpServletRequest,
+            @ApiParam(
+                    value = "The replay request.",
+                    required = true
+            ) final SubmitReplayRequestEntity replayRequestEntity) {
+
+        // ensure the event id is specified
+        if (replayRequestEntity == null || replayRequestEntity.getEventId() == null) {
+            throw new IllegalArgumentException("The id of the event must be specified.");
+        }
+
+        // replicate if cluster manager
+        if (isReplicateRequest()) {
+            // determine where this request should be sent
+            if (replayRequestEntity.getClusterNodeId() == null) {
+                throw new IllegalArgumentException("The id of the node in the cluster is required.");
+            } else {
+                return replicate(HttpMethod.POST, replayRequestEntity, replayRequestEntity.getClusterNodeId());
+            }
+        }
+
+        // handle expects request (usually from the cluster manager)
+        final String expects = httpServletRequest.getHeader(RequestReplicator.REQUEST_VALIDATION_HTTP_HEADER);
+        if (expects != null) {
+            return generateContinueResponse().build();
+        }
+
+        // submit the provenance replay request
+        final ProvenanceEventDTO event = serviceFacade.submitReplay(replayRequestEntity.getEventId());
+
+        // create a response entity
+        final ProvenanceEventEntity entity = new ProvenanceEventEntity();
+        entity.setProvenanceEvent(event);
+
+        // generate the response
+        URI uri = URI.create(generateResourceUri("provenance-events", event.getId()));
+        return clusterContext(generateCreatedResponse(uri, entity)).build();
+    }
+
+    // setters
+
+    public void setServiceFacade(NiFiServiceFacade serviceFacade) {
+        this.serviceFacade = serviceFacade;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceResource.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/ProvenanceResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceResource.java
index f4501f5..70339ea 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ProvenanceResource.java
@@ -16,29 +16,12 @@
  */
 package org.apache.nifi.web.api;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.StreamingOutput;
-
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import com.wordnik.swagger.annotations.Authorization;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AccessDeniedException;
 import org.apache.nifi.authorization.AuthorizationRequest;
@@ -50,28 +33,31 @@ import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
-import org.apache.nifi.controller.repository.claim.ContentDirection;
-import org.apache.nifi.stream.io.StreamUtils;
-import org.apache.nifi.web.DownloadableContent;
 import org.apache.nifi.web.NiFiServiceFacade;
 import org.apache.nifi.web.api.dto.provenance.ProvenanceDTO;
-import org.apache.nifi.web.api.dto.provenance.ProvenanceEventDTO;
 import org.apache.nifi.web.api.dto.provenance.ProvenanceOptionsDTO;
 import org.apache.nifi.web.api.dto.provenance.lineage.LineageDTO;
 import org.apache.nifi.web.api.dto.provenance.lineage.LineageRequestDTO;
 import org.apache.nifi.web.api.entity.LineageEntity;
 import org.apache.nifi.web.api.entity.ProvenanceEntity;
-import org.apache.nifi.web.api.entity.ProvenanceEventEntity;
 import org.apache.nifi.web.api.entity.ProvenanceOptionsEntity;
-import org.apache.nifi.web.api.entity.SubmitReplayRequestEntity;
-import org.apache.nifi.web.api.request.LongParameter;
 
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiParam;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
-import com.wordnik.swagger.annotations.Authorization;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
 
 
 /**
@@ -166,246 +152,6 @@ public class ProvenanceResource extends ApplicationResource {
     }
 
     /**
-     * Creates a new replay request for the content associated with the specified provenance event id.
-     *
-     * @param httpServletRequest request
-     * @param replayRequestEntity The replay request
-     * @return A provenanceEventEntity
-     */
-    @POST
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("replays")
-    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE') and hasRole('ROLE_DFM')")
-    @ApiOperation(
-            value = "Replays content from a provenance event",
-            response = ProvenanceEventEntity.class,
-            authorizations = {
-                @Authorization(value = "Provenance and Data Flow Manager", type = "ROLE_PROVENANCE and ROLE_DFM")
-            }
-    )
-    @ApiResponses(
-            value = {
-                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-                @ApiResponse(code = 401, message = "Client could not be authenticated."),
-                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-                @ApiResponse(code = 404, message = "The specified resource could not be found."),
-                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-            }
-    )
-    public Response submitReplay(
-        @Context final HttpServletRequest httpServletRequest,
-        @ApiParam(
-            value = "The replay request.",
-            required = true
-        ) final SubmitReplayRequestEntity replayRequestEntity) {
-
-        authorizeProvenanceRequest();
-
-        // ensure the event id is specified
-        if (replayRequestEntity == null || replayRequestEntity.getEventId() == null) {
-            throw new IllegalArgumentException("The id of the event must be specified.");
-        }
-
-        // replicate if cluster manager
-        if (isReplicateRequest()) {
-            // determine where this request should be sent
-            if (replayRequestEntity.getClusterNodeId() == null) {
-                throw new IllegalArgumentException("The id of the node in the cluster is required.");
-            } else {
-                return replicate(HttpMethod.POST, replayRequestEntity, replayRequestEntity.getClusterNodeId());
-            }
-        }
-
-        // handle expects request (usually from the cluster manager)
-        final String expects = httpServletRequest.getHeader(RequestReplicator.REQUEST_VALIDATION_HTTP_HEADER);
-        if (expects != null) {
-            return generateContinueResponse().build();
-        }
-
-        // submit the provenance replay request
-        final ProvenanceEventDTO event = serviceFacade.submitReplay(replayRequestEntity.getEventId());
-
-        // create a response entity
-        final ProvenanceEventEntity entity = new ProvenanceEventEntity();
-        entity.setProvenanceEvent(event);
-
-        // generate the response
-        URI uri = URI.create(generateResourceUri("provenance", "events", event.getId()));
-        return clusterContext(generateCreatedResponse(uri, entity)).build();
-    }
-
-    /**
-     * Gets the content for the input of the specified event.
-     *
-     * @param clusterNodeId The id of the node within the cluster this content is on. Required if clustered.
-     * @param id The id of the provenance event associated with this content.
-     * @return The content stream
-     */
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.WILDCARD)
-    @Path("events/{id}/content/input")
-    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
-    @ApiOperation(
-            value = "Gets the input content for a provenance event",
-            authorizations = {
-                @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
-            }
-    )
-    @ApiResponses(
-            value = {
-                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-                @ApiResponse(code = 401, message = "Client could not be authenticated."),
-                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-                @ApiResponse(code = 404, message = "The specified resource could not be found."),
-                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-            }
-    )
-    public Response getInputContent(
-            @ApiParam(
-                    value = "The id of the node where the content exists if clustered.",
-                    required = false
-            )
-            @QueryParam("clusterNodeId") final String clusterNodeId,
-            @ApiParam(
-                    value = "The provenance event id.",
-                    required = true
-            )
-            @PathParam("id") final LongParameter id) {
-
-        authorizeProvenanceRequest();
-
-        // ensure proper input
-        if (id == null) {
-            throw new IllegalArgumentException("The event id must be specified.");
-        }
-
-        // replicate if cluster manager
-        if (isReplicateRequest()) {
-            // determine where this request should be sent
-            if (clusterNodeId == null) {
-                throw new IllegalArgumentException("The id of the node in the cluster is required.");
-            } else {
-                return replicate(HttpMethod.GET, clusterNodeId);
-            }
-        }
-
-        // get the uri of the request
-        final String uri = generateResourceUri("provenance", "events", String.valueOf(id.getLong()), "content", "input");
-
-        // get an input stream to the content
-        final DownloadableContent content = serviceFacade.getContent(id.getLong(), uri, ContentDirection.INPUT);
-
-        // generate a streaming response
-        final StreamingOutput response = new StreamingOutput() {
-            @Override
-            public void write(OutputStream output) throws IOException, WebApplicationException {
-                try (InputStream is = content.getContent()) {
-                    // stream the content to the response
-                    StreamUtils.copy(is, output);
-
-                    // flush the response
-                    output.flush();
-                }
-            }
-        };
-
-        // use the appropriate content type
-        String contentType = content.getType();
-        if (contentType == null) {
-            contentType = MediaType.APPLICATION_OCTET_STREAM;
-        }
-
-        return generateOkResponse(response).type(contentType).header("Content-Disposition", String.format("attachment; filename=\"%s\"", content.getFilename())).build();
-    }
-
-    /**
-     * Gets the content for the output of the specified event.
-     *
-     * @param clusterNodeId The id of the node within the cluster this content is on. Required if clustered.
-     * @param id The id of the provenance event associated with this content.
-     * @return The content stream
-     */
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.WILDCARD)
-    @Path("events/{id}/content/output")
-    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
-    @ApiOperation(
-            value = "Gets the output content for a provenance event",
-            authorizations = {
-                @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
-            }
-    )
-    @ApiResponses(
-            value = {
-                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-                @ApiResponse(code = 401, message = "Client could not be authenticated."),
-                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-                @ApiResponse(code = 404, message = "The specified resource could not be found."),
-                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-            }
-    )
-    public Response getOutputContent(
-            @ApiParam(
-                    value = "The id of the node where the content exists if clustered.",
-                    required = false
-            )
-            @QueryParam("clusterNodeId") final String clusterNodeId,
-            @ApiParam(
-                    value = "The provenance event id.",
-                    required = true
-            )
-            @PathParam("id") final LongParameter id) {
-
-        authorizeProvenanceRequest();
-
-        // ensure proper input
-        if (id == null) {
-            throw new IllegalArgumentException("The event id must be specified.");
-        }
-
-        // replicate if cluster manager
-        if (isReplicateRequest()) {
-            // determine where this request should be sent
-            if (clusterNodeId == null) {
-                throw new IllegalArgumentException("The id of the node in the cluster is required.");
-            } else {
-                return replicate(HttpMethod.GET, clusterNodeId);
-            }
-        }
-
-        // get the uri of the request
-        final String uri = generateResourceUri("provenance", "events", String.valueOf(id.getLong()), "content", "output");
-
-        // get an input stream to the content
-        final DownloadableContent content = serviceFacade.getContent(id.getLong(), uri, ContentDirection.OUTPUT);
-
-        // generate a streaming response
-        final StreamingOutput response = new StreamingOutput() {
-            @Override
-            public void write(OutputStream output) throws IOException, WebApplicationException {
-                try (InputStream is = content.getContent()) {
-                    // stream the content to the response
-                    StreamUtils.copy(is, output);
-
-                    // flush the response
-                    output.flush();
-                }
-            }
-        };
-
-        // use the appropriate content type
-        String contentType = content.getType();
-        if (contentType == null) {
-            contentType = MediaType.APPLICATION_OCTET_STREAM;
-        }
-
-        return generateOkResponse(response).type(contentType).header("Content-Disposition", String.format("attachment; filename=\"%s\"", content.getFilename())).build();
-    }
-
-    /**
      * Creates provenance using the specified query criteria.
      *
      * @param httpServletRequest request
@@ -635,74 +381,6 @@ public class ProvenanceResource extends ApplicationResource {
     }
 
     /**
-     * Gets the details for a provenance event.
-     *
-     * @param id The id of the event
-     * @param clusterNodeId The id of node in the cluster that the event/flowfile originated from. This is only required when clustered.
-     * @return A provenanceEventEntity
-     */
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("events/{id}")
-    // TODO - @PreAuthorize("hasRole('ROLE_PROVENANCE')")
-    @ApiOperation(
-            value = "Gets a provenance event",
-            response = ProvenanceEventEntity.class,
-            authorizations = {
-                @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
-            }
-    )
-    @ApiResponses(
-            value = {
-                @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-                @ApiResponse(code = 401, message = "Client could not be authenticated."),
-                @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-                @ApiResponse(code = 404, message = "The specified resource could not be found."),
-                @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-            }
-    )
-    public Response getProvenanceEvent(
-            @ApiParam(
-                    value = "The id of the node where this event exists if clustered.",
-                    required = false
-            )
-            @QueryParam("clusterNodeId") final String clusterNodeId,
-            @ApiParam(
-                    value = "The provenence event id.",
-                    required = true
-            )
-            @PathParam("id") final LongParameter id) {
-
-        authorizeProvenanceRequest();
-
-        // ensure the id is specified
-        if (id == null) {
-            throw new IllegalArgumentException("Provenance event id must be specified.");
-        }
-
-        // replicate if cluster manager
-        if (isReplicateRequest()) {
-            // since we're cluster we must specify the cluster node identifier
-            if (clusterNodeId == null) {
-                throw new IllegalArgumentException("The cluster node identifier must be specified.");
-            }
-
-            return replicate(HttpMethod.GET, clusterNodeId);
-        }
-
-        // get the provenance event
-        final ProvenanceEventDTO event = serviceFacade.getProvenanceEvent(id.getLong());
-
-        // create a response entity
-        final ProvenanceEventEntity entity = new ProvenanceEventEntity();
-        entity.setProvenanceEvent(event);
-
-        // generate the response
-        return clusterContext(generateOkResponse(entity)).build();
-    }
-
-    /**
      * Submits a lineage request based on an event or a flowfile uuid.
      *
      * When querying for the lineage of an event you must specify the eventId and the eventDirection. The eventDirection must be 'parents' or 'children' and specifies whether we are going up or down

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.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/TemplateResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java
index 6994815..dcff518 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TemplateResource.java
@@ -16,7 +16,20 @@
  */
 package org.apache.nifi.web.api;
 
-import java.util.Set;
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import com.wordnik.swagger.annotations.Authorization;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.web.NiFiServiceFacade;
+import org.apache.nifi.web.api.dto.TemplateDTO;
+import org.apache.nifi.web.api.entity.TemplateEntity;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
@@ -29,22 +42,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authorization.Authorizer;
-import org.apache.nifi.authorization.RequestAction;
-import org.apache.nifi.authorization.resource.Authorizable;
-import org.apache.nifi.authorization.user.NiFiUserUtils;
-import org.apache.nifi.web.NiFiServiceFacade;
-import org.apache.nifi.web.api.dto.TemplateDTO;
-import org.apache.nifi.web.api.entity.TemplateEntity;
-
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiParam;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
-import com.wordnik.swagger.annotations.Authorization;
+import java.util.Set;
 
 /**
  * RESTful endpoint for managing a Template.
@@ -60,6 +58,34 @@ public class TemplateResource extends ApplicationResource {
     private Authorizer authorizer;
 
     /**
+     * Populate the uri's for the specified templates.
+     *
+     * @param templateEntities templates
+     * @return templates
+     */
+    public Set<TemplateEntity> populateRemainingTemplateEntitiesContent(Set<TemplateEntity> templateEntities) {
+        for (TemplateEntity templateEntity : templateEntities) {
+            if (templateEntity.getTemplate() != null) {
+                populateRemainingTemplateContent(templateEntity.getTemplate());
+            }
+        }
+        return templateEntities;
+    }
+
+    /**
+     * Populate the uri's for the specified templates.
+     *
+     * @param templateEntity templates
+     * @return templates
+     */
+    public TemplateEntity populateRemainingTemplateEntityContent(TemplateEntity templateEntity) {
+        if (templateEntity.getTemplate() != null) {
+            populateRemainingTemplateContent(templateEntity.getTemplate());
+        }
+        return templateEntity;
+    }
+
+    /**
      * Populates the uri for the specified templates.
      *
      * @param templates templates

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 10a28c7..cf1bca4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -220,7 +220,6 @@ public final class DtoFactory {
         actionDto.setSourceType(action.getSourceType().name());
         actionDto.setTimestamp(action.getTimestamp());
         actionDto.setUserDn(action.getUserIdentity());
-        actionDto.setUserName(action.getUserName());
         actionDto.setOperation(action.getOperation().name());
         actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails()));
         actionDto.setComponentDetails(createComponentDetailsDto(action.getComponentDetails()));
@@ -305,15 +304,6 @@ public final class DtoFactory {
         final HistoryDTO historyDto = new HistoryDTO();
         historyDto.setTotal(history.getTotal());
         historyDto.setLastRefreshed(history.getLastRefreshed());
-
-        if (history.getActions() != null) {
-            final List<ActionDTO> actionDtos = new ArrayList<>();
-            for (final Action action : history.getActions()) {
-                actionDtos.add(createActionDto(action));
-            }
-            historyDto.setActions(actionDtos);
-        }
-
         return historyDto;
     }
 
@@ -830,6 +820,7 @@ public final class DtoFactory {
 
         final TemplateDTO copy = new TemplateDTO();
         copy.setId(original.getId());
+        copy.setGroupId(template.getProcessGroup().getIdentifier());
         copy.setName(original.getName());
         copy.setDescription(original.getDescription());
         copy.setTimestamp(original.getTimestamp());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 b72d72c..2c6d948 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
@@ -19,6 +19,9 @@ package org.apache.nifi.web.controller;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.ClassUtils;
 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.Resource;
@@ -1138,22 +1141,8 @@ public class ControllerFacade implements Authorizable {
                 attributes = event.getAttributes();
             }
 
-            // calculate the dn chain
-            final List<String> dnChain = ProxiedEntitiesUtils.buildProxiedEntitiesChain(user);
-            dnChain.forEach(identity -> {
-                final Authorizable eventAuthorizable = flowController.createProvenanceAuthorizable(event.getComponentId());
-                final NiFiUser chainUser = new StandardNiFiUser(identity) {
-                    private static final long serialVersionUID = 7589311627013017356L;
-
-                    @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);
-            });
+            // authorize the event
+            authorizeEvent(event.getComponentId(), attributes);
 
             // get the filename and fall back to the identifier (should never happen)
             String filename = attributes.get(CoreAttributes.FILENAME.key());
@@ -1197,6 +1186,9 @@ public class ControllerFacade implements Authorizable {
             // replay the flow file
             final ProvenanceEventRecord event = flowController.replayFlowFile(originalEvent, user);
 
+            // authorize the replay
+            authorizeReplay(event.getComponentId(), event.getAttributes(), event.getSourceQueueIdentifier());
+
             // convert the event record
             return createProvenanceEventDto(event);
         } catch (final IOException ioe) {
@@ -1205,6 +1197,112 @@ 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 NiFiUser chainUser = new StandardNiFiUser(identity) {
+                @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 NiFiUser chainUser = new StandardNiFiUser(identity) {
+                @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
+     * @param eventAttributes event attributes
+     * @param connectionId connection id
+     */
+    private AuthorizationResult checkAuthorizationForReplay(final String componentId, final Map<String, String> eventAttributes, final String connectionId) {
+        // if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it`
+        if (connectionId == null) {
+            return AuthorizationResult.denied();
+        }
+
+        final AuthorizationResult result = checkAuthorizationForEvent(componentId, 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);
+    }
+
+    /**
+     * Authorizes access to replay a specified provenance event.
+     *
+     * @param componentId component id
+     * @param eventAttributes event attributes
+     * @param connectionId connection id
+     */
+    private void authorizeReplay(final String componentId, final Map<String, String> eventAttributes, final String connectionId) {
+        // if the connection id isn't specified, then the replay wouldn't be available anyways and we have nothing to authorize against so deny it`
+        if (connectionId == null) {
+            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);
+    }
+
+    /**
      * Get the provenance event with the specified event id.
      *
      * @param eventId event id
@@ -1217,6 +1315,10 @@ public class ControllerFacade implements Authorizable {
                 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);
+
             // convert the event
             return createProvenanceEventDto(event);
         } catch (final IOException ioe) {
@@ -1308,9 +1410,13 @@ public class ControllerFacade implements Authorizable {
             dto.setInputContentClaimFileSize(FormatUtils.formatDataSize(event.getPreviousFileSize()));
         }
 
+        // determine if authorized for event replay
+        final AuthorizationResult replayAuthorized = checkAuthorizationForReplay(event.getComponentId(), event.getAttributes(), event.getSourceQueueIdentifier());
+
         // replay
-        dto.setReplayAvailable(contentAvailability.isReplayable());
-        dto.setReplayExplanation(contentAvailability.getReasonNotReplayable());
+        dto.setReplayAvailable(contentAvailability.isReplayable() && Result.Approved.equals(replayAuthorized.getResult()));
+        dto.setReplayExplanation(contentAvailability.isReplayable()
+                && !Result.Approved.equals(replayAuthorized.getResult()) ? replayAuthorized.getExplanation() : contentAvailability.getReasonNotReplayable());
         dto.setSourceConnectionIdentifier(event.getSourceQueueIdentifier());
 
         // sets the component details if it can find the component still in the flow
@@ -1366,56 +1472,72 @@ public class ControllerFacade implements Authorizable {
     }
 
     private void search(final SearchResultsDTO results, final String search, final ProcessGroup group) {
-        final ComponentSearchResultDTO groupMatch = search(search, group);
-        if (groupMatch != null) {
-            results.getProcessGroupResults().add(groupMatch);
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+
+        if (group.isAuthorized(authorizer, RequestAction.READ, user)) {
+            final ComponentSearchResultDTO groupMatch = search(search, group);
+            if (groupMatch != null) {
+                results.getProcessGroupResults().add(groupMatch);
+            }
         }
 
         for (final ProcessorNode procNode : group.getProcessors()) {
-            final ComponentSearchResultDTO match = search(search, procNode);
-            if (match != null) {
-                match.setGroupId(group.getIdentifier());
-                results.getProcessorResults().add(match);
+            if (procNode.isAuthorized(authorizer, RequestAction.READ, user)) {
+                final ComponentSearchResultDTO match = search(search, procNode);
+                if (match != null) {
+                    match.setGroupId(group.getIdentifier());
+                    results.getProcessorResults().add(match);
+                }
             }
         }
 
         for (final Connection connection : group.getConnections()) {
-            final ComponentSearchResultDTO match = search(search, connection);
-            if (match != null) {
-                match.setGroupId(group.getIdentifier());
-                results.getConnectionResults().add(match);
+            if (connection.isAuthorized(authorizer, RequestAction.READ, user)) {
+                final ComponentSearchResultDTO match = search(search, connection);
+                if (match != null) {
+                    match.setGroupId(group.getIdentifier());
+                    results.getConnectionResults().add(match);
+                }
             }
         }
 
         for (final RemoteProcessGroup remoteGroup : group.getRemoteProcessGroups()) {
-            final ComponentSearchResultDTO match = search(search, remoteGroup);
-            if (match != null) {
-                match.setGroupId(group.getIdentifier());
-                results.getRemoteProcessGroupResults().add(match);
+            if (remoteGroup.isAuthorized(authorizer, RequestAction.READ, user)) {
+                final ComponentSearchResultDTO match = search(search, remoteGroup);
+                if (match != null) {
+                    match.setGroupId(group.getIdentifier());
+                    results.getRemoteProcessGroupResults().add(match);
+                }
             }
         }
 
         for (final Port port : group.getInputPorts()) {
-            final ComponentSearchResultDTO match = search(search, port);
-            if (match != null) {
-                match.setGroupId(group.getIdentifier());
-                results.getInputPortResults().add(match);
+            if (port.isAuthorized(authorizer, RequestAction.READ, user)) {
+                final ComponentSearchResultDTO match = search(search, port);
+                if (match != null) {
+                    match.setGroupId(group.getIdentifier());
+                    results.getInputPortResults().add(match);
+                }
             }
         }
 
         for (final Port port : group.getOutputPorts()) {
-            final ComponentSearchResultDTO match = search(search, port);
-            if (match != null) {
-                match.setGroupId(group.getIdentifier());
-                results.getOutputPortResults().add(match);
+            if (port.isAuthorized(authorizer, RequestAction.READ, user)) {
+                final ComponentSearchResultDTO match = search(search, port);
+                if (match != null) {
+                    match.setGroupId(group.getIdentifier());
+                    results.getOutputPortResults().add(match);
+                }
             }
         }
 
         for (final Funnel funnel : group.getFunnels()) {
-            final ComponentSearchResultDTO match = search(search, funnel);
-            if (match != null) {
-                match.setGroupId(group.getIdentifier());
-                results.getFunnelResults().add(match);
+            if (funnel.isAuthorized(authorizer, RequestAction.READ, user)) {
+                final ComponentSearchResultDTO match = search(search, funnel);
+                if (match != null) {
+                    match.setGroupId(group.getIdentifier());
+                    results.getFunnelResults().add(match);
+                }
             }
         }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 1a2669b..1ac13ce 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
@@ -604,7 +604,7 @@ public class StandardConnectionDAO extends ComponentDAO implements ConnectionDAO
                         .accessAttempt(false)
                         .action(RequestAction.WRITE)
                         .resource(connection.getResource())
-                        .eventAttributes(attributes)
+                        .resourceContext(attributes)
                         .build();
 
                 // perform the authorization

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
index 8faedfb..a1a63a6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
@@ -327,6 +327,12 @@
         <property name="requestReplicator" ref="requestReplicator" />
         <property name="authorizer" ref="authorizer"/>
     </bean>
+    <bean id="provenanceEventResource" class="org.apache.nifi.web.api.ProvenanceEventResource" scope="singleton">
+        <property name="serviceFacade" ref="serviceFacade"/>
+        <property name="properties" ref="nifiProperties"/>
+        <property name="clusterCoordinator" ref="clusterCoordinator"/>
+        <property name="requestReplicator" ref="requestReplicator" />
+    </bean>
     <bean id="countersResource" class="org.apache.nifi.web.api.CountersResource" scope="singleton">
         <property name="serviceFacade" ref="serviceFacade"/>
         <property name="properties" ref="nifiProperties"/>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
index 2171ea8..ecc725b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-optimistic-locking/src/main/java/org/apache/nifi/web/revision/NaiveRevisionManager.java
@@ -217,7 +217,7 @@ public class NaiveRevisionManager implements RevisionManager {
 
                 for (final Revision revision : revisionList) {
                     final RevisionLock revisionLock = getRevisionLock(revision);
-                    revisionLock.unlock(revision, revision, user.getUserName());
+                    revisionLock.unlock(revision, revision, user.getIdentity());
                     logger.debug("Relinquished lock for {}", revision);
                 }
 
@@ -300,7 +300,7 @@ public class NaiveRevisionManager implements RevisionManager {
 
                 for (final Revision revision : revisionList) {
                     final Revision updatedRevision = updatedRevisions.get(revision);
-                    getRevisionLock(revision).unlock(revision, updatedRevision, user.getUserName());
+                    getRevisionLock(revision).unlock(revision, updatedRevision, user.getIdentity());
 
                     if (updatedRevision.getVersion() != revision.getVersion()) {
                         logger.debug("Unlocked Revision {} and updated associated Version to {}", revision, updatedRevision.getVersion());


[4/5] nifi git commit: NIFI-1781: - Updating UI according to permissions through out the application. - Shuffling provenance events, template, and cluster search REST APIs according to resources being authorized. - Moving template upload controls. - Remo

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java
index d8c2736..01f6d70 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerAuditor.java
@@ -80,7 +80,6 @@ public class ControllerAuditor extends NiFiAuditor {
                 // create the config action
                 FlowChangeAction configAction = new FlowChangeAction();
                 configAction.setUserIdentity(user.getIdentity());
-                configAction.setUserName(user.getUserName());
                 configAction.setOperation(Operation.Configure);
                 configAction.setTimestamp(new Date());
                 configAction.setSourceId("Flow Controller");
@@ -133,7 +132,6 @@ public class ControllerAuditor extends NiFiAuditor {
                 // create the config action
                 FlowChangeAction configAction = new FlowChangeAction();
                 configAction.setUserIdentity(user.getIdentity());
-                configAction.setUserName(user.getUserName());
                 configAction.setOperation(Operation.Configure);
                 configAction.setTimestamp(new Date());
                 configAction.setSourceId("Flow Controller");

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
index ded90f8..a122983 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
@@ -16,13 +16,6 @@
  */
 package org.apache.nifi.audit;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
@@ -30,13 +23,13 @@ import org.apache.nifi.action.Operation;
 import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
 import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ConfiguredComponent;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.ScheduledState;
-import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.controller.service.ControllerServiceReference;
 import org.apache.nifi.controller.service.ControllerServiceState;
@@ -49,6 +42,13 @@ import org.aspectj.lang.annotation.Aspect;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Audits controller service creation/removal and configuration changes.
  */
@@ -168,7 +168,6 @@ public class ControllerServiceAuditor extends NiFiAuditor {
                     // create a configuration action
                     FlowChangeAction configurationAction = new FlowChangeAction();
                     configurationAction.setUserIdentity(user.getIdentity());
-                    configurationAction.setUserName(user.getUserName());
                     configurationAction.setOperation(operation);
                     configurationAction.setTimestamp(actionTimestamp);
                     configurationAction.setSourceId(controllerService.getIdentifier());
@@ -188,7 +187,6 @@ public class ControllerServiceAuditor extends NiFiAuditor {
                 // create a controller service action
                 FlowChangeAction serviceAction = new FlowChangeAction();
                 serviceAction.setUserIdentity(user.getIdentity());
-                serviceAction.setUserName(user.getUserName());
                 serviceAction.setTimestamp(new Date());
                 serviceAction.setSourceId(controllerService.getIdentifier());
                 serviceAction.setSourceName(controllerService.getName());
@@ -272,7 +270,6 @@ public class ControllerServiceAuditor extends NiFiAuditor {
                 // create a processor action
                 FlowChangeAction processorAction = new FlowChangeAction();
                 processorAction.setUserIdentity(user.getIdentity());
-                processorAction.setUserName(user.getUserName());
                 processorAction.setTimestamp(new Date());
                 processorAction.setSourceId(processor.getIdentifier());
                 processorAction.setSourceName(processor.getName());
@@ -290,7 +287,6 @@ public class ControllerServiceAuditor extends NiFiAuditor {
                 // create a reporting task action
                 FlowChangeAction reportingTaskAction = new FlowChangeAction();
                 reportingTaskAction.setUserIdentity(user.getIdentity());
-                reportingTaskAction.setUserName(user.getUserName());
                 reportingTaskAction.setTimestamp(new Date());
                 reportingTaskAction.setSourceId(reportingTask.getIdentifier());
                 reportingTaskAction.setSourceName(reportingTask.getName());
@@ -308,7 +304,6 @@ public class ControllerServiceAuditor extends NiFiAuditor {
                 // create a controller service action
                 FlowChangeAction serviceAction = new FlowChangeAction();
                 serviceAction.setUserIdentity(user.getIdentity());
-                serviceAction.setUserName(user.getUserName());
                 serviceAction.setTimestamp(new Date());
                 serviceAction.setSourceId(controllerService.getIdentifier());
                 serviceAction.setSourceName(controllerService.getName());
@@ -388,7 +383,6 @@ public class ControllerServiceAuditor extends NiFiAuditor {
             // create the controller service action for adding this controller service
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(controllerService.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java
index 7230f9c..4f96772 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/FunnelAuditor.java
@@ -16,24 +16,23 @@
  */
 package org.apache.nifi.audit;
 
-import java.util.Date;
-
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
 import org.apache.nifi.action.Operation;
 import org.apache.nifi.action.details.ActionDetails;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.connectable.Funnel;
-import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.web.dao.FunnelDAO;
-
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Date;
+
 @Aspect
 public class FunnelAuditor extends NiFiAuditor {
 
@@ -121,7 +120,6 @@ public class FunnelAuditor extends NiFiAuditor {
             // create the action for adding this funnel
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(funnel.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java
index 3e5b0b5..93ac1f7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/PortAuditor.java
@@ -204,7 +204,6 @@ public class PortAuditor extends NiFiAuditor {
                     // create the port action for updating the name
                     FlowChangeAction portAction = new FlowChangeAction();
                     portAction.setUserIdentity(user.getIdentity());
-                    portAction.setUserName(user.getUserName());
                     portAction.setOperation(Operation.Configure);
                     portAction.setTimestamp(timestamp);
                     portAction.setSourceId(updatedPort.getIdentifier());
@@ -224,7 +223,6 @@ public class PortAuditor extends NiFiAuditor {
                 // create a processor action
                 FlowChangeAction processorAction = new FlowChangeAction();
                 processorAction.setUserIdentity(user.getIdentity());
-                processorAction.setUserName(user.getUserName());
                 processorAction.setTimestamp(new Date());
                 processorAction.setSourceId(updatedPort.getIdentifier());
                 processorAction.setSourceName(updatedPort.getName());
@@ -321,7 +319,6 @@ public class PortAuditor extends NiFiAuditor {
             // create the port action for adding this processor
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(port.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java
index a4277c6..391f9e2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessGroupAuditor.java
@@ -143,7 +143,6 @@ public class ProcessGroupAuditor extends NiFiAuditor {
                     // create the port action for updating the name
                     FlowChangeAction processGroupAction = new FlowChangeAction();
                     processGroupAction.setUserIdentity(user.getIdentity());
-                    processGroupAction.setUserName(user.getUserName());
                     processGroupAction.setOperation(operation);
                     processGroupAction.setTimestamp(timestamp);
                     processGroupAction.setSourceId(updatedProcessGroup.getIdentifier());
@@ -188,7 +187,6 @@ public class ProcessGroupAuditor extends NiFiAuditor {
         // if the user was starting/stopping this process group
         FlowChangeAction action = new FlowChangeAction();
         action.setUserIdentity(user.getIdentity());
-        action.setUserName(user.getUserName());
         action.setSourceId(processGroup.getIdentifier());
         action.setSourceName(processGroup.getName());
         action.setSourceType(Component.ProcessGroup);
@@ -264,7 +262,6 @@ public class ProcessGroupAuditor extends NiFiAuditor {
             // create the process group action for adding this process group
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(processGroup.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
index 8da70f0..32aab33 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
@@ -16,17 +16,7 @@
  */
 package org.apache.nifi.audit;
 
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
+import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
@@ -34,22 +24,32 @@ import org.apache.nifi.action.Operation;
 import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
 import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ScheduledState;
 import org.apache.nifi.processor.Relationship;
-import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
 import org.apache.nifi.web.api.dto.ProcessorDTO;
 import org.apache.nifi.web.dao.ProcessorDAO;
-import org.apache.commons.lang3.StringUtils;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Audits processor creation/removal and configuration changes.
  */
@@ -177,7 +177,6 @@ public class ProcessorAuditor extends NiFiAuditor {
                     // create a configuration action
                     FlowChangeAction configurationAction = new FlowChangeAction();
                     configurationAction.setUserIdentity(user.getIdentity());
-                    configurationAction.setUserName(user.getUserName());
                     configurationAction.setOperation(operation);
                     configurationAction.setTimestamp(actionTimestamp);
                     configurationAction.setSourceId(processor.getIdentifier());
@@ -197,7 +196,6 @@ public class ProcessorAuditor extends NiFiAuditor {
                 // create a processor action
                 FlowChangeAction processorAction = new FlowChangeAction();
                 processorAction.setUserIdentity(user.getIdentity());
-                processorAction.setUserName(user.getUserName());
                 processorAction.setTimestamp(new Date());
                 processorAction.setSourceId(processor.getIdentifier());
                 processorAction.setSourceName(processor.getName());
@@ -293,7 +291,6 @@ public class ProcessorAuditor extends NiFiAuditor {
             // create the processor action for adding this processor
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(processor.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java
index 1780790..2560b24 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RelationshipAuditor.java
@@ -16,14 +16,7 @@
  */
 package org.apache.nifi.audit;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
+import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
@@ -32,28 +25,34 @@ import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.ConnectDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
 import org.apache.nifi.action.details.FlowChangeConnectDetails;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Connection;
 import org.apache.nifi.connectable.Funnel;
 import org.apache.nifi.connectable.Port;
 import org.apache.nifi.controller.ProcessorNode;
-import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.flowfile.FlowFilePrioritizer;
+import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.processor.Relationship;
 import org.apache.nifi.remote.RemoteGroupPort;
 import org.apache.nifi.remote.TransferDirection;
-import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
 import org.apache.nifi.web.dao.ConnectionDAO;
-
-import org.apache.commons.lang3.StringUtils;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Audits relationship creation/removal.
  */
@@ -188,7 +187,6 @@ public class RelationshipAuditor extends NiFiAuditor {
                     // create a configuration action
                     FlowChangeAction configurationAction = new FlowChangeAction();
                     configurationAction.setUserIdentity(user.getIdentity());
-                    configurationAction.setUserName(user.getUserName());
                     configurationAction.setOperation(Operation.Configure);
                     configurationAction.setTimestamp(actionTimestamp);
                     configurationAction.setSourceId(connection.getIdentifier());
@@ -352,7 +350,6 @@ public class RelationshipAuditor extends NiFiAuditor {
             // create a new relationship action
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(actionTimestamp);
             action.setSourceId(connectionId);

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java
index e19bf29..d9a5df6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/RemoteProcessGroupAuditor.java
@@ -247,7 +247,6 @@ public class RemoteProcessGroupAuditor extends NiFiAuditor {
                     // create the port action for updating the name
                     FlowChangeAction remoteProcessGroupAction = new FlowChangeAction();
                     remoteProcessGroupAction.setUserIdentity(user.getIdentity());
-                    remoteProcessGroupAction.setUserName(user.getUserName());
                     remoteProcessGroupAction.setOperation(Operation.Configure);
                     remoteProcessGroupAction.setTimestamp(timestamp);
                     remoteProcessGroupAction.setSourceId(updatedRemoteProcessGroup.getIdentifier());
@@ -268,7 +267,6 @@ public class RemoteProcessGroupAuditor extends NiFiAuditor {
                 // create a processor action
                 FlowChangeAction remoteProcessGroupAction = new FlowChangeAction();
                 remoteProcessGroupAction.setUserIdentity(user.getIdentity());
-                remoteProcessGroupAction.setUserName(user.getUserName());
                 remoteProcessGroupAction.setTimestamp(new Date());
                 remoteProcessGroupAction.setSourceId(updatedRemoteProcessGroup.getIdentifier());
                 remoteProcessGroupAction.setSourceName(updatedRemoteProcessGroup.getName());
@@ -356,7 +354,6 @@ public class RemoteProcessGroupAuditor extends NiFiAuditor {
             // create the remote process group action
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(remoteProcessGroup.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
index 0dc8ee3..e198d5e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
@@ -16,13 +16,6 @@
  */
 package org.apache.nifi.audit;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
@@ -30,11 +23,11 @@ import org.apache.nifi.action.Operation;
 import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
 import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
+import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.ScheduledState;
-import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.web.api.dto.ReportingTaskDTO;
 import org.apache.nifi.web.dao.ReportingTaskDAO;
 import org.aspectj.lang.ProceedingJoinPoint;
@@ -43,6 +36,13 @@ import org.aspectj.lang.annotation.Aspect;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Audits reporting creation/removal and configuration changes.
  */
@@ -161,7 +161,6 @@ public class ReportingTaskAuditor extends NiFiAuditor {
                     // create a configuration action
                     FlowChangeAction configurationAction = new FlowChangeAction();
                     configurationAction.setUserIdentity(user.getIdentity());
-                    configurationAction.setUserName(user.getUserName());
                     configurationAction.setOperation(operation);
                     configurationAction.setTimestamp(actionTimestamp);
                     configurationAction.setSourceId(reportingTask.getIdentifier());
@@ -181,7 +180,6 @@ public class ReportingTaskAuditor extends NiFiAuditor {
                 // create a reporting task action
                 FlowChangeAction taskAction = new FlowChangeAction();
                 taskAction.setUserIdentity(user.getIdentity());
-                taskAction.setUserName(user.getUserName());
                 taskAction.setTimestamp(new Date());
                 taskAction.setSourceId(reportingTask.getIdentifier());
                 taskAction.setSourceName(reportingTask.getName());
@@ -277,7 +275,6 @@ public class ReportingTaskAuditor extends NiFiAuditor {
             // create the reporting task action for adding this reporting task
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(new Date());
             action.setSourceId(reportingTask.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
index 27b76b1..ce7313e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
@@ -232,7 +232,6 @@ public class SnippetAuditor extends NiFiAuditor {
             // create the action for adding this funnel
             action = new FlowChangeAction();
             action.setUserIdentity(user.getIdentity());
-            action.setUserName(user.getUserName());
             action.setOperation(operation);
             action.setTimestamp(timestamp);
             action.setSourceId(id);

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/AuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/AuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/AuthorizableLookup.java
index f5421e5..01f06c2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/AuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/AuthorizableLookup.java
@@ -38,6 +38,20 @@ public interface AuthorizableLookup {
     Authorizable getProcessor(String id);
 
     /**
+     * Get the authorizable for querying Provenance.
+     *
+     * @return authorizable
+     */
+    Authorizable getProvenance();
+
+    /**
+     * Get the authorizable for viewing/reseting Counters.
+     *
+     * @return authorizable
+     */
+    Authorizable getCounters();
+
+    /**
      * Get the authorizable InputPort.
      *
      * @param id input port id

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
index 40361ef..dd1f7e0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
@@ -73,6 +73,7 @@ import org.apache.nifi.web.api.entity.ConnectionEntity;
 import org.apache.nifi.web.api.entity.ControllerConfigurationEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentsEntity;
+import org.apache.nifi.web.api.entity.CurrentUserEntity;
 import org.apache.nifi.web.api.entity.FlowConfigurationEntity;
 import org.apache.nifi.web.api.entity.FlowEntity;
 import org.apache.nifi.web.api.entity.FunnelEntity;
@@ -86,6 +87,7 @@ import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
 import org.apache.nifi.web.api.entity.ScheduleComponentsEntity;
 import org.apache.nifi.web.api.entity.SnippetEntity;
+import org.apache.nifi.web.api.entity.TemplateEntity;
 import org.apache.nifi.web.api.entity.UserEntity;
 import org.apache.nifi.web.api.entity.UserGroupEntity;
 
@@ -440,7 +442,7 @@ public interface NiFiServiceFacade {
      *
      * @return templates
      */
-    Set<TemplateDTO> getTemplates();
+    Set<TemplateEntity> getTemplates();
 
     /**
      * Deletes the specified template.
@@ -832,9 +834,16 @@ public interface NiFiServiceFacade {
      */
     PortEntity deleteOutputPort(Revision revision, String outputPortId);
 
+    // ------------
+    // Current user
+    // ------------
+
+    CurrentUserEntity getCurrentUser();
+
     // ----------------------------------------
     // Flow methods
     // ----------------------------------------
+
     /**
      * Returns the flow.
      *

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
index e9117a9..5a9de3e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
@@ -20,7 +20,6 @@ import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.web.security.anonymous.NiFiAnonymousUserFilter;
 import org.apache.nifi.web.security.jwt.JwtAuthenticationFilter;
 import org.apache.nifi.web.security.jwt.JwtAuthenticationProvider;
-import org.apache.nifi.web.security.node.NodeAuthorizedUserFilter;
 import org.apache.nifi.web.security.otp.OtpAuthenticationFilter;
 import org.apache.nifi.web.security.otp.OtpAuthenticationProvider;
 import org.apache.nifi.web.security.x509.X509AuthenticationFilter;
@@ -54,8 +53,6 @@ public class NiFiWebApiSecurityConfiguration extends WebSecurityConfigurerAdapte
 
     private NiFiProperties properties;
 
-    private NodeAuthorizedUserFilter nodeAuthorizedUserFilter;
-
     private X509AuthenticationFilter x509AuthenticationFilter;
     private X509CertificateExtractor certificateExtractor;
     private X509PrincipalExtractor principalExtractor;
@@ -94,9 +91,6 @@ public class NiFiWebApiSecurityConfiguration extends WebSecurityConfigurerAdapte
                 .sessionManagement()
                     .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
 
-        // cluster authorized user
-        http.addFilterBefore(nodeAuthorizedUserFilterBean(), AnonymousAuthenticationFilter.class);
-
         // x509
         http.addFilterBefore(x509FilterBean(), AnonymousAuthenticationFilter.class);
 
@@ -126,17 +120,6 @@ public class NiFiWebApiSecurityConfiguration extends WebSecurityConfigurerAdapte
     }
 
     @Bean
-    public NodeAuthorizedUserFilter nodeAuthorizedUserFilterBean() throws Exception {
-        if (nodeAuthorizedUserFilter == null) {
-            nodeAuthorizedUserFilter = new NodeAuthorizedUserFilter();
-            nodeAuthorizedUserFilter.setProperties(properties);
-            nodeAuthorizedUserFilter.setCertificateExtractor(certificateExtractor);
-            nodeAuthorizedUserFilter.setCertificateIdentityProvider(certificateIdentityProvider);
-        }
-        return nodeAuthorizedUserFilter;
-    }
-
-    @Bean
     public JwtAuthenticationFilter jwtFilterBean() throws Exception {
         if (jwtAuthenticationFilter == null) {
             jwtAuthenticationFilter = new JwtAuthenticationFilter();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardAuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardAuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardAuthorizableLookup.java
index 13a5c20..4139888 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardAuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardAuthorizableLookup.java
@@ -16,9 +16,11 @@
  */
 package org.apache.nifi.web;
 
+import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.resource.AccessPoliciesAuthorizable;
 import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
 import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.resource.TenantAuthorizable;
 import org.apache.nifi.controller.ConfiguredComponent;
 import org.apache.nifi.controller.Snippet;
@@ -46,6 +48,30 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     private static final TenantAuthorizable TENANT_AUTHORIZABLE = new TenantAuthorizable();
     private static final Authorizable ACCESS_POLICIES_AUTHORIZABLE = new AccessPoliciesAuthorizable();
 
+    private static final Authorizable PROVENANCE_AUTHORIZABLE = new Authorizable() {
+        @Override
+        public Authorizable getParentAuthorizable() {
+            return null;
+        }
+
+        @Override
+        public Resource getResource() {
+            return ResourceFactory.getProvenanceResource();
+        }
+    };
+
+    private static final Authorizable COUNTERS_AUTHORIZABLE = new Authorizable() {
+        @Override
+        public Authorizable getParentAuthorizable() {
+            return null;
+        }
+
+        @Override
+        public Resource getResource() {
+            return ResourceFactory.getCountersResource();
+        }
+    };
+
     // nifi core components
     private ControllerFacade controllerFacade;
 
@@ -127,6 +153,16 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
+    public Authorizable getProvenance() {
+        return PROVENANCE_AUTHORIZABLE;
+    }
+
+    @Override
+    public Authorizable getCounters() {
+        return COUNTERS_AUTHORIZABLE;
+    }
+
+    @Override
     public Authorizable getControllerServiceReferencingComponent(String controllerSeriveId, String id) {
         final ControllerServiceNode controllerService = controllerServiceDAO.getControllerService(controllerSeriveId);
         final ControllerServiceReference referencingComponents = controllerService.getReferences();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
index 1691217..8a6b438 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiContentAccess.java
@@ -16,22 +16,11 @@
  */
 package org.apache.nifi.web;
 
-import java.io.Serializable;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.MultivaluedMap;
-
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.authorization.AccessDeniedException;
-import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.cluster.coordination.ClusterCoordinator;
 import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
 import org.apache.nifi.cluster.manager.NodeResponse;
@@ -39,13 +28,17 @@ import org.apache.nifi.cluster.manager.exception.IllegalClusterStateException;
 import org.apache.nifi.cluster.protocol.NodeIdentifier;
 import org.apache.nifi.controller.repository.claim.ContentDirection;
 import org.apache.nifi.util.NiFiProperties;
-import org.apache.nifi.web.util.WebUtils;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
 
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.ClientResponse.Status;
-import com.sun.jersey.core.util.MultivaluedMapImpl;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MultivaluedMap;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -87,19 +80,6 @@ public class StandardNiFiContentAccess implements ContentAccess {
                 headers.put("X-ProxiedEntitiesChain", request.getProxiedEntitiesChain());
             }
 
-            // add the user's authorities (if any) to the headers
-            final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-            if (authentication != null) {
-                final Object userDetailsObj = authentication.getPrincipal();
-                if (userDetailsObj instanceof NiFiUserDetails) {
-                    // serialize user details object
-                    final String hexEncodedUserDetails = WebUtils.serializeObjectToHex((Serializable) userDetailsObj);
-
-                    // put serialized user details in header
-                    headers.put("X-ProxiedEntityUserDetails", hexEncodedUserDetails);
-                }
-            }
-
             // ensure we were able to detect the cluster node id
             if (request.getClusterNodeId() == null) {
                 throw new IllegalArgumentException("Unable to determine the which node has the content.");

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 180b6bc..da253ca 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -143,6 +143,7 @@ import org.apache.nifi.web.api.entity.ControllerConfigurationEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentsEntity;
+import org.apache.nifi.web.api.entity.CurrentUserEntity;
 import org.apache.nifi.web.api.entity.FlowConfigurationEntity;
 import org.apache.nifi.web.api.entity.FlowEntity;
 import org.apache.nifi.web.api.entity.FunnelEntity;
@@ -156,6 +157,7 @@ import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
 import org.apache.nifi.web.api.entity.ScheduleComponentsEntity;
 import org.apache.nifi.web.api.entity.SnippetEntity;
+import org.apache.nifi.web.api.entity.TemplateEntity;
 import org.apache.nifi.web.api.entity.TenantEntity;
 import org.apache.nifi.web.api.entity.UserEntity;
 import org.apache.nifi.web.api.entity.UserGroupEntity;
@@ -639,7 +641,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
                     final D dto = dtoCreation.apply(component);
 
                     final Revision updatedRevision = revisionManager.getRevision(revision.getComponentId()).incrementRevision(revision.getClientId());
-                    final FlowModification lastModification = new FlowModification(updatedRevision, user.getUserName());
+                    final FlowModification lastModification = new FlowModification(updatedRevision, user.getIdentity());
                     return new StandardRevisionUpdate<>(dto, lastModification);
                 }
             });
@@ -1243,7 +1245,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
                     controllerFacade.save();
 
                     final D dto = dtoCreation.apply(component);
-                    final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getUserName());
+                    final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getIdentity());
                     return new StandardRevisionUpdate<D>(dto, lastMod);
                 });
             } finally {
@@ -1271,7 +1273,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     public AccessPolicyEntity createAccessPolicy(final Revision revision, final AccessPolicyDTO accessPolicyDTO) {
         // TODO read lock on users and groups (and resource+action?) while the policy is being created?
         final Authorizable tenantAuthorizable = authorizableLookup.getTenantAuthorizable();
-        final String creator = NiFiUserUtils.getNiFiUserName();
+        final String creator = NiFiUserUtils.getNiFiUserIdentity();
         final AccessPolicy newAccessPolicy = accessPolicyDAO.createAccessPolicy(accessPolicyDTO);
         final AccessPolicyDTO newAccessPolicyDto = dtoFactory.createAccessPolicyDto(newAccessPolicy,
                 newAccessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()),
@@ -1288,7 +1290,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     @Override
     public UserEntity createUser(final Revision revision, final UserDTO userDTO) {
         final Authorizable tenantAuthorizable = authorizableLookup.getTenantAuthorizable();
-        final String creator = NiFiUserUtils.getNiFiUserName();
+        final String creator = NiFiUserUtils.getNiFiUserIdentity();
         final User newUser = userDAO.createUser(userDTO);
         final UserDTO newUserDto = dtoFactory.createUserDto(newUser, newUser.getGroups().stream()
                 .map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()));
@@ -1300,7 +1302,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     @Override
     public UserGroupEntity createUserGroup(final Revision revision, final UserGroupDTO userGroupDTO) {
         final Authorizable tenantAuthorizable = authorizableLookup.getTenantAuthorizable();
-        final String creator = NiFiUserUtils.getNiFiUserName();
+        final String creator = NiFiUserUtils.getNiFiUserIdentity();
         final Group newUserGroup = userGroupDAO.createUserGroup(userGroupDTO);
         final UserGroupDTO newUserGroupDto = dtoFactory.createUserGroupDto(newUserGroup, newUserGroup.getUsers().stream()
                 .map(userId -> {
@@ -1615,7 +1617,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
 
                     controllerFacade.save();
 
-                    final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getUserName());
+                    final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getIdentity());
                     return new StandardRevisionUpdate<ControllerServiceDTO>(dto, lastMod);
                 });
             } finally {
@@ -1631,7 +1633,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
 
                         controllerFacade.save();
 
-                        final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getUserName());
+                        final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getIdentity());
                         return new StandardRevisionUpdate<ControllerServiceDTO>(dto, lastMod);
                     });
                 } finally {
@@ -1759,7 +1761,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     private ControllerServiceReferencingComponentsEntity createControllerServiceReferencingComponentsEntity(
             final ControllerServiceReference reference, final Map<String, Revision> revisions, final Set<ControllerServiceNode> visited) {
 
-        final String modifier = NiFiUserUtils.getNiFiUserName();
+        final String modifier = NiFiUserUtils.getNiFiUserIdentity();
         final Set<ConfiguredComponent> referencingComponents = reference.getReferencingComponents();
 
         final Set<ControllerServiceReferencingComponentEntity> componentEntities = new HashSet<>();
@@ -1827,7 +1829,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
                 controllerFacade.save();
 
                 final ReportingTaskDTO dto = dtoFactory.createReportingTaskDto(reportingTask);
-                final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getUserName());
+                final FlowModification lastMod = new FlowModification(revision.incrementRevision(revision.getClientId()), user.getIdentity());
                 return new StandardRevisionUpdate<ReportingTaskDTO>(dto, lastMod);
             });
 
@@ -1882,7 +1884,6 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         // create a purge action to record that records are being removed
         final FlowChangeAction purgeAction = new FlowChangeAction();
         purgeAction.setUserIdentity(user.getIdentity());
-        purgeAction.setUserName(user.getUserName());
         purgeAction.setOperation(Operation.Purge);
         purgeAction.setTimestamp(new Date());
         purgeAction.setSourceId("Flow Controller");
@@ -2127,12 +2128,18 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     }
 
     @Override
-    public Set<TemplateDTO> getTemplates() {
-        final Set<TemplateDTO> templateDtos = new LinkedHashSet<>();
-        for (final Template template : templateDAO.getTemplates()) {
-            templateDtos.add(dtoFactory.createTemplateDTO(template));
-        }
-        return templateDtos;
+    public Set<TemplateEntity> getTemplates() {
+        return templateDAO.getTemplates().stream()
+                .map(template -> {
+                    final TemplateDTO dto = dtoFactory.createTemplateDTO(template);
+                    final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(template);
+
+                    final TemplateEntity entity = new TemplateEntity();
+                    entity.setId(dto.getId());
+                    entity.setAccessPolicy(accessPolicy);
+                    entity.setTemplate(dto);
+                    return entity;
+                }).collect(Collectors.toSet());
     }
 
     @Override
@@ -2599,6 +2606,19 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
     }
 
     @Override
+    public CurrentUserEntity getCurrentUser() {
+        final NiFiUser user = NiFiUserUtils.getNiFiUser();
+        final CurrentUserEntity entity = new CurrentUserEntity();
+        entity.setIdentity(user.getIdentity());
+        entity.setAnonymous(user.isAnonymous());
+        entity.setProvenancePermissions(dtoFactory.createAccessPolicyDto(authorizableLookup.getProvenance()));
+        entity.setCountersPermissions(dtoFactory.createAccessPolicyDto(authorizableLookup.getCounters()));
+        entity.setTenantsPermissions(dtoFactory.createAccessPolicyDto(authorizableLookup.getTenantAuthorizable()));
+        entity.setControllerPermissions(dtoFactory.createAccessPolicyDto(authorizableLookup.getController()));
+        return entity;
+    }
+
+    @Override
     public ProcessGroupFlowEntity getProcessGroupFlow(final String groupId, final boolean recurse) {
         return revisionManager.get(groupId,
                 rev -> {
@@ -2823,7 +2843,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         historyQuery.setStartDate(historyQueryDto.getStartDate());
         historyQuery.setEndDate(historyQueryDto.getEndDate());
         historyQuery.setSourceId(historyQueryDto.getSourceId());
-        historyQuery.setUserName(historyQueryDto.getUserName());
+        historyQuery.setUserIdentity(historyQueryDto.getUserIdentity());
         historyQuery.setOffset(historyQueryDto.getOffset());
         historyQuery.setCount(historyQueryDto.getCount());
         historyQuery.setSortColumn(historyQueryDto.getSortColumn());
@@ -2833,10 +2853,25 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
         final History history = auditService.getActions(historyQuery);
 
         // only retain authorized actions
-        history.getActions().stream().filter(action -> authorizeAction(action)).collect(Collectors.toList());
+        final HistoryDTO historyDto = dtoFactory.createHistoryDto(history);
+        if (history.getActions() != null) {
+            final List<ActionDTO> actionDtos = new ArrayList<>();
+            for (final Action action : history.getActions()) {
+                if (authorizeAction(action)) {
+                    actionDtos.add(dtoFactory.createActionDto(action));
+                } else {
+                    final ActionDTO actionDto = new ActionDTO();
+                    actionDto.setTimestamp(action.getTimestamp());
+                    actionDto.setId(action.getId());
+                    actionDto.setSourceId(action.getSourceId());
+                    actionDtos.add(actionDto);
+                }
+            }
+            historyDto.setActions(actionDtos);
+        }
 
         // create the response
-        return dtoFactory.createHistoryDto(history);
+        return historyDto;
     }
 
     @Override
@@ -2869,7 +2904,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
                 final PreviousValueDTO dto = new PreviousValueDTO();
                 dto.setPreviousValue(previousValue.getPreviousValue());
                 dto.setTimestamp(previousValue.getTimestamp());
-                dto.setUserName(previousValue.getUserName());
+                dto.setUserIdentity(previousValue.getUserIdentity());
                 previousValueDtos.add(dto);
             }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
index f263ac6..b42f839 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiWebConfigurationContext.java
@@ -34,7 +34,6 @@ import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.user.NiFiUser;
-import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.cluster.coordination.ClusterCoordinator;
 import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
@@ -54,16 +53,12 @@ import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.ProcessorEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
 import org.apache.nifi.web.util.ClientResponseUtils;
-import org.apache.nifi.web.util.WebUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
 
 import javax.ws.rs.HttpMethod;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
-import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -182,8 +177,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
             action.setSourceName(configurationAction.getName());
             action.setSourceType(componentType);
             action.setOperation(Operation.Configure);
-            action.setUserIdentity(getCurrentUserDn());
-            action.setUserName(getCurrentUserName());
+            action.setUserIdentity(getCurrentUserIdentity());
             action.setComponentDetails(extensionDetails);
             action.setActionDetails(configureDetails);
             actions.add(action);
@@ -203,20 +197,13 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
     }
 
     @Override
-    public String getCurrentUserDn() {
+    public String getCurrentUserIdentity() {
         final NiFiUser user = NiFiUserUtils.getNiFiUser();
         authorizeFlowAccess(user);
         return user.getIdentity();
     }
 
     @Override
-    public String getCurrentUserName() {
-        final NiFiUser user = NiFiUserUtils.getNiFiUser();
-        authorizeFlowAccess(user);
-        return user.getUserName();
-    }
-
-    @Override
     public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) throws ResourceNotFoundException, ClusterRequestException {
         final String id = requestContext.getId();
 
@@ -841,19 +828,6 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
         if (StringUtils.isNotBlank(config.getProxiedEntitiesChain())) {
             headers.put("X-ProxiedEntitiesChain", config.getProxiedEntitiesChain());
         }
-
-        // add the user's authorities (if any) to the headers
-        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        if (authentication != null) {
-            final Object userDetailsObj = authentication.getPrincipal();
-            if (userDetailsObj instanceof NiFiUserDetails) {
-                // serialize user details object
-                final String hexEncodedUserDetails = WebUtils.serializeObjectToHex((Serializable) userDetailsObj);
-
-                // put serialized user details in header
-                headers.put("X-ProxiedEntityUserDetails", hexEncodedUserDetails);
-            }
-        }
         return headers;
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.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/AccessResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
index b425562..e0162bc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
@@ -16,21 +16,11 @@
  */
 package org.apache.nifi.web.api;
 
-import java.net.URI;
-import java.security.cert.X509Certificate;
-import java.util.concurrent.TimeUnit;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import io.jsonwebtoken.JwtException;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.admin.service.AdministrationException;
 import org.apache.nifi.authentication.AuthenticationResponse;
@@ -75,12 +65,19 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
 
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
-
-import io.jsonwebtoken.JwtException;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
 
 /**
  * RESTful endpoint for managing access.
@@ -207,7 +204,6 @@ public class AccessResource extends ApplicationResource {
 
                         // set the user identity
                         accessStatus.setIdentity(nifiUser.getIdentity());
-                        accessStatus.setUsername(nifiUser.getUserName());
 
                         // attempt authorize to /flow
                         accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());
@@ -226,7 +222,6 @@ public class AccessResource extends ApplicationResource {
 
                     // set the user identity
                     accessStatus.setIdentity(nifiUser.getIdentity());
-                    accessStatus.setUsername(nifiUser.getUserName());
 
                     // attempt authorize to /flow
                     accessStatus.setStatus(AccessStatusDTO.Status.ACTIVE.name());

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.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/ApplicationResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
index 262e274..120c387 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java
@@ -25,7 +25,6 @@ import org.apache.nifi.authorization.Authorizer;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
-import org.apache.nifi.authorization.user.NiFiUserDetails;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
 import org.apache.nifi.cluster.coordination.ClusterCoordinator;
 import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
@@ -41,12 +40,8 @@ import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.dto.SnippetDTO;
 import org.apache.nifi.web.api.entity.ComponentEntity;
 import org.apache.nifi.web.api.request.ClientIdParameter;
-import org.apache.nifi.web.security.jwt.JwtAuthenticationFilter;
-import org.apache.nifi.web.util.WebUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -58,7 +53,6 @@ import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriBuilderException;
 import javax.ws.rs.core.UriInfo;
-import java.io.Serializable;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
@@ -80,13 +74,10 @@ public abstract class ApplicationResource {
 
     public static final String VERSION = "version";
     public static final String CLIENT_ID = "clientId";
-    public static final String CLUSTER_CONTEXT_HTTP_HEADER = "X-ClusterContext";
     public static final String PROXY_SCHEME_HTTP_HEADER = "X-ProxyScheme";
     public static final String PROXY_HOST_HTTP_HEADER = "X-ProxyHost";
     public static final String PROXY_PORT_HTTP_HEADER = "X-ProxyPort";
     public static final String PROXY_CONTEXT_PATH_HTTP_HEADER = "X-ProxyContextPath";
-    public static final String PROXIED_ENTITIES_CHAIN_HTTP_HEADER = "X-ProxiedEntitiesChain";
-    public static final String PROXIED_ENTITY_USER_DETAILS_HTTP_HEADER = "X-ProxiedEntityUserDetails";
 
     private static final Logger logger = LoggerFactory.getLogger(ApplicationResource.class);
 
@@ -324,24 +315,6 @@ public abstract class ApplicationResource {
             result.put(PROXY_SCHEME_HTTP_HEADER, httpServletRequest.getScheme());
         }
 
-        if (httpServletRequest.isSecure()) {
-
-            // add the user's authorities (if any) to the headers
-            final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-            if (authentication != null) {
-                final Object userDetailsObj = authentication.getPrincipal();
-                if (userDetailsObj instanceof NiFiUserDetails) {
-                    // serialize user details object
-                    final String hexEncodedUserDetails = WebUtils.serializeObjectToHex((Serializable) userDetailsObj);
-
-                    // put serialized user details in header
-                    result.put(PROXIED_ENTITY_USER_DETAILS_HTTP_HEADER, hexEncodedUserDetails);
-
-                    // remove the access token if present, since the user is already authenticated/authorized
-                    result.remove(JwtAuthenticationFilter.AUTHORIZATION);
-                }
-            }
-        }
         return result;
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
index 30cff5f..31ecd4c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
@@ -33,7 +33,6 @@ import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.resource.ResourceFactory;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
-import org.apache.nifi.cluster.coordination.node.NodeConnectionState;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.web.IllegalClusterResourceRequestException;
 import org.apache.nifi.web.NiFiServiceFacade;
@@ -41,9 +40,7 @@ import org.apache.nifi.web.Revision;
 import org.apache.nifi.web.api.dto.ClusterDTO;
 import org.apache.nifi.web.api.dto.NodeDTO;
 import org.apache.nifi.web.api.dto.RevisionDTO;
-import org.apache.nifi.web.api.dto.search.NodeSearchResultDTO;
 import org.apache.nifi.web.api.entity.ClusterEntity;
-import org.apache.nifi.web.api.entity.ClusterSearchResultsEntity;
 import org.apache.nifi.web.api.entity.ControllerConfigurationEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
 import org.apache.nifi.web.api.entity.HistoryEntity;
@@ -69,8 +66,6 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * RESTful endpoint for managing a Flow Controller.
@@ -488,81 +483,6 @@ public class ControllerResource extends ApplicationResource {
     }
 
     /**
-     * Searches the cluster for a node with a given address.
-     *
-     * @param value Search value that will be matched against a node's address
-     * @return Nodes that match the specified criteria
-     */
-    @GET
-    @Consumes(MediaType.WILDCARD)
-    @Produces(MediaType.APPLICATION_JSON)
-    @Path("cluster/search-results")
-    // TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
-    @ApiOperation(
-            value = "Searches the cluster for a node with the specified address",
-            response = ClusterSearchResultsEntity.class,
-            authorizations = {
-                    @Authorization(value = "Read Only", type = "ROLE_MONITOR"),
-                    @Authorization(value = "DFM", type = "ROLE_DFM"),
-                    @Authorization(value = "Admin", type = "ROLE_ADMIN")
-            }
-    )
-    @ApiResponses(
-            value = {
-                    @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
-                    @ApiResponse(code = 401, message = "Client could not be authenticated."),
-                    @ApiResponse(code = 403, message = "Client is not authorized to make this request."),
-                    @ApiResponse(code = 404, message = "The specified resource could not be found."),
-                    @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
-            }
-    )
-    public Response searchCluster(
-            @ApiParam(
-                    value = "Node address to search for.",
-                    required = true
-            )
-            @QueryParam("q") @DefaultValue(StringUtils.EMPTY) String value) {
-
-        authorizeController(RequestAction.READ);
-
-        // ensure connected to the cluster
-        if (!isConnectedToCluster()) {
-            throw new IllegalClusterResourceRequestException("Only a node connected to a cluster can process the request.");
-        }
-
-        final List<NodeSearchResultDTO> nodeMatches = new ArrayList<>();
-
-        // get the nodes in the cluster
-        final ClusterDTO cluster = serviceFacade.getCluster();
-
-        // check each to see if it matches the search term
-        for (NodeDTO node : cluster.getNodes()) {
-            // ensure the node is connected
-            if (!NodeConnectionState.CONNECTED.name().equals(node.getStatus())) {
-                continue;
-            }
-
-            // determine the current nodes address
-            final String address = node.getAddress() + ":" + node.getApiPort();
-
-            // count the node if there is no search or it matches the address
-            if (StringUtils.isBlank(value) || StringUtils.containsIgnoreCase(address, value)) {
-                final NodeSearchResultDTO nodeMatch = new NodeSearchResultDTO();
-                nodeMatch.setId(node.getNodeId());
-                nodeMatch.setAddress(address);
-                nodeMatches.add(nodeMatch);
-            }
-        }
-
-        // build the response
-        ClusterSearchResultsEntity results = new ClusterSearchResultsEntity();
-        results.setNodeResults(nodeMatches);
-
-        // generate an 200 - OK response
-        return noCache(Response.ok(results)).build();
-    }
-
-    /**
      * Gets the contents of the specified node in this NiFi cluster.
      *
      * @param id The node id.


[5/5] nifi git commit: NIFI-1781: - Updating UI according to permissions through out the application. - Shuffling provenance events, template, and cluster search REST APIs according to resources being authorized. - Moving template upload controls. - Remo

Posted by ma...@apache.org.
NIFI-1781:
- Updating UI according to permissions through out the application.
- Shuffling provenance events, template, and cluster search REST APIs according to resources being authorized.
- Moving template upload controls.
- Removing username where appropriate.
- Addressing issues when authorizing flow configuration actions.
- Code clean up.


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

Branch: refs/heads/master
Commit: ce5330330ac1e377144fc1d29d5ef9fb2f60e29f
Parents: 8eb0a38
Author: Matt Gilman <ma...@gmail.com>
Authored: Fri Jul 1 15:10:27 2016 -0400
Committer: Matt Gilman <ma...@gmail.com>
Committed: Fri Jul 1 15:10:27 2016 -0400

----------------------------------------------------------------------
 .../java/org/apache/nifi/action/Action.java     |   2 -
 .../authorization/AuthorizationRequest.java     |  38 +-
 .../apache/nifi/authorization/Authorizer.java   |   2 +-
 .../authorization/resource/Authorizable.java    |  48 ++-
 .../nifi/authorization/user/NiFiUser.java       |   5 -
 .../nifi/web/NiFiWebConfigurationContext.java   |  11 +-
 .../org/apache/nifi/util/NiFiProperties.java    |   3 +-
 .../java/org/apache/nifi/web/util/WebUtils.java |  94 +----
 .../nifi/admin/AuditDataSourceFactoryBean.java  |  31 +-
 .../nifi/admin/dao/impl/StandardActionDAO.java  |  64 ++-
 .../nifi/admin/dao/impl/StandardKeyDAO.java     |   7 +-
 .../org/apache/nifi/history/HistoryQuery.java   |  10 +-
 .../org/apache/nifi/history/PreviousValue.java  |  10 +-
 .../nifi/web/api/dto/AccessStatusDTO.java       |  15 -
 .../nifi/web/api/dto/PreviousValueDTO.java      |  15 +-
 .../nifi/web/api/dto/action/ActionDTO.java      |  22 +-
 .../web/api/dto/action/HistoryQueryDTO.java     |  19 +-
 .../dto/search/UserGroupSearchResultDTO.java    |  44 ---
 .../web/api/dto/search/UserSearchResultDTO.java |  59 ---
 .../nifi/web/api/entity/AuthorityEntity.java    |  54 ---
 .../nifi/web/api/entity/CurrentUserEntity.java  | 102 +++++
 .../nifi/web/api/entity/IdentityEntity.java     |  63 ---
 .../nifi/web/api/entity/TemplateEntity.java     |   5 +-
 .../nifi/web/api/entity/TemplatesEntity.java    |  14 +-
 .../web/api/entity/UserSearchResultsEntity.java |  56 ---
 .../nifi/authorization/FileAuthorizer.java      |   2 +-
 .../nifi/authorization/user/NiFiUserUtils.java  |   4 +-
 .../authorization/user/StandardNiFiUser.java    |  19 +-
 .../org/apache/nifi/controller/Template.java    |  53 ++-
 .../nifi/groups/StandardProcessGroup.java       |   4 +
 .../apache/nifi/action/FlowChangeAction.java    |  10 -
 .../nifi/audit/ComponentStateAuditor.java       |   3 -
 .../apache/nifi/audit/ControllerAuditor.java    |   2 -
 .../nifi/audit/ControllerServiceAuditor.java    |  22 +-
 .../org/apache/nifi/audit/FunnelAuditor.java    |   8 +-
 .../java/org/apache/nifi/audit/PortAuditor.java |   3 -
 .../apache/nifi/audit/ProcessGroupAuditor.java  |   3 -
 .../org/apache/nifi/audit/ProcessorAuditor.java |  29 +-
 .../apache/nifi/audit/RelationshipAuditor.java  |  25 +-
 .../nifi/audit/RemoteProcessGroupAuditor.java   |   3 -
 .../apache/nifi/audit/ReportingTaskAuditor.java |  19 +-
 .../org/apache/nifi/audit/SnippetAuditor.java   |   1 -
 .../org/apache/nifi/web/AuthorizableLookup.java |  14 +
 .../org/apache/nifi/web/NiFiServiceFacade.java  |  11 +-
 .../web/NiFiWebApiSecurityConfiguration.java    |  17 -
 .../nifi/web/StandardAuthorizableLookup.java    |  36 ++
 .../nifi/web/StandardNiFiContentAccess.java     |  46 +--
 .../nifi/web/StandardNiFiServiceFacade.java     |  75 +++-
 .../StandardNiFiWebConfigurationContext.java    |  30 +-
 .../org/apache/nifi/web/api/AccessResource.java |  41 +-
 .../nifi/web/api/ApplicationResource.java       |  27 --
 .../apache/nifi/web/api/ControllerResource.java |  80 ----
 .../org/apache/nifi/web/api/FlowResource.java   | 289 +++++++++-----
 .../nifi/web/api/ProcessGroupResource.java      | 130 ++----
 .../nifi/web/api/ProvenanceEventResource.java   | 391 +++++++++++++++++++
 .../apache/nifi/web/api/ProvenanceResource.java | 366 ++---------------
 .../apache/nifi/web/api/TemplateResource.java   |  60 ++-
 .../org/apache/nifi/web/api/dto/DtoFactory.java |  11 +-
 .../nifi/web/controller/ControllerFacade.java   | 212 +++++++---
 .../web/dao/impl/StandardConnectionDAO.java     |   2 +-
 .../src/main/resources/nifi-web-api-context.xml |   6 +
 .../nifi/web/revision/NaiveRevisionManager.java |   4 +-
 .../security/node/NodeAuthorizedUserFilter.java | 128 ------
 .../x509/X509AuthenticationProvider.java        |   2 +-
 .../src/main/webapp/WEB-INF/pages/canvas.jsp    |   2 +
 .../src/main/webapp/WEB-INF/pages/templates.jsp |   1 -
 .../WEB-INF/partials/canvas/canvas-header.jsp   |  21 +-
 .../WEB-INF/partials/canvas/navigation.jsp      |   8 +-
 .../partials/canvas/upload-template-dialog.jsp  |  35 ++
 .../partials/templates/templates-content.jsp    |  19 -
 .../nifi-web-ui/src/main/webapp/css/header.css  |  11 +-
 .../nifi-web-ui/src/main/webapp/css/main.css    |  75 ++++
 .../src/main/webapp/css/templates.css           |  90 -----
 .../nf-ng-canvas-global-menu-controller.js      |  50 +--
 .../nf-ng-canvas-operate-controller.js          | 138 +++++++
 .../nf-ng-canvas-toolbox-controller.js          |  27 +-
 .../components/nf-ng-template-component.js      |  16 +-
 .../src/main/webapp/js/nf/canvas/nf-actions.js  |   7 +
 .../src/main/webapp/js/nf/canvas/nf-canvas.js   |  92 +----
 .../main/webapp/js/nf/canvas/nf-context-menu.js |   2 +-
 .../js/nf/canvas/nf-processor-configuration.js  |   5 -
 .../nf/canvas/nf-remote-process-group-ports.js  |  19 +-
 .../src/main/webapp/js/nf/canvas/nf-settings.js |  32 +-
 .../webapp/js/nf/cluster/nf-cluster-table.js    |   6 +-
 .../src/main/webapp/js/nf/cluster/nf-cluster.js |  35 +-
 .../webapp/js/nf/counters/nf-counters-table.js  |   2 +-
 .../main/webapp/js/nf/counters/nf-counters.js   |  36 +-
 .../webapp/js/nf/history/nf-history-model.js    |   2 +-
 .../webapp/js/nf/history/nf-history-table.js    |  19 +-
 .../src/main/webapp/js/nf/history/nf-history.js |  36 +-
 .../src/main/webapp/js/nf/login/nf-login.js     |   2 -
 .../src/main/webapp/js/nf/nf-common.js          | 117 ++++--
 .../js/nf/provenance/nf-provenance-lineage.js   |   2 +-
 .../js/nf/provenance/nf-provenance-table.js     |  95 +++--
 .../webapp/js/nf/provenance/nf-provenance.js    |  35 +-
 .../webapp/js/nf/summary/nf-cluster-search.js   |   2 +-
 .../js/nf/templates/nf-templates-table.js       | 100 +++--
 .../main/webapp/js/nf/templates/nf-templates.js | 124 +-----
 .../PersistentProvenanceRepository.java         |  94 ++---
 .../TestPersistentProvenanceRepository.java     |  59 ++-
 .../VolatileProvenanceRepository.java           |  46 +--
 .../TestVolatileProvenanceRepository.java       |  24 +-
 .../script/ExecuteScriptGroovyTest.groovy       |   4 +-
 103 files changed, 2105 insertions(+), 2366 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-api/src/main/java/org/apache/nifi/action/Action.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/action/Action.java b/nifi-api/src/main/java/org/apache/nifi/action/Action.java
index 4ab167e..ed6505f 100644
--- a/nifi-api/src/main/java/org/apache/nifi/action/Action.java
+++ b/nifi-api/src/main/java/org/apache/nifi/action/Action.java
@@ -33,8 +33,6 @@ public interface Action extends Serializable {
 
     String getUserIdentity();
 
-    String getUserName();
-
     String getSourceId();
 
     String getSourceName();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizationRequest.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizationRequest.java b/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizationRequest.java
index 7e6999c..da0a276 100644
--- a/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizationRequest.java
+++ b/nifi-api/src/main/java/org/apache/nifi/authorization/AuthorizationRequest.java
@@ -22,7 +22,7 @@ import java.util.Map;
 import java.util.Objects;
 
 /**
- * Represents an authorization request for a given user/entity performing an action against a resource within some context.
+ * Represents an authorization request for a given user/entity performing an action against a resource within some userContext.
  */
 public class AuthorizationRequest {
 
@@ -31,8 +31,8 @@ public class AuthorizationRequest {
     private final RequestAction action;
     private final boolean isAccessAttempt;
     private final boolean isAnonymous;
-    private final Map<String, String> context;
-    private final Map<String, String> eventAttributes;
+    private final Map<String, String> userContext;
+    private final Map<String, String> resourceContext;
 
     private AuthorizationRequest(final Builder builder) {
         Objects.requireNonNull(builder.resource, "The resource is required when creating an authorization request");
@@ -45,8 +45,8 @@ public class AuthorizationRequest {
         this.action = builder.action;
         this.isAccessAttempt = builder.isAccessAttempt;
         this.isAnonymous = builder.isAnonymous;
-        this.context = builder.context == null ? null : Collections.unmodifiableMap(builder.context);
-        this.eventAttributes = builder.context == null ? null : Collections.unmodifiableMap(builder.eventAttributes);
+        this.userContext = builder.userContext == null ? null : Collections.unmodifiableMap(builder.userContext);
+        this.resourceContext = builder.resourceContext == null ? null : Collections.unmodifiableMap(builder.resourceContext);
     }
 
     /**
@@ -95,12 +95,12 @@ public class AuthorizationRequest {
     }
 
     /**
-     * The context of the user request to make additional access decisions. May be null.
+     * The userContext of the user request to make additional access decisions. May be null.
      *
-     * @return  The context of the user request
+     * @return  The userContext of the user request
      */
-    public Map<String, String> getContext() {
-        return context;
+    public Map<String, String> getUserContext() {
+        return userContext;
     }
 
     /**
@@ -108,8 +108,8 @@ public class AuthorizationRequest {
      *
      * @return  The event attributes
      */
-    public Map<String, String> getEventAttributes() {
-        return eventAttributes;
+    public Map<String, String> getResourceContext() {
+        return resourceContext;
     }
 
     /**
@@ -122,8 +122,8 @@ public class AuthorizationRequest {
         private Boolean isAnonymous;
         private Boolean isAccessAttempt;
         private RequestAction action;
-        private Map<String, String> context;
-        private Map<String, String> eventAttributes;
+        private Map<String, String> userContext;
+        private Map<String, String> resourceContext;
 
         public Builder resource(final Resource resource) {
             this.resource = resource;
@@ -150,13 +150,17 @@ public class AuthorizationRequest {
             return this;
         }
 
-        public Builder context(final Map<String, String> context) {
-            this.context = new HashMap<>(context);
+        public Builder userContext(final Map<String, String> userContext) {
+            if (userContext != null) {
+                this.userContext = new HashMap<>(userContext);
+            }
             return this;
         }
 
-        public Builder eventAttributes(final Map<String, String> eventAttributes) {
-            this.eventAttributes = new HashMap<>(eventAttributes);
+        public Builder resourceContext(final Map<String, String> resourceContext) {
+            if (resourceContext != null) {
+                this.resourceContext = new HashMap<>(resourceContext);
+            }
             return this;
         }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-api/src/main/java/org/apache/nifi/authorization/Authorizer.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/Authorizer.java b/nifi-api/src/main/java/org/apache/nifi/authorization/Authorizer.java
index 5aec6f0..cb8c7f1 100644
--- a/nifi-api/src/main/java/org/apache/nifi/authorization/Authorizer.java
+++ b/nifi-api/src/main/java/org/apache/nifi/authorization/Authorizer.java
@@ -30,7 +30,7 @@ public interface Authorizer {
      *
      * @param   request The authorization request
      * @return  the authorization result
-     * @throws  AuthorizationAccessException if unable to access the authorities
+     * @throws  AuthorizationAccessException if unable to access the policies
      */
     AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java b/nifi-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
index 09fab19..90374dd 100644
--- a/nifi-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
+++ b/nifi-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java
@@ -25,6 +25,8 @@ import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.Resource;
 import org.apache.nifi.authorization.user.NiFiUser;
 
+import java.util.Map;
+
 public interface Authorizable {
 
     /**
@@ -64,7 +66,7 @@ public interface Authorizable {
      * @param user user
      * @return is authorized
      */
-    default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user) {
+    default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) {
         // TODO - include user details context
 
         // build the request
@@ -74,6 +76,7 @@ public interface Authorizable {
                 .accessAttempt(false)
                 .action(action)
                 .resource(getResource())
+                .resourceContext(resourceContext)
                 .build();
 
         // perform the authorization
@@ -93,22 +96,39 @@ public interface Authorizable {
     }
 
     /**
+     * Returns the result of an authorization request for the specified user for the specified action on the specified
+     * resource. This method does not imply the user is directly attempting to access the specified resource. If the user is
+     * attempting a direct access use Authorizable.authorize().
+     *
+     * @param authorizer authorizer
+     * @param action action
+     * @param user user
+     * @return is authorized
+     */
+    default AuthorizationResult checkAuthorization(Authorizer authorizer, RequestAction action, NiFiUser user) {
+        return checkAuthorization(authorizer, action, user, null);
+    }
+
+    /**
      * Authorizes the current user for the specified action on the specified resource. This method does imply the user is
      * directly accessing the specified resource.
      *
      * @param authorizer authorizer
      * @param action action
+     * @param user user
+     * @param resourceContext resource context
      */
-    default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user) throws AccessDeniedException {
+    default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user, Map<String, String> resourceContext) throws AccessDeniedException {
         // TODO - include user details context
 
         final AuthorizationRequest request = new AuthorizationRequest.Builder()
-            .identity(user.getIdentity())
-            .anonymous(user.isAnonymous())
-            .accessAttempt(true)
-            .action(action)
-            .resource(getResource())
-            .build();
+                .identity(user.getIdentity())
+                .anonymous(user.isAnonymous())
+                .accessAttempt(true)
+                .action(action)
+                .resource(getResource())
+                .resourceContext(resourceContext)
+                .build();
 
         final AuthorizationResult result = authorizer.authorize(request);
         if (Result.ResourceNotFound.equals(result.getResult())) {
@@ -122,4 +142,16 @@ public interface Authorizable {
             throw new AccessDeniedException(result.getExplanation());
         }
     }
+
+    /**
+     * Authorizes the current user for the specified action on the specified resource. This method does imply the user is
+     * directly accessing the specified resource.
+     *
+     * @param authorizer authorizer
+     * @param action action
+     * @param user user
+     */
+    default void authorize(Authorizer authorizer, RequestAction action, NiFiUser user) throws AccessDeniedException {
+        authorize(authorizer, action, user, null);
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-api/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java b/nifi-api/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java
index d5dee54..9ec04e2 100644
--- a/nifi-api/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java
+++ b/nifi-api/src/main/java/org/apache/nifi/authorization/user/NiFiUser.java
@@ -28,11 +28,6 @@ public interface NiFiUser {
     String getIdentity();
 
     /**
-     * @return the user name for this user
-     */
-    String getUserName();
-
-    /**
      * @return the next user in the proxied entities chain, or <code>null</code> if no more users exist in the chain.
      */
     NiFiUser getChain();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-api/src/main/java/org/apache/nifi/web/NiFiWebConfigurationContext.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/web/NiFiWebConfigurationContext.java b/nifi-api/src/main/java/org/apache/nifi/web/NiFiWebConfigurationContext.java
index a0a605c..5082af2 100644
--- a/nifi-api/src/main/java/org/apache/nifi/web/NiFiWebConfigurationContext.java
+++ b/nifi-api/src/main/java/org/apache/nifi/web/NiFiWebConfigurationContext.java
@@ -16,11 +16,11 @@
  */
 package org.apache.nifi.web;
 
+import org.apache.nifi.controller.ControllerService;
+
 import java.util.Collection;
 import java.util.Map;
 
-import org.apache.nifi.controller.ControllerService;
-
 /**
  * NiFi web context providing limited access to dataflow configuration for
  * component custom UIs.
@@ -58,12 +58,7 @@ public interface NiFiWebConfigurationContext {
     /**
      * @return the current user identity. The value may be a DN, an email, a username, or any string that identities the user. Returns null if no user is found
      */
-    String getCurrentUserDn();
-
-    /**
-     * @return the current user name. Returns null if no user is found
-     */
-    String getCurrentUserName();
+    String getCurrentUserIdentity();
 
     /**
      * Sets the annotation data for the underlying component.

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
index 73a54c5..2e84c5b 100644
--- a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
+++ b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
@@ -518,7 +518,7 @@ public class NiFiProperties extends Properties {
     }
 
     /**
-     * @return the user authorities file
+     * @return the user login identity provider file
      */
     public File getLoginIdentityProviderConfigurationFile() {
         final String value = getProperty(LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE);
@@ -774,7 +774,6 @@ public class NiFiProperties extends Properties {
      * Returns true if client certificates are required for REST API. Determined if the following conditions are all true:
      *
      * - login identity provider is not populated
-     * - anonymous authorities is empty
      * - Kerberos service support is not enabled
      *
      * @return true if client certificates are required for access to the REST API

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java b/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
index e27f91c..18083ca 100644
--- a/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
+++ b/nifi-commons/nifi-web-utils/src/main/java/org/apache/nifi/web/util/WebUtils.java
@@ -16,12 +16,20 @@
  */
 package org.apache.nifi.web.util;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.json.JSONConfiguration;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.security.util.CertificateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateParsingException;
 import java.security.cert.X509Certificate;
@@ -29,25 +37,6 @@ import java.util.List;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-
-import org.apache.nifi.security.util.CertificateUtils;
-
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.config.ClientConfig;
-import com.sun.jersey.api.client.config.DefaultClientConfig;
-import com.sun.jersey.api.json.JSONConfiguration;
-import com.sun.jersey.client.urlconnection.HTTPSProperties;
-
 /**
  * Common utilities related to web development.
  *
@@ -139,59 +128,4 @@ public final class WebUtils {
 
     }
 
-    /**
-     * Serializes the given object to hexadecimal. Serialization uses Java's
-     * native serialization mechanism, the ObjectOutputStream.
-     *
-     * @param obj an object
-     * @return the serialized object as hex
-     */
-    public static String serializeObjectToHex(final Serializable obj) {
-
-        final ByteArrayOutputStream serializedObj = new ByteArrayOutputStream();
-
-        // IOException can never be thrown because we are serializing to an in memory byte array
-        try {
-            final ObjectOutputStream oos = new ObjectOutputStream(serializedObj);
-            oos.writeObject(obj);
-            oos.close();
-        } catch (final IOException ioe) {
-            throw new RuntimeException(ioe);
-        }
-
-        logger.debug(String.format("Serialized object '%s' size: %d", obj, serializedObj.size()));
-
-        // hex encode the binary
-        return new String(Hex.encodeHex(serializedObj.toByteArray(), /* tolowercase */ true));
-    }
-
-    /**
-     * Deserializes a Java serialized, hex-encoded string into a Java object.
-     * This method is the inverse of the serializeObjectToHex method in this
-     * class.
-     *
-     * @param hexEncodedObject a string
-     * @return the object
-     * @throws ClassNotFoundException if the class could not be found
-     */
-    public static Serializable deserializeHexToObject(final String hexEncodedObject) throws ClassNotFoundException {
-
-        // decode the hex encoded object
-        byte[] serializedObj;
-        try {
-            serializedObj = Hex.decodeHex(hexEncodedObject.toCharArray());
-        } catch (final DecoderException de) {
-            throw new IllegalArgumentException(de);
-        }
-
-        // IOException can never be thrown because we are deserializing from an in memory byte array
-        try {
-            // deserialize bytes into object
-            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serializedObj));
-            return (Serializable) ois.readObject();
-        } catch (final IOException ioe) {
-            throw new RuntimeException(ioe);
-        }
-
-    }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/AuditDataSourceFactoryBean.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/AuditDataSourceFactoryBean.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/AuditDataSourceFactoryBean.java
index 87cd420..18df4bc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/AuditDataSourceFactoryBean.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/AuditDataSourceFactoryBean.java
@@ -16,18 +16,19 @@
  */
 package org.apache.nifi.admin;
 
-import java.io.File;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
 import org.apache.commons.lang3.StringUtils;
-import org.h2.jdbcx.JdbcConnectionPool;
 import org.apache.nifi.util.NiFiProperties;
+import org.h2.jdbcx.JdbcConnectionPool;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.FactoryBean;
 
+import java.io.File;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
 /**
  *
  */
@@ -38,7 +39,7 @@ public class AuditDataSourceFactoryBean implements FactoryBean {
     private static final int MAX_CONNECTIONS = 5;
 
     // database file name
-    private static final String AUDIT_DATABASE_FILE_NAME = "nifi-audit";
+    private static final String AUDIT_DATABASE_FILE_NAME = "nifi-flow-audit";
 
     // ------------
     // action table
@@ -46,7 +47,6 @@ public class AuditDataSourceFactoryBean implements FactoryBean {
     private static final String CREATE_ACTION_TABLE = "CREATE TABLE ACTION ("
             + "ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
             + "IDENTITY VARCHAR2(4096) NOT NULL, "
-            + "USER_NAME VARCHAR2(4096) NOT NULL, "
             + "SOURCE_ID VARCHAR2(100) NOT NULL, "
             + "SOURCE_NAME VARCHAR2(1000) NOT NULL, "
             + "SOURCE_TYPE VARCHAR2(1000) NOT NULL, "
@@ -107,10 +107,6 @@ public class AuditDataSourceFactoryBean implements FactoryBean {
             + "FOREIGN KEY (ACTION_ID) REFERENCES ACTION(ID)"
             + ")";
 
-    private static final String RENAME_DN_COLUMN = "ALTER TABLE ACTION ALTER COLUMN USER_DN RENAME TO IDENTITY";
-    private static final String RESIZE_IDENTITY_COLUMN = "ALTER TABLE ACTION MODIFY IDENTITY VARCHAR(4096)";
-    private static final String RESIZE_USER_NAME_COLUMN = "ALTER TABLE ACTION MODIFY USER_NAME VARCHAR(4096)";
-
     private JdbcConnectionPool connectionPool;
 
     private NiFiProperties properties;
@@ -173,17 +169,6 @@ public class AuditDataSourceFactoryBean implements FactoryBean {
                     statement.execute(CREATE_CONFIGURE_DETAILS_TABLE);
                     statement.execute(CREATE_CONNECT_DETAILS_TABLE);
                     statement.execute(CREATE_PURGE_DETAILS_TABLE);
-                } else {
-                    logger.info("Existing database found and connected to at: " + databaseUrl);
-                    RepositoryUtils.closeQuietly(rs);
-
-                    // check if the DN column exists to see if we need to transform the table
-                    rs = connection.getMetaData().getColumns(null, null, "ACTION", "USER_DN");
-                    if (rs.next()) {
-                        statement.execute(RENAME_DN_COLUMN);
-                        statement.execute(RESIZE_IDENTITY_COLUMN);
-                        statement.execute(RESIZE_USER_NAME_COLUMN);
-                    }
                 }
 
                 // commit any changes

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
index 8fdfd34..df1774c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardActionDAO.java
@@ -16,18 +16,7 @@
  */
 package org.apache.nifi.admin.dao.impl;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.Component;
 import org.apache.nifi.action.FlowChangeAction;
@@ -52,7 +41,19 @@ import org.apache.nifi.admin.dao.DataAccessException;
 import org.apache.nifi.history.History;
 import org.apache.nifi.history.HistoryQuery;
 import org.apache.nifi.history.PreviousValue;
-import org.apache.commons.lang3.StringUtils;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  *
@@ -63,15 +64,14 @@ public class StandardActionDAO implements ActionDAO {
     // action table
     // ------------
     private static final String INSERT_ACTION = "INSERT INTO ACTION ("
-            + "IDENTITY, USER_NAME, SOURCE_ID, SOURCE_NAME, SOURCE_TYPE, OPERATION, ACTION_TIMESTAMP"
+            + "IDENTITY, SOURCE_ID, SOURCE_NAME, SOURCE_TYPE, OPERATION, ACTION_TIMESTAMP"
             + ") VALUES ("
             + "?, "
             + "?, "
             + "?, "
             + "?, "
             + "?, "
-            + "?, "
-            + "?, "
+            + "? "
             + ")";
 
     // -----------------
@@ -178,7 +178,7 @@ public class StandardActionDAO implements ActionDAO {
 
     private static final String SELECT_PREVIOUS_VALUES = "SELECT CD.VALUE, "
             + "A.ACTION_TIMESTAMP, "
-            + "A.USER_NAME "
+            + "A.IDENTITY "
             + "FROM CONFIGURE_DETAILS CD "
             + "INNER JOIN ACTION A "
             + "ON CD.ACTION_ID = A.ID "
@@ -198,7 +198,7 @@ public class StandardActionDAO implements ActionDAO {
         this.columnMap.put("sourceName", "SOURCE_NAME");
         this.columnMap.put("sourceType", "SOURCE_TYPE");
         this.columnMap.put("operation", "OPERATION");
-        this.columnMap.put("userName", "USER_NAME");
+        this.columnMap.put("userIdentity", "IDENTITY");
     }
 
     @Override
@@ -217,19 +217,17 @@ public class StandardActionDAO implements ActionDAO {
             // obtain a statement to insert to the action table
             statement = connection.prepareStatement(INSERT_ACTION, Statement.RETURN_GENERATED_KEYS);
             statement.setString(1, StringUtils.left(action.getUserIdentity(), 4096));
-            statement.setString(2, StringUtils.left(action.getUserName(), 4096));
-            statement.setString(3, action.getSourceId());
-            statement.setString(4, StringUtils.left(action.getSourceName(), 1000));
-            statement.setString(5, action.getSourceType().toString());
-            statement.setString(6, action.getOperation().toString());
-            statement.setTimestamp(7, new java.sql.Timestamp(action.getTimestamp().getTime()));
+            statement.setString(2, action.getSourceId());
+            statement.setString(3, StringUtils.left(action.getSourceName(), 1000));
+            statement.setString(4, action.getSourceType().toString());
+            statement.setString(5, action.getOperation().toString());
+            statement.setTimestamp(6, new java.sql.Timestamp(action.getTimestamp().getTime()));
 
             // insert the action
             int updateCount = statement.executeUpdate();
 
             final FlowChangeAction createdAction = new FlowChangeAction();
             createdAction.setUserIdentity(action.getUserIdentity());
-            createdAction.setUserName(action.getUserName());
             createdAction.setSourceId(action.getSourceId());
             createdAction.setSourceName(action.getSourceName());
             createdAction.setSourceType(action.getSourceType());
@@ -458,8 +456,8 @@ public class StandardActionDAO implements ActionDAO {
             }
 
             // append the user id as necessary
-            if (historyQuery.getUserName() != null) {
-                where.add("UPPER(USER_NAME) LIKE ?");
+            if (historyQuery.getUserIdentity() != null) {
+                where.add("UPPER(IDENTITY) LIKE ?");
             }
 
             // append the source id as necessary
@@ -487,8 +485,8 @@ public class StandardActionDAO implements ActionDAO {
             }
 
             // set the user id as necessary
-            if (historyQuery.getUserName() != null) {
-                statement.setString(paramIndex++, "%" + historyQuery.getUserName().toUpperCase() + "%");
+            if (historyQuery.getUserIdentity() != null) {
+                statement.setString(paramIndex++, "%" + historyQuery.getUserIdentity().toUpperCase() + "%");
             }
 
             // set the source id as necessary
@@ -535,8 +533,8 @@ public class StandardActionDAO implements ActionDAO {
             }
 
             // set the user id as necessary
-            if (historyQuery.getUserName() != null) {
-                statement.setString(paramIndex++, "%" + historyQuery.getUserName().toUpperCase() + "%");
+            if (historyQuery.getUserIdentity() != null) {
+                statement.setString(paramIndex++, "%" + historyQuery.getUserIdentity().toUpperCase() + "%");
             }
 
             // set the source id as necessary
@@ -562,7 +560,6 @@ public class StandardActionDAO implements ActionDAO {
                 FlowChangeAction action = new FlowChangeAction();
                 action.setId(actionId);
                 action.setUserIdentity(rs.getString("IDENTITY"));
-                action.setUserName(rs.getString("USER_NAME"));
                 action.setOperation(Operation.valueOf(rs.getString("OPERATION")));
                 action.setTimestamp(new Date(rs.getTimestamp("ACTION_TIMESTAMP").getTime()));
                 action.setSourceId(rs.getString("SOURCE_ID"));
@@ -636,7 +633,6 @@ public class StandardActionDAO implements ActionDAO {
                 action = new FlowChangeAction();
                 action.setId(rs.getInt("ID"));
                 action.setUserIdentity(rs.getString("IDENTITY"));
-                action.setUserName(rs.getString("USER_NAME"));
                 action.setOperation(operation);
                 action.setTimestamp(new Date(rs.getTimestamp("ACTION_TIMESTAMP").getTime()));
                 action.setSourceId(rs.getString("SOURCE_ID"));
@@ -907,7 +903,7 @@ public class StandardActionDAO implements ActionDAO {
                 final PreviousValue previousValue = new PreviousValue();
                 previousValue.setPreviousValue(rs.getString("VALUE"));
                 previousValue.setTimestamp(new Date(rs.getTimestamp("ACTION_TIMESTAMP").getTime()));
-                previousValue.setUserName(rs.getString("USER_NAME"));
+                previousValue.setUserIdentity(rs.getString("IDENTITY"));
                 previousValues.add(previousValue);
             }
         } catch (SQLException sqle) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
index cc337fd..9d19361 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/dao/impl/StandardKeyDAO.java
@@ -157,16 +157,11 @@ public class StandardKeyDAO implements KeyDAO {
 
     @Override
     public void deleteKeys(String identity) {
-        // ensure there are some authorities to create
         PreparedStatement statement = null;
         try {
             // add each authority for the specified user
             statement = connection.prepareStatement(DELETE_KEYS);
-            statement.setString(1, identity);
-
-            // insert the authorities
-            int count = statement.executeUpdate();
-            System.out.println();
+            statement.executeUpdate();
         } catch (SQLException sqle) {
             throw new DataAccessException(sqle);
         } catch (DataAccessException dae) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/HistoryQuery.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/HistoryQuery.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/HistoryQuery.java
index 53cc13c..e9970c5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/HistoryQuery.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/HistoryQuery.java
@@ -23,7 +23,7 @@ import java.util.Date;
  */
 public class HistoryQuery {
 
-    private String userName;
+    private String userIdentity;
     private String sourceId;
     private Date startDate;
     private Date endDate;
@@ -56,12 +56,12 @@ public class HistoryQuery {
         this.startDate = startDate;
     }
 
-    public String getUserName() {
-        return userName;
+    public String getUserIdentity() {
+        return userIdentity;
     }
 
-    public void setUserName(String userName) {
-        this.userName = userName;
+    public void setUserIdentity(String userIdentity) {
+        this.userIdentity = userIdentity;
     }
 
     public Integer getOffset() {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/PreviousValue.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/PreviousValue.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/PreviousValue.java
index 6ece5cf..e4cce3e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/PreviousValue.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/history/PreviousValue.java
@@ -25,7 +25,7 @@ public class PreviousValue {
 
     private String previousValue;
     private Date timestamp;
-    private String userName;
+    private String userIdentity;
 
     public String getPreviousValue() {
         return previousValue;
@@ -43,12 +43,12 @@ public class PreviousValue {
         this.timestamp = timestamp;
     }
 
-    public String getUserName() {
-        return userName;
+    public String getUserIdentity() {
+        return userIdentity;
     }
 
-    public void setUserName(String userName) {
-        this.userName = userName;
+    public void setUserIdentity(String userIdentity) {
+        this.userIdentity = userIdentity;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessStatusDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessStatusDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessStatusDTO.java
index 5962cc2..fa334c4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessStatusDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessStatusDTO.java
@@ -52,21 +52,6 @@ public class AccessStatusDTO {
     }
 
     /**
-     * @return the username
-     */
-    @ApiModelProperty(
-            value = "The username.",
-            readOnly = true
-    )
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    /**
      * @return the user access status
      */
     @ApiModelProperty(

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PreviousValueDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PreviousValueDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PreviousValueDTO.java
index 132456c..558f471 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PreviousValueDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PreviousValueDTO.java
@@ -17,10 +17,11 @@
 package org.apache.nifi.web.api.dto;
 
 import com.wordnik.swagger.annotations.ApiModelProperty;
-import java.util.Date;
+import org.apache.nifi.web.api.dto.util.DateTimeAdapter;
+
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.apache.nifi.web.api.dto.util.DateTimeAdapter;
+import java.util.Date;
 
 /**
  * The previous value for a processor property.
@@ -30,7 +31,7 @@ public class PreviousValueDTO {
 
     private String previousValue;
     private Date timestamp;
-    private String userName;
+    private String userIdentity;
 
     /**
      * @return previous value
@@ -67,11 +68,11 @@ public class PreviousValueDTO {
     @ApiModelProperty(
             value = "The user who changed the previous value."
     )
-    public String getUserName() {
-        return userName;
+    public String getUserIdentity() {
+        return userIdentity;
     }
 
-    public void setUserName(String userName) {
-        this.userName = userName;
+    public void setUserIdentity(String userIdentity) {
+        this.userIdentity = userIdentity;
     }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/ActionDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/ActionDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/ActionDTO.java
index d4dea38..1332f5c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/ActionDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/ActionDTO.java
@@ -17,13 +17,14 @@
 package org.apache.nifi.web.api.dto.action;
 
 import com.wordnik.swagger.annotations.ApiModelProperty;
-import java.util.Date;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.nifi.web.api.dto.action.component.details.ComponentDetailsDTO;
 import org.apache.nifi.web.api.dto.action.details.ActionDetailsDTO;
 import org.apache.nifi.web.api.dto.util.DateTimeAdapter;
 
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.Date;
+
 /**
  * An action performed in this NiFi.
  */
@@ -32,7 +33,6 @@ public class ActionDTO {
 
     private Integer id;
     private String userDn;
-    private String userName;
     private Date timestamp;
 
     private String sourceId;
@@ -72,20 +72,6 @@ public class ActionDTO {
     }
 
     /**
-     * @return user name who perform this action
-     */
-    @ApiModelProperty(
-            value = "The name of the user that performed the action."
-    )
-    public String getUserName() {
-        return userName;
-    }
-
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
-    /**
      * @return action's timestamp
      */
     @XmlJavaTypeAdapter(DateTimeAdapter.class)

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/HistoryQueryDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/HistoryQueryDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/HistoryQueryDTO.java
index 7d4d21d..8dde361 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/HistoryQueryDTO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/action/HistoryQueryDTO.java
@@ -17,10 +17,11 @@
 package org.apache.nifi.web.api.dto.action;
 
 import com.wordnik.swagger.annotations.ApiModelProperty;
-import java.util.Date;
+import org.apache.nifi.web.api.dto.util.DateTimeAdapter;
+
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.apache.nifi.web.api.dto.util.DateTimeAdapter;
+import java.util.Date;
 
 /**
  * A history query to find desired actions.
@@ -28,7 +29,7 @@ import org.apache.nifi.web.api.dto.util.DateTimeAdapter;
 @XmlType(name = "historyQuery")
 public class HistoryQueryDTO {
 
-    private String userName;
+    private String userIdentity;
     private String sourceId;
     private Date startDate;
     private Date endDate;
@@ -38,17 +39,17 @@ public class HistoryQueryDTO {
     private String sortOrder;
 
     /**
-     * @return user name
+     * @return user identity
      */
     @ApiModelProperty(
-            value = "The name of the source component."
+            value = "The user identity."
     )
-    public String getUserName() {
-        return userName;
+    public String getUserIdentity() {
+        return userIdentity;
     }
 
-    public void setUserName(String userName) {
-        this.userName = userName;
+    public void setUserIdentity(String userIdentity) {
+        this.userIdentity = userIdentity;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserGroupSearchResultDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserGroupSearchResultDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserGroupSearchResultDTO.java
deleted file mode 100644
index ef81b88..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserGroupSearchResultDTO.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.web.api.dto.search;
-
-import com.wordnik.swagger.annotations.ApiModelProperty;
-import javax.xml.bind.annotation.XmlType;
-
-/**
- * A search result for a matching user group.
- */
-@XmlType(name = "userGroupSearchResult")
-public class UserGroupSearchResultDTO {
-
-    private String group;
-
-    /**
-     * @return name of the group that matched
-     */
-    @ApiModelProperty(
-            value = "The name of the group that matched the search."
-    )
-    public String getGroup() {
-        return group;
-    }
-
-    public void setGroup(String group) {
-        this.group = group;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserSearchResultDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserSearchResultDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserSearchResultDTO.java
deleted file mode 100644
index 8bed771..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/UserSearchResultDTO.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.web.api.dto.search;
-
-import com.wordnik.swagger.annotations.ApiModelProperty;
-import javax.xml.bind.annotation.XmlType;
-
-/**
- * A search result for a matching user.
- */
-@XmlType(name = "userSearchResult")
-public class UserSearchResultDTO {
-
-    private String userName;
-    private String userDn;
-
-    /**
-     * @return dn of the user that matched
-     */
-    @ApiModelProperty(
-            value = "The dn of the user that matched the search."
-    )
-    public String getUserDn() {
-        return userDn;
-    }
-
-    public void setUserDn(String userDn) {
-        this.userDn = userDn;
-    }
-
-    /**
-     * @return username of user that matched
-     */
-    @ApiModelProperty(
-            value = "The name of the user that matched the search."
-    )
-    public String getUserName() {
-        return userName;
-    }
-
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AuthorityEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AuthorityEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AuthorityEntity.java
deleted file mode 100644
index 9b023ba..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/AuthorityEntity.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.web.api.entity;
-
-import java.util.Set;
-
-import javax.xml.bind.annotation.XmlRootElement;
-
-/**
- * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a set of user authorities.
- */
-@XmlRootElement(name = "authoritiesEntity")
-public class AuthorityEntity extends Entity {
-
-    private String userId;
-    private Set<String> authorities;
-
-    /**
-     * @return current user id
-     */
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    /**
-     * @return set of authorities that are being serialized
-     */
-    public Set<String> getAuthorities() {
-        return authorities;
-    }
-
-    public void setAuthorities(Set<String> authorities) {
-        this.authorities = authorities;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
new file mode 100644
index 0000000..1a7ff1c
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/CurrentUserEntity.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.api.entity;
+
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds the users identity.
+ */
+@XmlRootElement(name = "currentEntity")
+public class CurrentUserEntity extends Entity {
+
+    private String identity;
+    private boolean anonymous;
+
+    private AccessPolicyDTO provenancePermissions;
+    private AccessPolicyDTO countersPermissions;
+    private AccessPolicyDTO tenantsPermissions;
+    private AccessPolicyDTO controllerPermissions;
+
+    /**
+     * @return the user identity being serialized
+     */
+    public String getIdentity() {
+        return identity;
+    }
+
+    public void setIdentity(String identity) {
+        this.identity = identity;
+    }
+
+    /**
+     * @return if the user is anonymous
+     */
+    public boolean isAnonymous() {
+        return anonymous;
+    }
+
+    public void setAnonymous(boolean anonymous) {
+        this.anonymous = anonymous;
+    }
+
+    /**
+     * @return if the use can query provenance
+     */
+    public AccessPolicyDTO getProvenancePermissions() {
+        return provenancePermissions;
+    }
+
+    public void setProvenancePermissions(AccessPolicyDTO provenancePermissions) {
+        this.provenancePermissions = provenancePermissions;
+    }
+
+    /**
+     * @return permissions for accessing counters
+     */
+    public AccessPolicyDTO getCountersPermissions() {
+        return countersPermissions;
+    }
+
+    public void setCountersPermissions(AccessPolicyDTO countersPermissions) {
+        this.countersPermissions = countersPermissions;
+    }
+
+    /**
+     * @return permissions for accessing users
+     */
+    public AccessPolicyDTO getTenantsPermissions() {
+        return tenantsPermissions;
+    }
+
+    public void setTenantsPermissions(AccessPolicyDTO tenantsPermissions) {
+        this.tenantsPermissions = tenantsPermissions;
+    }
+
+    /**
+     * @return permissions for accessing the controller
+     */
+    public AccessPolicyDTO getControllerPermissions() {
+        return controllerPermissions;
+    }
+
+    public void setControllerPermissions(AccessPolicyDTO controllerPermissions) {
+        this.controllerPermissions = controllerPermissions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/IdentityEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/IdentityEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/IdentityEntity.java
deleted file mode 100644
index ee38efe..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/IdentityEntity.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.web.api.entity;
-
-import javax.xml.bind.annotation.XmlRootElement;
-
-/**
- * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds the users identity.
- */
-@XmlRootElement(name = "identityEntity")
-public class IdentityEntity extends Entity {
-
-    private String userId;
-    private String identity;
-    private boolean anonymous;
-
-    /**
-     * @return current user id
-     */
-    public String getUserId() {
-        return userId;
-    }
-
-    public void setUserId(String userId) {
-        this.userId = userId;
-    }
-
-    /**
-     * @return the user identity being serialized
-     */
-    public String getIdentity() {
-        return identity;
-    }
-
-    public void setIdentity(String identity) {
-        this.identity = identity;
-    }
-
-    /**
-     * @return if the user is anonymous
-     */
-    public boolean isAnonymous() {
-        return anonymous;
-    }
-
-    public void setAnonymous(boolean anonymous) {
-        this.anonymous = anonymous;
-    }
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplateEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplateEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplateEntity.java
index 553d686..483de4f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplateEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplateEntity.java
@@ -16,14 +16,15 @@
  */
 package org.apache.nifi.web.api.entity;
 
-import javax.xml.bind.annotation.XmlRootElement;
 import org.apache.nifi.web.api.dto.TemplateDTO;
 
+import javax.xml.bind.annotation.XmlRootElement;
+
 /**
  * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a TemplateDTO.
  */
 @XmlRootElement(name = "templateEntity")
-public class TemplateEntity extends Entity {
+public class TemplateEntity extends ComponentEntity {
 
     private TemplateDTO template;
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplatesEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplatesEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplatesEntity.java
index 3a9f46d..42ea3cd 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplatesEntity.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/TemplatesEntity.java
@@ -16,12 +16,12 @@
  */
 package org.apache.nifi.web.api.entity;
 
-import java.util.Date;
-import java.util.Set;
+import org.apache.nifi.web.api.dto.util.TimeAdapter;
+
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.apache.nifi.web.api.dto.TemplateDTO;
-import org.apache.nifi.web.api.dto.util.TimeAdapter;
+import java.util.Date;
+import java.util.Set;
 
 /**
  * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a set of TemplateDTOs.
@@ -29,7 +29,7 @@ import org.apache.nifi.web.api.dto.util.TimeAdapter;
 @XmlRootElement(name = "templatesEntity")
 public class TemplatesEntity extends Entity {
 
-    private Set<TemplateDTO> templates;
+    private Set<TemplateEntity> templates;
     private Date generated;
 
     /**
@@ -37,11 +37,11 @@ public class TemplatesEntity extends Entity {
      *
      * @return The TemplateDTO object
      */
-    public Set<TemplateDTO> getTemplates() {
+    public Set<TemplateEntity> getTemplates() {
         return templates;
     }
 
-    public void setTemplates(Set<TemplateDTO> templates) {
+    public void setTemplates(Set<TemplateEntity> templates) {
         this.templates = templates;
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/UserSearchResultsEntity.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/UserSearchResultsEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/UserSearchResultsEntity.java
deleted file mode 100644
index fcdeee3..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/UserSearchResultsEntity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.web.api.entity;
-
-import java.util.List;
-import javax.xml.bind.annotation.XmlRootElement;
-import org.apache.nifi.web.api.dto.search.UserGroupSearchResultDTO;
-import org.apache.nifi.web.api.dto.search.UserSearchResultDTO;
-
-/**
- * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to UserSearchResultDTOs and
- * UserGroupSearchResultDTOs.
- */
-@XmlRootElement(name = "userSearchResultsEntity")
-public class UserSearchResultsEntity {
-
-    private List<UserSearchResultDTO> userResults;
-    private List<UserGroupSearchResultDTO> userGroupResults;
-
-    /**
-     * @return user search results
-     */
-    public List<UserSearchResultDTO> getUserResults() {
-        return userResults;
-    }
-
-    public void setUserResults(List<UserSearchResultDTO> userResults) {
-        this.userResults = userResults;
-    }
-
-    /**
-     * @return user group search results
-     */
-    public List<UserGroupSearchResultDTO> getUserGroupResults() {
-        return userGroupResults;
-    }
-
-    public void setUserGroupResults(List<UserGroupSearchResultDTO> userGroupResults) {
-        this.userGroupResults = userGroupResults;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
index 7c04298..e49e24e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java
@@ -69,7 +69,7 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.GZIPInputStream;
 
 /**
- * Provides identity checks and grants authorities.
+ * Provides authorizes requests to resources using policies persisted in a file.
  */
 public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
index 840df69..4a75274 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/NiFiUserUtils.java
@@ -47,13 +47,13 @@ public final class NiFiUserUtils {
         return user;
     }
 
-    public static String getNiFiUserName() {
+    public static String getNiFiUserIdentity() {
         // get the nifi user to extract the username
         NiFiUser user = NiFiUserUtils.getNiFiUser();
         if (user == null) {
             return "unknown";
         } else {
-            return user.getUserName();
+            return user.getIdentity();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java
index 8c41a1f..8d50151 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-authorization/src/main/java/org/apache/nifi/authorization/user/StandardNiFiUser.java
@@ -16,32 +16,24 @@
  */
 package org.apache.nifi.authorization.user;
 
-import java.io.Serializable;
 import java.util.Objects;
 
 /**
  * An implementation of NiFiUser.
  */
-public class StandardNiFiUser implements NiFiUser, Serializable {
-    private static final long serialVersionUID = -5503790026187817496L;
+public class StandardNiFiUser implements NiFiUser {
 
     public static final StandardNiFiUser ANONYMOUS = new StandardNiFiUser("anonymous");
 
     private final String identity;
-    private final String userName;
     private final NiFiUser chain;
 
     public StandardNiFiUser(String identity) {
-        this(identity, identity, null);
+        this(identity, null);
     }
 
     public StandardNiFiUser(String identity, NiFiUser chain) {
-        this(identity, identity, chain);
-    }
-
-    public StandardNiFiUser(String identity, String userName, NiFiUser chain) {
         this.identity = identity;
-        this.userName = userName;
         this.chain = chain;
     }
 
@@ -52,11 +44,6 @@ public class StandardNiFiUser implements NiFiUser, Serializable {
     }
 
     @Override
-    public String getUserName() {
-        return userName;
-    }
-
-    @Override
     public NiFiUser getChain() {
         return chain;
     }
@@ -89,6 +76,6 @@ public class StandardNiFiUser implements NiFiUser, Serializable {
 
     @Override
     public String toString() {
-        return String.format("identity[%s], userName[%s]", getIdentity(), getUserName(), ", ");
+        return String.format("identity[%s]", getIdentity());
     }
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
index b330581..5231095 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java
@@ -16,9 +16,6 @@
  */
 package org.apache.nifi.controller;
 
-import java.util.HashSet;
-import java.util.Set;
-
 import org.apache.nifi.authorization.AccessDeniedException;
 import org.apache.nifi.authorization.AuthorizationRequest;
 import org.apache.nifi.authorization.AuthorizationResult;
@@ -32,6 +29,7 @@ import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.connectable.Connection;
 import org.apache.nifi.controller.label.Label;
+import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.groups.RemoteProcessGroup;
 import org.apache.nifi.web.api.dto.ConnectionDTO;
@@ -43,6 +41,9 @@ import org.apache.nifi.web.api.dto.ProcessorDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
 import org.apache.nifi.web.api.dto.TemplateDTO;
 
+import java.util.HashSet;
+import java.util.Set;
+
 public class Template implements Authorizable {
 
     private final TemplateDTO dto;
@@ -84,53 +85,68 @@ public class Template implements Authorizable {
         return ResourceFactory.getComponentResource(ResourceType.Template, dto.getId(), dto.getName());
     }
 
+    private ProcessGroup getRootGroup(final ProcessGroup currentGroup) {
+        if (currentGroup.getParent() == null) {
+            return currentGroup;
+        } else {
+            return getRootGroup(currentGroup.getParent());
+        }
+    }
+
     private Set<Authorizable> getAuthorizableComponents() {
-        return getAuthorizableComponents(processGroup);
+        return getAuthorizableComponents(processGroup.getIdentifier(), dto.getSnippet());
     }
 
-    private Set<Authorizable> getAuthorizableComponents(final ProcessGroup processGroup) {
+    private Set<Authorizable> getAuthorizableComponents(final String currentGroupId, final FlowSnippetDTO snippet) {
         final Set<Authorizable> authComponents = new HashSet<>();
-        final FlowSnippetDTO snippet = dto.getSnippet();
 
-        authComponents.add(processGroup);
+        // If there is any component in the DTO that still exists in the flow, check its authorizations...
+        // need to go to the root group in case a sensitive processor was moved out of this processGroup
+        final ProcessGroup root = getRootGroup(processGroup);
+
+        // include the current group
+        final ProcessGroup currentGroup = root.findProcessGroup(currentGroupId);
+        authComponents.add(currentGroup);
 
-        // If there is any component in the DTO that still exists in the flow, check its authorizations
         for (final ConnectionDTO connectionDto : snippet.getConnections()) {
-            final Connection connection = processGroup.getConnection(connectionDto.getId());
+            final Connection connection = root.findConnection(connectionDto.getId());
             if (connection != null) {
                 authComponents.add(connection);
             }
         }
 
-        // TODO: Authorize Controller Services
         for (final ControllerServiceDTO service : snippet.getControllerServices()) {
+            final ControllerServiceNode controllerService = root.findControllerService(service.getId());
+            if (controllerService != null) {
+                authComponents.add(controllerService);
+            }
         }
 
         for (final LabelDTO labelDto : snippet.getLabels()) {
-            final Label label = processGroup.getLabel(labelDto.getId());
+            final Label label = root.findLabel(labelDto.getId());
             if (label != null) {
                 authComponents.add(label);
             }
         }
 
         for (final ProcessorDTO processorDto : snippet.getProcessors()) {
-            final ProcessorNode procNode = processGroup.getProcessor(processorDto.getId());
+            final ProcessorNode procNode = root.findProcessor(processorDto.getId());
             if (procNode != null) {
                 authComponents.add(procNode);
             }
         }
 
         for (final RemoteProcessGroupDTO groupDto : snippet.getRemoteProcessGroups()) {
-            final RemoteProcessGroup rpg = processGroup.getRemoteProcessGroup(groupDto.getId());
+            final RemoteProcessGroup rpg = root.findRemoteProcessGroup(groupDto.getId());
             if (rpg != null) {
                 authComponents.add(rpg);
             }
         }
 
         for (final ProcessGroupDTO groupDto : snippet.getProcessGroups()) {
-            final ProcessGroup group = processGroup.getProcessGroup(groupDto.getId());
+            final ProcessGroup group = root.findProcessGroup(groupDto.getId());
             if (group != null) {
-                authComponents.addAll(getAuthorizableComponents(group));
+                authComponents.addAll(getAuthorizableComponents(groupDto.getId(), groupDto.getContents()));
             }
         }
 
@@ -170,12 +186,15 @@ public class Template implements Authorizable {
         if (Result.ResourceNotFound.equals(result.getResult())) {
             for (final Authorizable child : getAuthorizableComponents()) {
                 final AuthorizationResult childResult = child.checkAuthorization(authorizer, action, user);
-                if (Result.Denied.equals(childResult)) {
+
+                // if the authoriable in this template explicitly says no, respect it
+                if (Result.Denied.equals(childResult.getResult())) {
                     return childResult;
                 }
             }
 
-            return AuthorizationResult.denied();
+            // if all authorizables are approved or no longer have a policy, approve it
+            return AuthorizationResult.approved();
         } else {
             return result;
         }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
index 6b643e6..a931841 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
@@ -2249,6 +2249,10 @@ public final class StandardProcessGroup implements ProcessGroup {
                 childGroup.verifyCanDelete(true);
             }
 
+            if (!templates.isEmpty()) {
+                throw new IllegalStateException(String.format("Cannot delete Process Group because it contains %s Templates. The Templates must be deleted first.", templates.size()));
+            }
+
             if (!ignoreConnections) {
                 for (final Port port : inputPorts.values()) {
                     for (final Connection connection : port.getIncomingConnections()) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-user-actions/src/main/java/org/apache/nifi/action/FlowChangeAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-user-actions/src/main/java/org/apache/nifi/action/FlowChangeAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-user-actions/src/main/java/org/apache/nifi/action/FlowChangeAction.java
index ad22059..4d8d1d0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-user-actions/src/main/java/org/apache/nifi/action/FlowChangeAction.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-user-actions/src/main/java/org/apache/nifi/action/FlowChangeAction.java
@@ -27,7 +27,6 @@ public class FlowChangeAction implements Action {
 
     private Integer id;
     private String userIdentity;
-    private String userName;
     private Date timestamp;
 
     private String sourceId;
@@ -66,15 +65,6 @@ public class FlowChangeAction implements Action {
     }
 
     @Override
-    public String getUserName() {
-        return userName;
-    }
-
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
-    @Override
     public String getSourceId() {
         return sourceId;
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java
index e231456..2f70796 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ComponentStateAuditor.java
@@ -73,7 +73,6 @@ public class ComponentStateAuditor extends NiFiAuditor {
             // create the clear action
             FlowChangeAction configAction = new FlowChangeAction();
             configAction.setUserIdentity(user.getIdentity());
-            configAction.setUserName(user.getUserName());
             configAction.setOperation(Operation.ClearState);
             configAction.setTimestamp(new Date());
             configAction.setSourceId(processor.getIdentifier());
@@ -120,7 +119,6 @@ public class ComponentStateAuditor extends NiFiAuditor {
             // create the clear action
             FlowChangeAction configAction = new FlowChangeAction();
             configAction.setUserIdentity(user.getIdentity());
-            configAction.setUserName(user.getUserName());
             configAction.setOperation(Operation.ClearState);
             configAction.setTimestamp(new Date());
             configAction.setSourceId(controllerService.getIdentifier());
@@ -167,7 +165,6 @@ public class ComponentStateAuditor extends NiFiAuditor {
             // create the clear action
             FlowChangeAction configAction = new FlowChangeAction();
             configAction.setUserIdentity(user.getIdentity());
-            configAction.setUserName(user.getUserName());
             configAction.setOperation(Operation.ClearState);
             configAction.setTimestamp(new Date());
             configAction.setSourceId(reportingTask.getIdentifier());


[2/5] nifi git commit: NIFI-1781: - Updating UI according to permissions through out the application. - Shuffling provenance events, template, and cluster search REST APIs according to resources being authorized. - Moving template upload controls. - Remo

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.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/node/NodeAuthorizedUserFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java
deleted file mode 100644
index 8451c7c..0000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/node/NodeAuthorizedUserFilter.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.security.node;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.security.cert.X509Certificate;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.nifi.authorization.user.NiFiUserDetails;
-import org.apache.nifi.controller.FlowController;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authentication.AuthenticationResponse;
-import org.apache.nifi.authorization.user.NiFiUser;
-import org.apache.nifi.util.NiFiProperties;
-import org.apache.nifi.web.security.token.NiFiAuthenticationToken;
-import org.apache.nifi.web.security.x509.X509CertificateExtractor;
-import org.apache.nifi.web.security.x509.X509IdentityProvider;
-import org.apache.nifi.web.util.WebUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.web.context.support.WebApplicationContextUtils;
-import org.springframework.web.filter.GenericFilterBean;
-
-/**
- * Custom filter to extract a user's authorities from the request where the user was authenticated by the cluster manager and populate the threadlocal with the authorized user. If the request contains
- * the appropriate header with authorities and the application instance is a node connected to the cluster, then the authentication/authorization steps remaining in the filter chain are skipped.
- *
- * Checking if the application instance is a connected node is important because it prevents external clients from faking the request headers and bypassing the authentication processing chain.
- */
-public class NodeAuthorizedUserFilter extends GenericFilterBean {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(NodeAuthorizedUserFilter.class);
-
-    public static final String PROXY_USER_DETAILS = "X-ProxiedEntityUserDetails";
-
-    private NiFiProperties properties;
-    private X509CertificateExtractor certificateExtractor;
-    private X509IdentityProvider certificateIdentityProvider;
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
-        final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
-
-        // get the proxied user's authorities
-        final String hexEncodedUserDetails = httpServletRequest.getHeader(PROXY_USER_DETAILS);
-
-        // check if the request has the necessary header information and this instance is configured as a node
-        if (StringUtils.isNotBlank(hexEncodedUserDetails) && properties.isNode()) {
-
-            // get the flow controller from the Spring context
-            final ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
-            final FlowController flowController = ctx.getBean("flowController", FlowController.class);
-
-            // check that we are connected to the cluster
-            if (flowController.getNodeId() != null) {
-                try {
-                    // attempt to extract the client certificate
-                    final X509Certificate[] certificate = certificateExtractor.extractClientCertificate(httpServletRequest);
-                    if (certificate != null) {
-                        // authenticate the certificate
-                        final AuthenticationResponse authenticationResponse = certificateIdentityProvider.authenticate(certificate);
-
-                        // only consider the pre-authorized user when the request came directly from the NCM according to the DN in the certificate
-                        final String clusterManagerIdentity = flowController.getClusterManagerDN();
-                        if (clusterManagerIdentity != null && clusterManagerIdentity.equals(authenticationResponse.getIdentity())) {
-                            // deserialize hex encoded object
-                            final Serializable userDetailsObj = WebUtils.deserializeHexToObject(hexEncodedUserDetails);
-
-                            // if we have a valid object, set the authentication token and bypass the remaining authentication processing chain
-                            if (userDetailsObj instanceof NiFiUserDetails) {
-                                final NiFiUserDetails userDetails = (NiFiUserDetails) userDetailsObj;
-                                final NiFiUser user = userDetails.getNiFiUser();
-
-                                // log the request attempt - response details will be logged later
-                                logger.info(String.format("Attempting request for (%s) %s %s (source ip: %s)", user.getIdentity(), httpServletRequest.getMethod(),
-                                        httpServletRequest.getRequestURL().toString(), request.getRemoteAddr()));
-
-                                // create the authorized nifi token
-                                final NiFiAuthenticationToken token = new NiFiAuthenticationToken(userDetails);
-                                SecurityContextHolder.getContext().setAuthentication(token);
-                            }
-                        }
-                    }
-                } catch (final ClassNotFoundException cnfe) {
-                    LOGGER.warn("Classpath issue detected because failed to deserialize authorized user in request header due to: " + cnfe, cnfe);
-                } catch (final IllegalArgumentException iae) {
-                    // unable to authenticate a serialized user from the incoming request
-                }
-            }
-        }
-
-        chain.doFilter(request, response);
-    }
-
-    public void setProperties(NiFiProperties properties) {
-        this.properties = properties;
-    }
-
-    public void setCertificateIdentityProvider(X509IdentityProvider certificateIdentityProvider) {
-        this.certificateIdentityProvider = certificateIdentityProvider;
-    }
-
-    public void setCertificateExtractor(X509CertificateExtractor certificateExtractor) {
-        this.certificateExtractor = certificateExtractor;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.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/x509/X509AuthenticationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
index b72d5e1..92e690c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/x509/X509AuthenticationProvider.java
@@ -65,7 +65,7 @@ public class X509AuthenticationProvider implements AuthenticationProvider {
         }
 
         if (StringUtils.isBlank(request.getProxiedEntitiesChain())) {
-            return new NiFiAuthenticationToken(new NiFiUserDetails(new StandardNiFiUser(authenticationResponse.getIdentity(), authenticationResponse.getUsername(), null)));
+            return new NiFiAuthenticationToken(new NiFiUserDetails(new StandardNiFiUser(authenticationResponse.getIdentity())));
         } else {
             // build the entire proxy chain if applicable - <end-user><proxy1><proxy2>
             final List<String> proxyChain = new ArrayList<>(ProxiedEntitiesUtils.tokenizeProxiedEntitiesChain(request.getProxiedEntitiesChain()));

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 77ee3f3..39fdffd 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
@@ -49,6 +49,7 @@
         <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/jquery.tab.js"></script>
+        <script type="text/javascript" src="js/jquery/jquery.form.min.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>
@@ -103,6 +104,7 @@
         <jsp:include page="/WEB-INF/partials/canvas/new-process-group-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/new-remote-process-group-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/new-template-dialog.jsp"/>
+        <jsp:include page="/WEB-INF/partials/canvas/upload-template-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/instantiate-template-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/fill-color-dialog.jsp"/>
         <jsp:include page="/WEB-INF/partials/canvas/connections-dialog.jsp"/>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
index 91409e7..0803d22 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/templates.jsp
@@ -35,7 +35,6 @@
         <script type="text/javascript" src="js/jquery/jquery-2.1.1.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/jquery.form.min.js"></script>
         <script type="text/javascript" src="js/jquery/combo/jquery.combo.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>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 0f3a434..050b25e 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
@@ -97,7 +97,8 @@
                     </md-menu-item>
                     <md-menu-item layout-align="space-around center">
                         <a id="counters-link"
-                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.counters.shell.launch();">
+                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.counters.shell.launch();"
+                           ng-class="{disabled: !appCtrl.nf.Common.canAccessCounters()}">
                             <i class="icon icon-counter"></i>Counters
                         </a>
                     </md-menu-item>
@@ -109,24 +110,26 @@
                     </md-menu-item>
                     <md-menu-divider></md-menu-divider>
                     <md-menu-item
-                            ng-if="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.dataProvenance.enabled();"
                             layout-align="space-around center">
                         <a id="provenance-link"
-                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.dataProvenance.shell.launch();">
+                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.dataProvenance.shell.launch();"
+                           ng-class="{disabled: !appCtrl.nf.Common.canAccessProvenance()}">
                             <i class="icon icon-provenance"></i>Data Provenance
                         </a>
                     </md-menu-item>
                     <md-menu-divider></md-menu-divider>
                     <md-menu-item layout-align="space-around center">
                         <a id="flow-settings-link"
-                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.controllerSettings.shell.launch();">
+                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.controllerSettings.shell.launch();"
+                           ng-class="{disabled: !appCtrl.nf.Common.canAccessController()}">
                             <i class="fa fa-wrench"></i>Controller Settings
                         </a>
                     </md-menu-item>
-                    <md-menu-item ng-if="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.cluster.enabled();"
+                    <md-menu-item ng-if="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.cluster.visible();"
                                   layout-align="space-around center">
                         <a id="cluster-link"
-                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.cluster.shell.launch();">
+                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.cluster.shell.launch();"
+                           ng-class="{disabled: !appCtrl.nf.Common.canAccessController()}">
                             <i class="fa fa-cubes"></i>Cluster
                         </a>
                     </md-menu-item>
@@ -136,10 +139,10 @@
                             <i class="fa fa-history"></i>Flow Configuration History
                         </a>
                     </md-menu-item>
-                    <md-menu-item ng-if="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.users.enabled();"
-                                  layout-align="space-around center">
+                    <md-menu-item layout-align="space-around center">
                         <a id="users-link" layout="row"
-                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.users.shell.launch();;">
+                           ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.users.shell.launch();"
+                           ng-class="{disabled: !appCtrl.nf.Common.canAccessTenants()}">
                             <i class="fa fa-users"></i>Users
                             <div id="has-pending-accounts" class="hidden"></div>
                         </a>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 59d2a45..b2b2606 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
@@ -127,7 +127,13 @@
                     <div id="operate-template" class="action-button" title="Create Template">
                         <button ng-click="appCtrl.nf.Actions['template'](appCtrl.nf.CanvasUtils.getSelection());"
                                 ng-disabled="!(appCtrl.nf.Canvas.canWrite() && (appCtrl.nf.CanvasUtils.getSelection().empty() || appCtrl.nf.CanvasUtils.canRead(appCtrl.nf.CanvasUtils.getSelection())));">
-                            <div class="graph-control-action-icon icon icon-template"></div></button>
+                            <div class="graph-control-action-icon icon icon-template-save"></div></button>
+                    </div>
+                    <div class="button-spacer-small">&nbsp;</div>
+                    <div id="operate-template-upload" class="action-button" title="Upload Template">
+                        <button ng-click="appCtrl.nf.Actions['uploadTemplate']();"
+                                ng-disabled="!(appCtrl.nf.Canvas.canWrite() && appCtrl.nf.CanvasUtils.getSelection().empty());">
+                            <div class="graph-control-action-icon icon icon-template-import"></div></button>
                     </div>
                     <div class="clear"></div>
                 </div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-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/upload-template-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-dialog.jsp
new file mode 100644
index 0000000..3c63209
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/upload-template-dialog.jsp
@@ -0,0 +1,35 @@
+<%--
+ 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="upload-template-dialog" class="hidden small-dialog">
+    <div class="dialog-content">
+        <div id="select-template-container">
+            <div id="template-browse-container">
+                <span id="select-template-label">Select Template</span>
+                <button id="select-template-button" class="fa fa-search">
+                    <form id="template-upload-form" enctype="multipart/form-data" method="post">
+                        <input type="file" name="template" id="template-file-field"/>
+                    </form>
+                </button>
+            </div>
+        </div>
+        <div id="submit-template-container">
+            <div id="selected-template-name"></div>
+        </div>
+        <div id="upload-template-status" class="import-status"></div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/templates/templates-content.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/templates/templates-content.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/templates/templates-content.jsp
index 8ec0a59..00b4e5e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/templates/templates-content.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/templates/templates-content.jsp
@@ -29,25 +29,6 @@
                 <div id="templates-filter-type" class="filter-type"></div>
             </div>
         </div>
-        <div id="upload-template-container" class="hidden">
-            <div id="select-template-container">
-                <div id="template-browse-container">
-                    <button id="select-template-button" class="fa fa-plus">
-                        <form id="template-upload-form" enctype="multipart/form-data" method="post">
-                            <input type="file" name="template" id="template-file-field"/>
-                        </form>
-                    </button>
-                    <div id="upload-template-status" class="import-status"></div>
-                </div>
-            </div>
-            <div id="submit-template-container">
-                <button><div id="upload-template-button" title="Upload template" class="icon icon-template-import"></div></button>
-                <button id="cancel-upload-template-button" title="Cancel" class="fa fa-undo"></button>
-                <div id="selected-template-name"></div>
-            </div>
-            <div id="template-upload-form-container">
-            </div>
-        </div>
     </div>
     <div id="templates-table"></div>
 </div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
index 72a34fa..caf4003 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
@@ -104,7 +104,7 @@ md-toolbar.md-small .md-toolbar-tools {
     margin-bottom: 3px;
 }
 
-#global-menu-content a{
+#global-menu-content a {
     height: 28px;
     padding: 6px 16px;
     cursor: pointer;
@@ -112,6 +112,15 @@ md-toolbar.md-small .md-toolbar-tools {
     padding-right: 10px;
 }
 
+#global-menu-content a.disabled {
+    color: #a8a8a8;
+    cursor: not-allowed;
+}
+
+#global-menu-content a.disabled i {
+    color: #bebebe;
+}
+
 #global-menu-content a:hover{
     background-color:#C7D2D7;
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
index f2a8d42..a809760 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/main.css
@@ -614,4 +614,79 @@ div.secondary-button:hover {
 
 md-progress-linear > div {
     background-color: #eaeef0 !important;
+}
+
+/* new template */
+
+#new-template-description {
+    height: 210px;
+}
+
+/* upload */
+
+#select-template-container {
+}
+
+#template-browse-container {
+    display: block;
+    height: 20px;
+}
+
+#select-template-label {
+    font-weight: bold;
+    font-size: 14px;
+    line-height: 28px;
+}
+
+#select-template-button {
+    position: absolute;
+    top: 66px;
+    left: 135px;
+    cursor: pointer;
+    overflow: hidden;
+}
+
+#template-file-field {
+    height: 28px;
+    display: inline;
+    position: absolute;
+    top: 0;
+    left: 0;
+    opacity: 0;
+    filter: alpha(opacity = 0);
+    z-index: 3000;
+    cursor: pointer;
+}
+
+#submit-template-container {
+    margin-top: 20px;
+}
+
+#selected-template-name {
+    font-weight: bold;
+    font-family: Roboto;
+    font-size: 13px;
+}
+
+#upload-template-status {
+    margin-top: 10px;
+    font-weight: bold;
+    font-family: Roboto;
+    font-size: 13px;
+    color: #ba554a;
+}
+
+#upload-template-container button {
+    float: right;
+    font-size: 16px;
+    line-height: 14px;
+    margin-left: 1px;
+}
+
+#template-file-upload {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 22px;
+    width: 300px;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/templates.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/templates.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/templates.css
index ed3d5e7..762fdf5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/templates.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/templates.css
@@ -90,96 +90,6 @@ input.templates-filter-list {
     float: left;
 }
 
-#new-template-description {
-    height: 210px;
-}
-
-/* upload */
-
-#select-template-container {
-}
-
-#template-browse-container {
-    display: block;
-    height: 20px;
-}
-
-#template-file-field {
-    height: 22px;
-    display: inline;
-    position: absolute;
-    top: -1px;
-    right: -1px;
-    float: right;
-    opacity: 0;
-    filter: alpha(opacity = 0);
-    z-index: 3000;
-    cursor: pointer;
-}
-
-.import-status-error {
-    color: #ff0000;
-}
-
-.import-status {
-    color: #888888;
-}
-
-#upload-template-container {
-    float: right;
-    position: relative;
-    top: -28px;
-    overflow: hidden;
-}
-
-#submit-template-container {
-    display: none;
-}
-
-#selected-template-name {
-    float: right;
-    font-weight: bold;
-    margin-right: 20px;
-    margin-top: 6px;
-    font-family: Roboto;
-    font-size: 13px;
-    color: #728e9b;
-}
-
-#upload-template-status {
-    float: right;
-    font-weight: bold;
-    margin-right: 20px;
-    margin-top: 6px;
-    line-height: normal;
-    font-family: Roboto;
-    font-size: 13px;
-    color: #728e9b;
-}
-
-#upload-template-container button {
-    float: right;
-    font-size: 16px;
-    line-height: 14px;
-    margin-left: 1px;
-}
-
-#template-upload-form-container {
-    display: none;
-}
-
-#upload-template-button {
-    margin-right: 0;
-}
-
-#template-file-upload {
-    position: absolute;
-    top: 0;
-    left: 0;
-    height: 22px;
-    width: 300px;
-}
-
 /* templates table */
 
 #templates-table {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
index 0823f56..0d00e27 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-global-menu-controller.js
@@ -62,7 +62,9 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
                  * Launch the counters shell.
                  */
                 launch: function () {
-                    nf.Shell.showPage('counters');
+                    if (nf.Common.canAccessCounters()) {
+                        nf.Shell.showPage('counters');
+                    }
                 }
             }
         };
@@ -92,15 +94,6 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
         this.dataProvenance = {
 
             /**
-             * Determines if the data provenance menu item is enabled.
-             *
-             * @returns {*|boolean}
-             */
-            enabled: function () {
-                return nf.Common.canAccessProvenance();
-            },
-
-            /**
              * The data provenance menu item's shell controller.
              */
             shell: {
@@ -109,7 +102,9 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
                  * Launch the data provenance shell.
                  */
                 launch: function () {
-                    nf.Shell.showPage('provenance');
+                    if (nf.Common.canAccessProvenance()) {
+                        nf.Shell.showPage('provenance');
+                    }
                 }
             }
         };
@@ -128,14 +123,16 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
                  * Launch the settings shell.
                  */
                 launch: function () {
-                    nf.Settings.showSettings().done(function() {
-                        $('#settings-refresh-container').width($('#shell').width());
-                        
-                        // add a shell:resize listener
-                        $('#shell').on('shell:resize', function () {
+                    if (nf.Common.canAccessController()) {
+                        nf.Settings.showSettings().done(function() {
                             $('#settings-refresh-container').width($('#shell').width());
+                            
+                            // add a shell:resize listener
+                            $('#shell').on('shell:resize', function () {
+                                $('#settings-refresh-container').width($('#shell').width());
+                            });
                         });
-                    });
+                    }
                 }
             }
         };
@@ -150,7 +147,7 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
              *
              * @returns {*|boolean}
              */
-            enabled: function () {
+            visible: function () {
                 return nf.Canvas.isClustered();
             },
 
@@ -163,7 +160,9 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
                  * Launch the cluster shell.
                  */
                 launch: function () {
-                    nf.Shell.showPage('cluster');
+                    if (nf.Common.canAccessController()) {
+                        nf.Shell.showPage('cluster');
+                    }
                 }
             }
         };
@@ -193,15 +192,6 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
         this.users = {
 
             /**
-             * Determines if the users menu item is enabled.
-             *
-             * @returns {*|boolean}
-             */
-            enabled: function () {
-                return nf.Common.isAdmin();
-            },
-
-            /**
              * The users menu item's shell controller.
              */
             shell: {
@@ -210,7 +200,9 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
                  * Launch the users shell.
                  */
                 launch: function () {
-                    nf.Shell.showPage('users');
+                    if (nf.Common.canAccessTenants()) {
+                        nf.Shell.showPage('users');
+                    }
                 }
             }
         };

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js
index d14b724..cb329ba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-operate-controller.js
@@ -89,6 +89,143 @@ nf.ng.Canvas.OperateCtrl = function () {
         };
 
         /**
+         * The canvas operator's create template component.
+         */
+        this.templateUpload = {
+
+            /**
+             * The canvas operator's create template component's modal.
+             */
+            modal: {
+
+                /**
+                 * Gets the modal element.
+                 *
+                 * @returns {*|jQuery|HTMLElement}
+                 */
+                getElement: function () {
+                    return $('#upload-template-dialog');
+                },
+
+                /**
+                 * Initialize the modal.
+                 */
+                init: function () {
+                    // initialize the form
+                    var templateForm = $('#template-upload-form').ajaxForm({
+                        url: '../nifi-api/process-groups/' + encodeURIComponent(nf.Canvas.getGroupId()) + '/templates/upload',
+                        dataType: 'xml',
+                        success: function (response, statusText, xhr, form) {
+                            // see if the import was successful
+                            if (response.documentElement.tagName === 'templateEntity') {
+                                // close the dialog
+                                $('#upload-template-dialog').modal('hide');
+
+                                // close the settings dialog
+                                nf.Dialog.showOkDialog({
+                                    headerText: 'Success',
+                                    dialogContent: 'Template successfully imported.'
+                                });
+                            } else {
+                                // import failed
+                                var status = 'Unable to import template. Please check the log for errors.';
+                                if (response.documentElement.tagName === 'errorResponse') {
+                                    // if a more specific error was given, use it
+                                    var errorMessage = response.documentElement.getAttribute('statusText');
+                                    if (!nf.Common.isBlank(errorMessage)) {
+                                        status = errorMessage;
+                                    }
+                                }
+                                $('#upload-template-status').text(status);
+                            }
+                        },
+                        error: function (xhr, statusText, error) {
+                            $('#upload-template-status').text(error);
+                        }
+                    });
+                    
+                    // configure the upload template dialog
+                    this.getElement().modal({
+                        headerText: 'Upload Template',
+                        buttons: [{
+                            buttonText: 'Upload',
+                            color: {
+                                base: '#728E9B',
+                                hover: '#004849',
+                                text: '#ffffff'
+                            },
+                            handler: {
+                                click: function () {
+                                    // submit the template
+                                    templateForm.submit();
+                                }
+                            }
+                        }, {
+                            buttonText: 'Cancel',
+                            color: {
+                                base: '#E3E8EB',
+                                hover: '#C7D2D7',
+                                text: '#004849'
+                            },
+                            handler: {
+                                click: function () {
+                                    // hide the dialog
+                                    $('#upload-template-dialog').modal('hide');
+
+                                    // reset the form to ensure that the change fire will fire
+                                    templateForm.resetForm();
+                                }
+                            }
+                        }],
+                        handler: {
+                            close: function () {
+                                // set the filename
+                                $('#selected-template-name').text('');
+                                $('#upload-template-status').text('');
+                            }
+                        }
+                    });
+
+                    // add a handler for the change file input chain event
+                    $('#template-file-field').on('change', function (e) {
+                        var filename = $(this).val();
+                        if (!nf.Common.isBlank(filename)) {
+                            filename = filename.replace(/^.*[\\\/]/, '');
+                        }
+
+                        // set the filename and clear any status
+                        $('#selected-template-name').text(filename);
+                        $('#upload-template-status').text('');
+                    });
+                },
+
+                /**
+                 * Updates the modal config.
+                 *
+                 * @param {string} name             The name of the property to update.
+                 * @param {object|array} config     The config for the `name`.
+                 */
+                update: function (name, config) {
+                    this.getElement().modal(name, config);
+                },
+
+                /**
+                 * Show the modal.
+                 */
+                show: function () {
+                    this.getElement().modal('show');
+                },
+
+                /**
+                 * Hide the modal.
+                 */
+                hide: function () {
+                    this.getElement().modal('hide');
+                }
+            }
+        };
+
+        /**
          * The canvas operator's fillcolor component.
          */
         this.fillcolor = {
@@ -275,6 +412,7 @@ nf.ng.Canvas.OperateCtrl = function () {
          */
         init: function () {
             this.template.modal.init();
+            this.templateUpload.modal.init();
             this.fillcolor.modal.init();
             this.fillcolor.modal.minicolors.init();
         }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
index 35a3a14..568e1be 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-toolbox-controller.js
@@ -76,26 +76,13 @@ nf.ng.Canvas.ToolboxCtrl = function (processorComponent,
          * Initialize the toolbox controller.
          */
         init: function() {
-            // ensure the user can create graph components
-            if (nf.Common.isDFM()) {
-                // initialize modal dialogs
-                processorComponent.modal.init();
-                inputPortComponent.modal.init();
-                outputPortComponent.modal.init();
-                groupComponent.modal.init();
-                remoteGroupComponent.modal.init();
-                templateComponent.modal.init();
-            } else {
-                // disable components
-                processorComponent.disabled();
-                inputPortComponent.disabled();
-                outputPortComponent.disabled();
-                groupComponent.disabled();
-                remoteGroupComponent.disabled();
-                funnelComponent.disabled();
-                templateComponent.disabled();
-                labelComponent.disabled();
-            }
+            // initialize modal dialogs
+            processorComponent.modal.init();
+            inputPortComponent.modal.init();
+            outputPortComponent.modal.init();
+            groupComponent.modal.init();
+            remoteGroupComponent.modal.init();
+            templateComponent.modal.init();
         },
 
         /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-template-component.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-template-component.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-template-component.js
index 3c8a71a..b332c5b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-template-component.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-template-component.js
@@ -161,18 +161,20 @@ nf.ng.TemplateComponent = function (serviceProvider) {
             var self = this;
             $.ajax({
                 type: 'GET',
-                url: serviceProvider.headerCtrl.toolboxCtrl.config.urls.api + '/process-groups/' + encodeURIComponent(nf.Canvas.getGroupId()) + '/templates',
+                url: serviceProvider.headerCtrl.toolboxCtrl.config.urls.api + '/flow/templates',
                 dataType: 'json'
             }).done(function (response) {
                 var templates = response.templates;
                 if (nf.Common.isDefinedAndNotNull(templates) && templates.length > 0) {
                     var options = [];
-                    $.each(templates, function (_, template) {
-                        options.push({
-                            text: template.name,
-                            value: template.id,
-                            description: nf.Common.escapeHtml(template.description)
-                        });
+                    $.each(templates, function (_, templateEntity) {
+                        if (templateEntity.accessPolicy.canRead === true) {
+                            options.push({
+                                text: templateEntity.template.name,
+                                value: templateEntity.id,
+                                description: nf.Common.escapeHtml(templateEntity.template.description)
+                            });
+                        }
                     });
 
                     // configure the templates combo

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 747be03..3cd8c55 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
@@ -1170,6 +1170,13 @@ nf.Actions = (function () {
         },
 
         /**
+         * Uploads a new template.
+         */
+        uploadTemplate: function () {
+            $('#upload-template-dialog').modal('show');
+        },
+
+        /**
          * Creates a new template based off the currently selected components. If no components
          * are selected, a template of the entire canvas is made.
          */

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
index 0104b36..ed9327e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
@@ -126,8 +126,7 @@ nf.Canvas = (function () {
     var config = {
         urls: {
             api: '../nifi-api',
-            identity: '../nifi-api/flow/identity',
-            authorities: '../nifi-api/flow/authorities',
+            currentUser: '../nifi-api/flow/current-user',
             kerberos: '../nifi-api/access/kerberos',
             revision: '../nifi-api/flow/revision',
             banners: '../nifi-api/flow/banners',
@@ -168,54 +167,6 @@ nf.Canvas = (function () {
     };
 
     /**
-     * Checks the current revision against this version of the flow.
-     */
-    // var checkRevision = function () {
-    //     // get the revision
-    //     return $.ajax({
-    //         type: 'GET',
-    //         url: config.urls.revision,
-    //         dataType: 'json'
-    //     }).done(function (response) {
-    //         if (nf.Common.isDefinedAndNotNull(response.revision)) {
-    //             var revision = response.revision;
-    //             var currentRevision = nf.Client.getRevision();
-    //
-    //             // if there is a newer revision, there are outstanding
-    //             // changes that need to be updated
-    //             if (revision.version > currentRevision.version && revision.clientId !== currentRevision.clientId) {
-    //                 var refreshContainer = $('#refresh-required-container');
-    //                 var settingsRefreshIcon = $('#settings-refresh-required-icon');
-    //
-    //                 // insert the refresh needed text in the canvas - if necessary
-    //                 if (!refreshContainer.is(':visible')) {
-    //                     $('#stats-last-refreshed').addClass('alert');
-    //                     var refreshMessage = "This flow has been modified by '" + revision.lastModifier + "'. Please refresh.";
-    //
-    //                     // update the tooltip
-    //                     var refreshRequiredIcon = $('#refresh-required-icon');
-    //                     if (refreshRequiredIcon.data('qtip')) {
-    //                         refreshRequiredIcon.qtip('option', 'content.text', refreshMessage);
-    //                     } else {
-    //                         refreshRequiredIcon.qtip($.extend({
-    //                             content: refreshMessage
-    //                         }, nf.CanvasUtils.config.systemTooltipConfig));
-    //                     }
-    //
-    //                     refreshContainer.show();
-    //                 }
-    //
-    //                 // insert the refresh needed text in the settings - if necessary
-    //                 if (!settingsRefreshIcon.is(':visible')) {
-    //                     $('#settings-last-refreshed').addClass('alert');
-    //                     settingsRefreshIcon.show();
-    //                 }
-    //             }
-    //         }
-    //     }).fail(nf.Common.handleAjaxError);
-    // };
-
-    /**
      * Initializes the canvas.
      */
     var initCanvas = function () {
@@ -563,7 +514,7 @@ nf.Canvas = (function () {
                     evt.preventDefault();
                 } else if (evt.keyCode === 67) {
                     // ctrl-c
-                    if (nf.Common.isDFM() && nf.CanvasUtils.isCopyable(selection)) {
+                    if (nf.Canvas.canWrite() && nf.CanvasUtils.isCopyable(selection)) {
                         nf.Actions.copy(selection);
 
                         // only want to prevent default if the action was performed, otherwise default copy would be overridden
@@ -571,7 +522,7 @@ nf.Canvas = (function () {
                     }
                 } else if (evt.keyCode === 86) {
                     // ctrl-v
-                    if (nf.Common.isDFM() && nf.CanvasUtils.isPastable()) {
+                    if (nf.Canvas.canWrite() && nf.CanvasUtils.isPastable()) {
                         nf.Actions.paste(selection);
 
                         // only want to prevent default if the action was performed, otherwise default paste would be overridden
@@ -581,7 +532,7 @@ nf.Canvas = (function () {
             } else {
                 if (evt.keyCode === 8 || evt.keyCode === 46) {
                     // backspace or delete
-                    if (nf.Common.isDFM() && nf.CanvasUtils.areDeletable(selection)) {
+                    if (nf.Canvas.canWrite() && nf.CanvasUtils.areDeletable(selection)) {
                         nf.Actions['delete'](selection);
                     }
 
@@ -755,36 +706,22 @@ nf.Canvas = (function () {
                 }
             }).promise();
 
-            // load the identity and authorities for the current user
+            // load the current user
             var userXhr = $.Deferred(function (deferred) {
                 ticketExchange.always(function () {
-                    // get the current user's identity
-                    var identityXhr = $.ajax({
-                        type: 'GET',
-                        url: config.urls.identity,
-                        dataType: 'json'
-                    });
-
-                    // get the current user's authorities
-                    var authoritiesXhr = $.ajax({
+                    // get the current user
+                    $.ajax({
                         type: 'GET',
-                        url: config.urls.authorities,
+                        url: config.urls.currentUser,
                         dataType: 'json'
-                    });
-
-                    $.when(authoritiesXhr, identityXhr).done(function (authoritiesResult, identityResult) {
-                        var authoritiesResponse = authoritiesResult[0];
-                        var identityResponse = identityResult[0];
-
-                        // set the user's authorities
-                        nf.Common.setAuthorities(authoritiesResponse.authorities);
-
+                    }).done(function (currentUser) {
                         // at this point the user may be themselves or anonymous
-
+                        nf.Common.setCurrentUser(currentUser)
+                        
                         // if the user is logged, we want to determine if they were logged in using a certificate
-                        if (identityResponse.anonymous === false) {
-                            // rendner the users name
-                            $('#current-user').text(identityResponse.identity).show();
+                        if (currentUser.anonymous === false) {
+                            // render the users name
+                            $('#current-user').text(currentUser.identity).show();
 
                             // render the logout button if there is a token locally
                             if (nf.Storage.getItem('jwt') !== null) {
@@ -805,6 +742,7 @@ nf.Canvas = (function () {
                     });
                 });
             }).promise();
+            
             userXhr.done(function () {
                 // load the client id
                 var clientXhr = nf.Client.init();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/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 b5b1156..77258b7 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
@@ -172,7 +172,7 @@ nf.ContextMenu = (function () {
      * @param {selection} selection         The selection of currently selected components
      */
     var isPastable = function (selection) {
-        return nf.Common.isDFM() && nf.CanvasUtils.isPastable();
+        return nf.Canvas.canWrite() && nf.CanvasUtils.isPastable();
     };
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
index d7c4c35..e60699b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js
@@ -580,11 +580,6 @@ nf.ProcessorConfiguration = (function () {
                     dataType: 'json'
                 }));
 
-                // get the processor state if we're a DFM
-                if (nf.Common.isDFM()) {
-                    requests.push();
-                }
-
                 // once everything is loaded, show the dialog
                 $.when.apply(window, requests).done(function (processorResult, historyResult) {
                     // get the updated processor'

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
index 7cd6720..9907c6c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
@@ -156,12 +156,13 @@ nf.RemoteProcessGroupPorts = (function () {
                 },
                 handler: {
                     click: function () {
-                        // if this is a DFM, the over status of this node may have changed
-                        if (nf.Common.isDFM()) {
-                            // get the component in question
-                            var remoteProcessGroupId = $('#remote-process-group-ports-id').text();
-                            var remoteProcessGroupData = d3.select('#id-' + remoteProcessGroupId).datum();
+                        // get the component in question
+                        var remoteProcessGroupId = $('#remote-process-group-ports-id').text();
+                        var remoteProcessGroup = d3.select('#id-' + remoteProcessGroupId);
+                        var remoteProcessGroupData = remoteProcessGroup.datum();
 
+                        // if can modify, the over status of this node may have changed
+                        if (nf.CanvasUtils.canModify(remoteProcessGroup)) {
                             // reload the remote process group
                             nf.RemoteProcessGroup.reload(remoteProcessGroupData.component);
                         }
@@ -204,8 +205,12 @@ nf.RemoteProcessGroupPorts = (function () {
         var portContainerEditContainer = $('<div class="remote-port-edit-container"></div>').appendTo(portContainer);
         var portContainerDetailsContainer = $('<div class="remote-port-details-container"></div>').appendTo(portContainer);
 
-        // only DFMs can update the remote group port
-        if (nf.Common.isDFM()) {
+        // get the component in question
+        var remoteProcessGroupId = $('#remote-process-group-ports-id').text();
+        var remoteProcessGroup = d3.select('#id-' + remoteProcessGroupId);
+
+        // if can modify, support updating the remote group port
+        if (nf.CanvasUtils.canModify(remoteProcessGroup)) {
             // show the enabled transmission switch
             var transmissionSwitch;
             if (port.connected === true) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
index 707cecf..cca62ce 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-settings.js
@@ -922,6 +922,12 @@ nf.Settings = (function () {
      * Shows the process group configuration.
      */
     var showSettings = function () {
+        if (nf.Common.canModifyController()) {
+            $('#new-service-or-task').show();
+        } else {
+            $('#new-service-or-task').hide();
+        }
+
         // show the settings dialog
         nf.Shell.showContent('#settings').done(function () {
             reset();
@@ -964,18 +970,20 @@ nf.Settings = (function () {
                         $('#new-service-or-task').hide();
                         $('#settings-save').show();
                     } else {
-                        $('#new-service-or-task').show();
-
-                        // update the tooltip on the button
-                        $('#new-service-or-task').attr('title', function () {
-                            if (tab === 'Controller Services') {
-                                $('#settings-save').hide();
-                                return 'Create a new controller service';
-                            } else if (tab === 'Reporting Tasks') {
-                                $('#settings-save').hide();
-                                return 'Create a new reporting task';
-                            }
-                        });
+                        if (nf.Common.canModifyController()) {
+                            $('#new-service-or-task').show();
+
+                            // update the tooltip on the button
+                            $('#new-service-or-task').attr('title', function () {
+                                if (tab === 'Controller Services') {
+                                    $('#settings-save').hide();
+                                    return 'Create a new controller service';
+                                } else if (tab === 'Reporting Tasks') {
+                                    $('#settings-save').hide();
+                                    return 'Create a new reporting task';
+                                }
+                            });
+                        }
 
                         // resize the table
                         nf.Settings.resetTableSize();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
index 7aa2450..5d25e4e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
@@ -426,7 +426,7 @@ nf.ClusterTable = (function () {
             ];
 
             // only allow the admin to modify the cluster
-            if (nf.Common.isAdmin()) {
+            if (nf.Common.canModifyController()) {
                 // function for formatting the actions column
                 var actionFormatter = function (row, cell, value, columnDef, dataContext) {
                     var canDisconnect = false;
@@ -477,7 +477,7 @@ nf.ClusterTable = (function () {
 
             // initialize the sort
             sort({
-                columnId: 'userName',
+                columnId: 'node',
                 sortAsc: true
             }, clusterData);
 
@@ -487,7 +487,7 @@ nf.ClusterTable = (function () {
             clusterGrid.setSortColumn('node', true);
             clusterGrid.onSort.subscribe(function (e, args) {
                 sort({
-                    columnId: args.sortCol.field,
+                    columnId: args.sortCol.id,
                     sortAsc: args.sortAsc
                 }, clusterData);
             });

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster.js
index 383d8ce..ae672bb 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster.js
@@ -37,32 +37,21 @@ nf.Cluster = (function () {
         urls: {
             banners: '../nifi-api/flow/banners',
             about: '../nifi-api/flow/about',
-            authorities: '../nifi-api/flow/authorities'
+            currentUser: '../nifi-api/flow/current-user'
         }
     };
 
     /**
-     * Loads the current users authorities.
+     * Loads the current user.
      */
-    var loadAuthorities = function () {
-        return $.Deferred(function (deferred) {
-            $.ajax({
-                type: 'GET',
-                url: config.urls.authorities,
-                dataType: 'json'
-            }).done(function (response) {
-                if (nf.Common.isDefinedAndNotNull(response.authorities)) {
-                    // record the users authorities
-                    nf.Common.setAuthorities(response.authorities);
-                    deferred.resolve();
-                } else {
-                    deferred.reject();
-                }
-            }).fail(function (xhr, status, error) {
-                nf.Common.handleAjaxError(xhr, status, error);
-                deferred.reject();
-            });
-        }).promise();
+    var loadCurrentUser = function () {
+        return $.ajax({
+            type: 'GET',
+            url: config.urls.currentUser,
+            dataType: 'json'
+        }).done(function (currentUser) {
+            nf.Common.setCurrentUser(currentUser);
+        }).fail(nf.Common.handleAjaxError);
     };
 
     /**
@@ -131,8 +120,8 @@ nf.Cluster = (function () {
         init: function () {
             nf.Storage.init();
             
-            // load the users authorities
-            loadAuthorities().done(function () {
+            // load the current user
+            loadCurrentUser().done(function () {
                 // create the counters table
                 nf.ClusterTable.init();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters-table.js
index 3c32a0d..81854ee 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters-table.js
@@ -173,7 +173,7 @@ nf.CountersTable = (function () {
             ];
 
             // only allow dfm's to reset counters
-            if (nf.Common.isDFM()) {
+            if (nf.Common.canModifyCounters()) {
                 // function for formatting the actions column
                 var actionFormatter = function (row, cell, value, columnDef, dataContext) {
                     return '<div title="Connect" class="pointer reset-counter fa fa-undo" style="margin-top: 2px;"></div>';

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters.js
index 4b7c921..6a6b36d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/counters/nf-counters.js
@@ -31,32 +31,22 @@ nf.Counters = (function () {
         urls: {
             banners: '../nifi-api/flow/banners',
             about: '../nifi-api/flow/about',
-            authorities: '../nifi-api/flow/authorities'
+            currentUser: '../nifi-api/flow/current-user'
         }
     };
 
     /**
-     * Loads the current users authorities.
+     * Loads the current user.
      */
-    var loadAuthorities = function () {
-        return $.Deferred(function (deferred) {
-            $.ajax({
-                type: 'GET',
-                url: config.urls.authorities,
-                dataType: 'json'
-            }).done(function (response) {
-                if (nf.Common.isDefinedAndNotNull(response.authorities)) {
-                    // record the users authorities
-                    nf.Common.setAuthorities(response.authorities);
-                    deferred.resolve();
-                } else {
-                    deferred.reject();
-                }
-            }).fail(function (xhr, status, error) {
-                nf.Common.handleAjaxError(xhr, status, error);
-                deferred.reject();
-            });
-        }).promise();
+    var loadCurrentUser = function () {
+        return $.ajax({
+            type: 'GET',
+            url: config.urls.currentUser,
+            dataType: 'json'
+        }).done(function (currentUser) {
+            nf.Common.setCurrentUser(currentUser);
+
+        }).fail(nf.Common.handleAjaxError);
     };
 
     /**
@@ -125,8 +115,8 @@ nf.Counters = (function () {
         init: function () {
             nf.Storage.init();
             
-            // load the users authorities
-            loadAuthorities().done(function () {
+            // load the current user
+            loadCurrentUser().done(function () {
                 // create the counters table
                 nf.CountersTable.init();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-model.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-model.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-model.js
index d55d96b..366a275 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-model.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-model.js
@@ -149,7 +149,7 @@
                     $('.timezone').text(nf.Common.substringAfterLast(history.lastRefreshed, ' '));
 
                     // show the filter message if applicable
-                    if (query['sourceId'] || query['userName'] || query['startDate'] || query['endDate']) {
+                    if (query['sourceId'] || query['userIdentity'] || query['startDate'] || query['endDate']) {
                         $('#history-filter-overview').css('visibility', 'visible');
                     } else {
                         $('#history-filter-overview').css('visibility', 'hidden');

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-table.js
index 52816f6..1892f7b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history-table.js
@@ -119,7 +119,7 @@ nf.HistoryTable = (function () {
                             if (filterType === 'by id') {
                                 filter['sourceId'] = filterText;
                             } else if (filterType === 'by user') {
-                                filter['userName'] = filterText;
+                                filter['userIdentity'] = filterText;
                             }
                         }
 
@@ -274,6 +274,11 @@ nf.HistoryTable = (function () {
             return '<div title="View Details" class="pointer show-action-details fa fa-info-circle" style="margin-top: 4px;"></div>';
         };
 
+        // define how general values are formatted
+        var valueFormatter = function (row, cell, value, columnDef, dataContext) {
+            return nf.Common.formatValue(value);
+        };
+
         // initialize the templates table
         var historyColumns = [
             {
@@ -285,11 +290,11 @@ nf.HistoryTable = (function () {
                 width: 50,
                 maxWidth: 50
             },
-            {id: 'timestamp', name: 'Date/Time', field: 'timestamp', sortable: true, resizable: true},
-            {id: 'sourceName', name: 'Name', field: 'sourceName', sortable: true, resizable: true},
-            {id: 'sourceType', name: 'Type', field: 'sourceType', sortable: true, resizable: true},
-            {id: 'operation', name: 'Operation', field: 'operation', sortable: true, resizable: true},
-            {id: 'userName', name: 'User', field: 'userName', sortable: true, resizable: true}
+            {id: 'timestamp', name: 'Date/Time', field: 'timestamp', sortable: true, resizable: true, formatter: valueFormatter},
+            {id: 'sourceName', name: 'Name', field: 'sourceName', sortable: true, resizable: true, formatter: valueFormatter},
+            {id: 'sourceType', name: 'Type', field: 'sourceType', sortable: true, resizable: true, formatter: valueFormatter},
+            {id: 'operation', name: 'Operation', field: 'operation', sortable: true, resizable: true, formatter: valueFormatter},
+            {id: 'userIdentity', name: 'User', field: 'userIdentity', sortable: true, resizable: true, formatter: valueFormatter}
         ];
         var historyOptions = {
             forceFitColumns: true,
@@ -353,7 +358,7 @@ nf.HistoryTable = (function () {
         $('#history-table').data('gridInstance', historyGrid);
 
         // add the purge button if appropriate
-        if (nf.Common.isAdmin()) {
+        if (nf.Common.canModifyController()) {
             $('#history-purge-button').on('click', function () {
                 $('#history-purge-dialog').modal('show');
             }).show();

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history.js
index 674e862..c6087bc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/history/nf-history.js
@@ -31,33 +31,21 @@ nf.History = (function () {
         urls: {
             banners: '../nifi-api/flow/banners',
             about: '../nifi-api/flow/about',
-            authorities: '../nifi-api/flow/authorities'
+            currentUser: '../nifi-api/flow/current-user'
         }
     };
 
     /**
-     * Loads the current users authorities.
+     * Loads the current user.
      */
-    var loadAuthorities = function () {
-        // get the banners and update the page accordingly
-        return $.Deferred(function (deferred) {
-            $.ajax({
-                type: 'GET',
-                url: config.urls.authorities,
-                dataType: 'json'
-            }).done(function (response) {
-                if (nf.Common.isDefinedAndNotNull(response.authorities)) {
-                    // record the users authorities
-                    nf.Common.setAuthorities(response.authorities);
-                    deferred.resolve();
-                } else {
-                    deferred.reject();
-                }
-            }).fail(function (xhr, status, error) {
-                nf.Common.handleAjaxError(xhr, status, error);
-                deferred.reject();
-            });
-        }).promise();
+    var loadCurrentUser = function () {
+        return $.ajax({
+            type: 'GET',
+            url: config.urls.currentUser,
+            dataType: 'json'
+        }).done(function (currentUser) {
+            nf.Common.setCurrentUser(currentUser);
+        }).fail(nf.Common.handleAjaxError);
     };
 
     /**
@@ -126,8 +114,8 @@ nf.History = (function () {
         init: function () {
             nf.Storage.init();
             
-            // load the users authorities
-            loadAuthorities().done(function () {
+            // load the current user
+            loadCurrentUser().done(function () {
                 // create the history table
                 nf.HistoryTable.init();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
index a200d29..11faba5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
@@ -25,8 +25,6 @@ nf.Login = (function () {
 
     var config = {
         urls: {
-            identity: '../nifi-api/flow/identity',
-            users: '../nifi-api/controller/users',
             token: '../nifi-api/access/token',
             accessStatus: '../nifi-api/access',
             accessConfig: '../nifi-api/access/config'

http://git-wip-us.apache.org/repos/asf/nifi/blob/ce533033/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index 144f8f5..7872964 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -114,17 +114,17 @@ nf.Common = (function () {
         SUPPORTS_SVG: !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect,
 
         /**
-         * The authorities for the current user.
+         * The current user.
          */
-        authorities: undefined,
+        currentUser: undefined,
 
         /**
-         * Sets the authorities for the current user.
+         * Sets the current user.
          * 
-         * @argument {array} roles      The current users authorities
+         * @param currentUser
          */
-        setAuthorities: function (roles) {
-            nf.Common.authorities = roles;
+        setCurrentUser: function (currentUser) {
+            nf.Common.currentUser = currentUser;
         },
 
         /**
@@ -226,48 +226,89 @@ nf.Common = (function () {
          * @returns {boolean}
          */
         canAccessProvenance: function () {
-            var canAccessProvenance = false;
-            if (nf.Common.isDefinedAndNotNull(nf.Common.authorities)) {
-                $.each(nf.Common.authorities, function (i, authority) {
-                    if (authority === 'ROLE_PROVENANCE') {
-                        canAccessProvenance = true;
-                        return false;
-                    }
-                });
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.provenancePermissions.canRead === true;
+            } else {
+                return false;
             }
-            return canAccessProvenance;
         },
 
         /**
-         * Returns whether or not the current user is a DFM.
+         * Determines whether the current user can access counters.
+         * 
+         * @returns {boolean}
          */
-        isDFM: function () {
-            var dfm = false;
-            if (nf.Common.isDefinedAndNotNull(nf.Common.authorities)) {
-                $.each(nf.Common.authorities, function (i, authority) {
-                    if (authority === 'ROLE_DFM') {
-                        dfm = true;
-                        return false;
-                    }
-                });
+        canAccessCounters: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.countersPermissions.canRead === true;
+            } else {
+                return false;
             }
-            return dfm;
         },
 
         /**
-         * Returns whether or not the current user is a DFM.
+         * Determines whether the current user can modify counters.
+         * 
+         * @returns {boolean}
          */
-        isAdmin: function () {
-            var admin = false;
-            if (nf.Common.isDefinedAndNotNull(nf.Common.authorities)) {
-                $.each(nf.Common.authorities, function (i, authority) {
-                    if (authority === 'ROLE_ADMIN') {
-                        admin = true;
-                        return false;
-                    }
-                });
+        canModifyCounters: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.countersPermissions.canRead === true && nf.Common.currentUser.countersPermissions.canWrite === true;
+            } else {
+                return false;
+            }
+        },
+
+        /**
+         * Determines whether the current user can access tenants.
+         *
+         * @returns {boolean}
+         */
+        canAccessTenants: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.tenantsPermissions.canRead === true;
+            } else {
+                return false;
+            }
+        },
+
+        /**
+         * Determines whether the current user can modify tenants.
+         *
+         * @returns {boolean}
+         */
+        canModifyTenants: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.tenantsPermissions.canRead === true && nf.Common.currentUser.tenantsPermissions.canWrite === true;
+            } else {
+                return false;
+            }
+        },
+
+        /**
+         * Determines whether the current user can access the controller.
+         *
+         * @returns {boolean}
+         */
+        canAccessController: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.controllerPermissions.canRead === true;
+            } else {
+                return false;
+            }
+        },
+
+        /**
+         * Determines whether the current user can modify the controller.
+         *
+         * @returns {boolean}
+         */
+        canModifyController: function () {
+            if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
+                return nf.Common.currentUser.controllerPermissions.canRead === true && nf.Common.currentUser.controllerPermissions.canWrite === true;
+            } else {
+                return false;
             }
-            return admin;
         },
 
         /**
@@ -508,7 +549,7 @@ nf.Common = (function () {
                 if (!nf.Common.isEmpty(propertyHistory.previousValues)) {
                     var history = [];
                     $.each(propertyHistory.previousValues, function (_, previousValue) {
-                        history.push('<li>' + nf.Common.escapeHtml(previousValue.previousValue) + ' - ' + nf.Common.escapeHtml(previousValue.timestamp) + ' (' + nf.Common.escapeHtml(previousValue.userName) + ')</li>');
+                        history.push('<li>' + nf.Common.escapeHtml(previousValue.previousValue) + ' - ' + nf.Common.escapeHtml(previousValue.timestamp) + ' (' + nf.Common.escapeHtml(previousValue.userIdentity) + ')</li>');
                     });
                     tipContent.push('<b>History:</b><ul class="property-info">' + history.join('') + '</ul>');
                 }