You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2016/04/07 22:23:35 UTC

[7/9] nifi git commit: Revert "NIFI-1551:"

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
index 8c86226..bb85b6f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetOrCreateKeyAction.java
@@ -17,6 +17,8 @@
 package org.apache.nifi.admin.service.action;
 
 import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.authorization.AuthorityProvider;
+
 import org.apache.nifi.admin.dao.KeyDAO;
 import org.apache.nifi.key.Key;
 
@@ -32,7 +34,7 @@ public class GetOrCreateKeyAction implements AdministrationAction<Key> {
     }
 
     @Override
-    public Key execute(DAOFactory daoFactory) {
+    public Key execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
         final KeyDAO keyDao = daoFactory.getKeyDAO();
 
         Key key = keyDao.findLatestKeyByIdentity(identity);

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetPreviousValues.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetPreviousValues.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetPreviousValues.java
index 337643f..569439b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetPreviousValues.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetPreviousValues.java
@@ -16,13 +16,13 @@
  */
 package org.apache.nifi.admin.service.action;
 
+import java.util.List;
+import java.util.Map;
 import org.apache.nifi.admin.dao.ActionDAO;
 import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.authorization.AuthorityProvider;
 import org.apache.nifi.history.PreviousValue;
 
-import java.util.List;
-import java.util.Map;
-
 /**
  * Gets the action with the specified id.
  */
@@ -35,7 +35,7 @@ public class GetPreviousValues implements AdministrationAction<Map<String, List<
     }
 
     @Override
-    public Map<String, List<PreviousValue>> execute(DAOFactory daoFactory) {
+    public Map<String, List<PreviousValue>> execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
         ActionDAO actionDao = daoFactory.getActionDAO();
         return actionDao.getPreviousValues(componentId);
     }

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUserGroupAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUserGroupAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUserGroupAction.java
new file mode 100644
index 0000000..5377c46
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUserGroupAction.java
@@ -0,0 +1,50 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.user.NiFiUserGroup;
+
+/**
+ *
+ */
+public class GetUserGroupAction implements AdministrationAction<NiFiUserGroup> {
+
+    private final String group;
+
+    public GetUserGroupAction(String group) {
+        this.group = group;
+    }
+
+    @Override
+    public NiFiUserGroup execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        final UserDAO userDAO = daoFactory.getUserDAO();
+        final NiFiUserGroup userGroup = new NiFiUserGroup();
+
+        // set the group
+        userGroup.setGroup(group);
+
+        // get the users in this group
+        userGroup.setUsers(userDAO.findUsersForGroup(group));
+
+        // return the group
+        return userGroup;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUsersAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUsersAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUsersAction.java
new file mode 100644
index 0000000..42d180e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/GetUsersAction.java
@@ -0,0 +1,39 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Collection;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.user.NiFiUser;
+
+/**
+ *
+ */
+public class GetUsersAction implements AdministrationAction<Collection<NiFiUser>> {
+
+    @Override
+    public Collection<NiFiUser> execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        // get a UserDAO
+        UserDAO userDAO = daoFactory.getUserDAO();
+
+        // return the desired user
+        return userDAO.findUsers();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/HasPendingUserAccounts.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/HasPendingUserAccounts.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/HasPendingUserAccounts.java
new file mode 100644
index 0000000..3325642
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/HasPendingUserAccounts.java
@@ -0,0 +1,34 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.AuthorityProvider;
+
+/**
+ * Action for creating a NiFiUser account.
+ */
+public class HasPendingUserAccounts extends AbstractUserAction<Boolean> {
+
+    @Override
+    public Boolean execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+        return userDao.hasPendingUserAccounts();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserAccountAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserAccountAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserAccountAction.java
new file mode 100644
index 0000000..14596b2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserAccountAction.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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.user.NiFiUser;
+
+/**
+ * Invalidates a user account.
+ */
+public class InvalidateUserAccountAction implements AdministrationAction<Void> {
+
+    private final String id;
+
+    public InvalidateUserAccountAction(String id) {
+        this.id = id;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+
+        // get the current user details
+        NiFiUser user = userDao.findUserById(id);
+
+        // ensure the user exists
+        if (user == null) {
+            throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", id));
+        }
+
+        // invalidate the user account
+        user.setLastVerified(null);
+
+        // create the user entry
+        userDao.updateUser(user);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserGroupAccountsAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserGroupAccountsAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserGroupAccountsAction.java
new file mode 100644
index 0000000..0cb7e14
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/InvalidateUserGroupAccountsAction.java
@@ -0,0 +1,45 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.AuthorityProvider;
+
+/**
+ * Invalidates a user account.
+ */
+public class InvalidateUserGroupAccountsAction implements AdministrationAction<Void> {
+
+    private final String group;
+
+    public InvalidateUserGroupAccountsAction(String group) {
+        this.group = group;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+
+        // create the user entry
+        userDao.updateGroupVerification(group, null);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/PurgeActionsAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/PurgeActionsAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/PurgeActionsAction.java
index 9d970dc..6928e0d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/PurgeActionsAction.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/PurgeActionsAction.java
@@ -19,6 +19,7 @@ package org.apache.nifi.admin.service.action;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.admin.dao.ActionDAO;
 import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.authorization.AuthorityProvider;
 
 import java.util.Date;
 
@@ -36,7 +37,7 @@ public class PurgeActionsAction implements AdministrationAction<Void> {
     }
 
     @Override
-    public Void execute(DAOFactory daoFactory) {
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
         ActionDAO actionDao = daoFactory.getActionDAO();
 
         // remove the corresponding actions

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/RequestUserAccountAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/RequestUserAccountAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/RequestUserAccountAction.java
new file mode 100644
index 0000000..198a32d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/RequestUserAccountAction.java
@@ -0,0 +1,67 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Date;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.security.util.CertificateUtils;
+import org.apache.nifi.user.AccountStatus;
+import org.apache.nifi.user.NiFiUser;
+
+/**
+ *
+ */
+public class RequestUserAccountAction implements AdministrationAction<NiFiUser> {
+
+    private final String identity;
+    private final String justification;
+
+    public RequestUserAccountAction(String identity, String justification) {
+        this.identity = identity;
+        this.justification = justification;
+    }
+
+    @Override
+    public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+
+        // determine if this user already exists
+        NiFiUser user = userDao.findUserByDn(identity);
+        if (user != null) {
+            throw new IllegalArgumentException(String.format("User account for %s already exists.", identity));
+        }
+
+        // create the user
+        user = new NiFiUser();
+        user.setIdentity(identity);
+        user.setUserName(CertificateUtils.extractUsername(identity));
+        user.setJustification(justification);
+        user.setStatus(AccountStatus.PENDING);
+
+        // update user timestamps
+        Date now = new Date();
+        user.setCreation(now);
+
+        // create the new user account
+        userDao.createUser(user);
+
+        return user;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/SeedUserAccountsAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/SeedUserAccountsAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/SeedUserAccountsAction.java
new file mode 100644
index 0000000..c16cc71
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/SeedUserAccountsAction.java
@@ -0,0 +1,164 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.security.util.CertificateUtils;
+import org.apache.nifi.user.AccountStatus;
+import org.apache.nifi.user.NiFiUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Seeds the user accounts. This action is performed at start up because it
+ * takes the users specified in the authority provider and makes them available
+ * to be seen in the UI. This happens because the UI loads the users from the
+ * cache. Without pre loading the users, the table in the UI would only show a
+ * given user once they have visited the application.
+ */
+public class SeedUserAccountsAction extends AbstractUserAction<Void> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SeedUserAccountsAction.class);
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+        Set<String> authorizedIdentities = new HashSet<>();
+
+        // get the current user cache
+        final Set<NiFiUser> existingUsers;
+        try {
+            existingUsers = userDao.findUsers();
+        } catch (Exception e) {
+            // unable to access local cache... start up failure
+            logger.error(String.format("Unable to get existing user base. Cannot proceed until these users can be "
+                    + "verified against the current authority provider: %s", e));
+            throw new AdministrationException(e);
+        }
+
+        try {
+            // all users for all roles
+            for (final Authority authority : Authority.values()) {
+                authorizedIdentities.addAll(authorityProvider.getUsers(authority));
+            }
+        } catch (AuthorityAccessException aae) {
+            // unable to access the authority provider... honor the cache
+            logger.warn("Unable to access authority provider due to " + aae);
+            return null;
+        }
+
+        final Set<NiFiUser> accountsToRevoke = new HashSet<>(existingUsers);
+
+        // persist the users
+        for (String identity : authorizedIdentities) {
+            NiFiUser user = null;
+            try {
+                // locate the user for this dn
+                user = userDao.findUserByDn(identity);
+                boolean newAccount = false;
+
+                // if the user does not exist, create a new account
+                if (user == null) {
+                    logger.info(String.format("Creating user account: %s", identity));
+                    newAccount = true;
+
+                    // create the user
+                    user = new NiFiUser();
+                    user.setIdentity(identity);
+                    user.setUserName(CertificateUtils.extractUsername(identity));
+                    user.setJustification("User details specified by authority provider.");
+                } else {
+                    logger.info(String.format("User account already created: %s. Updating authorities...", identity));
+                }
+
+                // verify the account
+                verifyAccount(authorityProvider, user);
+
+                // persist the account accordingly
+                if (newAccount) {
+                    CreateUserAction createUser = new CreateUserAction(user);
+                    createUser.execute(daoFactory, authorityProvider);
+                } else {
+                    // this is not a new user and we have just verified their
+                    // account, do not revoke...
+                    accountsToRevoke.remove(user);
+
+                    // persist the user
+                    UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
+                    updateUser.execute(daoFactory, authorityProvider);
+
+                    // persist the user's authorities
+                    UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
+                    updateUserAuthorities.execute(daoFactory, authorityProvider);
+                }
+            } catch (DataAccessException dae) {
+                if (user != null) {
+                    logger.warn(String.format("Unable to access account details in local cache for user %s: %s", user, dae.getMessage()));
+                } else {
+                    logger.warn(String.format("Unable to access account details in local cache: %s", dae.getMessage()));
+                }
+            } catch (UnknownIdentityException uie) {
+                if (user != null) {
+                    logger.warn(String.format("Unable to find account details in authority provider for user %s: %s", user, uie.getMessage()));
+                } else {
+                    logger.warn(String.format("Unable to find account details in authority provider: %s", uie.getMessage()));
+                }
+            } catch (AuthorityAccessException aae) {
+                logger.warn("Unable to access authority provider due to " + aae);
+
+                // unable to access authority provider for this user, honor the cache for now
+                accountsToRevoke.remove(user);
+            }
+        }
+
+        // remove all users that are no longer in the provider
+        for (final NiFiUser user : accountsToRevoke) {
+            // allow pending requests to remain...
+            if (AccountStatus.PENDING.equals(user.getStatus())) {
+                continue;
+            }
+
+            try {
+                logger.info(String.format("User not authorized with configured provider: %s. Disabling account...", user.getIdentity()));
+
+                // disable the account and reset its last verified timestamp since it was not found
+                // in the current configured authority provider
+                user.setStatus(AccountStatus.DISABLED);
+                user.setLastVerified(null);
+
+                // update the user record
+                UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
+                updateUser.execute(daoFactory, authorityProvider);
+            } catch (final Exception e) {
+                // unable to revoke access for someone we know is not authorized... fail start up
+                logger.error(String.format("Unable to revoke access for user %s that is no longer authorized: %s", user, e));
+                throw new AdministrationException(e);
+            }
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserAction.java
new file mode 100644
index 0000000..2604a47
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserAction.java
@@ -0,0 +1,69 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.user.NiFiUser;
+
+/**
+ *
+ */
+public class UngroupUserAction extends AbstractUserAction<Void> {
+
+    private final String userId;
+
+    public UngroupUserAction(String userId) {
+        this.userId = userId;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
+        final UserDAO userDao = daoFactory.getUserDAO();
+
+        // get the user in question
+        final NiFiUser user = userDao.findUserById(userId);
+
+        // ensure the user exists
+        if (user == null) {
+            throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", userId));
+        }
+
+        // set the user group
+        user.setUserGroup(null);
+
+        // update the user locally
+        userDao.updateUser(user);
+
+        try {
+            // update the authority provider
+            authorityProvider.ungroupUser(user.getIdentity());
+        } catch (UnknownIdentityException uie) {
+            throw new AccountNotFoundException(String.format("Unable to ungroup user '%s': %s", user.getIdentity(), uie.getMessage()), uie);
+        } catch (AuthorityAccessException aae) {
+            throw new AdministrationException(String.format("Unable to ungroup user '%s': %s", user.getIdentity(), aae.getMessage()), aae);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserGroupAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserGroupAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserGroupAction.java
new file mode 100644
index 0000000..fa24fbe
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UngroupUserGroupAction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+
+/**
+ *
+ */
+public class UngroupUserGroupAction extends AbstractUserAction<Void> {
+
+    private final String group;
+
+    public UngroupUserGroupAction(String group) {
+        this.group = group;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
+        final UserDAO userDao = daoFactory.getUserDAO();
+
+        // update the user locally
+        userDao.ungroup(group);
+
+        try {
+            // update the authority provider
+            authorityProvider.ungroup(group);
+        } catch (UnknownIdentityException uie) {
+            throw new AccountNotFoundException(String.format("Unable to ungroup '%s': %s", group, uie.getMessage()), uie);
+        } catch (AuthorityAccessException aae) {
+            throw new AdministrationException(String.format("Unable to ungroup '%s': %s", group, aae.getMessage()), aae);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAction.java
new file mode 100644
index 0000000..ecb91e6
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAction.java
@@ -0,0 +1,124 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Date;
+import java.util.Set;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.user.AccountStatus;
+import org.apache.nifi.user.NiFiUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sets user authorities.
+ */
+public class UpdateUserAction extends AbstractUserAction<NiFiUser> {
+
+    private static final Logger logger = LoggerFactory.getLogger(UpdateUserAction.class);
+
+    private final String id;
+    private final Set<Authority> authorities;
+
+    public UpdateUserAction(String id, Set<Authority> authorities) {
+        this.id = id;
+        this.authorities = authorities;
+    }
+
+    @Override
+    public NiFiUser execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException, AdministrationException {
+        UserDAO userDao = daoFactory.getUserDAO();
+
+        // get the user
+        NiFiUser user = userDao.findUserById(id);
+
+        // ensure the user exists
+        if (user == null) {
+            throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", id));
+        }
+
+        // determine whether this users exists
+        boolean doesIdentityExist = false;
+        try {
+            doesIdentityExist = authorityProvider.doesDnExist(user.getIdentity());
+        } catch (AuthorityAccessException aae) {
+            throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
+        }
+
+        // if the user already doesn't exist, add them
+        if (!doesIdentityExist) {
+            try {
+                // add the account account and group if necessary
+                authorityProvider.addUser(user.getIdentity(), user.getUserGroup());
+            } catch (final IdentityAlreadyExistsException iaee) {
+                logger.warn(String.format("User '%s' already exists in the authority provider.  Continuing with user update.", user.getIdentity()));
+            } catch (AuthorityAccessException aae) {
+                throw new AdministrationException(String.format("Unable to access authorities for '%s': %s", user.getIdentity(), aae.getMessage()), aae);
+            }
+        }
+
+        try {
+            // update the authority provider as approprivate
+            authorityProvider.setAuthorities(user.getIdentity(), authorities);
+        } catch (UnknownIdentityException uie) {
+            throw new AccountNotFoundException(String.format("Unable to modify authorities for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
+        } catch (AuthorityAccessException aae) {
+            throw new AdministrationException(String.format("Unable to access authorities for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
+        }
+
+        try {
+            // get the user group
+            user.setUserGroup(authorityProvider.getGroupForUser(user.getIdentity()));
+        } catch (UnknownIdentityException uie) {
+            throw new AccountNotFoundException(String.format("Unable to determine the group for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
+        } catch (AuthorityAccessException aae) {
+            throw new AdministrationException(String.format("Unable to access the group for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
+        }
+
+        // since all the authorities were updated accordingly, set the authorities
+        user.getAuthorities().clear();
+        user.getAuthorities().addAll(authorities);
+
+        // update the users status in case they were previously pending or disabled
+        user.setStatus(AccountStatus.ACTIVE);
+
+        // update the users last verified time - this timestamp shouldn't be recorded
+        // until the both the user's authorities and group have been synced
+        Date now = new Date();
+        user.setLastVerified(now);
+
+        // persist the user's updates
+        UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
+        updateUser.execute(daoFactory, authorityProvider);
+
+        // persist the user's authorities
+        UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
+        updateUserAuthorities.execute(daoFactory, authorityProvider);
+
+        // return the user
+        return user;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAuthoritiesCacheAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAuthoritiesCacheAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAuthoritiesCacheAction.java
new file mode 100644
index 0000000..89661b2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserAuthoritiesCacheAction.java
@@ -0,0 +1,73 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Set;
+import org.apache.nifi.admin.dao.AuthorityDAO;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.commons.collections4.CollectionUtils;
+
+/**
+ * Updates a NiFiUser's authorities. Prior to invoking this action, the user's
+ * authorities should be set according to the business logic of the service in
+ * question. This should not be invoked directly when attempting to set user
+ * authorities as the authorityProvider is not called from this action.
+ */
+public class UpdateUserAuthoritiesCacheAction extends AbstractUserAction<Void> {
+
+    private final NiFiUser user;
+
+    public UpdateUserAuthoritiesCacheAction(NiFiUser user) {
+        this.user = user;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+        AuthorityDAO authorityDao = daoFactory.getAuthorityDAO();
+
+        // get the user
+        NiFiUser currentUser = userDao.findUserById(user.getId());
+
+        // ensure the user exists
+        if (currentUser == null) {
+            throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", user.getId()));
+        }
+
+        // determine what authorities need to be added/removed
+        Set<Authority> authorities = user.getAuthorities();
+        Set<Authority> authoritiesToAdd = determineAuthoritiesToAdd(currentUser, authorities);
+        Set<Authority> authoritiesToRemove = determineAuthoritiesToRemove(currentUser, authorities);
+
+        // update the user authorities locally
+        if (CollectionUtils.isNotEmpty(authoritiesToAdd)) {
+            authorityDao.createAuthorities(authoritiesToAdd, user.getId());
+        }
+        if (CollectionUtils.isNotEmpty(authoritiesToRemove)) {
+            authorityDao.deleteAuthorities(authoritiesToRemove, user.getId());
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserCacheAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserCacheAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserCacheAction.java
new file mode 100644
index 0000000..288e297
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserCacheAction.java
@@ -0,0 +1,47 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.user.NiFiUser;
+
+/**
+ * Updates a NiFiUser. This will not update the user authorities, they must be
+ * updated with the UpdateUserAuthoritiesAction.
+ */
+public class UpdateUserCacheAction extends AbstractUserAction<Void> {
+
+    private final NiFiUser user;
+
+    public UpdateUserCacheAction(NiFiUser user) {
+        this.user = user;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        UserDAO userDao = daoFactory.getUserDAO();
+
+        // update the user
+        userDao.updateUser(user);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserGroupAction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserGroupAction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserGroupAction.java
new file mode 100644
index 0000000..1d7941f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/action/UpdateUserGroupAction.java
@@ -0,0 +1,171 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.user.AccountStatus;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Updates all NiFiUser authorities in a specified group.
+ */
+public class UpdateUserGroupAction extends AbstractUserAction<Void> {
+
+    private static final Logger logger = LoggerFactory.getLogger(UpdateUserGroupAction.class);
+
+    private final String group;
+    private final Set<String> userIds;
+    private final Set<Authority> authorities;
+
+    public UpdateUserGroupAction(String group, Set<String> userIds, Set<Authority> authorities) {
+        this.group = group;
+        this.userIds = userIds;
+        this.authorities = authorities;
+    }
+
+    @Override
+    public Void execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) throws DataAccessException {
+        if (userIds == null && authorities == null) {
+            throw new IllegalArgumentException("Must specify user Ids or authorities.");
+        }
+
+        UserDAO userDao = daoFactory.getUserDAO();
+
+        // record the new users being added to this group
+        final Set<NiFiUser> newUsers = new HashSet<>();
+        final Set<String> newUserIdentities = new HashSet<>();
+
+        // if the user ids have been specified we need to create/update a group using the specified group name
+        if (userIds != null) {
+            if (userIds.isEmpty()) {
+                throw new IllegalArgumentException("When creating a group, at least one user id must be specified.");
+            }
+
+            // going to create a group using the specified user ids
+            for (final String userId : userIds) {
+                // get the user in question
+                final NiFiUser user = userDao.findUserById(userId);
+
+                // ensure the user exists
+                if (user == null) {
+                    throw new AccountNotFoundException(String.format("Unable to find account with ID %s.", userId));
+                }
+
+                try {
+                    // if the user is unknown to the authority provider we cannot continue
+                    if (!authorityProvider.doesDnExist(user.getIdentity()) || AccountStatus.DISABLED.equals(user.getStatus())) {
+                        throw new IllegalStateException(String.format("Unable to group these users because access for '%s' is not %s.", user.getIdentity(), AccountStatus.ACTIVE.toString()));
+                    }
+
+                    // record the user being added to this group
+                    newUsers.add(user);
+                    newUserIdentities.add(user.getIdentity());
+                } catch (final AuthorityAccessException aae) {
+                    throw new AdministrationException(String.format("Unable to access authority details: %s", aae.getMessage()), aae);
+                }
+            }
+
+            try {
+                // update the authority provider
+                authorityProvider.setUsersGroup(newUserIdentities, group);
+            } catch (UnknownIdentityException uie) {
+                throw new AccountNotFoundException(String.format("Unable to set user group '%s': %s", StringUtils.join(newUserIdentities, ", "), uie.getMessage()), uie);
+            } catch (AuthorityAccessException aae) {
+                throw new AdministrationException(String.format("Unable to set user group '%s': %s", StringUtils.join(newUserIdentities, ", "), aae.getMessage()), aae);
+            }
+        }
+
+        // get all the users that need to be updated
+        final Set<NiFiUser> users = new HashSet<>(userDao.findUsersForGroup(group));
+        users.addAll(newUsers);
+
+        // ensure the user exists
+        if (users.isEmpty()) {
+            throw new AccountNotFoundException(String.format("Unable to find user accounts with group id %s.", group));
+        }
+
+        // update each user in this group
+        for (final NiFiUser user : users) {
+            // if there are new authorities set them, otherwise refresh them according to the provider
+            if (authorities != null) {
+                try {
+                    // update the authority provider as approprivate
+                    authorityProvider.setAuthorities(user.getIdentity(), authorities);
+
+                    // since all the authorities were updated accordingly, set the authorities
+                    user.getAuthorities().clear();
+                    user.getAuthorities().addAll(authorities);
+                } catch (UnknownIdentityException uie) {
+                    throw new AccountNotFoundException(String.format("Unable to modify authorities for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
+                } catch (AuthorityAccessException aae) {
+                    throw new AdministrationException(String.format("Unable to access authorities for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
+                }
+            } else {
+                try {
+                    // refresh the authorities according to the provider
+                    user.getAuthorities().clear();
+                    user.getAuthorities().addAll(authorityProvider.getAuthorities(user.getIdentity()));
+                } catch (UnknownIdentityException uie) {
+                    throw new AccountNotFoundException(String.format("Unable to determine the authorities for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
+                } catch (AuthorityAccessException aae) {
+                    throw new AdministrationException(String.format("Unable to access authorities for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
+                }
+            }
+
+            try {
+                // get the user group
+                user.setUserGroup(authorityProvider.getGroupForUser(user.getIdentity()));
+            } catch (UnknownIdentityException uie) {
+                throw new AccountNotFoundException(String.format("Unable to determine the group for '%s': %s.", user.getIdentity(), uie.getMessage()), uie);
+            } catch (AuthorityAccessException aae) {
+                throw new AdministrationException(String.format("Unable to access the group for '%s': %s.", user.getIdentity(), aae.getMessage()), aae);
+            }
+
+            // update the users status in case they were previously pending or disabled
+            user.setStatus(AccountStatus.ACTIVE);
+
+            // update the users last verified time - this timestamp shouldn't be recorded
+            // until the both the user's authorities and group have been synced
+            Date now = new Date();
+            user.setLastVerified(now);
+
+            // persist the user's updates
+            UpdateUserCacheAction updateUser = new UpdateUserCacheAction(user);
+            updateUser.execute(daoFactory, authorityProvider);
+
+            // persist the user's authorities
+            UpdateUserAuthoritiesCacheAction updateUserAuthorities = new UpdateUserAuthoritiesCacheAction(user);
+            updateUserAuthorities.execute(daoFactory, authorityProvider);
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardUserService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardUserService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardUserService.java
index b3f749c..c37a562 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardUserService.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/impl/StandardUserService.java
@@ -16,24 +16,53 @@
  */
 package org.apache.nifi.admin.service.impl;
 
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
 import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.service.AccountDisabledException;
+import org.apache.nifi.admin.service.AccountPendingException;
 import org.apache.nifi.admin.service.AdministrationException;
 import org.apache.nifi.admin.service.UserService;
+import org.apache.nifi.admin.service.action.AuthorizeDownloadAction;
+import org.apache.nifi.admin.service.action.AuthorizeUserAction;
 import org.apache.nifi.admin.service.action.DeleteKeysAction;
+import org.apache.nifi.admin.service.action.DeleteUserAction;
+import org.apache.nifi.admin.service.action.DisableUserAction;
+import org.apache.nifi.admin.service.action.DisableUserGroupAction;
+import org.apache.nifi.admin.service.action.FindUserByDnAction;
+import org.apache.nifi.admin.service.action.FindUserByIdAction;
 import org.apache.nifi.admin.service.action.GetKeyByIdAction;
 import org.apache.nifi.admin.service.action.GetOrCreateKeyAction;
+import org.apache.nifi.admin.service.action.GetUserGroupAction;
+import org.apache.nifi.admin.service.action.GetUsersAction;
+import org.apache.nifi.admin.service.action.HasPendingUserAccounts;
+import org.apache.nifi.admin.service.action.InvalidateUserAccountAction;
+import org.apache.nifi.admin.service.action.InvalidateUserGroupAccountsAction;
+import org.apache.nifi.admin.service.action.RequestUserAccountAction;
+import org.apache.nifi.admin.service.action.SeedUserAccountsAction;
+import org.apache.nifi.admin.service.action.UpdateUserAction;
+import org.apache.nifi.admin.service.action.UpdateUserGroupAction;
+import org.apache.nifi.admin.service.action.UngroupUserAction;
+import org.apache.nifi.admin.service.action.UngroupUserGroupAction;
 import org.apache.nifi.admin.service.transaction.Transaction;
 import org.apache.nifi.admin.service.transaction.TransactionBuilder;
 import org.apache.nifi.admin.service.transaction.TransactionException;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.authorization.DownloadAuthorization;
 import org.apache.nifi.key.Key;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.nifi.user.NiFiUserGroup;
+import org.apache.nifi.util.FormatUtils;
 import org.apache.nifi.util.NiFiProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
 /**
  *
  */
@@ -42,12 +71,553 @@ public class StandardUserService implements UserService {
     private static final Logger logger = LoggerFactory.getLogger(StandardUserService.class);
 
     private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
-    private final Lock readLock = lock.readLock();
-    private final Lock writeLock = lock.writeLock();
+    private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
+    private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
 
     private TransactionBuilder transactionBuilder;
     private NiFiProperties properties;
 
+    /**
+     * Seed any users from the authority provider that are not already present.
+     */
+    public void seedUserAccounts() {
+        // do not seed node's user cache. when/if the node disconnects its
+        // cache will be populated lazily (as needed)
+        if (properties.isNode()) {
+            return;
+        }
+
+        Transaction transaction = null;
+        writeLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // seed the accounts
+            SeedUserAccountsAction seedUserAccounts = new SeedUserAccountsAction();
+            transaction.execute(seedUserAccounts);
+
+            // commit the transaction
+            transaction.commit();
+        } catch (AdministrationException ae) {
+            rollback(transaction);
+            throw ae;
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUser createPendingUserAccount(String dn, String justification) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // create the account request
+            RequestUserAccountAction requestUserAccount = new RequestUserAccountAction(dn, justification);
+            NiFiUser user = transaction.execute(requestUserAccount);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the nifi user
+            return user;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUserGroup updateGroup(final String group, final Set<String> userIds, final Set<Authority> authorities) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // if user ids have been specified, invalidate the user accounts before performing
+            // the desired updates. if case of an error, this will ensure that these users are
+            // authorized the next time the access the application
+            if (userIds != null) {
+                for (final String userId : userIds) {
+                    invalidateUserAccount(userId);
+                }
+            }
+
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // set the authorities for each user in this group if specified
+            final UpdateUserGroupAction updateUserGroup = new UpdateUserGroupAction(group, userIds, authorities);
+            transaction.execute(updateUserGroup);
+
+            // get all the users that are now in this group
+            final GetUserGroupAction getUserGroup = new GetUserGroupAction(group);
+            final NiFiUserGroup userGroup = transaction.execute(getUserGroup);
+
+            // commit the transaction
+            transaction.commit();
+
+            return userGroup;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void ungroupUser(String id) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // ungroup the specified user
+            final UngroupUserAction ungroupUser = new UngroupUserAction(id);
+            transaction.execute(ungroupUser);
+
+            // commit the transaction
+            transaction.commit();
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void ungroup(String group) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // ungroup the specified user
+            final UngroupUserGroupAction ungroupUserGroup = new UngroupUserGroupAction(group);
+            transaction.execute(ungroupUserGroup);
+
+            // commit the transaction
+            transaction.commit();
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUser checkAuthorization(String dn) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // create the connection
+            transaction = transactionBuilder.start();
+
+            // determine how long the cache is valid for
+            final int cacheSeconds;
+            try {
+                cacheSeconds = (int) FormatUtils.getTimeDuration(properties.getUserCredentialCacheDuration(), TimeUnit.SECONDS);
+            } catch (IllegalArgumentException iae) {
+                throw new AdministrationException("User credential cache duration is not configured correctly.");
+            }
+
+            // attempt to authorize the user
+            AuthorizeUserAction authorizeUser = new AuthorizeUserAction(dn, cacheSeconds);
+            NiFiUser user = transaction.execute(authorizeUser);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the nifi user
+            return user;
+        } catch (DataAccessException | TransactionException dae) {
+            rollback(transaction);
+            throw new AdministrationException(dae);
+        } catch (AccountDisabledException | AccountPendingException ade) {
+            rollback(transaction);
+            throw ade;
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void deleteUser(String id) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // create the connection
+            transaction = transactionBuilder.start();
+
+            // delete the user
+            DeleteUserAction deleteUser = new DeleteUserAction(id);
+            transaction.execute(deleteUser);
+
+            // commit the transaction
+            transaction.commit();
+        } catch (DataAccessException | TransactionException dae) {
+            rollback(transaction);
+            throw new AdministrationException(dae);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUser disable(String id) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // create the connection
+            transaction = transactionBuilder.start();
+
+            // disable the user
+            DisableUserAction disableUser = new DisableUserAction(id);
+            NiFiUser user = transaction.execute(disableUser);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the user
+            return user;
+        } catch (DataAccessException | TransactionException dae) {
+            rollback(transaction);
+            throw new AdministrationException(dae);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUserGroup disableGroup(String group) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // create the connection
+            transaction = transactionBuilder.start();
+
+            // disable the user
+            DisableUserGroupAction disableUser = new DisableUserGroupAction(group);
+            NiFiUserGroup userGroup = transaction.execute(disableUser);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the user
+            return userGroup;
+        } catch (DataAccessException | TransactionException dae) {
+            rollback(transaction);
+            throw new AdministrationException(dae);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUser update(String id, Set<Authority> authorities) {
+        Transaction transaction = null;
+
+        // may be empty but not null
+        if (authorities == null) {
+            throw new IllegalArgumentException("The specified authorities cannot be null.");
+        }
+
+        writeLock.lock();
+        try {
+            // invalidate the user account in preparation for potential subsequent errors
+            invalidateUserAccount(id);
+
+            // at this point the current user account has been invalidated so we will
+            // attempt to update the account. if any part fails we are assured the
+            // user will be need to be given approval before they access the system at
+            // a later time
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // update the user authorities
+            UpdateUserAction setUserAuthorities = new UpdateUserAction(id, authorities);
+            NiFiUser user = transaction.execute(setUserAuthorities);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the user
+            return user;
+        } catch (TransactionException | DataAccessException e) {
+            rollback(transaction);
+            throw new AdministrationException(e);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Invalidates the user with the specified id. This is done to ensure a user account will need to be re-validated in case an error occurs while modifying a user account. This method should only be
+     * invoked from within a write lock.
+     *
+     * @param id user account identifier
+     */
+    @Override
+    public void invalidateUserAccount(String id) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // invalidate the user account
+            InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(id);
+            transaction.execute(invalidateUserAccount);
+
+            // commit the transaction
+            transaction.commit();
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void invalidateUserGroupAccount(String group) {
+        Transaction transaction = null;
+
+        writeLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // invalidate the user account
+            InvalidateUserGroupAccountsAction invalidateUserGroupAccounts = new InvalidateUserGroupAccountsAction(group);
+            transaction.execute(invalidateUserGroupAccounts);
+
+            // commit the transaction
+            transaction.commit();
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            writeLock.unlock();
+        }
+    }
+
+    // -----------------
+    // read only methods
+    // -----------------
+    @Override
+    public Boolean hasPendingUserAccount() {
+        Transaction transaction = null;
+
+        readLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            final HasPendingUserAccounts hasPendingAccounts = new HasPendingUserAccounts();
+            final Boolean hasPendingUserAccounts = transaction.execute(hasPendingAccounts);
+
+            // commit the transaction
+            transaction.commit();
+
+            return hasPendingUserAccounts;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public DownloadAuthorization authorizeDownload(final List<String> dnChain, final Map<String, String> attributes) {
+        Transaction transaction = null;
+
+        readLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // authorize the download
+            AuthorizeDownloadAction authorizeDownload = new AuthorizeDownloadAction(dnChain, attributes);
+            DownloadAuthorization downloadAuthorization = transaction.execute(authorizeDownload);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the authorization
+            return downloadAuthorization;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public Collection<NiFiUser> getUsers() {
+        Transaction transaction = null;
+
+        readLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // get all users
+            GetUsersAction getUsers = new GetUsersAction();
+            Collection<NiFiUser> users = transaction.execute(getUsers);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the users
+            return users;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUser getUserById(String id) {
+        Transaction transaction = null;
+
+        readLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // return the desired user
+            FindUserByIdAction findUserById = new FindUserByIdAction(id);
+            NiFiUser user = transaction.execute(findUserById);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the user
+            return user;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            readLock.unlock();
+        }
+    }
+
+    @Override
+    public NiFiUser getUserByDn(String dn) {
+        Transaction transaction = null;
+
+        readLock.lock();
+        try {
+            // start the transaction
+            transaction = transactionBuilder.start();
+
+            // return the desired user
+            FindUserByDnAction findUserByDn = new FindUserByDnAction(dn);
+            NiFiUser user = transaction.execute(findUserByDn);
+
+            // commit the transaction
+            transaction.commit();
+
+            // return the user
+            return user;
+        } catch (TransactionException | DataAccessException te) {
+            rollback(transaction);
+            throw new AdministrationException(te);
+        } catch (Throwable t) {
+            rollback(transaction);
+            throw t;
+        } finally {
+            closeQuietly(transaction);
+            readLock.unlock();
+        }
+    }
+
     @Override
     public Key getKey(int id) {
         Transaction transaction = null;

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransaction.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransaction.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransaction.java
index 1390768..a3cfb5e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransaction.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransaction.java
@@ -16,19 +16,19 @@
  */
 package org.apache.nifi.admin.service.transaction.impl;
 
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
 import org.apache.nifi.admin.RepositoryUtils;
 import org.apache.nifi.admin.dao.DAOFactory;
 import org.apache.nifi.admin.dao.impl.DAOFactoryImpl;
 import org.apache.nifi.admin.service.action.AdministrationAction;
-import org.apache.nifi.admin.service.transaction.Transaction;
 import org.apache.nifi.admin.service.transaction.TransactionException;
+import org.apache.nifi.admin.service.transaction.Transaction;
+import org.apache.nifi.authorization.AuthorityProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.SQLException;
-
 /**
  * Transaction implementation that uses the specified SQL Connection and
  * AuthorityProvider.
@@ -37,9 +37,11 @@ public class StandardTransaction implements Transaction {
 
     private static final Logger logger = LoggerFactory.getLogger(StandardTransaction.class);
 
+    private final AuthorityProvider authorityProvider;
     private Connection connection;
 
-    public StandardTransaction(Connection connection) {
+    public StandardTransaction(AuthorityProvider authorityProvider, Connection connection) {
+        this.authorityProvider = authorityProvider;
         this.connection = connection;
     }
 
@@ -54,7 +56,7 @@ public class StandardTransaction implements Transaction {
         DAOFactory daoFactory = new DAOFactoryImpl(connection);
 
         // execute the specified action
-        return action.execute(daoFactory);
+        return action.execute(daoFactory, authorityProvider);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransactionBuilder.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransactionBuilder.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransactionBuilder.java
index 7d4a1fc..b6e5a30 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransactionBuilder.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/admin/service/transaction/impl/StandardTransactionBuilder.java
@@ -22,6 +22,7 @@ import javax.sql.DataSource;
 import org.apache.nifi.admin.service.transaction.Transaction;
 import org.apache.nifi.admin.service.transaction.TransactionBuilder;
 import org.apache.nifi.admin.service.transaction.TransactionException;
+import org.apache.nifi.authorization.AuthorityProvider;
 
 /**
  *
@@ -29,6 +30,7 @@ import org.apache.nifi.admin.service.transaction.TransactionException;
 public class StandardTransactionBuilder implements TransactionBuilder {
 
     private DataSource dataSource;
+    private AuthorityProvider authorityProvider;
 
     @Override
     public Transaction start() throws TransactionException {
@@ -38,7 +40,7 @@ public class StandardTransactionBuilder implements TransactionBuilder {
             connection.setAutoCommit(false);
 
             // create a new transaction
-            return new StandardTransaction(connection);
+            return new StandardTransaction(authorityProvider, connection);
         } catch (SQLException sqle) {
             throw new TransactionException(sqle.getMessage());
         }
@@ -48,4 +50,8 @@ public class StandardTransactionBuilder implements TransactionBuilder {
     public void setDataSource(DataSource dataSource) {
         this.dataSource = dataSource;
     }
+
+    public void setAuthorityProvider(AuthorityProvider authorityProvider) {
+        this.authorityProvider = authorityProvider;
+    }
 }