This is an automated email from the ASF dual-hosted git repository.

exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 2bbe593a65 NIFI-14245 Added Caching to Database User and Policy 
Providers in Registry (#9707)
2bbe593a65 is described below

commit 2bbe593a65afe942c8b1fe61fa42f98c916053d7
Author: Yoshiaki Takahashi <[email protected]>
AuthorDate: Mon Sep 8 22:59:28 2025 +0900

    NIFI-14245 Added Caching to Database User and Policy Providers in Registry 
(#9707)
    
    Signed-off-by: David Handermann <[email protected]>
---
 .../database/DatabaseAccessPolicyHolder.java       |  58 ++++++++++
 .../database/DatabaseAccessPolicyProvider.java     |  70 +++++-------
 .../database/DatabaseUserGroupHolder.java          |  89 +++++++++++++++
 .../database/DatabaseUserGroupProvider.java        | 120 ++++++++-------------
 .../authorization/file/AuthorizationsHolder.java   |  60 +----------
 .../file/FileAccessPolicyProvider.java             |   3 +-
 .../authorization/file/FileAuthorizer.java         |   3 +-
 .../authorization/file/UserGroupHolder.java        |  82 ++------------
 .../util/AccessPolicyProviderUtils.java            |  62 +++++++++++
 .../authorization/util/UserGroupProviderUtils.java |  71 ++++++++++++
 .../security/ldap/tenants/TenantHolder.java        |  31 +-----
 .../database/TestDatabaseAccessPolicyProvider.java |  12 ---
 .../database/TestDatabaseUserGroupProvider.java    | 115 +++++++++-----------
 13 files changed, 422 insertions(+), 354 deletions(-)

diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyHolder.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyHolder.java
new file mode 100644
index 0000000000..cd622d2e15
--- /dev/null
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyHolder.java
@@ -0,0 +1,58 @@
+/*
+ * 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.registry.security.authorization.database;
+
+import org.apache.nifi.registry.security.authorization.AccessPolicy;
+import 
org.apache.nifi.registry.security.authorization.util.AccessPolicyProviderUtils;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A holder to provide atomic access to data structures.
+ */
+public class DatabaseAccessPolicyHolder {
+
+    private final Set<AccessPolicy> allPolicies;
+    private final Map<String, Set<AccessPolicy>> policiesByResource;
+    private final Map<String, AccessPolicy> policiesById;
+
+    /**
+     * Creates a new holder and populates all convenience access policies data 
structures.
+     *
+     * @param allPolicies all access policies
+     */
+    public DatabaseAccessPolicyHolder(final Set<AccessPolicy> allPolicies) {
+        this.allPolicies = allPolicies;
+        this.policiesByResource = 
Collections.unmodifiableMap(AccessPolicyProviderUtils.createResourcePolicyMap(allPolicies));
+        this.policiesById = 
Collections.unmodifiableMap(AccessPolicyProviderUtils.createPoliciesByIdMap(allPolicies));
+    }
+
+    public Set<AccessPolicy> getAllPolicies() {
+        return allPolicies;
+    }
+
+    public Map<String, Set<AccessPolicy>> getPoliciesByResource() {
+        return policiesByResource;
+    }
+
+    public Map<String, AccessPolicy> getPoliciesById() {
+        return policiesById;
+    }
+
+}
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyProvider.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyProvider.java
index 6439f4112e..79f7c6bfe8 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyProvider.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseAccessPolicyProvider.java
@@ -50,6 +50,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Implementation of {@link 
org.apache.nifi.registry.security.authorization.ConfigurableAccessPolicyProvider}
 backed by a relational database.
@@ -63,6 +64,8 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
 
     private JdbcTemplate jdbcTemplate;
 
+    private final AtomicReference<DatabaseAccessPolicyHolder> 
accessPoliciesHolder = new AtomicReference<>();
+
     @AuthorizerContext
     public void setDataSource(final DataSource dataSource) {
         this.dataSource = dataSource;
@@ -81,6 +84,8 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
 
     @Override
     public void doOnConfigured(final AuthorizerConfigurationContext 
configurationContext) throws SecurityProviderCreationException {
+        refreshAccessPolicyHolder();
+
         final String initialAdminIdentity = 
AccessPolicyProviderUtils.getInitialAdminIdentity(configurationContext, 
identityMapper);
         final Set<String> nifiIdentities = 
AccessPolicyProviderUtils.getNiFiIdentities(configurationContext, 
identityMapper);
         final String nifiGroupName = 
AccessPolicyProviderUtils.getNiFiGroupName(configurationContext, 
identityMapper);
@@ -158,7 +163,7 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
     // ---- access policy methods
 
     @Override
-    public AccessPolicy addAccessPolicy(final AccessPolicy accessPolicy) 
throws AuthorizationAccessException {
+    public synchronized AccessPolicy addAccessPolicy(final AccessPolicy 
accessPolicy) throws AuthorizationAccessException {
         Objects.requireNonNull(accessPolicy);
 
         // insert to the policy table
@@ -168,11 +173,13 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
         // insert to the policy-user and policy groups table
         createPolicyUserAndGroups(accessPolicy);
 
+        refreshAccessPolicyHolder();
+
         return accessPolicy;
     }
 
     @Override
-    public AccessPolicy updateAccessPolicy(final AccessPolicy accessPolicy) 
throws AuthorizationAccessException {
+    public synchronized AccessPolicy updateAccessPolicy(final AccessPolicy 
accessPolicy) throws AuthorizationAccessException {
         Objects.requireNonNull(accessPolicy);
 
         // determine if policy exists
@@ -193,11 +200,17 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
         // re-create the associations
         createPolicyUserAndGroups(accessPolicy);
 
+        refreshAccessPolicyHolder();
+
         return accessPolicy;
     }
 
     @Override
     public Set<AccessPolicy> getAccessPolicies() throws 
AuthorizationAccessException {
+        return accessPoliciesHolder.get().getAllPolicies();
+    }
+
+    private Set<AccessPolicy> getDatabaseAccessPolicies() throws 
AuthorizationAccessException {
         // retrieve all the policies
         final String sql = "SELECT * FROM APP_POLICY";
         final List<DatabaseAccessPolicy> databasePolicies = 
jdbcTemplate.query(sql, new DatabaseAccessPolicyRowMapper());
@@ -237,36 +250,18 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
     @Override
     public AccessPolicy getAccessPolicy(final String identifier) throws 
AuthorizationAccessException {
         Validate.notBlank(identifier);
-
-        final DatabaseAccessPolicy databaseAccessPolicy = 
getDatabaseAcessPolicy(identifier);
-        if (databaseAccessPolicy == null) {
-            return null;
-        }
-
-        final Set<String> userIdentifiers = getPolicyUsers(identifier);
-        final Set<String> groupIdentifiers = getPolicyGroups(identifier);
-        return mapTopAccessPolicy(databaseAccessPolicy, userIdentifiers, 
groupIdentifiers);
+        return accessPoliciesHolder.get().getPoliciesById().get(identifier);
     }
 
     @Override
     public AccessPolicy getAccessPolicy(final String resourceIdentifier, 
RequestAction action) throws AuthorizationAccessException {
         Validate.notBlank(resourceIdentifier);
         Objects.requireNonNull(action);
-
-        final String policySql = "SELECT * FROM APP_POLICY WHERE RESOURCE = ? 
AND ACTION = ?";
-        final Object[] args = new Object[]{resourceIdentifier, 
action.toString()};
-        final DatabaseAccessPolicy databaseAccessPolicy = 
queryForObject(policySql, new DatabaseAccessPolicyRowMapper(), args);
-        if (databaseAccessPolicy == null) {
-            return null;
-        }
-
-        final Set<String> userIdentifiers = 
getPolicyUsers(databaseAccessPolicy.getIdentifier());
-        final Set<String> groupIdentifiers = 
getPolicyGroups(databaseAccessPolicy.getIdentifier());
-        return mapTopAccessPolicy(databaseAccessPolicy, userIdentifiers, 
groupIdentifiers);
+        return AccessPolicyProviderUtils.getAccessPolicy(resourceIdentifier, 
action, accessPoliciesHolder.get().getPoliciesByResource());
     }
 
     @Override
-    public AccessPolicy deleteAccessPolicy(final AccessPolicy accessPolicy) 
throws AuthorizationAccessException {
+    public synchronized AccessPolicy deleteAccessPolicy(final AccessPolicy 
accessPolicy) throws AuthorizationAccessException {
         Objects.requireNonNull(accessPolicy);
 
         final String sql = "DELETE FROM APP_POLICY WHERE IDENTIFIER = ?";
@@ -275,6 +270,8 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
             return null;
         }
 
+        refreshAccessPolicyHolder();
+
         return accessPolicy;
     }
 
@@ -295,11 +292,13 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
     protected void insertPolicyGroup(final String policyIdentifier, final 
String groupIdentifier) {
         final String policyGroupSql = "INSERT INTO 
APP_POLICY_GROUP(POLICY_IDENTIFIER, GROUP_IDENTIFIER) VALUES (?, ?)";
         jdbcTemplate.update(policyGroupSql, policyIdentifier, groupIdentifier);
+        refreshAccessPolicyHolder();
     }
 
     protected void insertPolicyUser(final String policyIdentifier, final 
String userIdentifier) {
         final String policyUserSql = "INSERT INTO 
APP_POLICY_USER(POLICY_IDENTIFIER, USER_IDENTIFIER) VALUES (?, ?)";
         jdbcTemplate.update(policyUserSql, policyIdentifier, userIdentifier);
+        refreshAccessPolicyHolder();
     }
 
     protected DatabaseAccessPolicy getDatabaseAcessPolicy(final String 
policyIdentifier) {
@@ -307,26 +306,6 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
         return queryForObject(sql, new DatabaseAccessPolicyRowMapper(), 
policyIdentifier);
     }
 
-    protected Set<String> getPolicyUsers(final String policyIdentifier) {
-        final String sql = "SELECT * FROM APP_POLICY_USER WHERE 
POLICY_IDENTIFIER = ?";
-
-        final Set<String> userIdentifiers = new HashSet<>();
-        jdbcTemplate.query(sql, (rs) -> {
-            userIdentifiers.add(rs.getString("USER_IDENTIFIER"));
-        }, policyIdentifier);
-        return userIdentifiers;
-    }
-
-    protected Set<String> getPolicyGroups(final String policyIdentifier) {
-        final String sql = "SELECT * FROM APP_POLICY_GROUP WHERE 
POLICY_IDENTIFIER = ?";
-
-        final Set<String> groupIdentifiers = new HashSet<>();
-        jdbcTemplate.query(sql, (rs) -> {
-            groupIdentifiers.add(rs.getString("GROUP_IDENTIFIER"));
-        }, policyIdentifier);
-        return groupIdentifiers;
-    }
-
     protected AccessPolicy mapTopAccessPolicy(final DatabaseAccessPolicy 
databaseAccessPolicy, final Set<String> userIdentifiers, final Set<String> 
groupIdentifiers) {
         return new AccessPolicy.Builder()
                 .identifier(databaseAccessPolicy.getIdentifier())
@@ -387,6 +366,11 @@ public class DatabaseAccessPolicyProvider extends 
AbstractConfigurableAccessPoli
         }
     }
 
+    private synchronized void refreshAccessPolicyHolder() {
+        final Set<AccessPolicy> allPolicies = getDatabaseAccessPolicies();
+        this.accessPoliciesHolder.set(new 
DatabaseAccessPolicyHolder(allPolicies));
+    }
+
     //-- util methods
 
     protected <T> T queryForObject(final String sql, final RowMapper<T> 
rowMapper, final Object... args) {
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupHolder.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupHolder.java
new file mode 100644
index 0000000000..7a67b970e9
--- /dev/null
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupHolder.java
@@ -0,0 +1,89 @@
+/*
+ * 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.registry.security.authorization.database;
+
+import org.apache.nifi.registry.security.authorization.Group;
+import org.apache.nifi.registry.security.authorization.User;
+import 
org.apache.nifi.registry.security.authorization.util.UserGroupProviderUtils;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A holder to provide atomic access to user group data structures.
+ */
+public class DatabaseUserGroupHolder {
+
+    private final Set<User> allUsers;
+    private final Map<String, User> usersById;
+    private final Map<String, User> usersByIdentity;
+
+    private final Set<Group> allGroups;
+    private final Map<String, Group> groupsById;
+    private final Map<String, Set<Group>> groupsByUserIdentity;
+
+    /**
+     * Creates a new holder and populates all convenience data structures.
+     *
+     * @param allUsers all users
+     */
+    public DatabaseUserGroupHolder(final Set<User> allUsers, final Set<Group> 
allGroups) {
+        this.allUsers = allUsers;
+        this.allGroups = allGroups;
+        this.usersById = 
Collections.unmodifiableMap(UserGroupProviderUtils.createUserByIdMap(allUsers));
+        this.usersByIdentity = 
Collections.unmodifiableMap(UserGroupProviderUtils.createUserByIdentityMap(allUsers));
+        this.groupsById = 
Collections.unmodifiableMap(UserGroupProviderUtils.createGroupByIdMap(allGroups));
+        this.groupsByUserIdentity = Collections.unmodifiableMap(
+                
UserGroupProviderUtils.createGroupsByUserIdentityMap(allGroups, allUsers));
+    }
+
+    public Set<User> getAllUsers() {
+        return allUsers;
+    }
+
+    public Map<String, User> getUsersById() {
+        return usersById;
+    }
+
+    public Map<String, User> getUsersByIdentity() {
+        return usersByIdentity;
+    }
+
+    public Set<Group> getAllGroups() {
+        return allGroups;
+    }
+
+    public Map<String, Group> getGroupsById() {
+        return groupsById;
+    }
+
+    public User getUser(String identity) {
+        if (identity == null) {
+            throw new IllegalArgumentException("Identity cannot be null");
+        }
+        return usersByIdentity.get(identity);
+    }
+
+    public Set<Group> getGroups(String userIdentity) {
+        if (userIdentity == null) {
+            throw new IllegalArgumentException("User Identity cannot be null");
+        }
+        return groupsByUserIdentity.get(userIdentity);
+    }
+
+}
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
index 700b1fb8a1..6a0e883046 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
@@ -48,6 +48,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Implementation of {@link 
org.apache.nifi.registry.security.authorization.ConfigurableUserGroupProvider} 
backed by a relational database.
@@ -61,6 +62,8 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
 
     private JdbcTemplate jdbcTemplate;
 
+    private final AtomicReference<DatabaseUserGroupHolder> userGroupHolder = 
new AtomicReference<>();
+
     @AuthorizerContext
     public void setDataSource(final DataSource dataSource) {
         this.dataSource = dataSource;
@@ -78,6 +81,8 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
 
     @Override
     public void onConfigured(final AuthorizerConfigurationContext 
configurationContext) throws SecurityProviderCreationException {
+        refreshUserGroupHolder();
+
         final Set<String> initialUserIdentities = 
UserGroupProviderUtils.getInitialUserIdentities(configurationContext, 
identityMapper);
 
         for (final String initialUserIdentity : initialUserIdentities) {
@@ -120,15 +125,18 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
     //-- User CRUD
 
     @Override
-    public User addUser(final User user) throws AuthorizationAccessException {
+    public synchronized User addUser(final User user) throws 
AuthorizationAccessException {
         Objects.requireNonNull(user);
         final String sql = "INSERT INTO UGP_USER(IDENTIFIER, IDENTITY) VALUES 
(?, ?)";
         jdbcTemplate.update(sql, user.getIdentifier(), user.getIdentity());
+
+        refreshUserGroupHolder();
+
         return user;
     }
 
     @Override
-    public User updateUser(final User user) throws 
AuthorizationAccessException {
+    public synchronized User updateUser(final User user) throws 
AuthorizationAccessException {
         Objects.requireNonNull(user);
 
         // update the user identity
@@ -140,11 +148,17 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
             return null;
         }
 
+        refreshUserGroupHolder();
+
         return user;
     }
 
     @Override
     public Set<User> getUsers() throws AuthorizationAccessException {
+        return userGroupHolder.get().getAllUsers();
+    }
+
+    private Set<User> getDatabaseUsers() throws AuthorizationAccessException {
         final String sql = "SELECT * FROM UGP_USER";
         final List<DatabaseUser> databaseUsers = jdbcTemplate.query(sql, new 
DatabaseUserRowMapper());
 
@@ -158,59 +172,21 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
     @Override
     public User getUser(final String identifier) throws 
AuthorizationAccessException {
         Validate.notBlank(identifier);
-
-        final DatabaseUser databaseUser = getDatabaseUser(identifier);
-        if (databaseUser == null) {
-            return null;
-        }
-
-        return mapToUser(databaseUser);
+        return userGroupHolder.get().getUsersById().get(identifier);
     }
 
     @Override
     public User getUserByIdentity(final String identity) throws 
AuthorizationAccessException {
         Validate.notBlank(identity);
-
-        final String sql = "SELECT * FROM UGP_USER WHERE IDENTITY = ?";
-        final DatabaseUser databaseUser = queryForObject(sql, new 
DatabaseUserRowMapper(), identity);
-        if (databaseUser == null) {
-            return null;
-        }
-
-        return mapToUser(databaseUser);
+        return userGroupHolder.get().getUsersByIdentity().get(identity);
     }
 
     @Override
     public UserAndGroups getUserAndGroups(final String userIdentity) throws 
AuthorizationAccessException {
         Validate.notBlank(userIdentity);
 
-        // retrieve the user
-        final User user = getUserByIdentity(userIdentity);
-
-        // if the user exists, then retrieve the groups for the user
-        final Set<Group> groups;
-        if (user == null) {
-            groups = null;
-        } else {
-            final String userGroupSql =
-                    "SELECT " +
-                            "G.IDENTIFIER AS IDENTIFIER, " +
-                            "G.IDENTITY AS IDENTITY " +
-                    "FROM " +
-                            "UGP_GROUP AS G, " +
-                            "UGP_USER_GROUP AS UG " +
-                    "WHERE " +
-                            "G.IDENTIFIER = UG.GROUP_IDENTIFIER AND " +
-                            "UG.USER_IDENTIFIER = ?";
-
-            final List<DatabaseGroup> databaseGroups = 
jdbcTemplate.query(userGroupSql, new DatabaseGroupRowMapper(), 
user.getIdentifier());
-
-            groups = new HashSet<>();
-            databaseGroups.forEach(g -> {
-                final Set<String> userIdentifiers = 
getUserIdentifiers(g.getIdentifier());
-                groups.add(mapToGroup(g, userIdentifiers));
-            });
-        }
+        final User user = userGroupHolder.get().getUser(userIdentity);
+        final Set<Group> groups = 
userGroupHolder.get().getGroups(userIdentity);
 
         return new UserAndGroups() {
             @Override
@@ -226,7 +202,7 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
     }
 
     @Override
-    public User deleteUser(final User user) throws 
AuthorizationAccessException {
+    public synchronized User deleteUser(final User user) throws 
AuthorizationAccessException {
         Objects.requireNonNull(user);
 
         final String deleteFromUserGroupSql = "DELETE FROM UGP_USER_GROUP 
WHERE USER_IDENTIFIER = ?";
@@ -238,12 +214,9 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
             return null;
         }
 
-        return user;
-    }
+        refreshUserGroupHolder();
 
-    private DatabaseUser getDatabaseUser(final String userIdentifier) {
-        final String sql = "SELECT * FROM UGP_USER WHERE IDENTIFIER = ?";
-        return queryForObject(sql, new DatabaseUserRowMapper(), 
userIdentifier);
+        return user;
     }
 
     private User mapToUser(final DatabaseUser databaseUser) {
@@ -256,7 +229,7 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
     //-- Group CRUD
 
     @Override
-    public Group addGroup(final Group group) throws 
AuthorizationAccessException {
+    public synchronized Group addGroup(final Group group) throws 
AuthorizationAccessException {
         Objects.requireNonNull(group);
 
         // insert to the group table...
@@ -266,11 +239,13 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
         // insert to the user-group table...
         createUserGroups(group);
 
+        refreshUserGroupHolder();
+
         return group;
     }
 
     @Override
-    public Group updateGroup(final Group group) throws 
AuthorizationAccessException {
+    public synchronized Group updateGroup(final Group group) throws 
AuthorizationAccessException {
         Objects.requireNonNull(group);
 
         // update the group identity
@@ -289,11 +264,17 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
         // re-create any user-group associations
         createUserGroups(group);
 
+        refreshUserGroupHolder();
+
         return group;
     }
 
     @Override
     public Set<Group> getGroups() throws AuthorizationAccessException {
+        return userGroupHolder.get().getAllGroups();
+    }
+
+    private Set<Group> getDatabaseGroups() throws AuthorizationAccessException 
{
         // retrieve all the groups
         final String sql = "SELECT * FROM UGP_GROUP";
         final List<DatabaseGroup> databaseGroups = jdbcTemplate.query(sql, new 
DatabaseGroupRowMapper());
@@ -319,18 +300,11 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
     @Override
     public Group getGroup(final String groupIdentifier) throws 
AuthorizationAccessException {
         Validate.notBlank(groupIdentifier);
-
-        final DatabaseGroup databaseGroup = getDatabaseGroup(groupIdentifier);
-        if (databaseGroup == null) {
-            return null;
-        }
-
-        final Set<String> userIdentifiers = 
getUserIdentifiers(groupIdentifier);
-        return mapToGroup(databaseGroup, userIdentifiers);
+        return userGroupHolder.get().getGroupsById().get(groupIdentifier);
     }
 
     @Override
-    public Group deleteGroup(final Group group) throws 
AuthorizationAccessException {
+    public synchronized Group deleteGroup(final Group group) throws 
AuthorizationAccessException {
         Objects.requireNonNull(group);
 
         final String sql = "DELETE FROM UGP_GROUP WHERE IDENTIFIER = ?";
@@ -339,6 +313,8 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
             return null;
         }
 
+        refreshUserGroupHolder();
+
         return group;
     }
 
@@ -351,22 +327,6 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
         }
     }
 
-    private DatabaseGroup getDatabaseGroup(final String groupIdentifier) {
-        final String sql = "SELECT * FROM UGP_GROUP WHERE IDENTIFIER = ?";
-        return queryForObject(sql, new DatabaseGroupRowMapper(), 
groupIdentifier);
-    }
-
-    private Set<String> getUserIdentifiers(final String groupIdentifier) {
-        final String sql = "SELECT * FROM UGP_USER_GROUP WHERE 
GROUP_IDENTIFIER = ?";
-
-        final Set<String> userIdentifiers = new HashSet<>();
-        jdbcTemplate.query(sql, (rs) -> {
-            userIdentifiers.add(rs.getString("USER_IDENTIFIER"));
-        }, groupIdentifier);
-
-        return userIdentifiers;
-    }
-
     private Group mapToGroup(final DatabaseGroup databaseGroup, final 
Set<String> userIdentifiers) {
         return new Group.Builder()
                 .identifier(databaseGroup.getIdentifier())
@@ -375,6 +335,12 @@ public class DatabaseUserGroupProvider implements 
ConfigurableUserGroupProvider
                 .build();
     }
 
+    private synchronized void refreshUserGroupHolder() {
+        final Set<User> allUsers = getDatabaseUsers();
+        final Set<Group> allGroups = getDatabaseGroups();
+        this.userGroupHolder.set(new DatabaseUserGroupHolder(allUsers, 
allGroups));
+    }
+
     //-- util methods
 
     private <T> T queryForObject(final String sql, final RowMapper<T> 
rowMapper, final Object... args) {
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/AuthorizationsHolder.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/AuthorizationsHolder.java
index 182fc65813..e0dfca0eaa 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/AuthorizationsHolder.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/AuthorizationsHolder.java
@@ -21,9 +21,9 @@ import 
org.apache.nifi.registry.security.authorization.file.generated.Authorizat
 import org.apache.nifi.registry.security.authorization.file.generated.Policies;
 import org.apache.nifi.registry.security.authorization.AccessPolicy;
 import org.apache.nifi.registry.security.authorization.RequestAction;
+import 
org.apache.nifi.registry.security.authorization.util.AccessPolicyProviderUtils;
 
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -52,10 +52,10 @@ public class AuthorizationsHolder {
         final Set<AccessPolicy> allPolicies = 
Collections.unmodifiableSet(createAccessPolicies(policies));
 
         // create a convenience map from resource id to policies
-        final Map<String, Set<AccessPolicy>> policiesByResourceMap = 
Collections.unmodifiableMap(createResourcePolicyMap(allPolicies));
+        final Map<String, Set<AccessPolicy>> policiesByResourceMap = 
Collections.unmodifiableMap(AccessPolicyProviderUtils.createResourcePolicyMap(allPolicies));
 
         // create a convenience map from policy id to policy
-        final Map<String, AccessPolicy> policiesByIdMap = 
Collections.unmodifiableMap(createPoliciesByIdMap(allPolicies));
+        final Map<String, AccessPolicy> policiesByIdMap = 
Collections.unmodifiableMap(AccessPolicyProviderUtils.createPoliciesByIdMap(allPolicies));
 
         // set all the holders
         this.allPolicies = allPolicies;
@@ -114,41 +114,6 @@ public class AuthorizationsHolder {
         return allPolicies;
     }
 
-    /**
-     * Creates a map from resource identifier to the set of policies for the 
given resource.
-     *
-     * @param allPolicies the set of all policies
-     * @return a map from resource identifier to policies
-     */
-    private Map<String, Set<AccessPolicy>> createResourcePolicyMap(final 
Set<AccessPolicy> allPolicies) {
-        Map<String, Set<AccessPolicy>> resourcePolicies = new HashMap<>();
-
-        for (AccessPolicy policy : allPolicies) {
-            Set<AccessPolicy> policies = 
resourcePolicies.get(policy.getResource());
-            if (policies == null) {
-                policies = new HashSet<>();
-                resourcePolicies.put(policy.getResource(), policies);
-            }
-            policies.add(policy);
-        }
-
-        return resourcePolicies;
-    }
-
-    /**
-     * Creates a Map from policy identifier to AccessPolicy.
-     *
-     * @param policies the set of all access policies
-     * @return the Map from policy identifier to AccessPolicy
-     */
-    private Map<String, AccessPolicy> createPoliciesByIdMap(final 
Set<AccessPolicy> policies) {
-        Map<String, AccessPolicy> policyMap = new HashMap<>();
-        for (AccessPolicy policy : policies) {
-            policyMap.put(policy.getIdentifier(), policy);
-        }
-        return policyMap;
-    }
-
     public Authorizations getAuthorizations() {
         return authorizations;
     }
@@ -165,23 +130,4 @@ public class AuthorizationsHolder {
         return policiesById;
     }
 
-    public AccessPolicy getAccessPolicy(final String resourceIdentifier, final 
RequestAction action) {
-        if (resourceIdentifier == null) {
-            throw new IllegalArgumentException("Resource Identifier cannot be 
null");
-        }
-
-        final Set<AccessPolicy> resourcePolicies = 
policiesByResource.get(resourceIdentifier);
-        if (resourcePolicies == null) {
-            return null;
-        }
-
-        for (AccessPolicy accessPolicy : resourcePolicies) {
-            if (accessPolicy.getAction() == action) {
-                return accessPolicy;
-            }
-        }
-
-        return null;
-    }
-
 }
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
index c9583f801f..004734c94e 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
@@ -199,7 +199,8 @@ public class FileAccessPolicyProvider extends 
AbstractConfigurableAccessPolicyPr
 
     @Override
     public AccessPolicy getAccessPolicy(String resourceIdentifier, 
RequestAction action) throws AuthorizationAccessException {
-        return authorizationsHolder.get().getAccessPolicy(resourceIdentifier, 
action);
+        return AccessPolicyProviderUtils.getAccessPolicy(
+                resourceIdentifier, action, 
authorizationsHolder.get().getPoliciesByResource());
     }
 
     @Override
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAuthorizer.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAuthorizer.java
index 1bbac9471a..8620299adb 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAuthorizer.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAuthorizer.java
@@ -253,7 +253,8 @@ public class FileAuthorizer extends 
AbstractPolicyBasedAuthorizer {
         return new UsersAndAccessPolicies() {
             @Override
             public AccessPolicy getAccessPolicy(String resourceIdentifier, 
RequestAction action) {
-                return 
authorizationsHolder.getAccessPolicy(resourceIdentifier, action);
+                return AccessPolicyProviderUtils.getAccessPolicy(
+                        resourceIdentifier, action, 
authorizationsHolder.getPoliciesByResource());
             }
 
             @Override
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/UserGroupHolder.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/UserGroupHolder.java
index 9257cd84b9..1661cc3186 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/UserGroupHolder.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/UserGroupHolder.java
@@ -22,9 +22,9 @@ import 
org.apache.nifi.registry.security.authorization.file.tenants.generated.Te
 import 
org.apache.nifi.registry.security.authorization.file.tenants.generated.Users;
 import org.apache.nifi.registry.security.authorization.Group;
 import org.apache.nifi.registry.security.authorization.User;
+import 
org.apache.nifi.registry.security.authorization.util.UserGroupProviderUtils;
 
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -61,16 +61,20 @@ public class UserGroupHolder {
         final Set<Group> allGroups = 
Collections.unmodifiableSet(createGroups(groups, users));
 
         // create a convenience map to retrieve a user by id
-        final Map<String, User> userByIdMap = 
Collections.unmodifiableMap(createUserByIdMap(allUsers));
+        final Map<String, User> userByIdMap = Collections.unmodifiableMap(
+                UserGroupProviderUtils.createUserByIdMap(allUsers));
 
         // create a convenience map to retrieve a user by identity
-        final Map<String, User> userByIdentityMap = 
Collections.unmodifiableMap(createUserByIdentityMap(allUsers));
+        final Map<String, User> userByIdentityMap = 
Collections.unmodifiableMap(
+                UserGroupProviderUtils.createUserByIdentityMap(allUsers));
 
         // create a convenience map to retrieve a group by id
-        final Map<String, Group> groupByIdMap = 
Collections.unmodifiableMap(createGroupByIdMap(allGroups));
+        final Map<String, Group> groupByIdMap = Collections.unmodifiableMap(
+                UserGroupProviderUtils.createGroupByIdMap(allGroups));
 
         // create a convenience map to retrieve the groups for a user identity
-        final Map<String, Set<Group>> groupsByUserIdentityMap = 
Collections.unmodifiableMap(createGroupsByUserIdentityMap(allGroups, allUsers));
+        final Map<String, Set<Group>> groupsByUserIdentityMap = 
Collections.unmodifiableMap(
+                
UserGroupProviderUtils.createGroupsByUserIdentityMap(allGroups, allUsers));
 
         // set all the holders
         this.allUsers = allUsers;
@@ -132,74 +136,6 @@ public class UserGroupHolder {
         return allGroups;
     }
 
-    /**
-     * Creates a Map from user identifier to User.
-     *
-     * @param users the set of all users
-     * @return the Map from user identifier to User
-     */
-    private Map<String, User> createUserByIdMap(final Set<User> users) {
-        Map<String, User> usersMap = new HashMap<>();
-        for (User user : users) {
-            usersMap.put(user.getIdentifier(), user);
-        }
-        return usersMap;
-    }
-
-    /**
-     * Creates a Map from user identity to User.
-     *
-     * @param users the set of all users
-     * @return the Map from user identity to User
-     */
-    private Map<String, User> createUserByIdentityMap(final Set<User> users) {
-        Map<String, User> usersMap = new HashMap<>();
-        for (User user : users) {
-            usersMap.put(user.getIdentity(), user);
-        }
-        return usersMap;
-    }
-
-    /**
-     * Creates a Map from group identifier to Group.
-     *
-     * @param groups the set of all groups
-     * @return the Map from group identifier to Group
-     */
-    private Map<String, Group> createGroupByIdMap(final Set<Group> groups) {
-        Map<String, Group> groupsMap = new HashMap<>();
-        for (Group group : groups) {
-            groupsMap.put(group.getIdentifier(), group);
-        }
-        return groupsMap;
-    }
-
-    /**
-     * Creates a Map from user identity to the set of Groups for that identity.
-     *
-     * @param groups all groups
-     * @param users all users
-     * @return a Map from User identity to the set of Groups for that identity
-     */
-    private Map<String, Set<Group>> createGroupsByUserIdentityMap(final 
Set<Group> groups, final Set<User> users) {
-        Map<String, Set<Group>> groupsByUserIdentity = new HashMap<>();
-
-        for (User user : users) {
-            Set<Group> userGroups = new HashSet<>();
-            for (Group group : groups) {
-                for (String groupUser : group.getUsers()) {
-                    if (groupUser.equals(user.getIdentifier())) {
-                        userGroups.add(group);
-                    }
-                }
-            }
-
-            groupsByUserIdentity.put(user.getIdentity(), userGroups);
-        }
-
-        return groupsByUserIdentity;
-    }
-
     public Tenants getTenants() {
         return tenants;
     }
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/AccessPolicyProviderUtils.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/AccessPolicyProviderUtils.java
index 111afbc9e5..78c6cc23a3 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/AccessPolicyProviderUtils.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/AccessPolicyProviderUtils.java
@@ -17,8 +17,10 @@
 package org.apache.nifi.registry.security.authorization.util;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.security.authorization.AccessPolicy;
 import 
org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext;
 import org.apache.nifi.registry.security.authorization.Group;
+import org.apache.nifi.registry.security.authorization.RequestAction;
 import org.apache.nifi.registry.security.authorization.UserGroupProvider;
 import 
org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
 import org.apache.nifi.registry.security.identity.IdentityMapper;
@@ -26,6 +28,7 @@ import org.apache.nifi.registry.util.PropertyValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Optional;
@@ -136,6 +139,65 @@ public final class AccessPolicyProviderUtils {
         return group;
     }
 
+    /**
+     * Creates a Map from resource identifier to the set of policies for the 
given resource.
+     *
+     * @param allPolicies the set of all policies
+     * @return a map from resource identifier to policies
+     */
+    public static Map<String, Set<AccessPolicy>> createResourcePolicyMap(final 
Set<AccessPolicy> allPolicies) {
+        Map<String, Set<AccessPolicy>> resourcePolicies = new HashMap<>();
+
+        for (AccessPolicy policy : allPolicies) {
+            Set<AccessPolicy> policies = 
resourcePolicies.computeIfAbsent(policy.getResource(), k -> new HashSet<>());
+            policies.add(policy);
+        }
+
+        return resourcePolicies;
+    }
+
+    /**
+     * Creates a Map from policy identifier to AccessPolicy.
+     *
+     * @param policies the set of all access policies
+     * @return the Map from policy identifier to AccessPolicy
+     */
+    public static Map<String, AccessPolicy> createPoliciesByIdMap(final 
Set<AccessPolicy> policies) {
+        Map<String, AccessPolicy> policyMap = new HashMap<>();
+        for (AccessPolicy policy : policies) {
+            policyMap.put(policy.getIdentifier(), policy);
+        }
+        return policyMap;
+    }
+
+    /**
+     * Returns the access policy by resource identifier and request action 
from the map of policies
+     *
+     * @param resourceIdentifier the resource identifier
+     * @param action the request action
+     * @param policiesByResource the map from resource identifier to policies
+     * @return the access policy
+     */
+    public static AccessPolicy getAccessPolicy(
+            final String resourceIdentifier, final RequestAction action, final 
Map<String, Set<AccessPolicy>> policiesByResource) {
+        if (resourceIdentifier == null) {
+            throw new IllegalArgumentException("Resource Identifier cannot be 
null");
+        }
+
+        final Set<AccessPolicy> resourcePolicies = 
policiesByResource.get(resourceIdentifier);
+        if (resourcePolicies == null) {
+            return null;
+        }
+
+        for (AccessPolicy accessPolicy : resourcePolicies) {
+            if (accessPolicy.getAction() == action) {
+                return accessPolicy;
+            }
+        }
+
+        return null;
+    }
+
     private AccessPolicyProviderUtils() {
 
     }
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/UserGroupProviderUtils.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/UserGroupProviderUtils.java
index f2890287be..71238fc326 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/UserGroupProviderUtils.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/util/UserGroupProviderUtils.java
@@ -18,8 +18,11 @@ package org.apache.nifi.registry.security.authorization.util;
 
 import org.apache.commons.lang3.StringUtils;
 import 
org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext;
+import org.apache.nifi.registry.security.authorization.Group;
+import org.apache.nifi.registry.security.authorization.User;
 import org.apache.nifi.registry.security.identity.IdentityMapper;
 
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -45,6 +48,74 @@ public final class UserGroupProviderUtils {
         return initialUserIdentities;
     }
 
+    /**
+     * Creates a Map from user identifier to User.
+     *
+     * @param users the set of all users
+     * @return the Map from user identifier to User
+     */
+    public static Map<String, User> createUserByIdMap(final Set<User> users) {
+        Map<String, User> usersMap = new HashMap<>();
+        for (User user : users) {
+            usersMap.put(user.getIdentifier(), user);
+        }
+        return usersMap;
+    }
+
+    /**
+     * Creates a Map from user identity to User.
+     *
+     * @param users the set of all users
+     * @return the map from user identity to User
+     */
+    public static Map<String, User> createUserByIdentityMap(final Set<User> 
users) {
+        Map<String, User> usersMap = new HashMap<>();
+        for (User user : users) {
+            usersMap.put(user.getIdentity(), user);
+        }
+        return usersMap;
+    }
+
+    /**
+     * Creates a Map from group identifier to Group.
+     *
+     * @param groups the set of all groups
+     * @return the map from group identifier to Group
+     */
+    public static Map<String, Group> createGroupByIdMap(final Set<Group> 
groups) {
+        Map<String, Group> groupsMap = new HashMap<>();
+        for (Group group : groups) {
+            groupsMap.put(group.getIdentifier(), group);
+        }
+        return groupsMap;
+    }
+
+    /**
+     * Creates a Map from user identity to the set of Groups for that identity.
+     *
+     * @param groups all groups
+     * @param users all users
+     * @return a Map from User identity to the set of Groups for that identity
+     */
+    public static Map<String, Set<Group>> createGroupsByUserIdentityMap(final 
Set<Group> groups, final Set<User> users) {
+        Map<String, Set<Group>> groupsByUserIdentity = new HashMap<>();
+
+        for (User user : users) {
+            Set<Group> userGroups = new HashSet<>();
+            for (Group group : groups) {
+                for (String groupUser : group.getUsers()) {
+                    if (groupUser.equals(user.getIdentifier())) {
+                        userGroups.add(group);
+                    }
+                }
+            }
+
+            groupsByUserIdentity.put(user.getIdentity(), userGroups);
+        }
+
+        return groupsByUserIdentity;
+    }
+
     private UserGroupProviderUtils() {
 
     }
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/TenantHolder.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/TenantHolder.java
index 413984516a..bd243c2fde 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/TenantHolder.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/TenantHolder.java
@@ -19,10 +19,10 @@ package org.apache.nifi.registry.security.ldap.tenants;
 
 import org.apache.nifi.registry.security.authorization.Group;
 import org.apache.nifi.registry.security.authorization.User;
+import 
org.apache.nifi.registry.security.authorization.util.UserGroupProviderUtils;
 
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -53,7 +53,8 @@ public class TenantHolder {
         final Map<String, Group> groupByIdMap = 
Collections.unmodifiableMap(createGroupByIdMap(allGroups));
 
         // create a convenience map to retrieve the groups for a user identity
-        final Map<String, Set<Group>> groupsByUserIdentityMap = 
Collections.unmodifiableMap(createGroupsByUserIdentityMap(allGroups, allUsers));
+        final Map<String, Set<Group>> groupsByUserIdentityMap = 
Collections.unmodifiableMap(
+                
UserGroupProviderUtils.createGroupsByUserIdentityMap(allGroups, allUsers));
 
         // set all the holders
         this.allUsers = allUsers;
@@ -106,32 +107,6 @@ public class TenantHolder {
         return groupsMap;
     }
 
-    /**
-     * Creates a Map from user identity to the set of Groups for that identity.
-     *
-     * @param groups all groups
-     * @param users all users
-     * @return a Map from User identity to the set of Groups for that identity
-     */
-    private Map<String, Set<Group>> createGroupsByUserIdentityMap(final 
Set<Group> groups, final Set<User> users) {
-        Map<String, Set<Group>> groupsByUserIdentity = new HashMap<>();
-
-        for (User user : users) {
-            Set<Group> userGroups = new HashSet<>();
-            for (Group group : groups) {
-                for (String groupUser : group.getUsers()) {
-                    if (groupUser.equals(user.getIdentifier())) {
-                        userGroups.add(group);
-                    }
-                }
-            }
-
-            groupsByUserIdentity.put(user.getIdentity(), userGroups);
-        }
-
-        return groupsByUserIdentity;
-    }
-
     Set<User> getAllUsers() {
         return allUsers;
     }
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseAccessPolicyProvider.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseAccessPolicyProvider.java
index ba14642011..c3d7ab362c 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseAccessPolicyProvider.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseAccessPolicyProvider.java
@@ -172,18 +172,6 @@ public class TestDatabaseAccessPolicyProvider extends 
DatabaseBaseTest {
         assertEquals(1, rowsUpdated);
     }
 
-    private void addUserToPolicy(final String policyIdentifier, final String 
userIdentifier) {
-        final String policyUserSql = "INSERT INTO 
APP_POLICY_USER(POLICY_IDENTIFIER, USER_IDENTIFIER) VALUES (?, ?)";
-        final int rowsUpdated = jdbcTemplate.update(policyUserSql, 
policyIdentifier, userIdentifier);
-        assertEquals(1, rowsUpdated);
-    }
-
-    private void addGroupToPolicy(final String policyIdentifier, final String 
groupIdentifier) {
-        final String policyGroupSql = "INSERT INTO 
APP_POLICY_GROUP(POLICY_IDENTIFIER, GROUP_IDENTIFIER) VALUES (?, ?)";
-        final int rowsUpdated = jdbcTemplate.update(policyGroupSql, 
policyIdentifier, groupIdentifier);
-        assertEquals(1, rowsUpdated);
-    }
-
     // -- Test onConfigured
 
     @Test
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
index fbf5d544cc..39d9042da3 100644
--- 
a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
@@ -102,32 +102,6 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
         assertEquals(1, updatedRows1);
     }
 
-    /**
-     * Helper method to create a group outside of the provider.
-     *
-     * @param groupIdentifier the group identifier
-     * @param groupIdentity the group identity
-     */
-    private void createGroup(final String groupIdentifier, final String 
groupIdentity) {
-        final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
-        final String sql = "INSERT INTO UGP_GROUP(IDENTIFIER, IDENTITY) VALUES 
(?, ?)";
-        final int updatedRows1 = jdbcTemplate.update(sql, groupIdentifier, 
groupIdentity);
-        assertEquals(1, updatedRows1);
-    }
-
-    /**
-     * Helper method to add a user to a group outside of the provider
-     *
-     * @param userIdentifier the user identifier
-     * @param groupIdentifier the group identifier
-     */
-    private void addUserToGroup(final String userIdentifier, final String 
groupIdentifier) {
-        final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
-        final String sql = "INSERT INTO UGP_USER_GROUP(USER_IDENTIFIER, 
GROUP_IDENTIFIER) VALUES (?, ?)";
-        final int updatedRows1 = jdbcTemplate.update(sql, userIdentifier, 
groupIdentifier);
-        assertEquals(1, updatedRows1);
-    }
-
     // -- Test onConfigured
 
     @Test
@@ -232,7 +206,8 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         final String userIdentifier = UUID.randomUUID().toString();
         final String userIdentity = "user1";
-        createUser(userIdentifier, userIdentity);
+        final User user1 = new 
User.Builder().identifier(userIdentifier).identity(userIdentity).build();
+        userGroupProvider.addUser(user1);
 
         final User retrievedUser1 = userGroupProvider.getUser(userIdentifier);
         assertNotNull(retrievedUser1);
@@ -254,7 +229,8 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         final String userIdentifier = UUID.randomUUID().toString();
         final String userIdentity = "user1";
-        createUser(userIdentifier, userIdentity);
+        final User user1 = new 
User.Builder().identifier(userIdentifier).identity(userIdentity).build();
+        userGroupProvider.addUser(user1);
 
         final User retrievedUser1 = 
userGroupProvider.getUserByIdentity(userIdentity);
         assertNotNull(retrievedUser1);
@@ -276,21 +252,25 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         // Create some users...
         final User user1 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user1").build();
-        createUser(user1.getIdentifier(), user1.getIdentity());
+        userGroupProvider.addUser(user1);
 
         final User user2 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user2").build();
-        createUser(user2.getIdentifier(), user2.getIdentity());
+        userGroupProvider.addUser(user2);
 
         // Create some groups...
-        final Group group1 = new 
Group.Builder().identifier(UUID.randomUUID().toString()).name("group1").build();
-        createGroup(group1.getIdentifier(), group1.getName());
-
-        final Group group2 = new 
Group.Builder().identifier(UUID.randomUUID().toString()).name("group2").build();
-        createGroup(group2.getIdentifier(), group2.getName());
+        final Group group1 = new Group.Builder()
+                .identifier(UUID.randomUUID().toString())
+                .name("group1")
+                .addUser(user1.getIdentifier())
+                .build();
+        userGroupProvider.addGroup(group1);
 
-        // Add users to groups...
-        addUserToGroup(user1.getIdentifier(), group1.getIdentifier());
-        addUserToGroup(user2.getIdentifier(), group2.getIdentifier());
+        final Group group2 = new Group.Builder()
+                .identifier(UUID.randomUUID().toString())
+                .name("group2")
+                .addUser(user2.getIdentifier())
+                .build();
+        userGroupProvider.addGroup(group2);
 
         // Retrieve UserAndGroups...
         final UserAndGroups user1AndGroups = 
userGroupProvider.getUserAndGroups(user1.getIdentity());
@@ -331,7 +311,7 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
         configureWithInitialUsers();
 
         final User user1 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user1").build();
-        createUser(user1.getIdentifier(), user1.getIdentity());
+        userGroupProvider.addUser(user1);
 
         final User retrievedUser1 = 
userGroupProvider.getUser(user1.getIdentifier());
         assertNotNull(retrievedUser1);
@@ -425,7 +405,8 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         final String user1Identifier = UUID.randomUUID().toString();
         final String user1Identity = "user1";
-        createUser(user1Identifier, user1Identity);
+        final User user1 = new 
User.Builder().identifier(user1Identifier).identity(user1Identity).build();
+        userGroupProvider.addUser(user1);
 
         final Set<Group> groupsBefore = userGroupProvider.getGroups();
         assertEquals(0, groupsBefore.size());
@@ -456,15 +437,16 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         final String group1Identifier = UUID.randomUUID().toString();
         final String group1Identity = "group1";
-        createGroup(group1Identifier, group1Identity);
+        final Group group1 = new 
Group.Builder().identifier(group1Identifier).name("group1").build();
+        userGroupProvider.addGroup(group1);
 
-        final Group group1 = userGroupProvider.getGroup(group1Identifier);
-        assertNotNull(group1);
-        assertEquals(group1Identifier, group1.getIdentifier());
-        assertEquals(group1Identity, group1.getName());
+        final Group retrievedGroup1 = 
userGroupProvider.getGroup(group1Identifier);
+        assertNotNull(retrievedGroup1);
+        assertEquals(group1Identifier, retrievedGroup1.getIdentifier());
+        assertEquals(group1Identity, retrievedGroup1.getName());
 
-        assertNotNull(group1.getUsers());
-        assertEquals(0, group1.getUsers().size());
+        assertNotNull(retrievedGroup1.getUsers());
+        assertEquals(0, retrievedGroup1.getUsers().size());
     }
 
     @Test
@@ -481,15 +463,18 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         // Create some users...
         final User user1 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user1").build();
-        createUser(user1.getIdentifier(), user1.getIdentity());
+        userGroupProvider.addUser(user1);
 
         final User user2 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user2").build();
-        createUser(user2.getIdentifier(), user2.getIdentity());
+        userGroupProvider.addUser(user2);
 
         // Create a group and add user1 to it...
-        final Group group1 = new 
Group.Builder().identifier(UUID.randomUUID().toString()).name("group1").build();
-        createGroup(group1.getIdentifier(), group1.getName());
-        addUserToGroup(user1.getIdentifier(), group1.getIdentifier());
+        final Group group1 = new Group.Builder()
+                .identifier(UUID.randomUUID().toString())
+                .name("group1")
+                .addUser(user1.getIdentifier())
+                .build();
+        userGroupProvider.addGroup(group1);
 
         // Retrieve the created group...
         final Group retrievedGroup1 = 
userGroupProvider.getGroup(group1.getIdentifier());
@@ -528,15 +513,18 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         // Create some users...
         final User user1 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user1").build();
-        createUser(user1.getIdentifier(), user1.getIdentity());
+        userGroupProvider.addUser(user1);
 
         final User user2 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user2").build();
-        createUser(user2.getIdentifier(), user2.getIdentity());
+        userGroupProvider.addUser(user2);
 
         // Create a group and add user1 to it...
-        final Group group1 = new 
Group.Builder().identifier(UUID.randomUUID().toString()).name("group1").build();
-        createGroup(group1.getIdentifier(), group1.getName());
-        addUserToGroup(user1.getIdentifier(), group1.getIdentifier());
+        final Group group1 = new Group.Builder()
+                .identifier(UUID.randomUUID().toString())
+                .name("group1")
+                .addUser(user1.getIdentifier())
+                .build();
+        userGroupProvider.addGroup(group1);
 
         // Retrieve the created group...
         final Group retrievedGroup1 = 
userGroupProvider.getGroup(group1.getIdentifier());
@@ -567,15 +555,18 @@ public class TestDatabaseUserGroupProvider extends 
DatabaseBaseTest {
 
         // Create some users...
         final User user1 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user1").build();
-        createUser(user1.getIdentifier(), user1.getIdentity());
+        userGroupProvider.addUser(user1);
 
         final User user2 = new 
User.Builder().identifier(UUID.randomUUID().toString()).identity("user2").build();
-        createUser(user2.getIdentifier(), user2.getIdentity());
+        userGroupProvider.addUser(user2);
 
         // Create a group and add user1 to it...
-        final Group group1 = new 
Group.Builder().identifier(UUID.randomUUID().toString()).name("group1").build();
-        createGroup(group1.getIdentifier(), group1.getName());
-        addUserToGroup(user1.getIdentifier(), group1.getIdentifier());
+        final Group group1 = new Group.Builder()
+                .identifier(UUID.randomUUID().toString())
+                .name("group1")
+                .addUser(user1.getIdentifier())
+                .build();
+        userGroupProvider.addGroup(group1);
 
         // Retrieve the created group...
         final Group retrievedGroup1 = 
userGroupProvider.getGroup(group1.getIdentifier());

Reply via email to