You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2016/10/27 15:51:17 UTC

nifi git commit: NIFI-2884: - Adding support to selecting multiple users before updating a policy. NIFI-2533: - Only including a user/group in the search results if they are not currently selected. NIFI-2286: - Providing a tooltip for the add user and re

Repository: nifi
Updated Branches:
  refs/heads/master 8c09bef4f -> 8dc60c72d


NIFI-2884: - Adding support to selecting multiple users before updating a policy.
NIFI-2533: - Only including a user/group in the search results if they are not currently selected.
NIFI-2286: - Providing a tooltip for the add user and remove policy button.

This closes #1155.

Signed-off-by: Bryan Bende <bb...@apache.org>


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

Branch: refs/heads/master
Commit: 8dc60c72d48dba910e97bb36d400031c5f0882d0
Parents: 8c09bef
Author: Matt Gilman <ma...@gmail.com>
Authored: Mon Oct 24 10:28:17 2016 -0400
Committer: Bryan Bende <bb...@apache.org>
Committed: Thu Oct 27 11:50:46 2016 -0400

----------------------------------------------------------------------
 .../apache/nifi/web/api/TenantsResource.java    |  23 +-
 .../partials/canvas/policy-management.jsp       |   4 +-
 .../partials/canvas/search-users-dialog.jsp     |  16 +-
 .../src/main/webapp/css/common-ui.css           |   9 +
 .../src/main/webapp/css/flow-status.css         |   7 -
 .../src/main/webapp/css/policy-management.css   |  65 ++++-
 .../webapp/js/nf/canvas/nf-policy-management.js | 242 ++++++++++++-------
 .../main/webapp/js/nf/users/nf-users-table.js   |   5 +
 8 files changed, 262 insertions(+), 109 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TenantsResource.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/TenantsResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TenantsResource.java
index 8073e8a..ab82ace 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TenantsResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/TenantsResource.java
@@ -38,7 +38,6 @@ import org.apache.nifi.web.api.dto.RevisionDTO;
 import org.apache.nifi.web.api.dto.TenantDTO;
 import org.apache.nifi.web.api.dto.UserDTO;
 import org.apache.nifi.web.api.dto.UserGroupDTO;
-import org.apache.nifi.web.api.entity.ClusterSearchResultsEntity;
 import org.apache.nifi.web.api.entity.TenantEntity;
 import org.apache.nifi.web.api.entity.TenantsEntity;
 import org.apache.nifi.web.api.entity.UserEntity;
@@ -166,6 +165,10 @@ public class TenantsResource extends ApplicationResource {
             throw new IllegalArgumentException("User ID cannot be specified.");
         }
 
+        if (StringUtils.isBlank(requestUserEntity.getComponent().getIdentity())) {
+            throw new IllegalArgumentException("User identity must be specified.");
+        }
+
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST, requestUserEntity);
         }
@@ -551,6 +554,10 @@ public class TenantsResource extends ApplicationResource {
             throw new IllegalArgumentException("User group ID cannot be specified.");
         }
 
+        if (StringUtils.isBlank(requestUserGroupEntity.getComponent().getIdentity())) {
+            throw new IllegalArgumentException("User group identity must be specified.");
+        }
+
         if (isReplicateRequest()) {
             return replicate(HttpMethod.POST, requestUserGroupEntity);
         }
@@ -864,19 +871,19 @@ public class TenantsResource extends ApplicationResource {
     // ------------
 
     /**
-     * Searches the cluster for a node with a given address.
+     * Searches for a tenant with a given identity.
      *
-     * @param value Search value that will be matched against a node's address
-     * @return Nodes that match the specified criteria
+     * @param value Search value that will be matched against a user/group identity
+     * @return Tenants match the specified criteria
      */
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
     @Path("search-results")
     @ApiOperation(
-            value = "Searches the cluster for a node with the specified address",
+            value = "Searches for a tenant with the specified identity",
             notes = NON_GUARANTEED_ENDPOINT,
-            response = ClusterSearchResultsEntity.class,
+            response = TenantsEntity.class,
             authorizations = {
                     @Authorization(value = "Read - /tenants", type = "")
             }
@@ -892,7 +899,7 @@ public class TenantsResource extends ApplicationResource {
     )
     public Response searchCluster(
             @ApiParam(
-                    value = "Node address to search for.",
+                    value = "Identity to search for.",
                     required = true
             )
             @QueryParam("q") @DefaultValue(StringUtils.EMPTY) String value) {
@@ -925,6 +932,7 @@ public class TenantsResource extends ApplicationResource {
 
                 final TenantEntity entity = new TenantEntity();
                 entity.setPermissions(userEntity.getPermissions());
+                entity.setRevision(userEntity.getRevision());
                 entity.setId(userEntity.getId());
                 entity.setComponent(tenant);
 
@@ -942,6 +950,7 @@ public class TenantsResource extends ApplicationResource {
 
                 final TenantEntity entity = new TenantEntity();
                 entity.setPermissions(userGroupEntity.getPermissions());
+                entity.setRevision(userGroupEntity.getRevision());
                 entity.setId(userGroupEntity.getId());
                 entity.setComponent(tenant);
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
index b833c7c..7cd08e0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/policy-management.jsp
@@ -78,8 +78,8 @@
             <div id="component-policy-target"></div>
             <div class="clear"></div>
         </div>
-        <button id="delete-policy-button" class="fa fa-trash policy-button"></button>
-        <button id="new-policy-user-button" class="fa fa-user-plus policy-button"></button>
+        <button id="delete-policy-button" class="fa fa-trash policy-button" title="Delete this policy"></button>
+        <button id="new-policy-user-button" class="fa fa-user-plus policy-button" title="Add users/groups to this policy"></button>
         <div class="clear"></div>
     </div>
     <div id="policy-table"></div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
index 03c62ca..43be5c0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/search-users-dialog.jsp
@@ -17,7 +17,21 @@
 <%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
 <div id="search-users-dialog" class="hidden">
     <div class="dialog-content">
-        <input id="search-users-field" type="text" placeholder="User Identity"/>
+        <div class="secure-port-setting">
+            <input id="search-users-field" type="text" placeholder="User Identity"/>
+        </div>
+        <div class="secure-port-setting">
+            <div class="setting-name">Allowed Users</div>
+            <div class="setting-field allowed-container">
+                <ul id="allowed-users" class="allowed"></ul>
+            </div>
+        </div>
+        <div class="secure-port-setting">
+            <div class="setting-name">Allowed Groups</div>
+            <div class="setting-field allowed-container">
+                <ul id="allowed-groups" class="allowed"></ul>
+            </div>
+        </div>
     </div>
 </div>
 <div id="search-users-results"></div>

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
index cf6a7a6..0466df5 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/common-ui.css
@@ -536,6 +536,15 @@ div.context-menu-item-text {
     color: #262626;
 }
 
+/* search */
+
+li.search-no-matches {
+    padding: 4px;
+    font-weight: bold;
+    color: #aaa;
+    font-style: italic;
+}
+
 /* progress bars */
 
 md-progress-linear > div {

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css
index c13344d..186d984 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/flow-status.css
@@ -170,13 +170,6 @@ input.search-flow {
     line-height: 1.4em;
 }
 
-#search-flow-results li.search-no-matches {
-    padding: 4px;
-    font-weight: bold;
-    color: #aaa;
-    font-style: italic;
-}
-
 div.search-glass-pane {
     position: absolute;
     background-image: url(../images/spacer.png);

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
index 21cdc1f..a1a5f89 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/policy-management.css
@@ -194,7 +194,7 @@ div.policy-selected-component-type {
 
 #search-users-dialog {
     width: 450px;
-    height: 250px;
+    height: 450px;
 }
 
 #search-users-results .ui-autocomplete {
@@ -211,6 +211,69 @@ div.policy-selected-component-type {
     border-radius: 0;
 }
 
+div.secure-port-setting {
+    margin-bottom: 15px;
+    width: 410px;
+}
+
+li.search-users-header {
+    font-weight: bold;
+    padding-top: 4px;
+    padding-left: 4px;
+    padding-right: 4px;
+    height: 14px;
+}
+
+div.search-users-match-header {
+    font-weight: normal;
+    margin-left: 10px;
+}
+
+li.search-users-no-matches {
+    padding: 4px;
+    font-weight: bold;
+    color: #aaa;
+    font-style: italic;
+}
+
+div.allowed-container {
+    width: 408px;
+    height: 100px;
+    border: 1px solid #aaa;
+    overflow-x: hidden;
+    overflow-y: scroll;
+}
+
+ul.allowed {
+    list-style-type: none;
+}
+
+ul.allowed li {
+    height: 16px;
+    width: 385px;
+    border-bottom: 1px solid #ddd;
+    color: #262626;
+    overflow: hidden;
+    margin: 2px;
+    padding: 2px;
+    line-height: 16px;
+    font-weight: normal;
+}
+
+span.allowed-entity {
+    float: left;
+    width: 360px;
+}
+
+div.remove-allowed-entity {
+    float: right;
+    width: 16px;
+    height: 16px;
+    cursor: pointer;
+    font-size: 14px;
+    line-height: 16px;
+}
+
 /*
     admin policy message
 */

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
index c8e87f3..d738b58 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js
@@ -50,85 +50,31 @@ nf.PolicyManagement = (function () {
                 },
                 handler: {
                     click: function () {
-                        var tenantSearchTerm = $('#search-users-field').val();
-
-                        // create the search request
-                        $.ajax({
-                            type: 'GET',
-                            data: {
-                                q: tenantSearchTerm
-                            },
-                            dataType: 'json',
-                            url: config.urls.searchTenants
-                        }).done(function (response) {
-                            var selectedUsers = $.map(response.users, function (user) {
-                                return $.extend({
-                                    type: 'user'
-                                }, user);
-                            });
-                            var selectedGroups = $.map(response.userGroups, function (userGroup) {
-                                return $.extend({
-                                    type: 'group'
-                                }, userGroup);
-                            });
-
-                            var selectedUser = [];
-                            selectedUser = selectedUser.concat(selectedUsers, selectedGroups);
-
-                            // add the user to the policy table
-                            var addUser = function (user) {
-                                // add to table and update policy
-                                var policyGrid = $('#policy-table').data('gridInstance');
-                                var policyData = policyGrid.getData();
-
-                                // begin the update
-                                policyData.beginUpdate();
-
-                                // remove the user
-                                policyData.addItem(user);
-
-                                // end the update
-                                policyData.endUpdate();
-
-                                // update the policy
-                                updatePolicy();
-                            };
-
-                            // ensure the search found some results
-                            if (!$.isArray(selectedUser) || selectedUser.length === 0) {
-                                nf.Dialog.showOkDialog({
-                                    headerText: 'User Search',
-                                    dialogContent: 'No users match \'' + nf.Common.escapeHtml(tenantSearchTerm) + '\'.'
-                                });
-                            } else if (selectedUser.length > 1) {
-                                var exactMatch = false;
-
-                                // look for an exact match
-                                $.each(selectedUser, function (_, userEntity) {
-                                    if (userEntity.component.identity === tenantSearchTerm) {
-                                        addUser(userEntity);
-                                        exactMatch = true;
-                                        return false;
-                                    }
-                                });
-
-                                // if there is an exact match, use it
-                                if (exactMatch) {
-                                    // close the dialog
-                                    $('#search-users-dialog').modal('hide');
-                                } else {
-                                    nf.Dialog.showOkDialog({
-                                        headerText: 'User Search',
-                                        dialogContent: 'More than one user matches \'' + nf.Common.escapeHtml(tenantSearchTerm) + '\'.'
-                                    });
-                                }
-                            } else if (selectedUser.length === 1) {
-                                addUser(selectedUser[0]);
-
-                                // close the dialog
-                                $('#search-users-dialog').modal('hide');
-                            }
+                        // add to table and update policy
+                        var policyGrid = $('#policy-table').data('gridInstance');
+                        var policyData = policyGrid.getData();
+
+                        // begin the update
+                        policyData.beginUpdate();
+
+                        // add all users/groups
+                        $.each(getTenantsToAdd($('#allowed-users')), function (_, user) {
+                            // remove the user
+                            policyData.addItem(user);
+                        });
+                        $.each(getTenantsToAdd($('#allowed-groups')), function (_, group) {
+                            // remove the user
+                            policyData.addItem(group);
                         });
+
+                        // end the update
+                        policyData.endUpdate();
+
+                        // update the policy
+                        updatePolicy();
+
+                        // close the dialog
+                        $('#search-users-dialog').modal('hide');
                     }
                 }
             },
@@ -150,11 +96,18 @@ nf.PolicyManagement = (function () {
                 close: function () {
                     // reset the search fields
                     $('#search-users-field').userSearchAutocomplete('reset').val('');
-                    $('#selected-user-id').text('');
+
+                    // clear the selected users/groups
+                    $('#allowed-users, #allowed-groups').empty();
                 }
             }
         });
 
+        // listen for removal requests
+        $(document).on('click', 'div.remove-allowed-entity', function () {
+            $(this).closest('li').remove();
+        });
+
         // configure the user auto complete
         $.widget('nf.userSearchAutocomplete', $.ui.autocomplete, {
             reset: function () {
@@ -169,18 +122,25 @@ nf.PolicyManagement = (function () {
                 // results are normalized into a single element array
                 var searchResults = items[0];
 
+                var allowedGroups = getAllAllowedGroups();
+                var allowedUsers = getAllAllowedUsers();
+
                 var self = this;
                 $.each(searchResults.userGroups, function (_, tenant) {
-                    self._renderGroup(ul, {
-                        label: tenant.component.identity,
-                        value: tenant.component.identity
-                    });
+                    // see if this match is not already selected
+                    if ($.inArray(tenant.id, allowedGroups) === -1) {
+                        self._renderGroup(ul, $.extend({
+                            type: 'group'
+                        }, tenant));
+                    }
                 });
                 $.each(searchResults.users, function (_, tenant) {
-                    self._renderUser(ul, {
-                        label: tenant.component.identity,
-                        value: tenant.component.identity
-                    });
+                    // see if this match is not already selected
+                    if ($.inArray(tenant.id, allowedUsers) === -1) {
+                        self._renderUser(ul, $.extend({
+                            type: 'user'
+                        }, tenant));
+                    }
                 });
 
                 // ensure there were some results
@@ -190,14 +150,14 @@ nf.PolicyManagement = (function () {
             },
             _resizeMenu: function () {
                 var ul = this.menu.element;
-                ul.width($('#search-users-field').width() + 6);
+                ul.width($('#search-users-field').outerWidth() - 6);
             },
             _renderUser: function (ul, match) {
-                var userContent = $('<a></a>').text(match.label);
+                var userContent = $('<a></a>').text(match.component.identity);
                 return $('<li></li>').data('ui-autocomplete-item', match).append(userContent).appendTo(ul);
             },
             _renderGroup: function (ul, match) {
-                var groupLabel = $('<span></span>').text(match.label);
+                var groupLabel = $('<span></span>').text(match.component.identity);
                 var groupContent = $('<a></a>').append('<div class="fa fa-users" style="margin-right: 5px;"></div>').append(groupLabel);
                 return $('<li></li>').data('ui-autocomplete-item', match).append(groupContent).appendTo(ul);
             }
@@ -224,10 +184,110 @@ nf.PolicyManagement = (function () {
                 }).done(function (searchResponse) {
                     response(searchResponse);
                 });
+            },
+            select: function (event, ui) {
+                addAllowedTenant(ui.item);
+
+                // reset the search field
+                $(this).val('');
+
+                // stop event propagation
+                return false;
             }
         });
     };
-    
+
+    /**
+     * Gets all allowed groups including those already in the policy and those selected while searching (not yet saved).
+     *
+     * @returns {Array}
+     */
+    var getAllAllowedGroups = function () {
+        var policyGrid = $('#policy-table').data('gridInstance');
+        var policyData = policyGrid.getData();
+
+        var userGroups = [];
+
+        // consider existing groups in the policy table
+        var items = policyData.getItems();
+        $.each(items, function (_, item) {
+            if (item.type === 'group') {
+                userGroups.push(item.id);
+            }
+        });
+
+        // also consider groups already selected in the search users dialog
+        $.each(getTenantsToAdd($('#allowed-groups')), function (_, group) {
+            userGroups.push(group.id);
+        });
+
+        return userGroups;
+    };
+
+    /**
+     * Gets the user groups that will be added upon applying the changes.
+     *
+     * @param {jQuery} container
+     * @returns {Array}
+     */
+    var getTenantsToAdd = function (container) {
+        var tenants = [];
+
+        // also consider groups already selected in the search users dialog
+        container.children('li').each(function (_, allowedTenant) {
+            var tenant = $(allowedTenant).data('tenant');
+            if (nf.Common.isDefinedAndNotNull(tenant)) {
+                tenants.push(tenant);
+            }
+        });
+
+        return tenants;
+    };
+
+    /**
+     * Gets all allowed users including those already in the policy and those selected while searching (not yet saved).
+     *
+     * @returns {Array}
+     */
+    var getAllAllowedUsers = function () {
+        var policyGrid = $('#policy-table').data('gridInstance');
+        var policyData = policyGrid.getData();
+
+        var users = [];
+
+        // consider existing users in the policy table
+        var items = policyData.getItems();
+        $.each(items, function (_, item) {
+            if (item.type === 'user') {
+                users.push(item.id);
+            }
+        });
+
+        // also consider users already selected in the search users dialog
+        $.each(getTenantsToAdd($('#allowed-users')), function (_, user) {
+            users.push(user.id);
+        });
+
+        return users;
+    };
+
+    /**
+     * Added the specified tenant to the listing of users/groups which will be added when applied.
+     *
+     * @param allowedTenant user/group to add
+     */
+    var addAllowedTenant = function (allowedTenant) {
+        var allowedTenants = allowedTenant.type === 'user' ? $('#allowed-users') : $('#allowed-groups');
+
+        // append the user
+        var tenant = $('<span></span>').addClass('allowed-entity ellipsis').text(allowedTenant.component.identity).ellipsis();
+        var tenantAction = $('<div></div>').addClass('remove-allowed-entity fa fa-trash');
+        $('<li></li>').data('tenant', allowedTenant).append(tenant).append(tenantAction).appendTo(allowedTenants);
+    };
+
+    /**
+     * Initializes the policy table.
+     */
     var initPolicyTable = function () {
         $('#override-policy-dialog').modal({
             headerText: 'Override Policy',

http://git-wip-us.apache.org/repos/asf/nifi/blob/8dc60c72/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js
index 79267e0..1656050 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js
@@ -824,7 +824,12 @@ nf.UsersTable = (function () {
                 $('#new-user-button').on('click', function () {
                     buildUsersList();
                     buildGroupsList();
+
+                    // show the dialog
                     $('#user-dialog').modal('show');
+
+                    // set the focus automatically, only when adding a new user
+                    $('#user-identity-edit-dialog').focus();
                 });
 
                 $('#new-user-button').prop('disabled', false);