Repository: nifi Updated Branches: refs/heads/master 9bb6dcb5e -> 714925358
NIFI-1884 - Defining API for Users, Groups, and Policies - Updating hashCode and equals methods - Documenting that returned sets are unmodifiable - Adding builders and unit tests - Refactoring update methods in MutableAuthorizer to not take a string id - Refactoring builders to use constructors for seeding - Fixing toString() methods and cleaning up constructors that don't need to worry about null sets - Changing MutableAuthorizer to an abstract class and providing implementation of authorize - This closes #452 Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/71492535 Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/71492535 Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/71492535 Branch: refs/heads/master Commit: 714925358e9b2394aabd1ef9a63ca80b8320f42f Parents: 9bb6dcb Author: Bryan Bende <[email protected]> Authored: Mon May 16 17:11:41 2016 -0400 Committer: Matt Gilman <[email protected]> Committed: Tue May 24 09:24:11 2016 -0400 ---------------------------------------------------------------------- .../AbstractPolicyBasedAuthorizer.java | 220 ++++++++++++ .../apache/nifi/authorization/AccessPolicy.java | 356 +++++++++++++++++++ .../org/apache/nifi/authorization/Group.java | 226 ++++++++++++ .../org/apache/nifi/authorization/User.java | 229 ++++++++++++ .../TestAbstractPolicyBasedAuthorizer.java | 165 +++++++++ .../nifi/authorization/TestAccessPolicy.java | 287 +++++++++++++++ .../apache/nifi/authorization/TestGroup.java | 169 +++++++++ .../org/apache/nifi/authorization/TestUser.java | 170 +++++++++ 8 files changed, 1822 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/main/java/org/apache/nifi/authorization/AbstractPolicyBasedAuthorizer.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/AbstractPolicyBasedAuthorizer.java b/nifi-api/src/main/java/org/apache/nifi/authorization/AbstractPolicyBasedAuthorizer.java new file mode 100644 index 0000000..1200017 --- /dev/null +++ b/nifi-api/src/main/java/org/apache/nifi/authorization/AbstractPolicyBasedAuthorizer.java @@ -0,0 +1,220 @@ +/* + * 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.authorization; + +import org.apache.nifi.authorization.exception.AuthorizationAccessException; + +import java.util.Set; + +/** + * An Authorizer that provides management of users, groups, and policies. + */ +public abstract class AbstractPolicyBasedAuthorizer implements Authorizer { + + @Override + public final AuthorizationResult authorize(AuthorizationRequest request) throws AuthorizationAccessException { + final Set<AccessPolicy> policies = getAccessPolicies(request.getResource()); + + if (policies == null || policies.isEmpty()) { + return AuthorizationResult.resourceNotFound(); + } + + final User user = getUserByIdentity(request.getIdentity()); + + if (user == null) { + return AuthorizationResult.denied("Unknown user with identity " + request.getIdentity()); + } + + for (AccessPolicy policy : policies) { + final boolean containsAction = policy.getActions().contains(request.getAction()); + final boolean containsUser = policy.getUsers().contains(user.getIdentifier()); + if (containsAction && (containsUser || containsGroup(user, policy)) ) { + return AuthorizationResult.approved(); + } + } + + return AuthorizationResult.denied(); + } + + + private boolean containsGroup(final User user, final AccessPolicy policy) { + if (user.getGroups().isEmpty() || policy.getGroups().isEmpty()) { + return false; + } + + for (String userGroup : user.getGroups()) { + if (policy.getGroups().contains(userGroup)) { + return true; + } + } + + return false; + } + + /** + * Adds a new group. + * + * @param group the Group to add + * @return the added Group + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Group addGroup(Group group) throws AuthorizationAccessException; + + /** + * Retrieves a Group by id. + * + * @param identifier the identifier of the Group to retrieve + * @return the Group with the given identifier, or null if no matching group was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Group getGroup(String identifier) throws AuthorizationAccessException; + + /** + * The group represented by the provided instance will be updated based on the provided instance. + * + * @param group an updated group instance + * @return the updated group instance, or null if no matching group was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Group updateGroup(Group group) throws AuthorizationAccessException; + + /** + * Deletes the given group. + * + * @param group the group to delete + * @return the deleted group, or null if no matching group was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Group deleteGroup(Group group) throws AuthorizationAccessException; + + /** + * Retrieves all groups. + * + * @return a list of groups + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Set<Group> getGroups() throws AuthorizationAccessException; + + + /** + * Adds the given user. + * + * @param user the user to add + * @return the user that was added + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract User addUser(User user) throws AuthorizationAccessException; + + /** + * Retrieves the user with the given identifier. + * + * @param identifier the id of the user to retrieve + * @return the user with the given id, or null if no matching user was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract User getUser(String identifier) throws AuthorizationAccessException; + + /** + * Retrieves the user with the given identity. + * + * @param identity the identity of the user to retrieve + * @return the user with the given identity, or null if no matching user was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract User getUserByIdentity(String identity) throws AuthorizationAccessException; + + /** + * The user represented by the provided instance will be updated based on the provided instance. + * + * @param user an updated user instance + * @return the updated user instance, or null if no matching user was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract User updateUser(User user) throws AuthorizationAccessException; + + /** + * Deletes the given user. + * + * @param user the user to delete + * @return the user that was deleted, or null if no matching user was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract User deleteUser(User user) throws AuthorizationAccessException; + + /** + * Retrieves all users. + * + * @return a list of users + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Set<User> getUsers() throws AuthorizationAccessException; + + + /** + * Adds the given policy. + * + * @param accessPolicy the policy to add + * @return the policy that was added + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract AccessPolicy addAccessPolicy(AccessPolicy accessPolicy) throws AuthorizationAccessException; + + /** + * Retrieves the policy with the given identifier. + * + * @param identifier the id of the policy to retrieve + * @return the policy with the given id, or null if no matching policy exists + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract AccessPolicy getAccessPolicy(String identifier) throws AuthorizationAccessException; + + /** + * The policy represented by the provided instance will be updated based on the provided instance. + * + * @param accessPolicy an updated policy + * @return the updated policy, or null if no matching policy was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract AccessPolicy updateAccessPolicy(AccessPolicy accessPolicy) throws AuthorizationAccessException; + + /** + * Deletes the given policy. + * + * @param policy the policy to delete + * @return the deleted policy, or null if no matching policy was found + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract AccessPolicy deleteAccessPolicy(AccessPolicy policy) throws AuthorizationAccessException; + + /** + * Retrieves all access policies. + * + * @return a list of policies + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException; + + /** + * Retrieves the access policies for the given Resource. + * + * @param resource the resource to retrieve policies for + * @return a set of policies for the given resource, or an empty set if there are none + * @throws AuthorizationAccessException if there was an unexpected error performing the operation + */ + public abstract Set<AccessPolicy> getAccessPolicies(Resource resource) throws AuthorizationAccessException; + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/main/java/org/apache/nifi/authorization/AccessPolicy.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/AccessPolicy.java b/nifi-api/src/main/java/org/apache/nifi/authorization/AccessPolicy.java new file mode 100644 index 0000000..f5c46e1 --- /dev/null +++ b/nifi-api/src/main/java/org/apache/nifi/authorization/AccessPolicy.java @@ -0,0 +1,356 @@ +/* + * 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.authorization; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * Defines a policy for a set of userIdentifiers to perform a set of actions on a given resource. + */ +public class AccessPolicy { + + private final String identifier; + + private final Resource resource; + + private final Set<String> users; + + private final Set<String> groups; + + private final Set<RequestAction> actions; + + private AccessPolicy(final AccessPolicyBuilder builder) { + this.identifier = builder.identifier; + this.resource = builder.resource; + this.users = Collections.unmodifiableSet(new HashSet<>(builder.users)); + this.groups = Collections.unmodifiableSet(new HashSet<>(builder.groups)); + this.actions = Collections.unmodifiableSet(new HashSet<>(builder.actions)); + + if (this.identifier == null || this.identifier.trim().isEmpty()) { + throw new IllegalArgumentException("Identifier can not be null or empty"); + } + + if (this.resource == null) { + throw new IllegalArgumentException("Resource can not be null"); + } + + if ((this.users == null || this.users.isEmpty()) && (this.groups == null || this.groups.isEmpty())) { + throw new IllegalArgumentException("Users & Groups can not both be null or empty"); + } + + if (this.actions == null || this.actions.isEmpty()) { + throw new IllegalArgumentException("Actions can not be null or empty"); + } + } + + /** + * @return the identifier for this policy + */ + public String getIdentifier() { + return identifier; + } + + /** + * @return the resource for this policy + */ + public Resource getResource() { + return resource; + } + + /** + * @return an unmodifiable set of user ids for this policy + */ + public Set<String> getUsers() { + return users; + } + + /** + * @return an unmodifiable set of group ids for this policy + */ + public Set<String> getGroups() { + return groups; + } + + /** + * @return an unmodifiable set of actions for this policy + */ + public Set<RequestAction> getActions() { + return actions; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + + final AccessPolicy other = (AccessPolicy) obj; + return Objects.equals(this.identifier, other.identifier); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.identifier); + } + + @Override + public String toString() { + return String.format("identifier[%s], resource[%s], users[%s], groups[%s], action[%s]", + getIdentifier(), getResource().getIdentifier(), getUsers(), getGroups(), getActions()); + } + + /** + * Builder for Access Policies. + */ + public static class AccessPolicyBuilder { + + private String identifier; + private Resource resource; + private Set<String> users = new HashSet<>(); + private Set<String> groups = new HashSet<>(); + private Set<RequestAction> actions = new HashSet<>(); + private final boolean fromPolicy; + + /** + * Default constructor for building a new AccessPolicy. + */ + public AccessPolicyBuilder() { + this.fromPolicy = false; + } + + /** + * Initializes the builder with the state of the provided policy. When using this constructor + * the identifier field of the builder can not be changed and will result in an IllegalStateException + * if attempting to do so. + * + * @param other the existing access policy to initialize from + */ + public AccessPolicyBuilder(final AccessPolicy other) { + if (other == null) { + throw new IllegalArgumentException("Can not initialize builder with a null access policy"); + } + + this.identifier = other.getIdentifier(); + this.resource = other.getResource(); + this.users.clear(); + this.users.addAll(other.getUsers()); + this.groups.clear(); + this.groups.addAll(other.getGroups()); + this.actions.clear(); + this.actions.addAll(other.getActions()); + this.fromPolicy = true; + } + + /** + * Sets the identifier of the builder. + * + * @param identifier the identifier to set + * @return the builder + * @throws IllegalStateException if this method is called when this builder was constructed from an existing Policy + */ + public AccessPolicyBuilder identifier(final String identifier) { + if (fromPolicy) { + throw new IllegalStateException( + "Identifier can not be changed when initialized from an existing policy"); + } + + this.identifier = identifier; + return this; + } + + /** + * Sets the resource of the builder. + * + * @param resource the resource to set + * @return the builder + */ + public AccessPolicyBuilder resource(final Resource resource) { + this.resource = resource; + return this; + } + + /** + * Adds all the users from the provided set to the builder's set of users. + * + * @param users the users to add + * @return the builder + */ + public AccessPolicyBuilder addUsers(final Set<String> users) { + if (users != null) { + this.users.addAll(users); + } + return this; + } + + /** + * Adds the given user to the builder's set of users. + * + * @param user the user to add + * @return the builder + */ + public AccessPolicyBuilder addUser(final String user) { + if (user != null) { + this.users.add(user); + } + return this; + } + + /** + * Removes all users in the provided set from the builder's set of users. + * + * @param users the users to remove + * @return the builder + */ + public AccessPolicyBuilder removeUsers(final Set<String> users) { + if (users != null) { + this.users.removeAll(users); + } + return this; + } + + /** + * Removes the provided user from the builder's set of users. + * + * @param user the user to remove + * @return the builder + */ + public AccessPolicyBuilder removeUser(final String user) { + if (user != null) { + this.users.remove(user); + } + return this; + } + + /** + * Clears the builder's set of users so that it is non-null and size == 0. + * + * @return the builder + */ + public AccessPolicyBuilder clearUsers() { + this.users.clear(); + return this; + } + + /** + * Adds all the groups from the provided set to the builder's set of groups. + * + * @param groups the groups to add + * @return the builder + */ + public AccessPolicyBuilder addGroups(final Set<String> groups) { + if (groups != null) { + this.groups.addAll(groups); + } + return this; + } + + /** + * Adds the given group to the builder's set of groups. + * + * @param group the group to add + * @return the builder + */ + public AccessPolicyBuilder addGroup(final String group) { + if (group != null) { + this.groups.add(group); + } + return this; + } + + /** + * Removes all groups in the provided set from the builder's set of groups. + * + * @param groups the groups to remove + * @return the builder + */ + public AccessPolicyBuilder removeGroups(final Set<String> groups) { + if (groups != null) { + this.groups.removeAll(groups); + } + return this; + } + + /** + * Removes the provided groups from the builder's set of groups. + * + * @param group the group to remove + * @return the builder + */ + public AccessPolicyBuilder removeGroup(final String group) { + if (group != null) { + this.groups.remove(group); + } + return this; + } + + /** + * Clears the builder's set of groups so that it is non-null and size == 0. + * + * @return the builder + */ + public AccessPolicyBuilder clearGroups() { + this.groups.clear(); + return this; + } + + /** + * Adds the provided action to the builder's set of actions. + * + * @param action the action to add + * @return the builder + */ + public AccessPolicyBuilder addAction(final RequestAction action) { + this.actions.add(action); + return this; + } + + /** + * Removes the provided action from the builder's set of actions. + * + * @param action the action to remove + * @return the builder + */ + public AccessPolicyBuilder removeAction(final RequestAction action) { + this.actions.remove(action); + return this; + } + + /** + * Clears the builder's set of actions so that it is non-null and size == 0. + * + * @return the builder + */ + public AccessPolicyBuilder clearActions() { + this.actions.clear(); + return this; + } + + /** + * @return a new AccessPolicy constructed from the state of the builder + */ + public AccessPolicy build() { + return new AccessPolicy(this); + } + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/main/java/org/apache/nifi/authorization/Group.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/Group.java b/nifi-api/src/main/java/org/apache/nifi/authorization/Group.java new file mode 100644 index 0000000..d7b0f2e --- /dev/null +++ b/nifi-api/src/main/java/org/apache/nifi/authorization/Group.java @@ -0,0 +1,226 @@ +/* + * 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.authorization; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * A group that users can belong to. + */ +public class Group { + + private final String identifier; + + private final String name; + + private final Set<String> users; + + private Group(final GroupBuilder builder) { + this.identifier = builder.identifier; + this.name = builder.name; + this.users = Collections.unmodifiableSet(new HashSet<>(builder.users)); + + if (this.identifier == null || this.identifier.trim().isEmpty()) { + throw new IllegalArgumentException("Identifier can not be null or empty"); + } + + if (this.name == null || this.name.trim().isEmpty()) { + throw new IllegalArgumentException("Name can not be null or empty"); + } + } + + /** + * @return the identifier of the group + */ + public String getIdentifier() { + return identifier; + } + + /** + * @return the name of the group + */ + public String getName() { + return name; + } + + /** + * @return an unmodifiable set of user identifiers that belong to this group + */ + public Set<String> getUsers() { + return users; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + + final Group other = (Group) obj; + return Objects.equals(this.identifier, other.identifier); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.identifier); + } + + @Override + public String toString() { + return String.format("identifier[%s], name[%s]", getIdentifier(), getName()); + } + + + /** + * Builder for creating Groups. + */ + public static class GroupBuilder { + + private String identifier; + private String name; + private Set<String> users = new HashSet<>(); + private final boolean fromGroup; + + public GroupBuilder() { + this.fromGroup = false; + } + + /** + * Initializes the builder with the state of the provided group. When using this constructor + * the identifier field of the builder can not be changed and will result in an IllegalStateException + * if attempting to do so. + * + * @param other the existing access policy to initialize from + */ + public GroupBuilder(final Group other) { + if (other == null) { + throw new IllegalArgumentException("Provided group can not be null"); + } + + this.identifier = other.getIdentifier(); + this.name = other.getName(); + this.users.clear(); + this.users.addAll(other.getUsers()); + this.fromGroup = true; + } + + /** + * Sets the identifier of the builder. + * + * @param identifier the identifier + * @return the builder + * @throws IllegalStateException if this method is called when this builder was constructed from an existing Group + */ + public GroupBuilder identifier(final String identifier) { + if (fromGroup) { + throw new IllegalStateException( + "Identifier can not be changed when initialized from an existing group"); + } + + this.identifier = identifier; + return this; + } + + /** + * Sets the name of the builder. + * + * @param name the name + * @return the builder + */ + public GroupBuilder name(final String name) { + this.name = name; + return this; + } + + /** + * Adds all users from the provided set to the builder's set of users. + * + * @param users a set of users to add + * @return the builder + */ + public GroupBuilder addUsers(final Set<String> users) { + if (users != null) { + this.users.addAll(users); + } + return this; + } + + /** + * Adds the given user to the builder's set of users. + * + * @param user the user to add + * @return the builder + */ + public GroupBuilder addUser(final String user) { + if (user != null) { + this.users.add(user); + } + return this; + } + + /** + * Removes the given user from the builder's set of users. + * + * @param user the user to remove + * @return the builder + */ + public GroupBuilder removeUser(final String user) { + if (user != null) { + this.users.remove(user); + } + return this; + } + + /** + * Removes all users from the provided set from the builder's set of users. + * + * @param users the users to remove + * @return the builder + */ + public GroupBuilder removeUsers(final Set<String> users) { + if (users != null) { + this.users.removeAll(users); + } + return this; + } + + /** + * Clears the builder's set of users so that users is non-null with size 0. + * + * @return the builder + */ + public GroupBuilder clearUsers() { + this.users.clear(); + return this; + } + + /** + * @return a new Group constructed from the state of the builder + */ + public Group build() { + return new Group(this); + } + + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/main/java/org/apache/nifi/authorization/User.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/main/java/org/apache/nifi/authorization/User.java b/nifi-api/src/main/java/org/apache/nifi/authorization/User.java new file mode 100644 index 0000000..e068736 --- /dev/null +++ b/nifi-api/src/main/java/org/apache/nifi/authorization/User.java @@ -0,0 +1,229 @@ +/* + * 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.authorization; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * A user to create authorization policies for. + */ +public class User { + + private final String identifier; + + private final String identity; + + private final Set<String> groups; + + private User(final UserBuilder builder) { + this.identifier = builder.identifier; + this.identity = builder.identity; + this.groups = Collections.unmodifiableSet(new HashSet<>(builder.groups)); + + if (identifier == null || identifier.trim().isEmpty()) { + throw new IllegalArgumentException("Identifier can not be null or empty"); + } + + if (identity == null || identity.trim().isEmpty()) { + throw new IllegalArgumentException("Identity can not be null or empty"); + } + + } + + /** + * @return the identifier of the user + */ + public String getIdentifier() { + return identifier; + } + + /** + * @return the identity string of the user + */ + public String getIdentity() { + return identity; + } + + /** + * @return an unmodifiable set of group ids + */ + public Set<String> getGroups() { + return groups; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + + final User other = (User) obj; + return Objects.equals(this.identifier, other.identifier); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.identifier); + } + + @Override + public String toString() { + return String.format("identifier[%s], identity[%s]", getIdentifier(), getIdentity()); + } + + /** + * Builder for Users. + */ + public static class UserBuilder { + + private String identifier; + private String identity; + private Set<String> groups = new HashSet<>(); + private final boolean fromUser; + + /** + * Default constructor for building a new User. + */ + public UserBuilder() { + this.fromUser = false; + } + + /** + * Initializes the builder with the state of the provided user. When using this constructor + * the identifier field of the builder can not be changed and will result in an IllegalStateException + * if attempting to do so. + * + * @param other the existing user to initialize from + */ + public UserBuilder(final User other) { + if (other == null) { + throw new IllegalArgumentException("Provided user can not be null"); + } + + this.identifier = other.getIdentifier(); + this.identity = other.getIdentity(); + this.groups.clear(); + this.groups.addAll(other.getGroups()); + this.fromUser = true; + } + + /** + * Sets the identifier of the builder. + * + * @param identifier the identifier to set + * @return the builder + * @throws IllegalStateException if this method is called when this builder was constructed from an existing User + */ + public UserBuilder identifier(final String identifier) { + if (fromUser) { + throw new IllegalStateException( + "Identifier can not be changed when initialized from an existing user"); + } + + this.identifier = identifier; + return this; + } + + /** + * Sets the identity of the builder. + * + * @param identity the identity to set + * @return the builder + */ + public UserBuilder identity(final String identity) { + this.identity = identity; + return this; + } + + /** + * Adds all groups from the provided set to the builder's set of groups. + * + * @param groups the groups to add + * @return the builder + */ + public UserBuilder addGroups(final Set<String> groups) { + if (groups != null) { + this.groups.addAll(groups); + } + return this; + } + + /** + * Adds the provided group to the builder's set of groups. + * + * @param group the group to add + * @return the builder + */ + public UserBuilder addGroup(final String group) { + if (group != null) { + this.groups.add(group); + } + return this; + } + + /** + * Removes all groups in the provided set from the builder's set of groups. + * + * @param groups the groups to remove + * @return the builder + */ + public UserBuilder removeGroups(final Set<String> groups) { + if (groups != null) { + this.groups.removeAll(groups); + } + return this; + } + + /** + * Removes the provided group from the builder's set of groups. + * + * @param group the group to remove + * @return the builder + */ + public UserBuilder removeGroup(final String group) { + if (group != null) { + this.groups.remove(group); + } + return this; + } + + /** + * Clears the builder's set of groups so that groups is non-null with size == 0. + * + * @return the builder + */ + public UserBuilder clearGroups() { + this.groups.clear(); + return this; + } + + /** + * @return a new User constructed from the state of the builder + */ + public User build() { + return new User(this); + } + + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/test/java/org/apache/nifi/authorization/TestAbstractPolicyBasedAuthorizer.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/test/java/org/apache/nifi/authorization/TestAbstractPolicyBasedAuthorizer.java b/nifi-api/src/test/java/org/apache/nifi/authorization/TestAbstractPolicyBasedAuthorizer.java new file mode 100644 index 0000000..8dbc781 --- /dev/null +++ b/nifi-api/src/test/java/org/apache/nifi/authorization/TestAbstractPolicyBasedAuthorizer.java @@ -0,0 +1,165 @@ +/* + * 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.authorization; + +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +public class TestAbstractPolicyBasedAuthorizer { + + static final Resource TEST_RESOURCE = new Resource() { + @Override + public String getIdentifier() { + return "1"; + } + + @Override + public String getName() { + return "resource1"; + } + }; + + @Test + public void testApproveBasedOnUser() { + AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class); + + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + + final Set<AccessPolicy> policiesForResource = new HashSet<>(); + policiesForResource.add(new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addUser(userIdentifier) + .addAction(RequestAction.READ) + .build()); + + when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(policiesForResource); + + final User user = new User.UserBuilder() + .identity(userIdentity) + .identifier(userIdentifier) + .build(); + + when(authorizer.getUserByIdentity(userIdentity)).thenReturn(user); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + assertEquals(AuthorizationResult.approved(), authorizer.authorize(request)); + } + + @Test + public void testApprovedBasedOnGroup() { + AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class); + + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + final String groupIdentifier = "groupIdentifier1"; + + final Set<AccessPolicy> policiesForResource = new HashSet<>(); + policiesForResource.add(new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addGroup(groupIdentifier) + .addAction(RequestAction.READ) + .build()); + + when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(policiesForResource); + + final User user = new User.UserBuilder() + .identity(userIdentity) + .identifier(userIdentifier) + .addGroup(groupIdentifier) + .build(); + + when(authorizer.getUserByIdentity(userIdentity)).thenReturn(user); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + assertEquals(AuthorizationResult.approved(), authorizer.authorize(request)); + } + + @Test + public void testDeny() { + AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class); + + final String userIdentifier = "userIdentifier1"; + final String userIdentity = "userIdentity1"; + + final Set<AccessPolicy> policiesForResource = new HashSet<>(); + policiesForResource.add(new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addUser("NOT_USER_1") + .addAction(RequestAction.READ) + .build()); + + when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(policiesForResource); + + final User user = new User.UserBuilder() + .identity(userIdentity) + .identifier(userIdentifier) + .build(); + + when(authorizer.getUserByIdentity(userIdentity)).thenReturn(user); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(userIdentity) + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + assertEquals(AuthorizationResult.denied().getResult(), authorizer.authorize(request).getResult()); + } + + @Test + public void testResourceNotFound() { + AbstractPolicyBasedAuthorizer authorizer = Mockito.mock(AbstractPolicyBasedAuthorizer.class); + when(authorizer.getAccessPolicies(TEST_RESOURCE)).thenReturn(new HashSet<>()); + + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity("userIdentity") + .resource(TEST_RESOURCE) + .action(RequestAction.READ) + .accessAttempt(true) + .anonymous(false) + .build(); + + assertEquals(AuthorizationResult.resourceNotFound(), authorizer.authorize(request)); + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/test/java/org/apache/nifi/authorization/TestAccessPolicy.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/test/java/org/apache/nifi/authorization/TestAccessPolicy.java b/nifi-api/src/test/java/org/apache/nifi/authorization/TestAccessPolicy.java new file mode 100644 index 0000000..28c0b9f --- /dev/null +++ b/nifi-api/src/test/java/org/apache/nifi/authorization/TestAccessPolicy.java @@ -0,0 +1,287 @@ +/* + * 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.authorization; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class TestAccessPolicy { + + static final Resource TEST_RESOURCE = new Resource() { + @Override + public String getIdentifier() { + return "1"; + } + + @Override + public String getName() { + return "resource1"; + } + }; + + @Test + public void testSimpleCreation() { + final String identifier = "1"; + final String user1 = "user1"; + final String user2 = "user2"; + final RequestAction action = RequestAction.READ; + + final AccessPolicy policy = new AccessPolicy.AccessPolicyBuilder() + .identifier(identifier) + .resource(TEST_RESOURCE) + .addUser(user1) + .addUser(user2) + .addAction(action) + .build(); + + assertEquals(identifier, policy.getIdentifier()); + + assertNotNull(policy.getResource()); + assertEquals(TEST_RESOURCE.getIdentifier(), policy.getResource().getIdentifier()); + + assertNotNull(policy.getUsers()); + assertEquals(2, policy.getUsers().size()); + assertTrue(policy.getUsers().contains(user1)); + assertTrue(policy.getUsers().contains(user2)); + + assertNotNull(policy.getActions()); + assertEquals(1, policy.getActions().size()); + assertTrue(policy.getActions().contains(action)); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingIdentifier() { + new AccessPolicy.AccessPolicyBuilder() + .resource(TEST_RESOURCE) + .addUser("user1") + .addAction(RequestAction.READ) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingResource() { + new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .addUser("user1") + .addAction(RequestAction.READ) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingUsersAndGroups() { + new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addAction(RequestAction.READ) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingActions() { + new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addUser("user1") + .build(); + } + + @Test + public void testFromPolicy() { + final String identifier = "1"; + final String user1 = "user1"; + final String user2 = "user2"; + final String group1 = "group1"; + final String group2 = "group2"; + final RequestAction action = RequestAction.READ; + + final AccessPolicy policy = new AccessPolicy.AccessPolicyBuilder() + .identifier(identifier) + .resource(TEST_RESOURCE) + .addUser(user1) + .addUser(user2) + .addGroup(group1) + .addGroup(group2) + .addAction(action) + .build(); + + assertEquals(identifier, policy.getIdentifier()); + + assertNotNull(policy.getResource()); + assertEquals(TEST_RESOURCE.getIdentifier(), policy.getResource().getIdentifier()); + + assertNotNull(policy.getUsers()); + assertEquals(2, policy.getUsers().size()); + assertTrue(policy.getUsers().contains(user1)); + assertTrue(policy.getUsers().contains(user2)); + + assertNotNull(policy.getGroups()); + assertEquals(2, policy.getGroups().size()); + assertTrue(policy.getGroups().contains(group1)); + assertTrue(policy.getGroups().contains(group2)); + + assertNotNull(policy.getActions()); + assertEquals(1, policy.getActions().size()); + assertTrue(policy.getActions().contains(action)); + + final AccessPolicy policy2 = new AccessPolicy.AccessPolicyBuilder(policy).build(); + assertEquals(policy.getIdentifier(), policy2.getIdentifier()); + assertEquals(policy.getResource().getIdentifier(), policy2.getResource().getIdentifier()); + assertEquals(policy.getUsers(), policy2.getUsers()); + assertEquals(policy.getActions(), policy2.getActions()); + } + + @Test(expected = IllegalStateException.class) + public void testFromPolicyAndChangeIdentifier() { + final AccessPolicy policy = new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addUser("user1") + .addAction(RequestAction.READ) + .build(); + + new AccessPolicy.AccessPolicyBuilder(policy).identifier("2").build(); + } + + @Test + public void testAddRemoveClearUsers() { + final AccessPolicy.AccessPolicyBuilder builder = new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addUser("user1") + .addAction(RequestAction.READ); + + final AccessPolicy policy1 = builder.build(); + assertEquals(1, policy1.getUsers().size()); + assertTrue(policy1.getUsers().contains("user1")); + + final Set<String> moreEntities = new HashSet<>(); + moreEntities.add("user2"); + moreEntities.add("user3"); + moreEntities.add("user4"); + + final AccessPolicy policy2 = builder.addUsers(moreEntities).build(); + assertEquals(4, policy2.getUsers().size()); + assertTrue(policy2.getUsers().contains("user1")); + assertTrue(policy2.getUsers().contains("user2")); + assertTrue(policy2.getUsers().contains("user3")); + assertTrue(policy2.getUsers().contains("user4")); + + final AccessPolicy policy3 = builder.removeUser("user3").build(); + assertEquals(3, policy3.getUsers().size()); + assertTrue(policy3.getUsers().contains("user1")); + assertTrue(policy3.getUsers().contains("user2")); + assertTrue(policy3.getUsers().contains("user4")); + + final Set<String> removeEntities = new HashSet<>(); + removeEntities.add("user1"); + removeEntities.add("user4"); + + final AccessPolicy policy4 = builder.removeUsers(removeEntities).build(); + assertEquals(1, policy4.getUsers().size()); + assertTrue(policy4.getUsers().contains("user2")); + + try { + builder.clearUsers().build(); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + + } + } + + @Test + public void testAddRemoveClearGroups() { + final AccessPolicy.AccessPolicyBuilder builder = new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addGroup("group1") + .addAction(RequestAction.READ); + + final AccessPolicy policy1 = builder.build(); + assertEquals(1, policy1.getGroups().size()); + assertTrue(policy1.getGroups().contains("group1")); + + final Set<String> moreGroups = new HashSet<>(); + moreGroups.add("group2"); + moreGroups.add("group3"); + moreGroups.add("group4"); + + final AccessPolicy policy2 = builder.addGroups(moreGroups).build(); + assertEquals(4, policy2.getGroups().size()); + assertTrue(policy2.getGroups().contains("group1")); + assertTrue(policy2.getGroups().contains("group2")); + assertTrue(policy2.getGroups().contains("group3")); + assertTrue(policy2.getGroups().contains("group4")); + + final AccessPolicy policy3 = builder.removeGroup("group3").build(); + assertEquals(3, policy3.getGroups().size()); + assertTrue(policy3.getGroups().contains("group1")); + assertTrue(policy3.getGroups().contains("group2")); + assertTrue(policy3.getGroups().contains("group4")); + + final Set<String> removeGroups = new HashSet<>(); + removeGroups.add("group1"); + removeGroups.add("group4"); + + final AccessPolicy policy4 = builder.removeGroups(removeGroups).build(); + assertEquals(1, policy4.getGroups().size()); + assertTrue(policy4.getGroups().contains("group2")); + + try { + builder.clearGroups().build(); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + + } + } + + + @Test + public void testAddRemoveClearActions() { + final AccessPolicy.AccessPolicyBuilder builder = new AccessPolicy.AccessPolicyBuilder() + .identifier("1") + .resource(TEST_RESOURCE) + .addUser("user1") + .addAction(RequestAction.READ); + + final AccessPolicy policy1 = builder.build(); + assertEquals(1, policy1.getActions().size()); + assertTrue(policy1.getActions().contains(RequestAction.READ)); + + final AccessPolicy policy2 = builder + .removeAction(RequestAction.READ) + .addAction(RequestAction.WRITE) + .build(); + + assertEquals(1, policy2.getActions().size()); + assertTrue(policy2.getActions().contains(RequestAction.WRITE)); + + try { + builder.clearActions().build(); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + + } + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/test/java/org/apache/nifi/authorization/TestGroup.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/test/java/org/apache/nifi/authorization/TestGroup.java b/nifi-api/src/test/java/org/apache/nifi/authorization/TestGroup.java new file mode 100644 index 0000000..39dbab6 --- /dev/null +++ b/nifi-api/src/test/java/org/apache/nifi/authorization/TestGroup.java @@ -0,0 +1,169 @@ +/* + * 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.authorization; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class TestGroup { + + @Test + public void testSimpleCreation() { + final String id = "1"; + final String name = "group1"; + final String user1 = "user1"; + final String user2 = "user2"; + + final Group group = new Group.GroupBuilder() + .identifier(id) + .name(name) + .addUser(user1) + .addUser(user2) + .build(); + + assertEquals(id, group.getIdentifier()); + assertEquals(name, group.getName()); + + assertNotNull(group.getUsers()); + assertEquals(2, group.getUsers().size()); + assertTrue(group.getUsers().contains(user1)); + assertTrue(group.getUsers().contains(user2)); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingId() { + new Group.GroupBuilder() + .name("group1") + .addUser("user1") + .addUser("user2") + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingName() { + new Group.GroupBuilder() + .identifier("1") + .addUser("user1") + .addUser("user2") + .build(); + } + + @Test + public void testMissingUsers() { + final String id = "1"; + final String name = "group1"; + + final Group group = new Group.GroupBuilder() + .identifier(id) + .name(name) + .build(); + + assertEquals(id, group.getIdentifier()); + assertEquals(name, group.getName()); + + assertNotNull(group.getUsers()); + assertEquals(0, group.getUsers().size()); + } + + @Test + public void testFromGroup() { + final String id = "1"; + final String name = "group1"; + final String user1 = "user1"; + final String user2 = "user2"; + + final Group group1 = new Group.GroupBuilder() + .identifier(id) + .name(name) + .addUser(user1) + .addUser(user2) + .build(); + + assertEquals(id, group1.getIdentifier()); + assertEquals(name, group1.getName()); + + assertNotNull(group1.getUsers()); + assertEquals(2, group1.getUsers().size()); + assertTrue(group1.getUsers().contains(user1)); + assertTrue(group1.getUsers().contains(user2)); + + final Group group2 = new Group.GroupBuilder(group1).build(); + assertEquals(group1.getIdentifier(), group2.getIdentifier()); + assertEquals(group1.getName(), group2.getName()); + assertEquals(group1.getUsers(), group2.getUsers()); + } + + @Test(expected = IllegalStateException.class) + public void testFromGroupAndChangeIdentifier() { + final Group group1 = new Group.GroupBuilder() + .identifier("1") + .name("group1") + .addUser("user1") + .build(); + + new Group.GroupBuilder(group1).identifier("2").build(); + } + + @Test + public void testAddRemoveClearUsers() { + final Group.GroupBuilder builder = new Group.GroupBuilder() + .identifier("1") + .name("group1") + .addUser("user1"); + + final Group group1 = builder.build(); + assertNotNull(group1.getUsers()); + assertEquals(1, group1.getUsers().size()); + assertTrue(group1.getUsers().contains("user1")); + + final Set<String> moreUsers = new HashSet<>(); + moreUsers.add("user2"); + moreUsers.add("user3"); + moreUsers.add("user4"); + + final Group group2 = builder.addUsers(moreUsers).build(); + assertEquals(4, group2.getUsers().size()); + assertTrue(group2.getUsers().contains("user1")); + assertTrue(group2.getUsers().contains("user2")); + assertTrue(group2.getUsers().contains("user3")); + assertTrue(group2.getUsers().contains("user4")); + + final Group group3 = builder.removeUser("user2").build(); + assertEquals(3, group3.getUsers().size()); + assertTrue(group3.getUsers().contains("user1")); + assertTrue(group3.getUsers().contains("user3")); + assertTrue(group3.getUsers().contains("user4")); + + final Set<String> removeUsers = new HashSet<>(); + removeUsers.add("user1"); + removeUsers.add("user4"); + + final Group group4 = builder.removeUsers(removeUsers).build(); + assertEquals(1, group4.getUsers().size()); + assertTrue(group4.getUsers().contains("user3")); + + final Group group5 = builder.clearUsers().build(); + assertEquals(0, group5.getUsers().size()); + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/71492535/nifi-api/src/test/java/org/apache/nifi/authorization/TestUser.java ---------------------------------------------------------------------- diff --git a/nifi-api/src/test/java/org/apache/nifi/authorization/TestUser.java b/nifi-api/src/test/java/org/apache/nifi/authorization/TestUser.java new file mode 100644 index 0000000..8e6f9aa --- /dev/null +++ b/nifi-api/src/test/java/org/apache/nifi/authorization/TestUser.java @@ -0,0 +1,170 @@ +/* + * 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.authorization; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class TestUser { + + @Test + public void testSimpleCreation() { + final String identifier = "1"; + final String identity = "user1"; + final String group1 = "group1"; + final String group2 = "group2"; + + final User user = new User.UserBuilder() + .identifier(identifier) + .identity(identity) + .addGroup(group1) + .addGroup(group2) + .build(); + + assertEquals(identifier, user.getIdentifier()); + assertEquals(identity, user.getIdentity()); + + assertNotNull(user.getGroups()); + assertEquals(2, user.getGroups().size()); + assertTrue(user.getGroups().contains(group1)); + assertTrue(user.getGroups().contains(group2)); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingIdentifier() { + new User.UserBuilder() + .identity("user1") + .addGroup("group1") + .addGroup("group2") + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingIdentity() { + new User.UserBuilder() + .identifier("1") + .addGroup("group1") + .addGroup("group2") + .build(); + } + + @Test + public void testMissingGroups() { + final String identifier = "1"; + final String identity = "user1"; + + final User user = new User.UserBuilder() + .identifier(identifier) + .identity(identity) + .build(); + + assertEquals(identifier, user.getIdentifier()); + assertEquals(identity, user.getIdentity()); + + assertNotNull(user.getGroups()); + assertEquals(0, user.getGroups().size()); + } + + @Test + public void testFromUser() { + final String identifier = "1"; + final String identity = "user1"; + final String group1 = "group1"; + final String group2 = "group2"; + + final User user = new User.UserBuilder() + .identifier(identifier) + .identity(identity) + .addGroup(group1) + .addGroup(group2) + .build(); + + assertEquals(identifier, user.getIdentifier()); + assertEquals(identity, user.getIdentity()); + + assertNotNull(user.getGroups()); + assertEquals(2, user.getGroups().size()); + assertTrue(user.getGroups().contains(group1)); + assertTrue(user.getGroups().contains(group2)); + + final User user2 = new User.UserBuilder(user).build(); + assertEquals(user.getIdentifier(), user2.getIdentifier()); + assertEquals(user.getIdentity(), user2.getIdentity()); + assertEquals(user.getGroups(), user2.getGroups()); + } + + @Test(expected = IllegalStateException.class) + public void testFromUserAndChangeIdentifier() { + final User user = new User.UserBuilder() + .identifier("1") + .identity("user1") + .addGroup("group1") + .addGroup("group2") + .build(); + + new User.UserBuilder(user).identifier("2").build(); + } + + @Test + public void testAddRemoveClearGroups() { + final User.UserBuilder builder = new User.UserBuilder() + .identifier("1") + .identity("user1") + .addGroup("group1"); + + final User user1 = builder.build(); + assertNotNull(user1.getGroups()); + assertEquals(1, user1.getGroups().size()); + assertTrue(user1.getGroups().contains("group1")); + + final Set<String> moreGroups = new HashSet<>(); + moreGroups.add("group2"); + moreGroups.add("group3"); + moreGroups.add("group4"); + + final User user2 = builder.addGroups(moreGroups).build(); + assertEquals(4, user2.getGroups().size()); + assertTrue(user2.getGroups().contains("group1")); + assertTrue(user2.getGroups().contains("group2")); + assertTrue(user2.getGroups().contains("group3")); + assertTrue(user2.getGroups().contains("group4")); + + final User user3 = builder.removeGroup("group2").build(); + assertEquals(3, user3.getGroups().size()); + assertTrue(user3.getGroups().contains("group1")); + assertTrue(user3.getGroups().contains("group3")); + assertTrue(user3.getGroups().contains("group4")); + + final Set<String> removeGroups = new HashSet<>(); + removeGroups.add("group1"); + removeGroups.add("group4"); + + final User user4 = builder.removeGroups(removeGroups).build(); + assertEquals(1, user4.getGroups().size()); + assertTrue(user4.getGroups().contains("group3")); + + final User user5 = builder.clearGroups().build(); + assertEquals(0, user5.getGroups().size()); + } + +}
