mirror of https://github.com/apache/nifi.git
NIFI-1952 Updated StandardPolicyBasedAuthorizerDAO to throw ResourceNotFoundExceptions when user/group/policy not found
Added spec for StandardPolicyBasedAuthorizerDAO Added exception mapper for AuthorizationAccessException, added mapper to nifi-web-api-context.xml Added rest endpoints to get all users and user groups Merged UsersResource and UserGroupsResource into TenantsResource This closes #582
This commit is contained in:
parent
b911c9dbdf
commit
64719b6f9b
|
@ -29,7 +29,7 @@ import java.util.Set;
|
||||||
public class UserDTO extends ComponentDTO {
|
public class UserDTO extends ComponentDTO {
|
||||||
|
|
||||||
private String identity;
|
private String identity;
|
||||||
private Set<UserGroupEntity> groups;
|
private Set<UserGroupEntity> userGroups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return users identity
|
* @return users identity
|
||||||
|
@ -49,11 +49,11 @@ public class UserDTO extends ComponentDTO {
|
||||||
* @return groups to which the user belongs
|
* @return groups to which the user belongs
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "The groups to which the user belongs.")
|
@ApiModelProperty(value = "The groups to which the user belongs.")
|
||||||
public Set<UserGroupEntity> getGroups() {
|
public Set<UserGroupEntity> getUserGroups() {
|
||||||
return groups;
|
return userGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGroups(Set<UserGroupEntity> groups) {
|
public void setUserGroups(Set<UserGroupEntity> userGroups) {
|
||||||
this.groups = groups;
|
this.userGroups = userGroups;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,31 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.authorization.resource;
|
package org.apache.nifi.web.api.entity;
|
||||||
|
|
||||||
import org.apache.nifi.authorization.Resource;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
public class UserGroupsAuthorizable implements Authorizable {
|
/**
|
||||||
@Override
|
* A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a collection of
|
||||||
public Authorizable getParentAuthorizable() {
|
* UserGroupEntity objects.
|
||||||
return null;
|
*/
|
||||||
|
@XmlRootElement(name = "userGroupsEntity")
|
||||||
|
public class UserGroupsEntity {
|
||||||
|
|
||||||
|
private Collection<UserGroupEntity> userGroups;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collection of UserGroupEntity objects that are being serialized.
|
||||||
|
*
|
||||||
|
* @return The UserGroupEntity objects
|
||||||
|
*/
|
||||||
|
public Collection<UserGroupEntity> getUserGroups() {
|
||||||
|
return userGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setUserGroups(Collection<UserGroupEntity> userGroups) {
|
||||||
public Resource getResource() {
|
this.userGroups = userGroups;
|
||||||
return ResourceFactory.getUserGroupsResource();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -16,45 +16,28 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.web.api.entity;
|
package org.apache.nifi.web.api.entity;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
import java.util.Collection;
|
||||||
import org.apache.nifi.web.api.dto.UserDTO;
|
|
||||||
import org.apache.nifi.web.api.dto.util.TimeAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a collection of UserDTO.
|
* A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a collection of UserEntity
|
||||||
|
* objects.
|
||||||
*/
|
*/
|
||||||
@XmlRootElement(name = "usersEntity")
|
@XmlRootElement(name = "usersEntity")
|
||||||
public class UsersEntity extends Entity {
|
public class UsersEntity extends Entity {
|
||||||
|
|
||||||
private Collection<UserDTO> users;
|
private Collection<UserEntity> users;
|
||||||
private Date generated;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collection of UserDTOs that are being serialized.
|
* The collection of UserEntity objects that are being serialized.
|
||||||
*
|
*
|
||||||
* @return The UserDTO object
|
* @return The UserEntity objects
|
||||||
*/
|
*/
|
||||||
public Collection<UserDTO> getUsers() {
|
public Collection<UserEntity> getUsers() {
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsers(Collection<UserDTO> users) {
|
public void setUsers(Collection<UserEntity> users) {
|
||||||
this.users = users;
|
this.users = users;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return When this content was generated
|
|
||||||
*/
|
|
||||||
@XmlJavaTypeAdapter(TimeAdapter.class)
|
|
||||||
public Date getGenerated() {
|
|
||||||
return generated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGenerated(Date generated) {
|
|
||||||
this.generated = generated;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,11 +327,8 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer {
|
||||||
addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
addAccessPolicy(authorizations, ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// grant the user read/write access to the /users resource
|
// grant the user read/write access to the /tenants resource
|
||||||
addAccessPolicy(authorizations, ResourceType.User.getValue(), adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
addAccessPolicy(authorizations, ResourceType.Tenant.getValue(), adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
||||||
|
|
||||||
// grant the user read/write access to the /groups resource
|
|
||||||
addAccessPolicy(authorizations, ResourceType.Group.getValue(), adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
|
||||||
|
|
||||||
// grant the user read/write access to the /policies resource
|
// grant the user read/write access to the /policies resource
|
||||||
addAccessPolicy(authorizations, ResourceType.Policy.getValue(), adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
addAccessPolicy(authorizations, ResourceType.Policy.getValue(), adminUser.getIdentifier(), READ_CODE + WRITE_CODE);
|
||||||
|
|
|
@ -79,8 +79,7 @@ public final class RoleAccessPolicy {
|
||||||
if (rootGroupId != null) {
|
if (rootGroupId != null) {
|
||||||
adminPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
|
adminPolicies.add(new RoleAccessPolicy(ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, READ_ACTION));
|
||||||
}
|
}
|
||||||
adminPolicies.add(new RoleAccessPolicy(ResourceType.User.getValue(), READ_WRITE_ACTION));
|
adminPolicies.add(new RoleAccessPolicy(ResourceType.Tenant.getValue(), READ_WRITE_ACTION));
|
||||||
adminPolicies.add(new RoleAccessPolicy(ResourceType.Group.getValue(), READ_WRITE_ACTION));
|
|
||||||
adminPolicies.add(new RoleAccessPolicy(ResourceType.Policy.getValue(), READ_WRITE_ACTION));
|
adminPolicies.add(new RoleAccessPolicy(ResourceType.Policy.getValue(), READ_WRITE_ACTION));
|
||||||
roleAccessPolicies.put(Role.ROLE_ADMIN, Collections.unmodifiableSet(adminPolicies));
|
roleAccessPolicies.put(Role.ROLE_ADMIN, Collections.unmodifiableSet(adminPolicies));
|
||||||
|
|
||||||
|
|
|
@ -235,7 +235,7 @@ public class FileAuthorizerTest {
|
||||||
|
|
||||||
// verify user4's policies
|
// verify user4's policies
|
||||||
final Map<String,Set<RequestAction>> user4Policies = getResourceActions(policies, user4);
|
final Map<String,Set<RequestAction>> user4Policies = getResourceActions(policies, user4);
|
||||||
assertEquals(6, user4Policies.size());
|
assertEquals(5, user4Policies.size());
|
||||||
|
|
||||||
assertTrue(user4Policies.containsKey(ResourceType.Flow.getValue()));
|
assertTrue(user4Policies.containsKey(ResourceType.Flow.getValue()));
|
||||||
assertEquals(1, user4Policies.get(ResourceType.Flow.getValue()).size());
|
assertEquals(1, user4Policies.get(ResourceType.Flow.getValue()).size());
|
||||||
|
@ -245,11 +245,8 @@ public class FileAuthorizerTest {
|
||||||
assertEquals(1, user4Policies.get(ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID).size());
|
assertEquals(1, user4Policies.get(ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID).size());
|
||||||
assertTrue(user4Policies.get(ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID).contains(RequestAction.READ));
|
assertTrue(user4Policies.get(ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID).contains(RequestAction.READ));
|
||||||
|
|
||||||
assertTrue(user4Policies.containsKey(ResourceType.User.getValue()));
|
assertTrue(user4Policies.containsKey(ResourceType.Tenant.getValue()));
|
||||||
assertEquals(2, user4Policies.get(ResourceType.User.getValue()).size());
|
assertEquals(2, user4Policies.get(ResourceType.Tenant.getValue()).size());
|
||||||
|
|
||||||
assertTrue(user4Policies.containsKey(ResourceType.Group.getValue()));
|
|
||||||
assertEquals(2, user4Policies.get(ResourceType.Group.getValue()).size());
|
|
||||||
|
|
||||||
assertTrue(user4Policies.containsKey(ResourceType.Policy.getValue()));
|
assertTrue(user4Policies.containsKey(ResourceType.Policy.getValue()));
|
||||||
assertEquals(2, user4Policies.get(ResourceType.Policy.getValue()).size());
|
assertEquals(2, user4Policies.get(ResourceType.Policy.getValue()).size());
|
||||||
|
@ -338,7 +335,7 @@ public class FileAuthorizerTest {
|
||||||
assertEquals(adminIdentity, adminUser.getIdentity());
|
assertEquals(adminIdentity, adminUser.getIdentity());
|
||||||
|
|
||||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||||
assertEquals(5, policies.size());
|
assertEquals(4, policies.size());
|
||||||
|
|
||||||
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
||||||
|
|
||||||
|
@ -375,7 +372,7 @@ public class FileAuthorizerTest {
|
||||||
assertEquals(adminIdentity, adminUser.getIdentity());
|
assertEquals(adminIdentity, adminUser.getIdentity());
|
||||||
|
|
||||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||||
assertEquals(4, policies.size());
|
assertEquals(3, policies.size());
|
||||||
|
|
||||||
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
||||||
|
|
||||||
|
@ -412,7 +409,7 @@ public class FileAuthorizerTest {
|
||||||
assertEquals(adminIdentity, adminUser.getIdentity());
|
assertEquals(adminIdentity, adminUser.getIdentity());
|
||||||
|
|
||||||
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
final Set<AccessPolicy> policies = authorizer.getAccessPolicies();
|
||||||
assertEquals(4, policies.size());
|
assertEquals(3, policies.size());
|
||||||
|
|
||||||
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
final String rootGroupResource = ResourceType.ProcessGroup.getValue() + "/" + ROOT_GROUP_ID;
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
package org.apache.nifi.authorization.resource;
|
package org.apache.nifi.authorization.resource;
|
||||||
|
|
||||||
import org.apache.nifi.authorization.AccessPolicy;
|
import org.apache.nifi.authorization.AccessPolicy;
|
||||||
import org.apache.nifi.authorization.Group;
|
|
||||||
import org.apache.nifi.authorization.Resource;
|
import org.apache.nifi.authorization.Resource;
|
||||||
import org.apache.nifi.authorization.User;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -85,18 +83,6 @@ public final class ResourceFactory {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final static Resource GROUP_RESOURCE = new Resource() {
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return ResourceType.Group.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Group";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static Resource INPUT_PORT_RESOURCE = new Resource() {
|
private final static Resource INPUT_PORT_RESOURCE = new Resource() {
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
|
@ -277,6 +263,18 @@ public final class ResourceFactory {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final static Resource TENANT_RESOURCE = new Resource() {
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return ResourceType.Tenant.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Tenant";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final static Resource TOKEN_RESOURCE = new Resource() {
|
private final static Resource TOKEN_RESOURCE = new Resource() {
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
|
@ -289,18 +287,6 @@ public final class ResourceFactory {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final static Resource USER_RESOURCE = new Resource() {
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return ResourceType.User.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "User";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static Resource POLICIES_RESOURCE = new Resource() {
|
private final static Resource POLICIES_RESOURCE = new Resource() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -314,32 +300,6 @@ public final class ResourceFactory {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final static Resource USERS_RESOURCE = new Resource() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return "/users";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Users";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static Resource USERGROUPS_RESOURCE = new Resource() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return "/user-groups";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "User Groups";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Resource for accessing Connections.
|
* Gets the Resource for accessing Connections.
|
||||||
*
|
*
|
||||||
|
@ -385,15 +345,6 @@ public final class ResourceFactory {
|
||||||
return FLOW_RESOURCE;
|
return FLOW_RESOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Resource for accessing Groups which allows management of user groups.
|
|
||||||
*
|
|
||||||
* @return The resource for accessing Groups
|
|
||||||
*/
|
|
||||||
public static Resource getGroupResource() {
|
|
||||||
return GROUP_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Resource for accessing Input Ports.
|
* Gets the Resource for accessing Input Ports.
|
||||||
*
|
*
|
||||||
|
@ -541,12 +492,12 @@ public final class ResourceFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Resource for accessing Users which includes creating, modifying, and deleting Users.
|
* Gets the Resource for accessing Tenants which includes creating, modifying, and deleting Users and UserGroups.
|
||||||
*
|
*
|
||||||
* @return The Resource for accessing Users
|
* @return The Resource for accessing Tenants
|
||||||
*/
|
*/
|
||||||
public static Resource getUserResource() {
|
public static Resource getTenantResource() {
|
||||||
return USER_RESOURCE;
|
return TENANT_RESOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -602,24 +553,6 @@ public final class ResourceFactory {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a Resource for accessing {@link User} configurations.
|
|
||||||
*
|
|
||||||
* @return The resource
|
|
||||||
*/
|
|
||||||
public static Resource getUsersResource() {
|
|
||||||
return USERS_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a Resource for accessing {@link Group}s configuration.
|
|
||||||
*
|
|
||||||
* @return The resource
|
|
||||||
*/
|
|
||||||
public static Resource getUserGroupsResource() {
|
|
||||||
return USERGROUPS_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a Resource for accessing a component configuration.
|
* Gets a Resource for accessing a component configuration.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,9 +20,9 @@ public enum ResourceType {
|
||||||
Connection("/connections"),
|
Connection("/connections"),
|
||||||
Controller("/controller"),
|
Controller("/controller"),
|
||||||
ControllerService("/controller-services"),
|
ControllerService("/controller-services"),
|
||||||
|
Counters("/counters"),
|
||||||
Funnel("/funnel"),
|
Funnel("/funnel"),
|
||||||
Flow("/flow"),
|
Flow("/flow"),
|
||||||
Group("/groups"),
|
|
||||||
InputPort("/input-ports"),
|
InputPort("/input-ports"),
|
||||||
Label("/labels"),
|
Label("/labels"),
|
||||||
OutputPort("/output-ports"),
|
OutputPort("/output-ports"),
|
||||||
|
@ -37,9 +37,8 @@ public enum ResourceType {
|
||||||
SiteToSite("/site-to-site"),
|
SiteToSite("/site-to-site"),
|
||||||
System("/system"),
|
System("/system"),
|
||||||
Template("/templates"),
|
Template("/templates"),
|
||||||
Token("/token"),
|
Tenant("/tenants"),
|
||||||
Counters("/counters"),
|
Token("/token");
|
||||||
User("/users");
|
|
||||||
|
|
||||||
final String value;
|
final String value;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.apache.nifi.authorization.resource;
|
||||||
|
|
||||||
import org.apache.nifi.authorization.Resource;
|
import org.apache.nifi.authorization.Resource;
|
||||||
|
|
||||||
public class UsersAuthorizable implements Authorizable {
|
public class TenantAuthorizable implements Authorizable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authorizable getParentAuthorizable() {
|
public Authorizable getParentAuthorizable() {
|
||||||
|
@ -27,7 +27,7 @@ public class UsersAuthorizable implements Authorizable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource getResource() {
|
public Resource getResource() {
|
||||||
return ResourceFactory.getUsersResource();
|
return ResourceFactory.getTenantResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,8 +17,6 @@
|
||||||
package org.apache.nifi.web;
|
package org.apache.nifi.web;
|
||||||
|
|
||||||
import org.apache.nifi.authorization.AccessPolicy;
|
import org.apache.nifi.authorization.AccessPolicy;
|
||||||
import org.apache.nifi.authorization.Group;
|
|
||||||
import org.apache.nifi.authorization.User;
|
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
import org.apache.nifi.controller.Snippet;
|
import org.apache.nifi.controller.Snippet;
|
||||||
|
|
||||||
|
@ -163,16 +161,10 @@ public interface AuthorizableLookup {
|
||||||
Snippet getSnippet(String id);
|
Snippet getSnippet(String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link Authorizable} that represents the resource of {@link User}s.
|
* Get the {@link Authorizable} that represents the resource of users and user groups.
|
||||||
* @return authorizable
|
* @return authorizable
|
||||||
*/
|
*/
|
||||||
Authorizable getUsersAuthorizable();
|
Authorizable getTenantAuthorizable();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link Authorizable} that represents the resource of {@link Group}s.
|
|
||||||
* @return authorizable
|
|
||||||
*/
|
|
||||||
Authorizable getUserGroupsAuthorizable();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link Authorizable} the represents the parent resource of {@link AccessPolicy} resources.
|
* Get the {@link Authorizable} the represents the parent resource of {@link AccessPolicy} resources.
|
||||||
|
|
|
@ -1220,6 +1220,13 @@ public interface NiFiServiceFacade {
|
||||||
*/
|
*/
|
||||||
UserEntity getUser(String userId, boolean prune);
|
UserEntity getUser(String userId, boolean prune);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the users.
|
||||||
|
* @param prune If true, the users in the groups to which the users belong will not be returned
|
||||||
|
* @return The user transfer objects
|
||||||
|
*/
|
||||||
|
Set<UserEntity> getUsers(boolean prune);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the specified user.
|
* Updates the specified user.
|
||||||
* @param revision Revision to compare with current base revision
|
* @param revision Revision to compare with current base revision
|
||||||
|
@ -1255,6 +1262,13 @@ public interface NiFiServiceFacade {
|
||||||
*/
|
*/
|
||||||
UserGroupEntity getUserGroup(String userGroupId, boolean prune);
|
UserGroupEntity getUserGroup(String userGroupId, boolean prune);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all user groups.
|
||||||
|
* @param prune If true, the user groups of the users in the user groups will not be returned
|
||||||
|
* @return The user group transfer objects
|
||||||
|
*/
|
||||||
|
Set<UserGroupEntity> getUserGroups(boolean prune);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the specified user group.
|
* Updates the specified user group.
|
||||||
* @param revision Revision to compare with current base revision
|
* @param revision Revision to compare with current base revision
|
||||||
|
|
|
@ -19,8 +19,7 @@ package org.apache.nifi.web;
|
||||||
import org.apache.nifi.authorization.resource.AccessPoliciesAuthorizable;
|
import org.apache.nifi.authorization.resource.AccessPoliciesAuthorizable;
|
||||||
import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
|
import org.apache.nifi.authorization.resource.AccessPolicyAuthorizable;
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
import org.apache.nifi.authorization.resource.UserGroupsAuthorizable;
|
import org.apache.nifi.authorization.resource.TenantAuthorizable;
|
||||||
import org.apache.nifi.authorization.resource.UsersAuthorizable;
|
|
||||||
import org.apache.nifi.controller.ConfiguredComponent;
|
import org.apache.nifi.controller.ConfiguredComponent;
|
||||||
import org.apache.nifi.controller.Snippet;
|
import org.apache.nifi.controller.Snippet;
|
||||||
import org.apache.nifi.controller.service.ControllerServiceNode;
|
import org.apache.nifi.controller.service.ControllerServiceNode;
|
||||||
|
@ -44,8 +43,7 @@ import org.apache.nifi.web.dao.TemplateDAO;
|
||||||
|
|
||||||
class StandardAuthorizableLookup implements AuthorizableLookup {
|
class StandardAuthorizableLookup implements AuthorizableLookup {
|
||||||
|
|
||||||
private static final UsersAuthorizable USERS_AUTHORIZABLE = new UsersAuthorizable();
|
private static final TenantAuthorizable TENANT_AUTHORIZABLE = new TenantAuthorizable();
|
||||||
private static final UserGroupsAuthorizable USER_GROUPS_AUTHORIZABLE = new UserGroupsAuthorizable();
|
|
||||||
private static final Authorizable ACCESS_POLICIES_AUTHORIZABLE = new AccessPoliciesAuthorizable();
|
private static final Authorizable ACCESS_POLICIES_AUTHORIZABLE = new AccessPoliciesAuthorizable();
|
||||||
|
|
||||||
// nifi core components
|
// nifi core components
|
||||||
|
@ -159,13 +157,8 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authorizable getUsersAuthorizable() {
|
public Authorizable getTenantAuthorizable() {
|
||||||
return USERS_AUTHORIZABLE;
|
return TENANT_AUTHORIZABLE;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Authorizable getUserGroupsAuthorizable() {
|
|
||||||
return USER_GROUPS_AUTHORIZABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -535,7 +535,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserEntity updateUser(final Revision revision, final UserDTO userDTO) {
|
public UserEntity updateUser(final Revision revision, final UserDTO userDTO) {
|
||||||
final Authorizable usersAuthorizable = authorizableLookup.getUsersAuthorizable();
|
final Authorizable usersAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
final RevisionUpdate<UserDTO> snapshot = updateComponent(revision,
|
final RevisionUpdate<UserDTO> snapshot = updateComponent(revision,
|
||||||
usersAuthorizable,
|
usersAuthorizable,
|
||||||
() -> userDAO.updateUser(userDTO),
|
() -> userDAO.updateUser(userDTO),
|
||||||
|
@ -547,7 +547,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserGroupEntity updateUserGroup(final Revision revision, final UserGroupDTO userGroupDTO) {
|
public UserGroupEntity updateUserGroup(final Revision revision, final UserGroupDTO userGroupDTO) {
|
||||||
final Authorizable userGroupsAuthorizable = authorizableLookup.getUserGroupsAuthorizable();
|
final Authorizable userGroupsAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
final RevisionUpdate<UserGroupDTO> snapshot = updateComponent(revision,
|
final RevisionUpdate<UserGroupDTO> snapshot = updateComponent(revision,
|
||||||
userGroupsAuthorizable,
|
userGroupsAuthorizable,
|
||||||
() -> userGroupDAO.updateUserGroup(userGroupDTO),
|
() -> userGroupDAO.updateUserGroup(userGroupDTO),
|
||||||
|
@ -985,7 +985,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final Set<UserGroupEntity> userGroups = user != null ? user.getGroups().stream().map(userGroupId -> getUserGroup(userGroupId, true)).collect(Collectors.toSet()) : null;
|
final Set<UserGroupEntity> userGroups = user != null ? user.getGroups().stream().map(userGroupId -> getUserGroup(userGroupId, true)).collect(Collectors.toSet()) : null;
|
||||||
final UserDTO snapshot = deleteComponent(
|
final UserDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
authorizableLookup.getUsersAuthorizable(),
|
authorizableLookup.getTenantAuthorizable(),
|
||||||
() -> userDAO.deleteUser(userId),
|
() -> userDAO.deleteUser(userId),
|
||||||
dtoFactory.createUserDto(user, userGroups));
|
dtoFactory.createUserDto(user, userGroups));
|
||||||
|
|
||||||
|
@ -999,7 +999,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
null;
|
null;
|
||||||
final UserGroupDTO snapshot = deleteComponent(
|
final UserGroupDTO snapshot = deleteComponent(
|
||||||
revision,
|
revision,
|
||||||
authorizableLookup.getUserGroupsAuthorizable(),
|
authorizableLookup.getTenantAuthorizable(),
|
||||||
() -> userGroupDAO.deleteUserGroup(userGroupId),
|
() -> userGroupDAO.deleteUserGroup(userGroupId),
|
||||||
dtoFactory.createUserGroupDto(userGroup, users));
|
dtoFactory.createUserGroupDto(userGroup, users));
|
||||||
|
|
||||||
|
@ -1283,7 +1283,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final User newUser = userDAO.createUser(userDTO);
|
final User newUser = userDAO.createUser(userDTO);
|
||||||
final UserDTO newUserDto = dtoFactory.createUserDto(newUser, newUser.getGroups().stream().map(userGroupId -> getUserGroup(userGroupId, true)).collect(Collectors.toSet()));
|
final UserDTO newUserDto = dtoFactory.createUserDto(newUser, newUser.getGroups().stream().map(userGroupId -> getUserGroup(userGroupId, true)).collect(Collectors.toSet()));
|
||||||
|
|
||||||
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(authorizableLookup.getUsersAuthorizable());
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(authorizableLookup.getTenantAuthorizable());
|
||||||
return entityFactory.createUserEntity(newUserDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), accessPolicy);
|
return entityFactory.createUserEntity(newUserDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), accessPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1296,7 +1296,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
final Group newUserGroup = userGroupDAO.createUserGroup(userGroupDTO);
|
final Group newUserGroup = userGroupDAO.createUserGroup(userGroupDTO);
|
||||||
final UserGroupDTO newUserGroupDto = dtoFactory.createUserGroupDto(newUserGroup, newUserGroup.getUsers().stream().map(userId -> getUser(userId, true)).collect(Collectors.toSet()));
|
final UserGroupDTO newUserGroupDto = dtoFactory.createUserGroupDto(newUserGroup, newUserGroup.getUsers().stream().map(userId -> getUser(userId, true)).collect(Collectors.toSet()));
|
||||||
|
|
||||||
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(authorizableLookup.getUserGroupsAuthorizable());
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(authorizableLookup.getTenantAuthorizable());
|
||||||
return entityFactory.createUserGroupEntity(newUserGroupDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), accessPolicy);
|
return entityFactory.createUserGroupEntity(newUserGroupDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), accessPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2354,7 +2354,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
@Override
|
@Override
|
||||||
public UserEntity getUser(final String userId, final boolean prune) {
|
public UserEntity getUser(final String userId, final boolean prune) {
|
||||||
return revisionManager.get(userId, rev -> {
|
return revisionManager.get(userId, rev -> {
|
||||||
final Authorizable usersAuthorizable = authorizableLookup.getUsersAuthorizable();
|
final Authorizable usersAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
||||||
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(usersAuthorizable);
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(usersAuthorizable);
|
||||||
final User user = userDAO.getUser(userId);
|
final User user = userDAO.getUser(userId);
|
||||||
|
@ -2367,7 +2367,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
|
|
||||||
private UserEntity getUserPruned(final String userId) {
|
private UserEntity getUserPruned(final String userId) {
|
||||||
return revisionManager.get(userId, rev -> {
|
return revisionManager.get(userId, rev -> {
|
||||||
final Authorizable usersAuthorizable = authorizableLookup.getUsersAuthorizable();
|
final Authorizable usersAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
||||||
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(usersAuthorizable);
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(usersAuthorizable);
|
||||||
final User user = userDAO.getUser(userId);
|
final User user = userDAO.getUser(userId);
|
||||||
|
@ -2375,10 +2375,29 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<UserEntity> getUsers(boolean prune) {
|
||||||
|
final Authorizable userAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
|
final Set<User> users = userDAO.getUsers();
|
||||||
|
final Set<String> ids = users.stream().map(user -> user.getIdentifier()).collect(Collectors.toSet());
|
||||||
|
return revisionManager.get(ids, () -> {
|
||||||
|
return users.stream()
|
||||||
|
.map(user -> {
|
||||||
|
final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(user.getIdentifier()));
|
||||||
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(userAuthorizable);
|
||||||
|
final Set<UserGroupEntity> userGroups = user.getGroups().stream()
|
||||||
|
.map(userGroupId -> prune ? getUserGroupPruned(userGroupId) : getUserGroup(userGroupId, false))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return entityFactory.createUserEntity(dtoFactory.createUserDto(user, userGroups), revision, accessPolicy);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserGroupEntity getUserGroup(final String userGroupId, final boolean prune) {
|
public UserGroupEntity getUserGroup(final String userGroupId, final boolean prune) {
|
||||||
return revisionManager.get(userGroupId, rev -> {
|
return revisionManager.get(userGroupId, rev -> {
|
||||||
final Authorizable userGroupsAuthorizable = authorizableLookup.getUserGroupsAuthorizable();
|
final Authorizable userGroupsAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
||||||
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(userGroupsAuthorizable);
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(userGroupsAuthorizable);
|
||||||
final Group userGroup = userGroupDAO.getUserGroup(userGroupId);
|
final Group userGroup = userGroupDAO.getUserGroup(userGroupId);
|
||||||
|
@ -2390,7 +2409,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
|
|
||||||
private UserGroupEntity getUserGroupPruned(final String userGroupId) {
|
private UserGroupEntity getUserGroupPruned(final String userGroupId) {
|
||||||
return revisionManager.get(userGroupId, rev -> {
|
return revisionManager.get(userGroupId, rev -> {
|
||||||
final Authorizable userGroupsAuthorizable = authorizableLookup.getUserGroupsAuthorizable();
|
final Authorizable userGroupsAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
final RevisionDTO revision = dtoFactory.createRevisionDTO(rev);
|
||||||
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(userGroupsAuthorizable);
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(userGroupsAuthorizable);
|
||||||
final Group userGroup = userGroupDAO.getUserGroup(userGroupId);
|
final Group userGroup = userGroupDAO.getUserGroup(userGroupId);
|
||||||
|
@ -2398,6 +2417,25 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<UserGroupEntity> getUserGroups(boolean prune) {
|
||||||
|
final Authorizable userGroupAuthorizable = authorizableLookup.getTenantAuthorizable();
|
||||||
|
final Set<Group> userGroups = userGroupDAO.getUserGroups();
|
||||||
|
final Set<String> ids = userGroups.stream().map(userGroup -> userGroup.getIdentifier()).collect(Collectors.toSet());
|
||||||
|
return revisionManager.get(ids, () -> {
|
||||||
|
return userGroups.stream()
|
||||||
|
.map(userGroup -> {
|
||||||
|
final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userGroup.getIdentifier()));
|
||||||
|
final AccessPolicyDTO accessPolicy = dtoFactory.createAccessPolicyDto(userGroupAuthorizable);
|
||||||
|
final Set<UserEntity> users = userGroup.getUsers().stream()
|
||||||
|
.map(userGroupId -> prune ? getUserPruned(userGroupId) : getUser(userGroupId, false))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return entityFactory.createUserGroupEntity(dtoFactory.createUserGroupDto(userGroup, users), revision, accessPolicy);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<LabelEntity> getLabels(final String groupId) {
|
public Set<LabelEntity> getLabels(final String groupId) {
|
||||||
final Set<Label> labels = labelDAO.getLabels(groupId);
|
final Set<Label> labels = labelDAO.getLabels(groupId);
|
||||||
|
|
|
@ -0,0 +1,848 @@
|
||||||
|
/*
|
||||||
|
* 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.api;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.annotations.Api;
|
||||||
|
import com.wordnik.swagger.annotations.ApiOperation;
|
||||||
|
import com.wordnik.swagger.annotations.ApiParam;
|
||||||
|
import com.wordnik.swagger.annotations.ApiResponse;
|
||||||
|
import com.wordnik.swagger.annotations.ApiResponses;
|
||||||
|
import com.wordnik.swagger.annotations.Authorization;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.nifi.authorization.Authorizer;
|
||||||
|
import org.apache.nifi.authorization.RequestAction;
|
||||||
|
import org.apache.nifi.authorization.resource.Authorizable;
|
||||||
|
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
||||||
|
import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
|
||||||
|
import org.apache.nifi.util.NiFiProperties;
|
||||||
|
import org.apache.nifi.web.NiFiServiceFacade;
|
||||||
|
import org.apache.nifi.web.Revision;
|
||||||
|
import org.apache.nifi.web.api.dto.RevisionDTO;
|
||||||
|
import org.apache.nifi.web.api.dto.UserDTO;
|
||||||
|
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
||||||
|
import org.apache.nifi.web.api.entity.UserEntity;
|
||||||
|
import org.apache.nifi.web.api.entity.UserGroupEntity;
|
||||||
|
import org.apache.nifi.web.api.entity.UserGroupsEntity;
|
||||||
|
import org.apache.nifi.web.api.entity.UsersEntity;
|
||||||
|
import org.apache.nifi.web.api.request.ClientIdParameter;
|
||||||
|
import org.apache.nifi.web.api.request.LongParameter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HttpMethod;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Path("tenants")
|
||||||
|
@Api(
|
||||||
|
value = "tenants",
|
||||||
|
description = "Endpoint for managing users and user groups."
|
||||||
|
)
|
||||||
|
public class TenantsResource extends ApplicationResource {
|
||||||
|
|
||||||
|
private final NiFiServiceFacade serviceFacade;
|
||||||
|
private final Authorizer authorizer;
|
||||||
|
|
||||||
|
public TenantsResource(NiFiServiceFacade serviceFacade, Authorizer authorizer, NiFiProperties properties, RequestReplicator requestReplicator, ClusterCoordinator clusterCoordinator) {
|
||||||
|
this.serviceFacade = serviceFacade;
|
||||||
|
this.authorizer = authorizer;
|
||||||
|
setProperties(properties);
|
||||||
|
setRequestReplicator(requestReplicator);
|
||||||
|
setClusterCoordinator(clusterCoordinator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified users.
|
||||||
|
*
|
||||||
|
* @param userEntities users
|
||||||
|
* @return user entities
|
||||||
|
*/
|
||||||
|
public Set<UserEntity> populateRemainingUserEntitiesContent(Set<UserEntity> userEntities) {
|
||||||
|
for (UserEntity userEntity : userEntities) {
|
||||||
|
populateRemainingUserEntityContent(userEntity);
|
||||||
|
}
|
||||||
|
return userEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified user.
|
||||||
|
*
|
||||||
|
* @param userEntity userEntity
|
||||||
|
* @return userEntity
|
||||||
|
*/
|
||||||
|
public UserEntity populateRemainingUserEntityContent(UserEntity userEntity) {
|
||||||
|
if (userEntity.getComponent() != null) {
|
||||||
|
populateRemainingUserContent(userEntity.getComponent());
|
||||||
|
}
|
||||||
|
return userEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified user.
|
||||||
|
*/
|
||||||
|
public UserDTO populateRemainingUserContent(UserDTO user) {
|
||||||
|
// populate the user href
|
||||||
|
user.setUri(generateResourceUri("tenants/users", user.getId()));
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified users.
|
||||||
|
*
|
||||||
|
* @param users users
|
||||||
|
* @return user data transfer objects
|
||||||
|
*/
|
||||||
|
public Set<UserDTO> populateRemainingUsersContent(Set<UserDTO> users) {
|
||||||
|
for (UserDTO userDTO : users) {
|
||||||
|
populateRemainingUserContent(userDTO);
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new user.
|
||||||
|
*
|
||||||
|
* @param httpServletRequest request
|
||||||
|
* @param userEntity An userEntity.
|
||||||
|
* @return An userEntity.
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("users")
|
||||||
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Creates a user",
|
||||||
|
response = UserEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response createUser(
|
||||||
|
@Context final HttpServletRequest httpServletRequest,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user configuration details.",
|
||||||
|
required = true
|
||||||
|
) final UserEntity userEntity) {
|
||||||
|
|
||||||
|
if (userEntity == null || userEntity.getComponent() == null) {
|
||||||
|
throw new IllegalArgumentException("User details must be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userEntity.getRevision() == null || (userEntity.getRevision().getVersion() == null || userEntity.getRevision().getVersion() != 0)) {
|
||||||
|
throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Processor.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userEntity.getComponent().getId() != null) {
|
||||||
|
throw new IllegalArgumentException("User ID cannot be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.POST, userEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle expects request (usually from the cluster manager)
|
||||||
|
final boolean validationPhase = isValidationPhase(httpServletRequest);
|
||||||
|
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
||||||
|
// authorize access
|
||||||
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
|
final Authorizable users = lookup.getTenantAuthorizable();
|
||||||
|
users.authorize(authorizer, RequestAction.WRITE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (validationPhase) {
|
||||||
|
return generateContinueResponse().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the user id as appropriate
|
||||||
|
userEntity.getComponent().setId(generateUuid());
|
||||||
|
|
||||||
|
// get revision from the config
|
||||||
|
final RevisionDTO revisionDTO = userEntity.getRevision();
|
||||||
|
Revision revision = new Revision(revisionDTO.getVersion(), revisionDTO.getClientId(), userEntity.getComponent().getId());
|
||||||
|
|
||||||
|
// create the user and generate the json
|
||||||
|
final UserEntity entity = serviceFacade.createUser(revision, userEntity.getComponent());
|
||||||
|
populateRemainingUserEntityContent(entity);
|
||||||
|
|
||||||
|
// build the response
|
||||||
|
return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the specified user.
|
||||||
|
*
|
||||||
|
* @param id The id of the user to retrieve
|
||||||
|
* @return An userEntity.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("users/{id}")
|
||||||
|
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Gets a user",
|
||||||
|
response = UserEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
|
||||||
|
@Authorization(value = "Administrator", type = "ROLE_ADMIN")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response getUser(
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user id.",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
@PathParam("id") final String id) {
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
// authorize access
|
||||||
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
|
final Authorizable users = lookup.getTenantAuthorizable();
|
||||||
|
users.authorize(authorizer, RequestAction.READ);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get the user
|
||||||
|
final UserEntity entity = serviceFacade.getUser(id, true);
|
||||||
|
populateRemainingUserEntityContent(entity);
|
||||||
|
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the of users in this NiFi.
|
||||||
|
*
|
||||||
|
* @return A UsersEntity.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("users")
|
||||||
|
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Gets all users",
|
||||||
|
response = UsersEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
|
||||||
|
@Authorization(value = "Administrator", type = "ROLE_ADMIN")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response getUsers() {
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
// authorize access
|
||||||
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
|
final Authorizable users = lookup.getTenantAuthorizable();
|
||||||
|
users.authorize(authorizer, RequestAction.READ);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get all the users
|
||||||
|
final Set<UserEntity> users = serviceFacade.getUsers(true);
|
||||||
|
|
||||||
|
// create the response entity
|
||||||
|
final UsersEntity entity = new UsersEntity();
|
||||||
|
entity.setUsers(populateRemainingUserEntitiesContent(users));
|
||||||
|
|
||||||
|
// generate the response
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a user.
|
||||||
|
*
|
||||||
|
* @param httpServletRequest request
|
||||||
|
* @param id The id of the user to update.
|
||||||
|
* @param userEntity An userEntity.
|
||||||
|
* @return An userEntity.
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("users/{id}")
|
||||||
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Updates a user",
|
||||||
|
response = UserEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response updateUser(
|
||||||
|
@Context final HttpServletRequest httpServletRequest,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user id.",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
@PathParam("id") final String id,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user configuration details.",
|
||||||
|
required = true
|
||||||
|
) final UserEntity userEntity) {
|
||||||
|
|
||||||
|
if (userEntity == null || userEntity.getComponent() == null) {
|
||||||
|
throw new IllegalArgumentException("User details must be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userEntity.getRevision() == null) {
|
||||||
|
throw new IllegalArgumentException("Revision must be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the ids are the same
|
||||||
|
final UserDTO userDTO = userEntity.getComponent();
|
||||||
|
if (!id.equals(userDTO.getId())) {
|
||||||
|
throw new IllegalArgumentException(String.format("The user id (%s) in the request body does not equal the "
|
||||||
|
+ "user id of the requested resource (%s).", userDTO.getId(), id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.PUT, userEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the revision
|
||||||
|
final Revision revision = getRevision(userEntity, id);
|
||||||
|
return withWriteLock(
|
||||||
|
serviceFacade,
|
||||||
|
revision,
|
||||||
|
lookup -> {
|
||||||
|
final Authorizable users = lookup.getTenantAuthorizable();
|
||||||
|
users.authorize(authorizer, RequestAction.WRITE);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() -> {
|
||||||
|
// update the user
|
||||||
|
final UserEntity entity = serviceFacade.updateUser(revision, userDTO);
|
||||||
|
populateRemainingUserEntityContent(entity);
|
||||||
|
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified user.
|
||||||
|
*
|
||||||
|
* @param httpServletRequest request
|
||||||
|
* @param version The revision is used to verify the client is working with
|
||||||
|
* the latest version of the flow.
|
||||||
|
* @param clientId Optional client id. If the client id is not specified, a
|
||||||
|
* new one will be generated. This value (whether specified or generated) is
|
||||||
|
* included in the response.
|
||||||
|
* @param id The id of the user to remove.
|
||||||
|
* @return A entity containing the client id and an updated revision.
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("users/{id}")
|
||||||
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Deletes a user",
|
||||||
|
response = UserEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response removeUser(
|
||||||
|
@Context final HttpServletRequest httpServletRequest,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The revision is used to verify the client is working with the latest version of the flow.",
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
@QueryParam(VERSION) final LongParameter version,
|
||||||
|
@ApiParam(
|
||||||
|
value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user id.",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
@PathParam("id") final String id) {
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle expects request (usually from the cluster manager)
|
||||||
|
final Revision revision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
|
||||||
|
return withWriteLock(
|
||||||
|
serviceFacade,
|
||||||
|
revision,
|
||||||
|
lookup -> {
|
||||||
|
final Authorizable users = lookup.getTenantAuthorizable();
|
||||||
|
users.authorize(authorizer, RequestAction.READ);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() -> {
|
||||||
|
// delete the specified user
|
||||||
|
final UserEntity entity = serviceFacade.deleteUser(revision, id);
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified user groups.
|
||||||
|
*
|
||||||
|
* @param userGroupEntities user groups
|
||||||
|
* @return user group entities
|
||||||
|
*/
|
||||||
|
public Set<UserGroupEntity> populateRemainingUserGroupEntitiesContent(Set<UserGroupEntity> userGroupEntities) {
|
||||||
|
for (UserGroupEntity userGroupEntity : userGroupEntities) {
|
||||||
|
populateRemainingUserGroupEntityContent(userGroupEntity);
|
||||||
|
}
|
||||||
|
return userGroupEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified user group.
|
||||||
|
*
|
||||||
|
* @param userGroupEntity userGroupEntity
|
||||||
|
* @return userGroupEntity
|
||||||
|
*/
|
||||||
|
public UserGroupEntity populateRemainingUserGroupEntityContent(UserGroupEntity userGroupEntity) {
|
||||||
|
if (userGroupEntity.getComponent() != null) {
|
||||||
|
populateRemainingUserGroupContent(userGroupEntity.getComponent());
|
||||||
|
}
|
||||||
|
return userGroupEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified userGroup.
|
||||||
|
*/
|
||||||
|
public UserGroupDTO populateRemainingUserGroupContent(UserGroupDTO userGroup) {
|
||||||
|
// populate the user group href
|
||||||
|
userGroup.setUri(generateResourceUri("tenants/user-groups", userGroup.getId()));
|
||||||
|
return userGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the uri for the specified user groups.
|
||||||
|
*
|
||||||
|
* @param userGroups user groups
|
||||||
|
* @return user group data transfer objects
|
||||||
|
*/
|
||||||
|
public Set<UserGroupDTO> populateRemainingUserGroupsContent(Set<UserGroupDTO> userGroups) {
|
||||||
|
for (UserGroupDTO userGroup : userGroups) {
|
||||||
|
populateRemainingUserGroupContent(userGroup);
|
||||||
|
}
|
||||||
|
return userGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new user group.
|
||||||
|
*
|
||||||
|
* @param httpServletRequest request
|
||||||
|
* @param userGroupEntity An userGroupEntity.
|
||||||
|
* @return An userGroupEntity.
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("user-groups")
|
||||||
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Creates a user group",
|
||||||
|
response = UserGroupEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response createUserGroup(
|
||||||
|
@Context final HttpServletRequest httpServletRequest,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user group configuration details.",
|
||||||
|
required = true
|
||||||
|
) final UserGroupEntity userGroupEntity) {
|
||||||
|
|
||||||
|
if (userGroupEntity == null || userGroupEntity.getComponent() == null) {
|
||||||
|
throw new IllegalArgumentException("User group details must be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userGroupEntity.getRevision() == null || (userGroupEntity.getRevision().getVersion() == null || userGroupEntity.getRevision().getVersion() != 0)) {
|
||||||
|
throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Processor.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userGroupEntity.getComponent().getId() != null) {
|
||||||
|
throw new IllegalArgumentException("User group ID cannot be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.POST, userGroupEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle expects request (usually from the cluster manager)
|
||||||
|
final boolean validationPhase = isValidationPhase(httpServletRequest);
|
||||||
|
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
||||||
|
// authorize access
|
||||||
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
|
final Authorizable userGroups = lookup.getTenantAuthorizable();
|
||||||
|
userGroups.authorize(authorizer, RequestAction.WRITE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (validationPhase) {
|
||||||
|
return generateContinueResponse().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the user group id as appropriate
|
||||||
|
userGroupEntity.getComponent().setId(generateUuid());
|
||||||
|
|
||||||
|
// get revision from the config
|
||||||
|
final RevisionDTO revisionDTO = userGroupEntity.getRevision();
|
||||||
|
Revision revision = new Revision(revisionDTO.getVersion(), revisionDTO.getClientId(), userGroupEntity.getComponent().getId());
|
||||||
|
|
||||||
|
// create the user group and generate the json
|
||||||
|
final UserGroupEntity entity = serviceFacade.createUserGroup(revision, userGroupEntity.getComponent());
|
||||||
|
populateRemainingUserGroupEntityContent(entity);
|
||||||
|
|
||||||
|
// build the response
|
||||||
|
return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the specified user group.
|
||||||
|
*
|
||||||
|
* @param id The id of the user group to retrieve
|
||||||
|
* @return An userGroupEntity.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("user-groups/{id}")
|
||||||
|
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Gets a user group",
|
||||||
|
response = UserGroupEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
|
||||||
|
@Authorization(value = "Administrator", type = "ROLE_ADMIN")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response getUserGroup(
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user group id.",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
@PathParam("id") final String id) {
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
// authorize access
|
||||||
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
|
final Authorizable userGroups = lookup.getTenantAuthorizable();
|
||||||
|
userGroups.authorize(authorizer, RequestAction.READ);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get the user group
|
||||||
|
final UserGroupEntity entity = serviceFacade.getUserGroup(id, true);
|
||||||
|
populateRemainingUserGroupEntityContent(entity);
|
||||||
|
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the of user groups in this NiFi.
|
||||||
|
*
|
||||||
|
* @return A UserGroupsEntity.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("user-groups")
|
||||||
|
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Gets all user groups",
|
||||||
|
response = UserGroupsEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
|
||||||
|
@Authorization(value = "Administrator", type = "ROLE_ADMIN")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response getUserGroups() {
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
// authorize access
|
||||||
|
serviceFacade.authorizeAccess(lookup -> {
|
||||||
|
final Authorizable userGroups = lookup.getTenantAuthorizable();
|
||||||
|
userGroups.authorize(authorizer, RequestAction.READ);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get all the user groups
|
||||||
|
final Set<UserGroupEntity> users = serviceFacade.getUserGroups(true);
|
||||||
|
|
||||||
|
// create the response entity
|
||||||
|
final UserGroupsEntity entity = new UserGroupsEntity();
|
||||||
|
entity.setUserGroups(populateRemainingUserGroupEntitiesContent(users));
|
||||||
|
|
||||||
|
// generate the response
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a user group.
|
||||||
|
*
|
||||||
|
* @param httpServletRequest request
|
||||||
|
* @param id The id of the user group to update.
|
||||||
|
* @param userGroupEntity An userGroupEntity.
|
||||||
|
* @return An userGroupEntity.
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("user-groups/{id}")
|
||||||
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Updates a user group",
|
||||||
|
response = UserGroupEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response updateUserGroup(
|
||||||
|
@Context final HttpServletRequest httpServletRequest,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user group id.",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
@PathParam("id") final String id,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user group configuration details.",
|
||||||
|
required = true
|
||||||
|
) final UserGroupEntity userGroupEntity) {
|
||||||
|
|
||||||
|
if (userGroupEntity == null || userGroupEntity.getComponent() == null) {
|
||||||
|
throw new IllegalArgumentException("User group details must be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userGroupEntity.getRevision() == null) {
|
||||||
|
throw new IllegalArgumentException("Revision must be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the ids are the same
|
||||||
|
final UserGroupDTO userGroupDTO = userGroupEntity.getComponent();
|
||||||
|
if (!id.equals(userGroupDTO.getId())) {
|
||||||
|
throw new IllegalArgumentException(String.format("The user group id (%s) in the request body does not equal the "
|
||||||
|
+ "user group id of the requested resource (%s).", userGroupDTO.getId(), id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.PUT, userGroupEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the revision
|
||||||
|
final Revision revision = getRevision(userGroupEntity, id);
|
||||||
|
return withWriteLock(
|
||||||
|
serviceFacade,
|
||||||
|
revision,
|
||||||
|
lookup -> {
|
||||||
|
final Authorizable userGroups = lookup.getTenantAuthorizable();
|
||||||
|
userGroups.authorize(authorizer, RequestAction.WRITE);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() -> {
|
||||||
|
// update the user group
|
||||||
|
final UserGroupEntity entity = serviceFacade.updateUserGroup(revision, userGroupDTO);
|
||||||
|
populateRemainingUserGroupEntityContent(entity);
|
||||||
|
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified user group.
|
||||||
|
*
|
||||||
|
* @param httpServletRequest request
|
||||||
|
* @param version The revision is used to verify the client is working with
|
||||||
|
* the latest version of the flow.
|
||||||
|
* @param clientId Optional client id. If the client id is not specified, a
|
||||||
|
* new one will be generated. This value (whether specified or generated) is
|
||||||
|
* included in the response.
|
||||||
|
* @param id The id of the user group to remove.
|
||||||
|
* @return A entity containing the client id and an updated revision.
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("user-groups/{id}")
|
||||||
|
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||||
|
@ApiOperation(
|
||||||
|
value = "Deletes a user group",
|
||||||
|
response = UserGroupEntity.class,
|
||||||
|
authorizations = {
|
||||||
|
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||||
|
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||||
|
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||||
|
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||||
|
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public Response removeUserGroup(
|
||||||
|
@Context final HttpServletRequest httpServletRequest,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The revision is used to verify the client is working with the latest version of the flow.",
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
@QueryParam(VERSION) final LongParameter version,
|
||||||
|
@ApiParam(
|
||||||
|
value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
||||||
|
@ApiParam(
|
||||||
|
value = "The user group id.",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
@PathParam("id") final String id) {
|
||||||
|
|
||||||
|
if (isReplicateRequest()) {
|
||||||
|
return replicate(HttpMethod.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle expects request (usually from the cluster manager)
|
||||||
|
final Revision revision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
|
||||||
|
return withWriteLock(
|
||||||
|
serviceFacade,
|
||||||
|
revision,
|
||||||
|
lookup -> {
|
||||||
|
final Authorizable userGroups = lookup.getTenantAuthorizable();
|
||||||
|
userGroups.authorize(authorizer, RequestAction.READ);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() -> {
|
||||||
|
// delete the specified user group
|
||||||
|
final UserGroupEntity entity = serviceFacade.deleteUserGroup(revision, id);
|
||||||
|
return clusterContext(generateOkResponse(entity)).build();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,381 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.api;
|
|
||||||
|
|
||||||
import com.wordnik.swagger.annotations.Api;
|
|
||||||
import com.wordnik.swagger.annotations.ApiOperation;
|
|
||||||
import com.wordnik.swagger.annotations.ApiParam;
|
|
||||||
import com.wordnik.swagger.annotations.ApiResponse;
|
|
||||||
import com.wordnik.swagger.annotations.ApiResponses;
|
|
||||||
import com.wordnik.swagger.annotations.Authorization;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.nifi.authorization.Authorizer;
|
|
||||||
import org.apache.nifi.authorization.RequestAction;
|
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
|
||||||
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
|
||||||
import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
|
|
||||||
import org.apache.nifi.util.NiFiProperties;
|
|
||||||
import org.apache.nifi.web.NiFiServiceFacade;
|
|
||||||
import org.apache.nifi.web.Revision;
|
|
||||||
import org.apache.nifi.web.api.dto.RevisionDTO;
|
|
||||||
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
|
||||||
import org.apache.nifi.web.api.entity.UserGroupEntity;
|
|
||||||
import org.apache.nifi.web.api.request.ClientIdParameter;
|
|
||||||
import org.apache.nifi.web.api.request.LongParameter;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.DefaultValue;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HttpMethod;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.QueryParam;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
@Path("/user-groups")
|
|
||||||
@Api(
|
|
||||||
value = "/user-groups",
|
|
||||||
description = "Endpoint for managing user groups."
|
|
||||||
)
|
|
||||||
public class UserGroupsResource extends ApplicationResource {
|
|
||||||
|
|
||||||
private final NiFiServiceFacade serviceFacade;
|
|
||||||
private final Authorizer authorizer;
|
|
||||||
|
|
||||||
public UserGroupsResource(NiFiServiceFacade serviceFacade, Authorizer authorizer, NiFiProperties properties, RequestReplicator requestReplicator, ClusterCoordinator clusterCoordinator) {
|
|
||||||
this.serviceFacade = serviceFacade;
|
|
||||||
this.authorizer = authorizer;
|
|
||||||
setProperties(properties);
|
|
||||||
setRequestReplicator(requestReplicator);
|
|
||||||
setClusterCoordinator(clusterCoordinator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the uri for the specified user group.
|
|
||||||
*
|
|
||||||
* @param userGroupEntity userGroupEntity
|
|
||||||
* @return userGroupEntity
|
|
||||||
*/
|
|
||||||
public UserGroupEntity populateRemainingUserGroupEntityContent(UserGroupEntity userGroupEntity) {
|
|
||||||
if (userGroupEntity.getComponent() != null) {
|
|
||||||
populateRemainingUserGroupContent(userGroupEntity.getComponent());
|
|
||||||
}
|
|
||||||
return userGroupEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the uri for the specified userGroup.
|
|
||||||
*/
|
|
||||||
public UserGroupDTO populateRemainingUserGroupContent(UserGroupDTO userGroup) {
|
|
||||||
// populate the user group href
|
|
||||||
userGroup.setUri(generateResourceUri("user-groups", userGroup.getId()));
|
|
||||||
return userGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new user group.
|
|
||||||
*
|
|
||||||
* @param httpServletRequest request
|
|
||||||
* @param userGroupEntity An userGroupEntity.
|
|
||||||
* @return An userGroupEntity.
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Creates a user group",
|
|
||||||
response = UserGroupEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response createUserGroup(
|
|
||||||
@Context final HttpServletRequest httpServletRequest,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user group configuration details.",
|
|
||||||
required = true
|
|
||||||
) final UserGroupEntity userGroupEntity) {
|
|
||||||
|
|
||||||
if (userGroupEntity == null || userGroupEntity.getComponent() == null) {
|
|
||||||
throw new IllegalArgumentException("User group details must be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userGroupEntity.getRevision() == null || (userGroupEntity.getRevision().getVersion() == null || userGroupEntity.getRevision().getVersion() != 0)) {
|
|
||||||
throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Processor.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userGroupEntity.getComponent().getId() != null) {
|
|
||||||
throw new IllegalArgumentException("User group ID cannot be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.POST, userGroupEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle expects request (usually from the cluster manager)
|
|
||||||
final boolean validationPhase = isValidationPhase(httpServletRequest);
|
|
||||||
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
|
||||||
// authorize access
|
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
|
||||||
final Authorizable userGroups = lookup.getUserGroupsAuthorizable();
|
|
||||||
userGroups.authorize(authorizer, RequestAction.WRITE);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (validationPhase) {
|
|
||||||
return generateContinueResponse().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the user group id as appropriate
|
|
||||||
userGroupEntity.getComponent().setId(generateUuid());
|
|
||||||
|
|
||||||
// get revision from the config
|
|
||||||
final RevisionDTO revisionDTO = userGroupEntity.getRevision();
|
|
||||||
Revision revision = new Revision(revisionDTO.getVersion(), revisionDTO.getClientId(), userGroupEntity.getComponent().getId());
|
|
||||||
|
|
||||||
// create the user group and generate the json
|
|
||||||
final UserGroupEntity entity = serviceFacade.createUserGroup(revision, userGroupEntity.getComponent());
|
|
||||||
populateRemainingUserGroupEntityContent(entity);
|
|
||||||
|
|
||||||
// build the response
|
|
||||||
return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the specified user group.
|
|
||||||
*
|
|
||||||
* @param id The id of the user group to retrieve
|
|
||||||
* @return An userGroupEntity.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Consumes(MediaType.WILDCARD)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("{id}")
|
|
||||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Gets a user group",
|
|
||||||
response = UserGroupEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
|
|
||||||
@Authorization(value = "Administrator", type = "ROLE_ADMIN")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response getUserGroup(
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user group id.",
|
|
||||||
required = true
|
|
||||||
)
|
|
||||||
@PathParam("id") final String id) {
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.GET);
|
|
||||||
}
|
|
||||||
|
|
||||||
// authorize access
|
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
|
||||||
final Authorizable userGroups = lookup.getUserGroupsAuthorizable();
|
|
||||||
userGroups.authorize(authorizer, RequestAction.READ);
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the user group
|
|
||||||
final UserGroupEntity entity = serviceFacade.getUserGroup(id, true);
|
|
||||||
populateRemainingUserGroupEntityContent(entity);
|
|
||||||
|
|
||||||
return clusterContext(generateOkResponse(entity)).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a user group.
|
|
||||||
*
|
|
||||||
* @param httpServletRequest request
|
|
||||||
* @param id The id of the user group to update.
|
|
||||||
* @param userGroupEntity An userGroupEntity.
|
|
||||||
* @return An userGroupEntity.
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("{id}")
|
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Updates a user group",
|
|
||||||
response = UserGroupEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response updateUserGroup(
|
|
||||||
@Context final HttpServletRequest httpServletRequest,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user group id.",
|
|
||||||
required = true
|
|
||||||
)
|
|
||||||
@PathParam("id") final String id,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user group configuration details.",
|
|
||||||
required = true
|
|
||||||
) final UserGroupEntity userGroupEntity) {
|
|
||||||
|
|
||||||
if (userGroupEntity == null || userGroupEntity.getComponent() == null) {
|
|
||||||
throw new IllegalArgumentException("User group details must be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userGroupEntity.getRevision() == null) {
|
|
||||||
throw new IllegalArgumentException("Revision must be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure the ids are the same
|
|
||||||
final UserGroupDTO userGroupDTO = userGroupEntity.getComponent();
|
|
||||||
if (!id.equals(userGroupDTO.getId())) {
|
|
||||||
throw new IllegalArgumentException(String.format("The user group id (%s) in the request body does not equal the "
|
|
||||||
+ "user group id of the requested resource (%s).", userGroupDTO.getId(), id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.PUT, userGroupEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the revision
|
|
||||||
final Revision revision = getRevision(userGroupEntity, id);
|
|
||||||
return withWriteLock(
|
|
||||||
serviceFacade,
|
|
||||||
revision,
|
|
||||||
lookup -> {
|
|
||||||
final Authorizable userGroups = lookup.getUserGroupsAuthorizable();
|
|
||||||
userGroups.authorize(authorizer, RequestAction.WRITE);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
() -> {
|
|
||||||
// update the user group
|
|
||||||
final UserGroupEntity entity = serviceFacade.updateUserGroup(revision, userGroupDTO);
|
|
||||||
populateRemainingUserGroupEntityContent(entity);
|
|
||||||
|
|
||||||
return clusterContext(generateOkResponse(entity)).build();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the specified user group.
|
|
||||||
*
|
|
||||||
* @param httpServletRequest request
|
|
||||||
* @param version The revision is used to verify the client is working with
|
|
||||||
* the latest version of the flow.
|
|
||||||
* @param clientId Optional client id. If the client id is not specified, a
|
|
||||||
* new one will be generated. This value (whether specified or generated) is
|
|
||||||
* included in the response.
|
|
||||||
* @param id The id of the user group to remove.
|
|
||||||
* @return A entity containing the client id and an updated revision.
|
|
||||||
*/
|
|
||||||
@DELETE
|
|
||||||
@Consumes(MediaType.WILDCARD)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("{id}")
|
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Deletes a user group",
|
|
||||||
response = UserGroupEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response removeUserGroup(
|
|
||||||
@Context final HttpServletRequest httpServletRequest,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The revision is used to verify the client is working with the latest version of the flow.",
|
|
||||||
required = false
|
|
||||||
)
|
|
||||||
@QueryParam(VERSION) final LongParameter version,
|
|
||||||
@ApiParam(
|
|
||||||
value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
|
|
||||||
required = false
|
|
||||||
)
|
|
||||||
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user group id.",
|
|
||||||
required = true
|
|
||||||
)
|
|
||||||
@PathParam("id") final String id) {
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.DELETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle expects request (usually from the cluster manager)
|
|
||||||
final Revision revision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
|
|
||||||
return withWriteLock(
|
|
||||||
serviceFacade,
|
|
||||||
revision,
|
|
||||||
lookup -> {
|
|
||||||
final Authorizable userGroups = lookup.getUserGroupsAuthorizable();
|
|
||||||
userGroups.authorize(authorizer, RequestAction.READ);
|
|
||||||
},
|
|
||||||
() -> {
|
|
||||||
},
|
|
||||||
() -> {
|
|
||||||
// delete the specified user group
|
|
||||||
final UserGroupEntity entity = serviceFacade.deleteUserGroup(revision, id);
|
|
||||||
return clusterContext(generateOkResponse(entity)).build();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,381 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.api;
|
|
||||||
|
|
||||||
import com.wordnik.swagger.annotations.Api;
|
|
||||||
import com.wordnik.swagger.annotations.ApiOperation;
|
|
||||||
import com.wordnik.swagger.annotations.ApiParam;
|
|
||||||
import com.wordnik.swagger.annotations.ApiResponse;
|
|
||||||
import com.wordnik.swagger.annotations.ApiResponses;
|
|
||||||
import com.wordnik.swagger.annotations.Authorization;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.nifi.authorization.Authorizer;
|
|
||||||
import org.apache.nifi.authorization.RequestAction;
|
|
||||||
import org.apache.nifi.authorization.resource.Authorizable;
|
|
||||||
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
|
||||||
import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
|
|
||||||
import org.apache.nifi.util.NiFiProperties;
|
|
||||||
import org.apache.nifi.web.NiFiServiceFacade;
|
|
||||||
import org.apache.nifi.web.Revision;
|
|
||||||
import org.apache.nifi.web.api.dto.RevisionDTO;
|
|
||||||
import org.apache.nifi.web.api.dto.UserDTO;
|
|
||||||
import org.apache.nifi.web.api.entity.UserEntity;
|
|
||||||
import org.apache.nifi.web.api.request.ClientIdParameter;
|
|
||||||
import org.apache.nifi.web.api.request.LongParameter;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.DefaultValue;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HttpMethod;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.QueryParam;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
@Path("/users")
|
|
||||||
@Api(
|
|
||||||
value = "/users",
|
|
||||||
description = "Endpoint for managing users."
|
|
||||||
)
|
|
||||||
public class UsersResource extends ApplicationResource {
|
|
||||||
|
|
||||||
private final NiFiServiceFacade serviceFacade;
|
|
||||||
private final Authorizer authorizer;
|
|
||||||
|
|
||||||
public UsersResource(NiFiServiceFacade serviceFacade, Authorizer authorizer, NiFiProperties properties, RequestReplicator requestReplicator, ClusterCoordinator clusterCoordinator) {
|
|
||||||
this.serviceFacade = serviceFacade;
|
|
||||||
this.authorizer = authorizer;
|
|
||||||
setProperties(properties);
|
|
||||||
setRequestReplicator(requestReplicator);
|
|
||||||
setClusterCoordinator(clusterCoordinator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the uri for the specified user.
|
|
||||||
*
|
|
||||||
* @param userEntity userEntity
|
|
||||||
* @return userEntity
|
|
||||||
*/
|
|
||||||
public UserEntity populateRemainingUserEntityContent(UserEntity userEntity) {
|
|
||||||
if (userEntity.getComponent() != null) {
|
|
||||||
populateRemainingUserContent(userEntity.getComponent());
|
|
||||||
}
|
|
||||||
return userEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the uri for the specified user.
|
|
||||||
*/
|
|
||||||
public UserDTO populateRemainingUserContent(UserDTO user) {
|
|
||||||
// populate the user href
|
|
||||||
user.setUri(generateResourceUri("users", user.getId()));
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new user.
|
|
||||||
*
|
|
||||||
* @param httpServletRequest request
|
|
||||||
* @param userEntity An userEntity.
|
|
||||||
* @return An userEntity.
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Creates a user",
|
|
||||||
response = UserEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response createUser(
|
|
||||||
@Context final HttpServletRequest httpServletRequest,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user configuration details.",
|
|
||||||
required = true
|
|
||||||
) final UserEntity userEntity) {
|
|
||||||
|
|
||||||
if (userEntity == null || userEntity.getComponent() == null) {
|
|
||||||
throw new IllegalArgumentException("User details must be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userEntity.getRevision() == null || (userEntity.getRevision().getVersion() == null || userEntity.getRevision().getVersion() != 0)) {
|
|
||||||
throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Processor.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userEntity.getComponent().getId() != null) {
|
|
||||||
throw new IllegalArgumentException("User ID cannot be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.POST, userEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle expects request (usually from the cluster manager)
|
|
||||||
final boolean validationPhase = isValidationPhase(httpServletRequest);
|
|
||||||
if (validationPhase || !isTwoPhaseRequest(httpServletRequest)) {
|
|
||||||
// authorize access
|
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
|
||||||
final Authorizable users = lookup.getUsersAuthorizable();
|
|
||||||
users.authorize(authorizer, RequestAction.WRITE);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (validationPhase) {
|
|
||||||
return generateContinueResponse().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the user id as appropriate
|
|
||||||
userEntity.getComponent().setId(generateUuid());
|
|
||||||
|
|
||||||
// get revision from the config
|
|
||||||
final RevisionDTO revisionDTO = userEntity.getRevision();
|
|
||||||
Revision revision = new Revision(revisionDTO.getVersion(), revisionDTO.getClientId(), userEntity.getComponent().getId());
|
|
||||||
|
|
||||||
// create the user and generate the json
|
|
||||||
final UserEntity entity = serviceFacade.createUser(revision, userEntity.getComponent());
|
|
||||||
populateRemainingUserEntityContent(entity);
|
|
||||||
|
|
||||||
// build the response
|
|
||||||
return clusterContext(generateCreatedResponse(URI.create(entity.getComponent().getUri()), entity)).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the specified user.
|
|
||||||
*
|
|
||||||
* @param id The id of the user to retrieve
|
|
||||||
* @return An userEntity.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Consumes(MediaType.WILDCARD)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("{id}")
|
|
||||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Gets a user",
|
|
||||||
response = UserEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
|
|
||||||
@Authorization(value = "Administrator", type = "ROLE_ADMIN")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response getUser(
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user id.",
|
|
||||||
required = true
|
|
||||||
)
|
|
||||||
@PathParam("id") final String id) {
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.GET);
|
|
||||||
}
|
|
||||||
|
|
||||||
// authorize access
|
|
||||||
serviceFacade.authorizeAccess(lookup -> {
|
|
||||||
final Authorizable users = lookup.getUsersAuthorizable();
|
|
||||||
users.authorize(authorizer, RequestAction.READ);
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the user
|
|
||||||
final UserEntity entity = serviceFacade.getUser(id, true);
|
|
||||||
populateRemainingUserEntityContent(entity);
|
|
||||||
|
|
||||||
return clusterContext(generateOkResponse(entity)).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a user.
|
|
||||||
*
|
|
||||||
* @param httpServletRequest request
|
|
||||||
* @param id The id of the user to update.
|
|
||||||
* @param userEntity An userEntity.
|
|
||||||
* @return An userEntity.
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("{id}")
|
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Updates a user",
|
|
||||||
response = UserEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response updateUser(
|
|
||||||
@Context final HttpServletRequest httpServletRequest,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user id.",
|
|
||||||
required = true
|
|
||||||
)
|
|
||||||
@PathParam("id") final String id,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user configuration details.",
|
|
||||||
required = true
|
|
||||||
) final UserEntity userEntity) {
|
|
||||||
|
|
||||||
if (userEntity == null || userEntity.getComponent() == null) {
|
|
||||||
throw new IllegalArgumentException("User details must be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userEntity.getRevision() == null) {
|
|
||||||
throw new IllegalArgumentException("Revision must be specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure the ids are the same
|
|
||||||
final UserDTO userDTO = userEntity.getComponent();
|
|
||||||
if (!id.equals(userDTO.getId())) {
|
|
||||||
throw new IllegalArgumentException(String.format("The user id (%s) in the request body does not equal the "
|
|
||||||
+ "user id of the requested resource (%s).", userDTO.getId(), id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.PUT, userEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the revision
|
|
||||||
final Revision revision = getRevision(userEntity, id);
|
|
||||||
return withWriteLock(
|
|
||||||
serviceFacade,
|
|
||||||
revision,
|
|
||||||
lookup -> {
|
|
||||||
final Authorizable users = lookup.getUsersAuthorizable();
|
|
||||||
users.authorize(authorizer, RequestAction.WRITE);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
() -> {
|
|
||||||
// update the user
|
|
||||||
final UserEntity entity = serviceFacade.updateUser(revision, userDTO);
|
|
||||||
populateRemainingUserEntityContent(entity);
|
|
||||||
|
|
||||||
return clusterContext(generateOkResponse(entity)).build();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the specified user.
|
|
||||||
*
|
|
||||||
* @param httpServletRequest request
|
|
||||||
* @param version The revision is used to verify the client is working with
|
|
||||||
* the latest version of the flow.
|
|
||||||
* @param clientId Optional client id. If the client id is not specified, a
|
|
||||||
* new one will be generated. This value (whether specified or generated) is
|
|
||||||
* included in the response.
|
|
||||||
* @param id The id of the user to remove.
|
|
||||||
* @return A entity containing the client id and an updated revision.
|
|
||||||
*/
|
|
||||||
@DELETE
|
|
||||||
@Consumes(MediaType.WILDCARD)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("{id}")
|
|
||||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
|
||||||
@ApiOperation(
|
|
||||||
value = "Deletes a user",
|
|
||||||
response = UserEntity.class,
|
|
||||||
authorizations = {
|
|
||||||
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ApiResponses(
|
|
||||||
value = {
|
|
||||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
|
||||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
|
||||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
|
||||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
|
||||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
public Response removeUser(
|
|
||||||
@Context final HttpServletRequest httpServletRequest,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The revision is used to verify the client is working with the latest version of the flow.",
|
|
||||||
required = false
|
|
||||||
)
|
|
||||||
@QueryParam(VERSION) final LongParameter version,
|
|
||||||
@ApiParam(
|
|
||||||
value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
|
|
||||||
required = false
|
|
||||||
)
|
|
||||||
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
|
||||||
@ApiParam(
|
|
||||||
value = "The user id.",
|
|
||||||
required = true
|
|
||||||
)
|
|
||||||
@PathParam("id") final String id) {
|
|
||||||
|
|
||||||
if (isReplicateRequest()) {
|
|
||||||
return replicate(HttpMethod.DELETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle expects request (usually from the cluster manager)
|
|
||||||
final Revision revision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
|
|
||||||
return withWriteLock(
|
|
||||||
serviceFacade,
|
|
||||||
revision,
|
|
||||||
lookup -> {
|
|
||||||
final Authorizable users = lookup.getUsersAuthorizable();
|
|
||||||
users.authorize(authorizer, RequestAction.READ);
|
|
||||||
},
|
|
||||||
() -> {
|
|
||||||
},
|
|
||||||
() -> {
|
|
||||||
// delete the specified user
|
|
||||||
final UserEntity entity = serviceFacade.deleteUser(revision, id);
|
|
||||||
return clusterContext(generateOkResponse(entity)).build();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* 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.api.config;
|
||||||
|
|
||||||
|
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.ext.ExceptionMapper;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps authorization access exceptions into client responses.
|
||||||
|
*/
|
||||||
|
@Provider
|
||||||
|
public class AuthorizationAccessExceptionMapper implements ExceptionMapper<AuthorizationAccessException> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AdministrationExceptionMapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response toResponse(AuthorizationAccessException e) {
|
||||||
|
// log the error
|
||||||
|
logger.error(String.format("%s. Returning %s response.", e, Response.Status.INTERNAL_SERVER_ERROR), e);
|
||||||
|
|
||||||
|
// generate the response
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).type("text/plain").build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -698,7 +698,7 @@ public final class DtoFactory {
|
||||||
|
|
||||||
final UserDTO dto = new UserDTO();
|
final UserDTO dto = new UserDTO();
|
||||||
dto.setId(user.getIdentifier());
|
dto.setId(user.getIdentifier());
|
||||||
dto.setGroups(groups);
|
dto.setUserGroups(groups);
|
||||||
dto.setIdentity(user.getIdentity());
|
dto.setIdentity(user.getIdentity());
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.nifi.web.dao;
|
||||||
import org.apache.nifi.authorization.User;
|
import org.apache.nifi.authorization.User;
|
||||||
import org.apache.nifi.web.api.dto.UserDTO;
|
import org.apache.nifi.web.api.dto.UserDTO;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface UserDAO {
|
public interface UserDAO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +45,13 @@ public interface UserDAO {
|
||||||
*/
|
*/
|
||||||
User getUser(String userId);
|
User getUser(String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all users.
|
||||||
|
*
|
||||||
|
* @return The user transfer objects
|
||||||
|
*/
|
||||||
|
Set<User> getUsers();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the specified user.
|
* Updates the specified user.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.nifi.web.dao;
|
||||||
import org.apache.nifi.authorization.Group;
|
import org.apache.nifi.authorization.Group;
|
||||||
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface UserGroupDAO {
|
public interface UserGroupDAO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +45,13 @@ public interface UserGroupDAO {
|
||||||
*/
|
*/
|
||||||
Group getUserGroup(String userGroupId);
|
Group getUserGroup(String userGroupId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all user groups.
|
||||||
|
*
|
||||||
|
* @return The user group transfer objects
|
||||||
|
*/
|
||||||
|
Set<Group> getUserGroups();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the specified user group.
|
* Updates the specified user group.
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,10 +28,13 @@ import org.apache.nifi.authorization.UsersAndAccessPolicies;
|
||||||
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||||
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
|
||||||
import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
|
import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
|
||||||
|
import org.apache.nifi.web.ResourceNotFoundException;
|
||||||
import org.apache.nifi.web.api.dto.AccessPolicyDTO;
|
import org.apache.nifi.web.api.dto.AccessPolicyDTO;
|
||||||
import org.apache.nifi.web.api.dto.UserDTO;
|
import org.apache.nifi.web.api.dto.UserDTO;
|
||||||
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
import org.apache.nifi.web.api.dto.UserGroupDTO;
|
||||||
import org.apache.nifi.web.api.entity.ComponentEntity;
|
import org.apache.nifi.web.api.entity.ComponentEntity;
|
||||||
|
import org.apache.nifi.web.api.entity.UserEntity;
|
||||||
|
import org.apache.nifi.web.api.entity.UserGroupEntity;
|
||||||
import org.apache.nifi.web.dao.AccessPolicyDAO;
|
import org.apache.nifi.web.dao.AccessPolicyDAO;
|
||||||
import org.apache.nifi.web.dao.UserDAO;
|
import org.apache.nifi.web.dao.UserDAO;
|
||||||
import org.apache.nifi.web.dao.UserGroupDAO;
|
import org.apache.nifi.web.dao.UserGroupDAO;
|
||||||
|
@ -41,7 +44,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGroupDAO, UserDAO {
|
public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGroupDAO, UserDAO {
|
||||||
|
|
||||||
private static final String MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER = "authorizer is not of type AbstractPolicyBasedAuthorizer";
|
static final String MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER = "This NiFi is not configured to internally manage users, groups, and policies. Please contact your system administrator.";
|
||||||
private final AbstractPolicyBasedAuthorizer authorizer;
|
private final AbstractPolicyBasedAuthorizer authorizer;
|
||||||
|
|
||||||
public StandardPolicyBasedAuthorizerDAO(final Authorizer authorizer) {
|
public StandardPolicyBasedAuthorizerDAO(final Authorizer authorizer) {
|
||||||
|
@ -156,34 +159,44 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessPolicy createAccessPolicy(final AccessPolicyDTO accessPolicyDTO) {
|
public AccessPolicy createAccessPolicy(final AccessPolicyDTO accessPolicyDTO) {
|
||||||
return authorizer.addAccessPolicy(buildAccessPolicy(accessPolicyDTO));
|
return authorizer.addAccessPolicy(buildAccessPolicy(accessPolicyDTO.getId(), accessPolicyDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessPolicy getAccessPolicy(final String accessPolicyId) {
|
public AccessPolicy getAccessPolicy(final String accessPolicyId) {
|
||||||
return authorizer.getAccessPolicy(accessPolicyId);
|
final AccessPolicy accessPolicy = authorizer.getAccessPolicy(accessPolicyId);
|
||||||
|
if (accessPolicy == null) {
|
||||||
|
throw new ResourceNotFoundException(String.format("Unable to find access policy with id '%s'.", accessPolicyId));
|
||||||
|
}
|
||||||
|
return accessPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessPolicy updateAccessPolicy(final AccessPolicyDTO accessPolicyDTO) {
|
public AccessPolicy updateAccessPolicy(final AccessPolicyDTO accessPolicyDTO) {
|
||||||
return authorizer.updateAccessPolicy(buildAccessPolicy(accessPolicyDTO));
|
return authorizer.updateAccessPolicy(buildAccessPolicy(getAccessPolicy(accessPolicyDTO.getId()).getIdentifier(), accessPolicyDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessPolicy deleteAccessPolicy(final String accessPolicyId) {
|
public AccessPolicy deleteAccessPolicy(final String accessPolicyId) {
|
||||||
return authorizer.deleteAccessPolicy(authorizer.getAccessPolicy(accessPolicyId));
|
return authorizer.deleteAccessPolicy(getAccessPolicy(accessPolicyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessPolicy buildAccessPolicy(final AccessPolicyDTO accessPolicyDTO) {
|
private AccessPolicy buildAccessPolicy(final String identifier, final AccessPolicyDTO accessPolicyDTO) {
|
||||||
|
final Set<UserGroupEntity> userGroups = accessPolicyDTO.getUserGroups();
|
||||||
|
final Set<UserEntity> users = accessPolicyDTO.getUsers();
|
||||||
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
final AccessPolicy.Builder builder = new AccessPolicy.Builder()
|
||||||
.identifier(accessPolicyDTO.getId())
|
.identifier(identifier)
|
||||||
.addGroups(accessPolicyDTO.getUserGroups().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
|
|
||||||
.addUsers(accessPolicyDTO.getUsers().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
|
|
||||||
.resource(accessPolicyDTO.getResource());
|
.resource(accessPolicyDTO.getResource());
|
||||||
if (accessPolicyDTO.getCanRead()) {
|
if (userGroups != null) {
|
||||||
|
builder.addGroups(userGroups.stream().map(ComponentEntity::getId).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
if (users != null) {
|
||||||
|
builder.addUsers(users.stream().map(ComponentEntity::getId).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
if (Boolean.TRUE == accessPolicyDTO.getCanRead()) {
|
||||||
builder.addAction(RequestAction.READ);
|
builder.addAction(RequestAction.READ);
|
||||||
}
|
}
|
||||||
if (accessPolicyDTO.getCanWrite()) {
|
if (Boolean.TRUE == accessPolicyDTO.getCanWrite()) {
|
||||||
builder.addAction(RequestAction.WRITE);
|
builder.addAction(RequestAction.WRITE);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
@ -196,28 +209,40 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Group createUserGroup(final UserGroupDTO userGroupDTO) {
|
public Group createUserGroup(final UserGroupDTO userGroupDTO) {
|
||||||
return authorizer.addGroup(buildUserGroup(userGroupDTO));
|
return authorizer.addGroup(buildUserGroup(userGroupDTO.getId(), userGroupDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Group getUserGroup(final String userGroupId) {
|
public Group getUserGroup(final String userGroupId) {
|
||||||
return authorizer.getGroup(userGroupId);
|
final Group userGroup = authorizer.getGroup(userGroupId);
|
||||||
|
if (userGroup == null) {
|
||||||
|
throw new ResourceNotFoundException(String.format("Unable to find user group with id '%s'.", userGroupId));
|
||||||
|
}
|
||||||
|
return userGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Group> getUserGroups() {
|
||||||
|
return authorizer.getGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Group updateUserGroup(final UserGroupDTO userGroupDTO) {
|
public Group updateUserGroup(final UserGroupDTO userGroupDTO) {
|
||||||
return authorizer.updateGroup(buildUserGroup(userGroupDTO));
|
return authorizer.updateGroup(buildUserGroup(getUserGroup(userGroupDTO.getId()).getIdentifier(), userGroupDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Group deleteUserGroup(final String userGroupId) {
|
public Group deleteUserGroup(final String userGroupId) {
|
||||||
return authorizer.deleteGroup(authorizer.getGroup(userGroupId));
|
return authorizer.deleteGroup(getUserGroup(userGroupId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Group buildUserGroup(final UserGroupDTO userGroupDTO) {
|
private Group buildUserGroup(final String identifier, final UserGroupDTO userGroupDTO) {
|
||||||
return new Group.Builder()
|
final Set<UserEntity> users = userGroupDTO.getUsers();
|
||||||
.addUsers(userGroupDTO.getUsers().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
|
final Group.Builder builder = new Group.Builder().identifier(identifier).name(userGroupDTO.getName());
|
||||||
.identifier(userGroupDTO.getId()).name(userGroupDTO.getName()).build();
|
if (users != null) {
|
||||||
|
builder.addUsers(users.stream().map(ComponentEntity::getId).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -227,29 +252,40 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User createUser(final UserDTO userDTO) {
|
public User createUser(final UserDTO userDTO) {
|
||||||
final User user = buildUser(userDTO);
|
return authorizer.addUser(buildUser(userDTO.getId(), userDTO));
|
||||||
return authorizer.addUser(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getUser(final String userId) {
|
public User getUser(final String userId) {
|
||||||
return authorizer.getUser(userId);
|
final User user = authorizer.getUser(userId);
|
||||||
|
if (user == null) {
|
||||||
|
throw new ResourceNotFoundException(String.format("Unable to find user with id '%s'.", userId));
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<User> getUsers() {
|
||||||
|
return authorizer.getUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User updateUser(final UserDTO userDTO) {
|
public User updateUser(final UserDTO userDTO) {
|
||||||
return authorizer.updateUser(buildUser(userDTO));
|
return authorizer.updateUser(buildUser(getUser(userDTO.getId()).getIdentifier(), userDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User deleteUser(final String userId) {
|
public User deleteUser(final String userId) {
|
||||||
return authorizer.deleteUser(authorizer.getUser(userId));
|
return authorizer.deleteUser(getUser(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private User buildUser(final UserDTO userDTO) {
|
private User buildUser(final String identifier, final UserDTO userDTO) {
|
||||||
return new User.Builder()
|
final Set<UserGroupEntity> groups = userDTO.getUserGroups();
|
||||||
.addGroups(userDTO.getGroups().stream().map(ComponentEntity::getId).collect(Collectors.toSet()))
|
final User.Builder builder = new User.Builder().identifier(identifier).identity(userDTO.getIdentity());
|
||||||
.identifier(userDTO.getIdentity()).identity(userDTO.getIdentity()).build();
|
if (groups != null) {
|
||||||
|
builder.addGroups(groups.stream().map(ComponentEntity::getId).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -361,14 +361,7 @@
|
||||||
<constructor-arg ref="clusterCoordinator"/>
|
<constructor-arg ref="clusterCoordinator"/>
|
||||||
<constructor-arg ref="requestReplicator" />
|
<constructor-arg ref="requestReplicator" />
|
||||||
</bean>
|
</bean>
|
||||||
<bean id="userGroupsResource" class="org.apache.nifi.web.api.UserGroupsResource" scope="singleton">
|
<bean id="tenantsResource" class="org.apache.nifi.web.api.TenantsResource" 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="serviceFacade"/>
|
||||||
<constructor-arg ref="authorizer"/>
|
<constructor-arg ref="authorizer"/>
|
||||||
<constructor-arg ref="nifiProperties"/>
|
<constructor-arg ref="nifiProperties"/>
|
||||||
|
@ -381,6 +374,7 @@
|
||||||
|
|
||||||
<!-- exception mapping -->
|
<!-- exception mapping -->
|
||||||
<bean class="org.apache.nifi.web.api.config.AccessDeniedExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.AccessDeniedExceptionMapper" scope="singleton"/>
|
||||||
|
<bean class="org.apache.nifi.web.api.config.AuthorizationAccessExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.InvalidAuthenticationExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.InvalidAuthenticationExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.AuthenticationCredentialsNotFoundExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.AuthenticationCredentialsNotFoundExceptionMapper" scope="singleton"/>
|
||||||
<bean class="org.apache.nifi.web.api.config.AdministrationExceptionMapper" scope="singleton"/>
|
<bean class="org.apache.nifi.web.api.config.AdministrationExceptionMapper" scope="singleton"/>
|
||||||
|
|
|
@ -0,0 +1,561 @@
|
||||||
|
/*
|
||||||
|
* 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.Group
|
||||||
|
import org.apache.nifi.authorization.RequestAction
|
||||||
|
import org.apache.nifi.authorization.User
|
||||||
|
import org.apache.nifi.web.ResourceNotFoundException
|
||||||
|
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.UserEntity
|
||||||
|
import org.apache.nifi.web.api.entity.UserGroupEntity
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.Unroll
|
||||||
|
|
||||||
|
class StandardPolicyBasedAuthorizerDAOSpec extends Specification {
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "test non-policy-based authorizer #method throws IllegalStateException"() {
|
||||||
|
when:
|
||||||
|
daoMethod()
|
||||||
|
|
||||||
|
then:
|
||||||
|
def e = thrown(IllegalStateException)
|
||||||
|
assert e.message.equalsIgnoreCase(StandardPolicyBasedAuthorizerDAO.MSG_NON_ABSTRACT_POLICY_BASED_AUTHORIZER)
|
||||||
|
|
||||||
|
where:
|
||||||
|
method | daoMethod
|
||||||
|
'createAccessPolicy' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).createAccessPolicy(new AccessPolicyDTO(id: '1', resource: '/1', canRead: true)) }
|
||||||
|
'createUser' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).createUser(new UserDTO(id: '1', identity: 'a')) }
|
||||||
|
'createUserGroup' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).createUserGroup(new UserGroupDTO(id: '1', name: 'a')) }
|
||||||
|
'deleteAccessPolicy' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).deleteAccessPolicy('1') }
|
||||||
|
'deleteUser' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).deleteUser('1') }
|
||||||
|
'deleteUserGroup' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).deleteUserGroup('1') }
|
||||||
|
'getAccessPolicy' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).getAccessPolicy('1') }
|
||||||
|
'getUser' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).getUser('1') }
|
||||||
|
'getUserGroup' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).getUserGroup('1') }
|
||||||
|
'hasAccessPolicy' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).hasAccessPolicy('1') }
|
||||||
|
'hasUser' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).hasUser('1') }
|
||||||
|
'hasUserGroup' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).hasUserGroup('1') }
|
||||||
|
'updateAccessPolicy' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).updateAccessPolicy(new AccessPolicyDTO(id: '1', resource: '/1', canRead: true)) }
|
||||||
|
'updateUser' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).updateUser(new UserDTO(id: '1', identity: 'a')) }
|
||||||
|
'updateUserGroup' | { new StandardPolicyBasedAuthorizerDAO(Mock(Authorizer)).updateUserGroup(new UserGroupDTO(id: '1', name: 'a')) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "HasAccessPolicy: accessPolicy: #accessPolicy"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.hasAccessPolicy('policy-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy('policy-id-1') >> accessPolicy
|
||||||
|
0 * _
|
||||||
|
result == (accessPolicy != null)
|
||||||
|
|
||||||
|
where:
|
||||||
|
accessPolicy | _
|
||||||
|
new AccessPolicy.Builder().identifier('policy-id-1').resource('/fake/resource').addUser('user-id-1').addGroup('user-group-id-1')
|
||||||
|
.addAction(RequestAction.READ).addAction(RequestAction.WRITE).build() | _
|
||||||
|
null | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "CreateAccessPolicy: accessPolicy=#accessPolicy"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new AccessPolicyDTO(id: 'policy-id-1', resource: '/fake/resource', canRead: true,
|
||||||
|
canWrite: true,
|
||||||
|
users: [new UserEntity(id: 'user-id-1')] as Set,
|
||||||
|
userGroups: [new UserGroupEntity(id: 'user-group-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.createAccessPolicy(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
noExceptionThrown()
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.addAccessPolicy(accessPolicy) >> accessPolicy
|
||||||
|
0 * _
|
||||||
|
result?.equals accessPolicy
|
||||||
|
|
||||||
|
where:
|
||||||
|
accessPolicy | _
|
||||||
|
new AccessPolicy.Builder().identifier('policy-id-1').resource('/fake/resource').addUser('user-id-1').addGroup('user-group-id-1')
|
||||||
|
.addAction(RequestAction.READ).addAction(RequestAction.WRITE).build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetAccessPolicy: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.getAccessPolicy('policy-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy('policy-id-1') >> accessPolicy
|
||||||
|
0 * _
|
||||||
|
assert result?.equals(accessPolicy)
|
||||||
|
|
||||||
|
where:
|
||||||
|
accessPolicy | _
|
||||||
|
new AccessPolicy.Builder().identifier('policy-id-1').resource('/fake/resource').addUser('user-id-1').addGroup('user-group-id-1')
|
||||||
|
.addAction(RequestAction.READ).addAction(RequestAction.WRITE).build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetAccessPolicy: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.getAccessPolicy('policy-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy('policy-id-1') >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "UpdateAccessPolicy: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new AccessPolicyDTO(id: 'policy-id-1', resource: '/fake/resource', canRead: true,
|
||||||
|
canWrite: true,
|
||||||
|
users: [new UserEntity(id: 'user-id-1')] as Set,
|
||||||
|
userGroups: [new UserGroupEntity(id: 'user-group-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.updateAccessPolicy(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy(requestDTO.id) >> accessPolicy
|
||||||
|
1 * authorizer.updateAccessPolicy(accessPolicy) >> accessPolicy
|
||||||
|
0 * _
|
||||||
|
result?.equals(accessPolicy)
|
||||||
|
|
||||||
|
where:
|
||||||
|
accessPolicy | _
|
||||||
|
new AccessPolicy.Builder().identifier('policy-id-1').resource('/fake/resource').addUser('user-id-1').addGroup('user-group-id-1')
|
||||||
|
.addAction(RequestAction.READ).addAction(RequestAction.WRITE).build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "UpdateAccessPolicy: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new AccessPolicyDTO(id: 'policy-id-1', resource: '/fake/resource', canRead: true,
|
||||||
|
canWrite: true,
|
||||||
|
users: [new UserEntity(id: 'user-id-1')] as Set,
|
||||||
|
userGroups: [new UserGroupEntity(id: 'user-group-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.updateAccessPolicy(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy(requestDTO.id) >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "DeleteAccessPolicy: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.deleteAccessPolicy('policy-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy('policy-id-1') >> accessPolicy
|
||||||
|
1 * authorizer.deleteAccessPolicy(accessPolicy) >> accessPolicy
|
||||||
|
0 * _
|
||||||
|
result?.equals(accessPolicy)
|
||||||
|
|
||||||
|
where:
|
||||||
|
accessPolicy | _
|
||||||
|
new AccessPolicy.Builder().identifier('policy-id-1').resource('/fake/resource').addUser('user-id-1').addGroup('user-group-id-1')
|
||||||
|
.addAction(RequestAction.READ).addAction(RequestAction.WRITE).build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "DeleteAccessPolicy: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.deleteAccessPolicy('policy-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getAccessPolicy('policy-id-1') >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "HasUserGroup: userGroup=#userGroup"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.hasUserGroup('user-group-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup('user-group-id-1') >> userGroup
|
||||||
|
0 * _
|
||||||
|
result == (userGroup != null)
|
||||||
|
|
||||||
|
where:
|
||||||
|
userGroup | _
|
||||||
|
new Group.Builder().identifier('user-group-id-1').name('user-group-id-1').addUser('user-id-1').build() | _
|
||||||
|
null | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "CreateUserGroup: userGroup=#userGroup"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new UserGroupDTO(id: 'user-group-id-1', name: 'user group identity', users: [new UserEntity(id: 'user-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.createUserGroup(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
noExceptionThrown()
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.addGroup(userGroup) >> userGroup
|
||||||
|
0 * _
|
||||||
|
result?.equals userGroup
|
||||||
|
|
||||||
|
where:
|
||||||
|
userGroup | _
|
||||||
|
new Group.Builder().identifier('user-group-id-1').name('user-group-id-1').addUser('user-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetUserGroup: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.getUserGroup('user-group-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup('user-group-id-1') >> userGroup
|
||||||
|
0 * _
|
||||||
|
result?.equals(userGroup)
|
||||||
|
|
||||||
|
where:
|
||||||
|
userGroup | _
|
||||||
|
new Group.Builder().identifier('user-group-id-1').name('user-group-id-1').addUser('user-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetUserGroup: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.getUserGroup('user-group-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup('user-group-id-1') >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetUserGroups: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.getUserGroups()
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroups() >> userGroups
|
||||||
|
0 * _
|
||||||
|
result?.equals(userGroups)
|
||||||
|
|
||||||
|
where:
|
||||||
|
userGroups | _
|
||||||
|
[new Group.Builder().identifier('user-group-id-1').name('user-group-id-1').addUser('user-id-1').build()] as Set | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "UpdateUserGroup: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new UserGroupDTO(id: 'user-group-id-1', name: 'user group identity', users: [new UserEntity(id: 'user-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.updateUserGroup(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup(requestDTO.id) >> userGroup
|
||||||
|
1 * authorizer.updateGroup(userGroup) >> userGroup
|
||||||
|
0 * _
|
||||||
|
result?.equals(userGroup)
|
||||||
|
|
||||||
|
where:
|
||||||
|
userGroup | _
|
||||||
|
new Group.Builder().identifier('user-group-id-1').name('user-group-id-1').addUser('user-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "UpdateUserGroup: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new UserGroupDTO(id: 'user-group-id-1', name: 'user group identity', users: [new UserEntity(id: 'user-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.updateUserGroup(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup(requestDTO.id) >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "DeleteUserGroup: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.deleteUserGroup('user-group-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup('user-group-id-1') >> userGroup
|
||||||
|
1 * authorizer.deleteGroup(userGroup) >> userGroup
|
||||||
|
0 * _
|
||||||
|
assert result?.equals(userGroup)
|
||||||
|
|
||||||
|
where:
|
||||||
|
userGroup | _
|
||||||
|
new Group.Builder().identifier('user-group-id-1').name('user-group-id-1').addUser('user-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "DeleteUserGroup: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.deleteUserGroup('user-group-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getGroup('user-group-id-1') >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "HasUser: user=#user"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.hasUser('user-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser('user-id-1') >> user
|
||||||
|
0 * _
|
||||||
|
result == (user != null)
|
||||||
|
|
||||||
|
where:
|
||||||
|
user | _
|
||||||
|
new User.Builder().identifier('user-id-1').identity('user identity').addGroup('user-group-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "CreateUser: user=#user"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new UserDTO(id: 'user-id-1', identity: 'user identity', userGroups: [new UserGroupEntity(id: 'user-group-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.createUser(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
noExceptionThrown()
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.addUser(user) >> user
|
||||||
|
0 * _
|
||||||
|
result?.equals user
|
||||||
|
|
||||||
|
where:
|
||||||
|
user | _
|
||||||
|
new User.Builder().identifier('user-id-1').identity('user identity').addGroup('user-group-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetUser: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.getUser('user-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser('user-id-1') >> user
|
||||||
|
result?.equals(user)
|
||||||
|
0 * _
|
||||||
|
|
||||||
|
where:
|
||||||
|
user | _
|
||||||
|
new User.Builder().identifier('user-id-1').identity('user identity').addGroup('user-group-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetUser: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.getUser('user-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser('user-id-1') >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "GetUsers: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.getUsers()
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUsers() >> users
|
||||||
|
result?.containsAll(users)
|
||||||
|
0 * _
|
||||||
|
|
||||||
|
where:
|
||||||
|
users | _
|
||||||
|
[new User.Builder().identifier('user-id-1').identity('user identity').addGroup('user-group-id-1').build()] as Set | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "UpdateUser: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new UserDTO(id: 'user-id-1', identity: 'user identity', userGroups: [new UserGroupEntity(id: 'user-group-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.updateUser(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser(requestDTO.id) >> user
|
||||||
|
1 * authorizer.updateUser(user) >> user
|
||||||
|
0 * _
|
||||||
|
result?.equals(user)
|
||||||
|
|
||||||
|
where:
|
||||||
|
user | _
|
||||||
|
new User.Builder().identifier('user-id-1').identity('user identity').addGroup('user-group-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "UpdateUser: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
def requestDTO = new UserDTO(id: 'user-id-1', identity: 'user identity', userGroups: [new UserGroupEntity(id: 'user-group-id-1')] as Set)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.updateUser(requestDTO)
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser(requestDTO.id) >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "DeleteUser: success"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = dao.deleteUser('user-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser('user-id-1') >> user
|
||||||
|
1 * authorizer.deleteUser(user) >> user
|
||||||
|
0 * _
|
||||||
|
result?.equals(user)
|
||||||
|
|
||||||
|
where:
|
||||||
|
user | _
|
||||||
|
new User.Builder().identifier('user-id-1').identity('user identity').addGroup('user-group-id-1').build() | _
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unroll
|
||||||
|
def "DeleteUser: failure"() {
|
||||||
|
given:
|
||||||
|
def authorizer = Mock AbstractPolicyBasedAuthorizer
|
||||||
|
def dao = new StandardPolicyBasedAuthorizerDAO(authorizer)
|
||||||
|
|
||||||
|
when:
|
||||||
|
dao.deleteUser('user-id-1')
|
||||||
|
|
||||||
|
then:
|
||||||
|
1 * authorizer.getUser('user-id-1') >> null
|
||||||
|
0 * _
|
||||||
|
thrown ResourceNotFoundException
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue