Repository: nifi
Updated Branches:
  refs/heads/master 32facaedb -> f47be77b6


http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 382a8c2..5aaddcd 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -34,9 +34,12 @@ import org.apache.nifi.action.details.PurgeDetails;
 import org.apache.nifi.annotation.behavior.Stateful;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.authorization.AccessPolicy;
 import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.Group;
 import org.apache.nifi.authorization.RequestAction;
 import org.apache.nifi.authorization.Resource;
+import org.apache.nifi.authorization.User;
 import org.apache.nifi.authorization.resource.Authorizable;
 import org.apache.nifi.cluster.coordination.heartbeat.NodeHeartbeat;
 import org.apache.nifi.cluster.coordination.node.NodeConnectionStatus;
@@ -136,6 +139,8 @@ import 
org.apache.nifi.web.api.dto.status.ProcessorStatusSnapshotDTO;
 import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO;
 import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusSnapshotDTO;
 import org.apache.nifi.web.api.entity.FlowBreadcrumbEntity;
+import org.apache.nifi.web.api.entity.UserEntity;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
 import org.apache.nifi.web.controller.ControllerFacade;
 import org.apache.nifi.web.revision.RevisionManager;
 
@@ -676,6 +681,44 @@ public final class DtoFactory {
     }
 
     /**
+     * Creates a {@link UserDTO} from the specified {@link User}.
+     *
+     * @param user user
+     * @return dto
+     */
+    public UserDTO createUserDto(final User user, final Set<UserGroupEntity> 
groups) {
+        if (user == null) {
+            return null;
+        }
+
+        final UserDTO dto = new UserDTO();
+        dto.setId(user.getIdentifier());
+        dto.setGroups(groups);
+        dto.setIdentity(user.getIdentity());
+
+        return dto;
+    }
+
+    /**
+     * Creates a {@link UserGroupDTO} from the specified {@link Group}.
+     *
+     * @param userGroup user group
+     * @return dto
+     */
+    public UserGroupDTO createUserGroupDto(final Group userGroup, 
Set<UserEntity> users) {
+        if (userGroup == null) {
+            return null;
+        }
+
+        final UserGroupDTO dto = new UserGroupDTO();
+        dto.setId(userGroup.getIdentifier());
+        dto.setUsers(users);
+        dto.setName(userGroup.getName());
+
+        return dto;
+    }
+
+    /**
      * Creates a FunnelDTO from the specified Funnel.
      *
      * @param funnel funnel
@@ -1469,6 +1512,23 @@ public final class DtoFactory {
         return dto;
     }
 
+    public AccessPolicyDTO createAccessPolicyDto(final AccessPolicy 
accessPolicy, Set<UserGroupEntity> userGroups, Set<UserEntity> users) {
+        if (accessPolicy == null) {
+            return null;
+        }
+
+        final AccessPolicyDTO dto = new AccessPolicyDTO();
+        dto.setUserGroups(userGroups);
+        dto.setUsers(users);
+        dto.setId(accessPolicy.getIdentifier());
+        dto.setResource(accessPolicy.getResource());
+        Set<RequestAction> accessPolicyActions = accessPolicy.getActions();
+        dto.setCanRead(accessPolicyActions.contains(RequestAction.READ));
+        dto.setCanWrite(accessPolicyActions.contains(RequestAction.WRITE));
+
+        return dto;
+
+    }
     /**
      * Creates the AccessPolicyDTO based on the specified Authorizable.
      *

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
index e5c3d9c..fa5620a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
@@ -23,6 +23,7 @@ import org.apache.nifi.web.api.dto.status.PortStatusDTO;
 import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO;
 import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO;
 import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
 import org.apache.nifi.web.api.entity.ConnectionEntity;
 import org.apache.nifi.web.api.entity.ControllerConfigurationEntity;
 import org.apache.nifi.web.api.entity.ControllerServiceEntity;
@@ -38,6 +39,8 @@ import 
org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
 import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
 import org.apache.nifi.web.api.entity.ReportingTaskEntity;
 import org.apache.nifi.web.api.entity.SnippetEntity;
+import org.apache.nifi.web.api.entity.UserEntity;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
 
 import java.util.List;
 
@@ -144,6 +147,48 @@ public final class EntityFactory {
         return entity;
     }
 
+    public UserEntity createUserEntity(final UserDTO dto, final RevisionDTO 
revision, final AccessPolicyDTO accessPolicy) {
+        final UserEntity entity = new UserEntity();
+        entity.setRevision(revision);
+        if (dto != null) {
+            entity.setAccessPolicy(accessPolicy);
+            entity.setId(dto.getId());
+
+            if (accessPolicy != null && accessPolicy.getCanRead()) {
+                entity.setComponent(dto);
+            }
+        }
+        return entity;
+    }
+
+    public UserGroupEntity createUserGroupEntity(final UserGroupDTO dto, final 
RevisionDTO revision, final AccessPolicyDTO accessPolicy) {
+        final UserGroupEntity entity = new UserGroupEntity();
+        entity.setRevision(revision);
+        if (dto != null) {
+            entity.setAccessPolicy(accessPolicy);
+            entity.setId(dto.getId());
+
+            if (accessPolicy != null && accessPolicy.getCanRead()) {
+                entity.setComponent(dto);
+            }
+        }
+        return entity;
+    }
+
+    public AccessPolicyEntity createAccessPolicyEntity(final AccessPolicyDTO 
dto, final RevisionDTO revision, final AccessPolicyDTO accessPolicy) {
+        final AccessPolicyEntity entity = new AccessPolicyEntity();
+        entity.setRevision(revision);
+        if (dto != null) {
+            entity.setAccessPolicy(accessPolicy);
+            entity.setId(dto.getId());
+
+            if (accessPolicy != null && accessPolicy.getCanRead()) {
+                entity.setComponent(dto);
+            }
+        }
+        return entity;
+    }
+
     public FunnelEntity createFunnelEntity(final FunnelDTO dto, final 
RevisionDTO revision, final AccessPolicyDTO accessPolicy) {
         final FunnelEntity entity = new FunnelEntity();
         entity.setRevision(revision);

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
new file mode 100644
index 0000000..2c0dc80
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/AccessPolicyDAO.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.dao;
+
+import org.apache.nifi.authorization.AccessPolicy;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+
+public interface AccessPolicyDAO {
+
+    /**
+     * @param accessPolicyId access policy ID
+     * @return Determines if the specified access policy exists
+     */
+    boolean hasAccessPolicy(String accessPolicyId);
+
+    /**
+     * Creates an access policy.
+     *
+     * @param accessPolicyDTO The access policy DTO
+     * @return The access policy transfer object
+     */
+    AccessPolicy createAccessPolicy(AccessPolicyDTO accessPolicyDTO);
+
+    /**
+     * Gets the acess policy with the specified ID.
+     *
+     * @param accessPolicyId The access policy ID
+     * @return The access policy transfer object
+     */
+    AccessPolicy getAccessPolicy(String accessPolicyId);
+
+    /**
+     * Updates the specified access policy.
+     *
+     * @param accessPolicyDTO The access policy DTO
+     * @return The access policy transfer object
+     */
+    AccessPolicy updateAccessPolicy(AccessPolicyDTO accessPolicyDTO);
+
+    /**
+     * Deletes the specified access policy.
+     *
+     * @param accessPolicyId The access policy ID
+     * @return The access policy transfer object of the deleted access policy
+     */
+    AccessPolicy deleteAccessPolicy(String accessPolicyId);
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserDAO.java
new file mode 100644
index 0000000..a6d4bb4
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserDAO.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.dao;
+
+import org.apache.nifi.authorization.User;
+import org.apache.nifi.web.api.dto.UserDTO;
+
+public interface UserDAO {
+
+    /**
+     * @param userId user ID
+     * @return Determines if the specified user exists
+     */
+    boolean hasUser(String userId);
+
+    /**
+     * Creates a user.
+     *
+     * @param userDTO The user DTO
+     * @return The user transfer object
+     */
+    User createUser(UserDTO userDTO);
+
+    /**
+     * Gets the user with the specified ID.
+     *
+     * @param userId The user ID
+     * @return The user transfer object
+     */
+    User getUser(String userId);
+
+    /**
+     * Updates the specified user.
+     *
+     * @param userDTO The user DTO
+     * @return The user transfer object
+     */
+    User updateUser(UserDTO userDTO);
+
+    /**
+     * Deletes the specified user.
+     *
+     * @param userId The user ID
+     * @return The user transfer object of the deleted user
+     */
+    User deleteUser(String userId);
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java
new file mode 100644
index 0000000..878d16f
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.dao;
+
+import org.apache.nifi.authorization.Group;
+import org.apache.nifi.web.api.dto.UserGroupDTO;
+
+public interface UserGroupDAO {
+
+    /**
+     * @param userGroupId user group ID
+     * @return Determines if the specified user group exists
+     */
+    boolean hasUserGroup(String userGroupId);
+
+    /**
+     * Creates a user group.
+     *
+     * @param userGroupDTO The user group DTO
+     * @return The user group transfer object
+     */
+    Group createUserGroup(UserGroupDTO userGroupDTO);
+
+    /**
+     * Gets the user group with the specified ID.
+     *
+     * @param userGroupId The user group ID
+     * @return The user group transfer object
+     */
+    Group getUserGroup(String userGroupId);
+
+    /**
+     * Updates the specified user group.
+     *
+     * @param userGroupDTO The user group DTO
+     * @return The user group transfer object
+     */
+    Group updateUserGroup(UserGroupDTO userGroupDTO);
+
+    /**
+     * Deletes the specified user group.
+     *
+     * @param userGroupId The user group ID
+     * @return The user group transfer object of the deleted user group
+     */
+    Group deleteUserGroup(String userGroupId);
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
new file mode 100644
index 0000000..25cc5ac
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web.dao.impl;
+
+import org.apache.nifi.authorization.AbstractPolicyBasedAuthorizer;
+import org.apache.nifi.authorization.AccessPolicy;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.AuthorizerConfigurationContext;
+import org.apache.nifi.authorization.AuthorizerInitializationContext;
+import org.apache.nifi.authorization.Group;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.User;
+import org.apache.nifi.authorization.UsersAndAccessPolicies;
+import org.apache.nifi.authorization.exception.AuthorizationAccessException;
+import org.apache.nifi.authorization.exception.AuthorizerCreationException;
+import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+import org.apache.nifi.web.api.dto.UserDTO;
+import org.apache.nifi.web.api.dto.UserGroupDTO;
+import org.apache.nifi.web.api.entity.ComponentEntity;
+import org.apache.nifi.web.dao.AccessPolicyDAO;
+import org.apache.nifi.web.dao.UserDAO;
+import org.apache.nifi.web.dao.UserGroupDAO;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, 
UserGroupDAO, UserDAO {
+
+    private static final String MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER = 
"authorizer is not of type AbstractPolicyBasedAuthorizer";
+    private final AbstractPolicyBasedAuthorizer authorizer;
+
+    public StandardPolicyBasedAuthorizerDAO(final Authorizer authorizer) {
+        if (authorizer instanceof AbstractPolicyBasedAuthorizer) {
+            this.authorizer = (AbstractPolicyBasedAuthorizer) authorizer;
+        } else {
+            this.authorizer = new AbstractPolicyBasedAuthorizer() {
+                @Override
+                public Group addGroup(final Group group) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public Group getGroup(final String identifier) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public Group updateGroup(final Group group) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public Group deleteGroup(final Group group) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public Set<Group> getGroups() throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public User addUser(final User user) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public User getUser(final String identifier) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public User getUserByIdentity(final String identity) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public User updateUser(final User user) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public User deleteUser(final User user) throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public Set<User> getUsers() throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public AccessPolicy addAccessPolicy(final AccessPolicy 
accessPolicy) throws AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public AccessPolicy getAccessPolicy(final String identifier) 
throws AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public AccessPolicy updateAccessPolicy(final AccessPolicy 
accessPolicy) throws AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public AccessPolicy deleteAccessPolicy(final AccessPolicy 
policy) throws AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public Set<AccessPolicy> getAccessPolicies() throws 
AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public UsersAndAccessPolicies getUsersAndAccessPolicies() 
throws AuthorizationAccessException {
+                    throw new 
IllegalStateException(MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER);
+                }
+
+                @Override
+                public void initialize(final AuthorizerInitializationContext 
initializationContext) throws AuthorizerCreationException {
+                }
+
+                @Override
+                public void onConfigured(final AuthorizerConfigurationContext 
configurationContext) throws AuthorizerCreationException {
+                }
+
+                @Override
+                public void preDestruction() throws 
AuthorizerDestructionException {
+                }
+            };
+        }
+    }
+
+    @Override
+    public boolean hasAccessPolicy(final String accessPolicyId) {
+        return authorizer.getAccessPolicy(accessPolicyId) != null;
+    }
+
+    @Override
+    public AccessPolicy createAccessPolicy(final AccessPolicyDTO 
accessPolicyDTO) {
+        return authorizer.addAccessPolicy(buildAccessPolicy(accessPolicyDTO));
+    }
+
+    @Override
+    public AccessPolicy getAccessPolicy(final String accessPolicyId) {
+        return authorizer.getAccessPolicy(accessPolicyId);
+    }
+
+    @Override
+    public AccessPolicy updateAccessPolicy(final AccessPolicyDTO 
accessPolicyDTO) {
+        return 
authorizer.updateAccessPolicy(buildAccessPolicy(accessPolicyDTO));
+    }
+
+    @Override
+    public AccessPolicy deleteAccessPolicy(final String accessPolicyId) {
+        return 
authorizer.deleteAccessPolicy(authorizer.getAccessPolicy(accessPolicyId));
+    }
+
+    private AccessPolicy buildAccessPolicy(final AccessPolicyDTO 
accessPolicyDTO) {
+        final AccessPolicy.Builder builder = new AccessPolicy.Builder()
+                .identifier(accessPolicyDTO.getId())
+                
.addGroups(accessPolicyDTO.getUserGroups().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
+                
.addUsers(accessPolicyDTO.getUsers().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
+                .resource(accessPolicyDTO.getResource());
+        if (accessPolicyDTO.getCanRead()) {
+            builder.addAction(RequestAction.READ);
+        }
+        if (accessPolicyDTO.getCanWrite()) {
+            builder.addAction(RequestAction.WRITE);
+        }
+        return builder.build();
+    }
+
+    @Override
+    public boolean hasUserGroup(final String userGroupId) {
+        return authorizer.getGroup(userGroupId) != null;
+    }
+
+    @Override
+    public Group createUserGroup(final UserGroupDTO userGroupDTO) {
+        return authorizer.addGroup(buildUserGroup(userGroupDTO));
+    }
+
+    @Override
+    public Group getUserGroup(final String userGroupId) {
+        return authorizer.getGroup(userGroupId);
+    }
+
+    @Override
+    public Group updateUserGroup(final UserGroupDTO userGroupDTO) {
+        return authorizer.updateGroup(buildUserGroup(userGroupDTO));
+    }
+
+    @Override
+    public Group deleteUserGroup(final String userGroupId) {
+        return authorizer.deleteGroup(authorizer.getGroup(userGroupId));
+    }
+
+    private Group buildUserGroup(final UserGroupDTO userGroupDTO) {
+        return new Group.Builder()
+                
.addUsers(userGroupDTO.getUsers().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
+                
.identifier(userGroupDTO.getId()).name(userGroupDTO.getName()).build();
+    }
+
+    @Override
+    public boolean hasUser(final String userId) {
+        return authorizer.getUser(userId) != null;
+    }
+
+    @Override
+    public User createUser(final UserDTO userDTO) {
+        final User user = buildUser(userDTO);
+        return authorizer.addUser(user);
+    }
+
+    @Override
+    public User getUser(final String userId) {
+        return authorizer.getUser(userId);
+    }
+
+    @Override
+    public User updateUser(final UserDTO userDTO) {
+        return authorizer.updateUser(buildUser(userDTO));
+    }
+
+    @Override
+    public User deleteUser(final String userId) {
+        return authorizer.deleteUser(authorizer.getUser(userId));
+    }
+
+    private User buildUser(final UserDTO userDTO) {
+        return new User.Builder()
+                
.addGroups(userDTO.getGroups().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
+                
.identifier(userDTO.getIdentity()).identity(userDTO.getIdentity()).build();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
index 39c386d..bff775b 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
@@ -108,6 +108,9 @@
         <property name="flowController" ref="flowController"/>
         <property name="snippetUtils" ref="snippetUtils"/>
     </bean>
+    <bean id="policyBasedAuthorizerDAO" 
class="org.apache.nifi.web.dao.impl.StandardPolicyBasedAuthorizerDAO">
+        <constructor-arg ref="authorizer"/>
+    </bean>
     <bean id="controllerFacade" 
class="org.apache.nifi.web.controller.ControllerFacade">
         <property name="properties" ref="nifiProperties"/>
         <property name="flowController" ref="flowController"/>
@@ -117,7 +120,24 @@
         <property name="dtoFactory" ref="dtoFactory"/>
         <property name="bulletinRepository" ref="bulletinRepository"/>
     </bean>
+    <bean id="authorizableLookup" 
class="org.apache.nifi.web.StandardAuthorizableLookup">
+        <property name="controllerFacade" ref="controllerFacade"/>
+        <property name="processorDAO" ref="processorDAO"/>
+        <property name="inputPortDAO" ref="inputPortDAO"/>
+        <property name="outputPortDAO" ref="outputPortDAO"/>
+        <property name="processGroupDAO" ref="processGroupDAO"/>
+        <property name="remoteProcessGroupDAO" ref="remoteProcessGroupDAO"/>
+        <property name="labelDAO" ref="labelDAO"/>
+        <property name="funnelDAO" ref="funnelDAO"/>
+        <property name="connectionDAO" ref="connectionDAO"/>
+        <property name="controllerServiceDAO" ref="controllerServiceDAO"/>
+        <property name="reportingTaskDAO" ref="reportingTaskDAO"/>
+        <property name="templateDAO" ref="templateDAO"/>
+        <property name="snippetDAO" ref="snippetDAO"/>
+        <property name="accessPolicyDAO" ref="policyBasedAuthorizerDAO"/>
+    </bean>
     <bean id="serviceFacade" 
class="org.apache.nifi.web.StandardNiFiServiceFacade">
+        <property name="authorizableLookup" ref="authorizableLookup" />
         <property name="properties" ref="nifiProperties"/>
         <property name="authorizer" ref="authorizer"/>
         <property name="controllerFacade" ref="controllerFacade"/>
@@ -133,6 +153,9 @@
         <property name="reportingTaskDAO" ref="reportingTaskDAO"/>
         <property name="templateDAO" ref="templateDAO"/>
         <property name="snippetDAO" ref="snippetDAO"/>
+        <property name="accessPolicyDAO" ref="policyBasedAuthorizerDAO"/>
+        <property name="userGroupDAO" ref="policyBasedAuthorizerDAO"/>
+        <property name="userDAO" ref="policyBasedAuthorizerDAO"/>
         <property name="auditService" ref="auditService"/>
         <property name="keyService" ref="keyService"/>
         <property name="snippetUtils" ref="snippetUtils"/>
@@ -342,6 +365,27 @@
         <property name="clusterCoordinator" ref="clusterCoordinator"/>
         <property name="requestReplicator" ref="requestReplicator" />
     </bean>
+    <bean id="accessPolicyResource" 
class="org.apache.nifi.web.api.AccessPolicyResource" scope="singleton">
+        <constructor-arg ref="serviceFacade"/>
+        <constructor-arg ref="authorizer"/>
+        <constructor-arg ref="nifiProperties"/>
+        <constructor-arg ref="clusterCoordinator"/>
+        <constructor-arg ref="requestReplicator" />
+    </bean>
+    <bean id="userGroupsResource" 
class="org.apache.nifi.web.api.UserGroupsResource" scope="singleton">
+        <constructor-arg ref="serviceFacade"/>
+        <constructor-arg ref="authorizer"/>
+        <constructor-arg ref="nifiProperties"/>
+        <constructor-arg ref="clusterCoordinator"/>
+        <constructor-arg ref="requestReplicator" />
+    </bean>
+    <bean id="usersResource" class="org.apache.nifi.web.api.UsersResource" 
scope="singleton">
+        <constructor-arg ref="serviceFacade"/>
+        <constructor-arg ref="authorizer"/>
+        <constructor-arg ref="nifiProperties"/>
+        <constructor-arg ref="clusterCoordinator"/>
+        <constructor-arg ref="requestReplicator" />
+    </bean>
 
     <!-- configuration for jaxb serialization -->
     <bean class="org.apache.nifi.web.util.ObjectMapperResolver" 
scope="singleton"/>

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/groovy/org/apache/nifi/web/StandardNiFiServiceFacadeSpec.groovy
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/groovy/org/apache/nifi/web/StandardNiFiServiceFacadeSpec.groovy
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/groovy/org/apache/nifi/web/StandardNiFiServiceFacadeSpec.groovy
new file mode 100644
index 0000000..a4c2b37
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/groovy/org/apache/nifi/web/StandardNiFiServiceFacadeSpec.groovy
@@ -0,0 +1,896 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.web
+
+import org.apache.nifi.authorization.*
+import org.apache.nifi.authorization.resource.Authorizable
+import org.apache.nifi.authorization.resource.ResourceFactory
+import org.apache.nifi.authorization.user.NiFiUser
+import org.apache.nifi.controller.service.ControllerServiceProvider
+import org.apache.nifi.web.api.dto.*
+import org.apache.nifi.web.api.entity.UserEntity
+import org.apache.nifi.web.controller.ControllerFacade
+import org.apache.nifi.web.dao.AccessPolicyDAO
+import org.apache.nifi.web.dao.UserDAO
+import org.apache.nifi.web.dao.UserGroupDAO
+import org.apache.nifi.web.revision.*
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class StandardNiFiServiceFacadeSpec extends Specification {
+
+    @Unroll
+    def "CreateUser: isAuthorized: #isAuthorized"() {
+        given:
+        def userDao = Mock UserDAO
+        def entityFactory = new EntityFactory()
+        def dtoFactory = new DtoFactory()
+        def authorizableLookup = Mock AuthorizableLookup
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setUserDAO userDao
+        niFiServiceFacade.setEntityFactory entityFactory
+        def newUser = new 
User.Builder().identifier(userDto.id).identity(userDto.identity).build()
+
+        when:
+        def userEntity = niFiServiceFacade.createUser(new Revision(0L, 
'client-1'), userDto)
+
+        then:
+        1 * userDao.createUser(_) >> newUser
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(parentAuthorizable, resource, isAuthorized, 
authorizationResult)
+        0 * _
+        userEntity != null
+        if (isAuthorized) {
+            assert userEntity?.component?.id == userDto.id
+            assert userEntity?.component?.identity?.equals(userDto.identity)
+            assert userEntity?.accessPolicy?.canRead
+            assert userEntity?.accessPolicy?.canWrite
+        } else {
+            assert userEntity.component == null
+        }
+
+
+        where:
+        userDto         | parentAuthorizable | resource                      | 
isAuthorized | authorizationResult
+        createUserDTO() | null               | ResourceFactory.usersResource | 
true         | AuthorizationResult.approved()
+        createUserDTO() | null               | ResourceFactory.usersResource | 
false        | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "GetUser: isAuthorized: #isAuthorized"() {
+        given:
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def authorizableLookup = Mock AuthorizableLookup
+        def dtoFactory = new DtoFactory()
+        def entityFactory = new EntityFactory()
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setUserDAO userDao
+        def requestedUser = new 
User.Builder().identifier(userDto.id).identity(userDto.identity).build()
+        def exception = null
+        def userEntity = null
+
+        when:
+        try {
+            userEntity = niFiServiceFacade.getUser(userDto.id, true)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        if (isAuthorized) {
+            1 * userDao.getUser(userDto.id) >> requestedUser
+        }
+        1 * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                isAuthorized, authorizationResult)
+        0 * _
+        if (isAuthorized) {
+            assert userEntity?.component?.id?.equals(userDto.id)
+        } else {
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        userDto         | isAuthorized | authorizationResult
+        createUserDTO() | true         | AuthorizationResult.approved()
+        createUserDTO() | false        | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "UpdateUser: isAuthorized: #isAuthorized, policy exists: 
#userExists"() {
+        given:
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def entityFactory = new EntityFactory()
+        def dtoFactory = new DtoFactory()
+        def authorizableLookup = Mock AuthorizableLookup
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setUserDAO userDao
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setControllerFacade controllerFacade
+        def user = new 
User.Builder().identifier(userDto.id).identity(userDto.identity).build()
+
+        when:
+        def userEntityUpdateResult = 
niFiServiceFacade.updateUser(currentRevision, userDto)
+
+        then:
+        1 * userDao.hasUser(userDto.id) >> userExists
+        if (!userExists) {
+            1 * userDao.createUser(userDto) >> user
+        } else {
+            1 * controllerFacade.save()
+            1 * userDao.updateUser(userDto) >> user
+            1 * revisionManager.updateRevision(_, _, _) >> { RevisionClaim 
revisionClaim, NiFiUser niFiUser, UpdateRevisionTask callback ->
+                callback.update()
+            }
+        }
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                isAuthorized, authorizationResult)
+        0 * _
+        userEntityUpdateResult != null
+        def userEntity = userEntityUpdateResult?.result
+        if (isAuthorized) {
+            assert userEntity?.component?.id?.equals(userDto.id)
+            assert userEntity?.accessPolicy?.canRead
+            assert userEntity?.accessPolicy?.canWrite
+        } else {
+            assert userEntity.component == null
+        }
+
+        where:
+        userExists | currentRevision                     | userDto         | 
isAuthorized | authorizationResult
+        false      | new Revision(0L, 'client1', 'root') | createUserDTO() | 
true         | AuthorizationResult.approved()
+        true       | new Revision(1L, 'client1', 'root') | createUserDTO() | 
true         | AuthorizationResult.approved()
+        false      | new Revision(0L, 'client1', 'root') | createUserDTO() | 
false        | AuthorizationResult.denied()
+        true       | new Revision(1L, 'client1', 'root') | createUserDTO() | 
false        | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "DeleteUser: isAuthorized: #isAuthorized, user exists: #userExists"() {
+        given:
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def authorizableLookup = Mock AuthorizableLookup
+        def dtoFactory = new DtoFactory()
+        def entityFactory = new EntityFactory()
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setUserDAO userDao
+        niFiServiceFacade.setControllerFacade controllerFacade
+        def user = new 
User.Builder().identifier(userDto.id).identity(userDto.identity).build()
+
+        when:
+        def userEntity = niFiServiceFacade.deleteUser(currentRevision, 
userDto.id)
+
+        then:
+        if (userExists) {
+            1 * userDao.getUser(userDto.id) >> user
+            1 * userDao.deleteUser(userDto.id) >> user
+        } else {
+            1 * userDao.getUser(userDto.id) >> null
+            1 * userDao.deleteUser(userDto.id) >> null
+        }
+        1 * controllerFacade.save()
+        1 * revisionManager.deleteRevision(_, _, _) >> { RevisionClaim 
revisionClaim, NiFiUser nifiUser, DeleteRevisionTask task ->
+            task.performTask()
+        }
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.usersResource,
+                isAuthorized, authorizationResult)
+        0 * _
+        userEntity?.component?.id == null
+        if (userExists) {
+            assert userEntity?.id?.equals(userDto.id)
+        } else {
+            assert userEntity?.id == null
+        }
+
+        where:
+        userExists | currentRevision             | userDto         | 
isAuthorized | authorizationResult
+        true       | new Revision(1L, 'client1') | createUserDTO() | true      
   | AuthorizationResult.approved()
+        false      | null                        | createUserDTO() | true      
   | AuthorizationResult.approved()
+        true       | new Revision(1L, 'client1') | createUserDTO() | false     
   | AuthorizationResult.denied()
+        false      | null                        | createUserDTO() | false     
   | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "CreateUserGroup: isAuthorized: #isAuthorized"() {
+        given:
+        def userGroupDao = Mock UserGroupDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def controllerServiceProvider = Mock ControllerServiceProvider
+        def entityFactory = new EntityFactory()
+        def dtoFactory = new DtoFactory()
+        dtoFactory.setControllerServiceProvider controllerServiceProvider
+        dtoFactory.setEntityFactory entityFactory
+        def authorizableLookup = Mock AuthorizableLookup
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setUserGroupDAO userGroupDao
+        niFiServiceFacade.setUserDAO userDao
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setControllerFacade controllerFacade
+        def newUserGroup = new 
Group.Builder().identifier(userGroupDto.id).name(userGroupDto.name).addUsers(userGroupDto.users.collect
 { it.id } as Set).build()
+        def exception = null
+        def userGroupEntity = null
+
+        when:
+        try {
+            userGroupEntity = niFiServiceFacade.createUserGroup(new 
Revision(0L, 'client-1'), userGroupDto)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        if (isAuthorized) {
+            1 * authorizableLookup.getUserGroupsAuthorizable() >>
+                    new SimpleAuthorizable(null, 
ResourceFactory.userGroupsResource, isAuthorized, 
authorizationResult.get(ResourceFactory.userGroupsResource))
+        }
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.usersResource, isAuthorized, 
authorizationResult.get(ResourceFactory.usersResource))
+        1 * userGroupDao.createUserGroup(_) >> newUserGroup
+        if (authorizationResult.get(ResourceFactory.usersResource) == 
AuthorizationResult.approved()) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = userGroupDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity)
+                        .addGroups(userEntity.groups.collect { it.id } as Set)
+                        .build()
+            }
+        }
+        userGroupDto.users.size() * revisionManager.get(_, _) >> { String id, 
ReadOnlyRevisionCallback callback ->
+            assert userGroupDto.users.collect { it.id }.contains(id)
+            def revisionDTO = userGroupDto.users.find { it.id.equals(id) 
}.revision
+            callback.withRevision new Revision(revisionDTO.version, 
revisionDTO.clientId, id)
+        }
+        0 * _
+        if (isAuthorized) {
+            assert userGroupEntity?.component?.id == userGroupDto.id
+            assert 
userGroupEntity?.component?.users?.equals(userGroupDto.users)
+            assert userGroupEntity?.accessPolicy?.canRead
+            assert userGroupEntity?.accessPolicy?.canWrite
+        } else {
+            assert userGroupEntity?.component == null
+            assert exception instanceof AccessDeniedException
+        }
+
+
+        where: // TODO add more use cases, specifically with varied 
authorization results, and the assertions to check them, to all spec methods 
that use AuthorizationResult
+        userGroupDto         | isAuthorized | authorizationResult
+        createUserGroupDTO() | true         | 
[(ResourceFactory.userGroupsResource): AuthorizationResult.approved(), 
(ResourceFactory.usersResource): AuthorizationResult.approved()]
+        createUserGroupDTO() | false        | 
[(ResourceFactory.userGroupsResource): AuthorizationResult.denied(), 
(ResourceFactory.usersResource): AuthorizationResult.denied()]
+    }
+
+    @Unroll
+    def "GetUserGroup: isAuthorized: #isAuthorized"() {
+        given:
+        def userGroupDao = Mock UserGroupDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def authorizableLookup = Mock AuthorizableLookup
+        def dtoFactory = new DtoFactory()
+        def entityFactory = new EntityFactory()
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setUserGroupDAO userGroupDao
+        niFiServiceFacade.setUserDAO userDao
+        def requestedUserGroup = new 
Group.Builder().identifier(userGroupDto.id).name(userGroupDto.name)
+                .addUsers(userGroupDto.users.collect { it.id } as Set).build()
+        def exception = null
+        def userGroupEntity = null
+
+        when:
+        try {
+            userGroupEntity = niFiServiceFacade.getUserGroup(userGroupDto.id, 
true)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        if (isAuthorized) {
+            1 * userGroupDao.getUserGroup(userGroupDto.id) >> 
requestedUserGroup
+            1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.usersResource, isAuthorized, 
authorizationResult)
+        }
+        1 * authorizableLookup.getUserGroupsAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUserGroupsResource(),
+                isAuthorized, authorizationResult)
+        _ * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        if (authorizationResult == AuthorizationResult.approved()) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = userGroupDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        0 * _
+        if (isAuthorized) {
+            assert userGroupEntity?.component?.id?.equals(userGroupDto.id)
+        } else {
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        userGroupDto                                                           
    | isAuthorized | authorizationResult
+        new UserGroupDTO(id: '1', name: 'test group', users: 
[createUserEntity()]) | true         | AuthorizationResult.approved()
+        new UserGroupDTO(id: '1', name: 'test group', users: 
[createUserEntity()]) | false        | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "UpdateUserGroup: isAuthorized: #isAuthorized, userGroupExists exists: 
#userGroupExists"() {
+        given:
+        def userGroupDao = Mock UserGroupDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def entityFactory = new EntityFactory()
+        def dtoFactory = new DtoFactory()
+        def authorizableLookup = Mock AuthorizableLookup
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setUserGroupDAO userGroupDao
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setControllerFacade controllerFacade
+        niFiServiceFacade.setUserDAO userDao
+        def userGroup = new 
Group.Builder().identifier(userGroupDto.id).name(userGroupDto.name)
+                .addUsers(userGroupDto.users.collect { it.id } as Set).build()
+        def userGroupsEntityUpdateResult = null
+        def exception = null
+
+        when:
+        try {
+            userGroupsEntityUpdateResult = 
niFiServiceFacade.updateUserGroup(currentRevision, userGroupDto)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        1 * userGroupDao.hasUserGroup(userGroupDto.id) >> userGroupExists
+        if (!userGroupExists) {
+            1 * userGroupDao.createUserGroup(userGroupDto) >> userGroup
+            1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                    isAuthorized, 
authorizationResult.get(ResourceFactory.getUsersResource()))
+        } else {
+            1 * controllerFacade.save()
+            1 * userGroupDao.updateUserGroup(userGroupDto) >> userGroup
+            1 * revisionManager.updateRevision(_, _, _) >> { RevisionClaim 
revisionClaim, NiFiUser niFiUser, UpdateRevisionTask callback ->
+                callback.update()
+            }
+            1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.usersResource,
+                    isAuthorized, 
authorizationResult.get(ResourceFactory.usersResource))
+        }
+        if (isAuthorized || userGroupExists) {
+            1 * authorizableLookup.getUserGroupsAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.userGroupsResource,
+                    isAuthorized, 
authorizationResult.get(ResourceFactory.userGroupsResource))
+        }
+        _ * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        if (authorizationResult.get(ResourceFactory.userGroupsResource) == 
AuthorizationResult.approved()) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = userGroupDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        0 * _
+        def userGroupEntity = userGroupsEntityUpdateResult?.result
+        if (isAuthorized) {
+            assert userGroupEntity?.component?.id?.equals(userGroupDto.id)
+            assert userGroupEntity?.accessPolicy?.canRead
+            assert userGroupEntity?.accessPolicy?.canWrite
+        } else {
+            assert userGroupEntity?.component == null
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        userGroupExists | currentRevision                     | userGroupDto   
                                                            | isAuthorized |
+                authorizationResult
+        false           | new Revision(0L, 'client1', 'root') | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | true   
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.approved(), (ResourceFactory.usersResource): 
AuthorizationResult.approved()]
+        true            | new Revision(1L, 'client1', 'root') | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | true   
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.approved(), (ResourceFactory.usersResource): 
AuthorizationResult.approved()]
+        false           | new Revision(0L, 'client1', 'root') | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | false  
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.denied(), (ResourceFactory.usersResource): 
AuthorizationResult.denied()]
+        true            | new Revision(1L, 'client1', 'root') | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | false  
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.denied(), (ResourceFactory.usersResource): 
AuthorizationResult.denied()]
+    }
+
+    @Unroll
+    def "DeleteUserGroup: isAuthorized: #isAuthorized, userGroup exists: 
#userGroupExists"() {
+        given:
+        def userGroupDao = Mock UserGroupDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def authorizableLookup = Mock AuthorizableLookup
+        def dtoFactory = new DtoFactory()
+        def entityFactory = new EntityFactory()
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setUserGroupDAO userGroupDao
+        niFiServiceFacade.setControllerFacade controllerFacade
+        niFiServiceFacade.setUserDAO userDao
+        def userGroup = new 
Group.Builder().identifier(userGroupDto.id).name(userGroupDto.name)
+                .addUsers(userGroupDto.users.collect { it.id } as Set).build()
+        def userGroupEntity = null
+        def exception = null
+
+        when:
+        try {
+            userGroupEntity = 
niFiServiceFacade.deleteUserGroup(currentRevision, userGroupDto.id)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        if (userGroupExists) {
+            1 * userGroupDao.getUserGroup(userGroupDto.id) >> userGroup
+            if (isAuthorized) {
+                1 * userGroupDao.deleteUserGroup(userGroupDto.id) >> userGroup
+            }
+            1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                    isAuthorized, 
authorizationResult.get(ResourceFactory.getUsersResource()))
+        } else {
+            1 * userGroupDao.getUserGroup(userGroupDto.id) >> null
+            1 * userGroupDao.deleteUserGroup(userGroupDto.id) >> null
+        }
+        if (!(!isAuthorized && userGroupExists)) {
+            1 * authorizableLookup.getUserGroupsAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.userGroupsResource,
+                    isAuthorized, 
authorizationResult.get(ResourceFactory.userGroupsResource))
+            1 * revisionManager.deleteRevision(_, _, _) >> { RevisionClaim 
revisionClaim, NiFiUser nifiUser, DeleteRevisionTask task ->
+                task.performTask()
+            }
+            1 * controllerFacade.save()
+        }
+        _ * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        if (authorizationResult.get(ResourceFactory.userGroupsResource) == 
AuthorizationResult.approved() && userGroupExists) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = userGroupDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        0 * _
+        userGroupEntity?.component?.id == null
+        if (userGroupExists && isAuthorized) {
+            assert userGroupEntity?.id?.equals(userGroupDto.id)
+        } else {
+            assert userGroupEntity?.id == null
+        }
+        if (authorizationResult.get(ResourceFactory.usersResource) == 
AuthorizationResult.denied()) {
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        userGroupExists | currentRevision                     | userGroupDto   
                                                            | isAuthorized |
+                authorizationResult
+        true            | new Revision(1L, 'client1', 'root') | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | true   
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.approved(), (ResourceFactory.usersResource): 
AuthorizationResult.approved()]
+        false           | null                                | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | true   
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.approved(), (ResourceFactory.usersResource): 
AuthorizationResult.approved()]
+        true            | new Revision(1L, 'client1', 'root') | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | false  
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.denied(), (ResourceFactory.usersResource): 
AuthorizationResult.denied()]
+        false           | null                                | new 
UserGroupDTO(id: '1', name: 'test group', users: [createUserEntity()]) | false  
      |
+                [(ResourceFactory.userGroupsResource): 
AuthorizationResult.denied(), (ResourceFactory.usersResource): 
AuthorizationResult.denied()]
+    }
+
+    @Unroll
+    def "CreateAccessPolicy: #isAuthorized"() {
+        given:
+        def accessPolicyDao = Mock AccessPolicyDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def entityFactory = new EntityFactory()
+        def dtoFactory = new DtoFactory()
+        dtoFactory.setEntityFactory entityFactory
+        def authorizableLookup = Mock AuthorizableLookup
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setAccessPolicyDAO accessPolicyDao
+        niFiServiceFacade.setUserDAO userDao
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setRevisionManager revisionManager
+        def builder = new 
AccessPolicy.Builder().identifier(accessPolicyDto.id).resource(accessPolicyDto.resource)
+                .addUsers(accessPolicyDto.users.collect { it.id } as Set)
+                .addGroups(accessPolicyDto.userGroups.collect { it.id } as Set)
+        if (accessPolicyDto.canRead) {
+            builder.addAction(RequestAction.READ)
+        }
+        if (accessPolicyDto.canWrite) {
+            builder.addAction(RequestAction.WRITE)
+        }
+        def newAccessPolicy = builder.build()
+        def accessPolicyEntity = null
+        def exception = null
+
+        when:
+        try {
+            accessPolicyEntity = niFiServiceFacade.createAccessPolicy(new 
Revision(0L, 'client-1'), accessPolicyDto)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        1 * accessPolicyDao.createAccessPolicy(accessPolicyDto) >> 
newAccessPolicy
+        if (isAuthorized) {
+            1 * 
authorizableLookup.getAccessPolicyAuthorizable(accessPolicyDto.id) >> new 
SimpleAuthorizable(null, ResourceFactory.getPolicyResource(accessPolicyDto.id),
+                    isAuthorized, authorizationResult)
+        }
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                isAuthorized, authorizationResult)
+        if (authorizationResult == AuthorizationResult.approved()) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = accessPolicyDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        1 * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        0 * _
+        if (isAuthorized) {
+            assert 
accessPolicyEntity?.component?.id?.equals(accessPolicyDto.id)
+            assert accessPolicyEntity?.accessPolicy?.canRead
+            assert accessPolicyEntity?.accessPolicy?.canWrite
+        } else {
+            assert accessPolicyEntity?.component == null
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        accessPolicyDto                                                        
                                                     | isAuthorized | 
authorizationResult
+        new AccessPolicyDTO(id: '1', resource: 
ResourceFactory.flowResource.identifier, users: [createUserEntity()], canRead: 
true) | true         | AuthorizationResult.approved()
+        new AccessPolicyDTO(id: '1', resource: 
ResourceFactory.flowResource.identifier, users: [createUserEntity()], canRead: 
true) | false        | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "GetAccessPolicy: isAuthorized: #isAuthorized"() {
+        given:
+        def accessPolicyDao = Mock AccessPolicyDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def authorizableLookup = Mock AuthorizableLookup
+        def dtoFactory = new DtoFactory()
+        def entityFactory = new EntityFactory()
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setAccessPolicyDAO accessPolicyDao
+        niFiServiceFacade.setUserDAO userDao
+        def builder = new 
AccessPolicy.Builder().identifier(accessPolicyDto.id).resource(accessPolicyDto.resource)
+                .addUsers(accessPolicyDto.users.collect { it.id } as Set)
+                .addGroups(accessPolicyDto.userGroups.collect { it.id } as Set)
+        if (accessPolicyDto.canRead) {
+            builder.addAction(RequestAction.READ)
+        }
+        if (accessPolicyDto.canWrite) {
+            builder.addAction(RequestAction.WRITE)
+        }
+        def requestedAccessPolicy = builder.build()
+        def exception = null
+        def accessPolicyEntity = null
+
+        when:
+        try {
+            accessPolicyEntity = 
niFiServiceFacade.getAccessPolicy(accessPolicyDto.id)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        if (isAuthorized) {
+            1 * accessPolicyDao.getAccessPolicy(accessPolicyDto.id) >> 
requestedAccessPolicy
+            1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                    isAuthorized, authorizationResult)
+        }
+        _ * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        1 * authorizableLookup.getAccessPolicyAuthorizable(accessPolicyDto.id) 
>> new SimpleAuthorizable(null, 
ResourceFactory.getPolicyResource(accessPolicyDto.id),
+                isAuthorized, authorizationResult)
+        if (authorizationResult == AuthorizationResult.approved()) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = accessPolicyDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        0 * _
+        if (isAuthorized) {
+            assert 
accessPolicyEntity?.component?.id?.equals(accessPolicyDto.id)
+        } else {
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        accessPolicyDto                                                        
                                                     | isAuthorized | 
authorizationResult
+        new AccessPolicyDTO(id: '1', resource: 
ResourceFactory.flowResource.identifier, users: [createUserEntity()], canRead: 
true) | true         | AuthorizationResult.approved()
+        new AccessPolicyDTO(id: '1', resource: 
ResourceFactory.flowResource.identifier, users: [createUserEntity()], canRead: 
true) | false        | AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "UpdateAccessPolicy: isAuthorized: #isAuthorized, policy exists: 
#hasPolicy"() {
+        given:
+        def accessPolicyDao = Mock AccessPolicyDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def entityFactory = new EntityFactory()
+        def dtoFactory = new DtoFactory()
+        def authorizableLookup = Mock AuthorizableLookup
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setAccessPolicyDAO accessPolicyDao
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setControllerFacade controllerFacade
+        niFiServiceFacade.setUserDAO userDao
+        def builder = new 
AccessPolicy.Builder().identifier(accessPolicyDto.id).resource(accessPolicyDto.resource)
+                .addUsers(accessPolicyDto.users.collect { it.id } as Set)
+                .addGroups(accessPolicyDto.userGroups.collect { it.id } as Set)
+        if (accessPolicyDto.canRead) {
+            builder.addAction(RequestAction.READ)
+        }
+        if (accessPolicyDto.canWrite) {
+            builder.addAction(RequestAction.WRITE)
+        }
+        def accessPolicy = builder.build()
+        def accessPolicyEntityUpdateResult = null
+        def exception = null
+
+        when:
+        try {
+            accessPolicyEntityUpdateResult = 
niFiServiceFacade.updateAccessPolicy(currentRevision, accessPolicyDto)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        1 * accessPolicyDao.hasAccessPolicy(accessPolicyDto.id) >> hasPolicy
+        if (!hasPolicy) {
+            1 * accessPolicyDao.createAccessPolicy(accessPolicyDto) >> 
accessPolicy
+        } else {
+            1 * controllerFacade.save()
+            1 * accessPolicyDao.updateAccessPolicy(accessPolicyDto) >> 
accessPolicy
+            1 * revisionManager.updateRevision(_, _, _) >> { RevisionClaim 
revisionClaim, NiFiUser niFiUser, UpdateRevisionTask callback ->
+                callback.update()
+            }
+        }
+        1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.getUsersResource(),
+                isAuthorized, authorizationResult)
+        if (isAuthorized || hasPolicy) {
+            1 * 
authorizableLookup.getAccessPolicyAuthorizable(accessPolicyDto.id) >> new 
SimpleAuthorizable(null, ResourceFactory.getPolicyResource(accessPolicyDto.id),
+                    isAuthorized, authorizationResult)
+        }
+        if (authorizationResult == AuthorizationResult.approved()) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = accessPolicyDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        1 * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        0 * _
+        def accessPolicyEntity = accessPolicyEntityUpdateResult?.result
+        if (isAuthorized) {
+            assert 
accessPolicyEntity?.component?.id?.equals(accessPolicyDto.id)
+            assert accessPolicyEntity?.accessPolicy?.canRead
+            assert accessPolicyEntity?.accessPolicy?.canWrite
+        } else {
+            assert accessPolicyEntity?.component == null
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        hasPolicy | currentRevision                     | accessPolicyDto      
                                                                                
                       | isAuthorized |
+                authorizationResult
+        false     | new Revision(0L, 'client1', 'root') | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | true         |
+                AuthorizationResult.approved()
+        true      | new Revision(1L, 'client1', 'root') | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | true         |
+                AuthorizationResult.approved()
+        false     | new Revision(0L, 'client1', 'root') | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | false        |
+                AuthorizationResult.denied()
+        true      | new Revision(1L, 'client1', 'root') | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | false        |
+                AuthorizationResult.denied()
+    }
+
+    @Unroll
+    def "DeleteAccessPolicy: isAuthorized: #isAuthorized, hasPolicy: 
#hasPolicy"() {
+        given:
+        def accessPolicyDao = Mock AccessPolicyDAO
+        def userDao = Mock UserDAO
+        def revisionManager = Mock RevisionManager
+        def authorizableLookup = Mock AuthorizableLookup
+        def dtoFactory = new DtoFactory()
+        def entityFactory = new EntityFactory()
+        def controllerFacade = Mock ControllerFacade
+        def niFiServiceFacade = new StandardNiFiServiceFacade()
+        niFiServiceFacade.setAuthorizableLookup authorizableLookup
+        niFiServiceFacade.setRevisionManager revisionManager
+        niFiServiceFacade.setDtoFactory dtoFactory
+        niFiServiceFacade.setEntityFactory entityFactory
+        niFiServiceFacade.setAccessPolicyDAO accessPolicyDao
+        niFiServiceFacade.setControllerFacade controllerFacade
+        niFiServiceFacade.setUserDAO userDao
+        def builder = new AccessPolicy.Builder()
+        
builder.identifier(accessPolicyDto.id).resource(accessPolicyDto.resource)
+                .addUsers(accessPolicyDto.users.collect { it.id } as Set)
+                .addGroups(accessPolicyDto.userGroups.collect { it.id } as Set)
+        if (accessPolicyDto.canRead) {
+            builder.addAction(RequestAction.READ)
+        }
+        if (accessPolicyDto.canWrite) {
+            builder.addAction(RequestAction.WRITE)
+        }
+        def accessPolicy = builder.build()
+        def accessPolicyEntity = null
+        def exception = null
+
+        when:
+        try {
+            accessPolicyEntity = 
niFiServiceFacade.deleteAccessPolicy(currentRevision, accessPolicyDto.id)
+        } catch (AccessDeniedException e) {
+            exception = e
+        }
+
+        then:
+        if (hasPolicy) {
+            1 * accessPolicyDao.getAccessPolicy(accessPolicyDto.id) >> 
accessPolicy
+            if (isAuthorized) {
+                1 * accessPolicyDao.deleteAccessPolicy(accessPolicyDto.id) >> 
accessPolicy
+            }
+            1 * authorizableLookup.getUsersAuthorizable() >> new 
SimpleAuthorizable(null, ResourceFactory.usersResource,
+                    isAuthorized, authorizationResult)
+        } else {
+            1 * accessPolicyDao.getAccessPolicy(accessPolicyDto.id) >> null
+            1 * accessPolicyDao.deleteAccessPolicy(accessPolicyDto.id) >> null
+        }
+        if (!(!isAuthorized && hasPolicy)) {
+            1 * 
authorizableLookup.getAccessPolicyAuthorizable(accessPolicyDto.id) >> new 
SimpleAuthorizable(null, ResourceFactory.getPolicyResource(accessPolicyDto.id),
+                    isAuthorized, authorizationResult)
+            1 * revisionManager.deleteRevision(_, _, _) >> { RevisionClaim 
revisionClaim, NiFiUser nifiUser, DeleteRevisionTask task ->
+                task.performTask()
+            }
+            1 * controllerFacade.save()
+        }
+        _ * revisionManager.get(_, _) >> { String id, ReadOnlyRevisionCallback 
callback ->
+            callback.withRevision(new Revision(1L, 'client1', 'root'))
+        }
+        if (authorizationResult == AuthorizationResult.approved() && 
hasPolicy) {
+            1 * userDao.getUser(_) >> { String userId ->
+                def userEntity = accessPolicyDto.users.find { 
it.id.equals(userId) }?.component
+                assert userEntity != null
+                new 
User.Builder().identifier(userEntity.id).identity(userEntity.identity).build()
+            }
+        }
+        0 * _
+        if (hasPolicy && isAuthorized) {
+            assert accessPolicyEntity?.id?.equals(accessPolicyDto.id)
+        } else {
+            assert accessPolicyEntity?.id == null
+        }
+        if (!isAuthorized && hasPolicy) {
+            assert exception instanceof AccessDeniedException
+        }
+
+        where:
+        hasPolicy | currentRevision                     | accessPolicyDto      
                                                                                
                       | isAuthorized |
+                authorizationResult
+        true      | new Revision(1L, 'client1', 'root') | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | true         |
+                AuthorizationResult.approved()
+        false     | null                                | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | true         |
+                AuthorizationResult.approved()
+        true       | new Revision(1L, 'client1', 'root') | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | false        |
+                AuthorizationResult.denied()
+        false      | null                                | new 
AccessPolicyDTO(id: '1', resource: ResourceFactory.flowResource.identifier, 
users: [createUserEntity()], canRead: true) | false        |
+                AuthorizationResult.denied()
+    }
+
+    private UserGroupDTO createUserGroupDTO() {
+        new UserGroupDTO(id: 'group-1', name: 'test group', users: 
[createUserEntity()] as Set)
+    }
+
+    private UserEntity createUserEntity() {
+        new UserEntity(id: 'user-1', component: createUserDTO(), revision: 
createRevisionDTO())
+    }
+
+    private UserDTO createUserDTO() {
+        new UserDTO(id: 'user-1', identity: 'user-1')
+    }
+
+    private RevisionDTO createRevisionDTO() {
+        new RevisionDTO(version: 0L, clientId: 'client-1', lastModifier: 
'user-1')
+    }
+
+    private class SimpleAuthorizable implements Authorizable {
+        final private Authorizable parentAuthorizable
+        final private Resource resource
+        final private boolean isAuthorized
+        final private AuthorizationResult authorizationResult;
+
+        SimpleAuthorizable(Authorizable parentAuthorizable, Resource resource, 
boolean isAuthorized, AuthorizationResult authorizationResult) {
+            this.parentAuthorizable = parentAuthorizable
+            this.resource = resource
+            this.isAuthorized = isAuthorized
+            this.authorizationResult = authorizationResult
+        }
+
+        @Override
+        Authorizable getParentAuthorizable() {
+            return parentAuthorizable
+        }
+
+        @Override
+        Resource getResource() {
+            return resource
+        }
+
+        @Override
+        boolean isAuthorized(Authorizer authorzr, RequestAction action) {
+            return isAuthorized
+        }
+
+        @Override
+        AuthorizationResult checkAuthorization(Authorizer authorzr, 
RequestAction action) {
+            return authorizationResult
+        }
+
+        @Override
+        void authorize(Authorizer authorzr, RequestAction action) throws 
AccessDeniedException {
+            if (!isAuthorized) {
+                throw new AccessDeniedException("test exception, access 
denied")
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/f47be77b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java
index 7f61e0e..6077bc3 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/accesscontrol/AdminAccessControlTest.java
@@ -44,7 +44,6 @@ import org.apache.nifi.web.api.entity.ProcessGroupsEntity;
 import org.apache.nifi.web.api.entity.ProcessorEntity;
 import org.apache.nifi.web.api.entity.ProcessorTypesEntity;
 import org.apache.nifi.web.api.entity.ProcessorsEntity;
-import org.apache.nifi.web.api.entity.UserEntity;
 import org.apache.nifi.web.api.entity.UsersEntity;
 import org.junit.AfterClass;
 import org.junit.Assert;
@@ -993,7 +992,7 @@ public class AdminAccessControlTest {
 
         // ensure the request succeeded
         Assert.assertEquals(200, putResponse.getStatus());
-        Assert.assertEquals("ACTIVE", 
putResponse.getEntity(UserEntity.class).getUser().getStatus());
+        Assert.assertEquals("ACTIVE", null);  // FIXME test should fail, needs 
to be updated to test updating user by changing the groups the user is in and 
the name of the user
     }
 
     @AfterClass

Reply via email to