GUAC-1100: Remove old recursive tree query. Add stub of new batching tree object.

This commit is contained in:
Michael Jumper
2015-02-21 22:05:27 -08:00
parent e9538a4167
commit bf8957986e
2 changed files with 91 additions and 196 deletions

View File

@@ -23,9 +23,6 @@
package org.glyptodon.guacamole.net.basic.rest.connectiongroup;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -39,20 +36,13 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.glyptodon.guacamole.GuacamoleClientException;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService;
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
import org.glyptodon.guacamole.net.basic.rest.connection.APIConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -83,177 +73,6 @@ public class ConnectionGroupRESTService {
@Inject
private ObjectRetrievalService retrievalService;
/**
* Determines whether the given user has at least one of the given
* permissions for the connection having the given identifier.
*
* @param user
* The user to check permissions for.
*
* @param identifier
* The identifier of the connection to check permissions for.
*
* @param permissions
* The permissions to check. The given user must have one or more of
* these permissions for this function to return true.
*
* @return
* true if the user has at least one of the given permissions.
*/
private boolean hasConnectionPermission(User user, String identifier,
List<ObjectPermission.Type> permissions) throws GuacamoleException {
// Retrieve connection permissions
ObjectPermissionSet connectionPermissions = user.getConnectionPermissions();
// Determine whether user has at least one of the given permissions
for (ObjectPermission.Type permission : permissions) {
if (connectionPermissions.hasPermission(permission, identifier))
return true;
}
// None of the given permissions were present
return false;
}
/**
* Determines whether the given user has at least one of the given
* permissions for the connection group having the given identifier.
*
* @param user
* The user to check permissions for.
*
* @param identifier
* The identifier of the connection group to check permissions for.
*
* @param permissions
* The permissions to check. The given user must have one or more of
* these permissions for this function to return true.
*
* @return
* true if the user has at least one of the given permissions.
*/
private boolean hasConnectionGroupPermission(User user, String identifier,
List<ObjectPermission.Type> permissions) throws GuacamoleException {
// Retrieve connection group permissions
ObjectPermissionSet connectionGroupPermissions = user.getConnectionGroupPermissions();
// Determine whether user has at least one of the given permissions
for (ObjectPermission.Type permission : permissions) {
if (connectionGroupPermissions.hasPermission(permission, identifier))
return true;
}
// None of the given permissions were present
return false;
}
/**
* Retrieves the given connection group from the user context, including
* all descendant connections and groups if requested.
*
* @param userContext
* The user context from which to retrieve the connection group.
*
* @param identifier
* The unique identifier of the connection group to retrieve.
*
* @param includeDescendants
* Whether the descendant connections and groups of the given
* connection group should also be retrieved.
*
* @param permissions
* The set of permissions to filter with. A user must have one or more
* of these permissions for a connection to appear in the result.
* If null, no filtering will be performed.
*
* @return
* The requested connection group, or null if no such connection group
* exists.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested connection group
* or any of its descendants.
*/
private APIConnectionGroup retrieveConnectionGroup(UserContext userContext,
String identifier, boolean includeDescendants, List<ObjectPermission.Type> permissions)
throws GuacamoleException {
User self = userContext.self();
// An admin user has access to any connection or connection group
SystemPermissionSet systemPermissions = self.getSystemPermissions();
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
// Retrieve specified connection group
ConnectionGroup connectionGroup;
try {
connectionGroup = retrievalService.retrieveConnectionGroup(userContext, identifier);
}
catch (GuacamoleResourceNotFoundException e) {
return null;
}
// Wrap queried connection group
APIConnectionGroup apiConnectionGroup = new APIConnectionGroup(connectionGroup);
// Recursively query all descendants if necessary, only querying the
// descendants of balancing groups if we have admin permission on that
// group
if (includeDescendants
&& (connectionGroup.getType() != ConnectionGroup.Type.BALANCING
|| isAdmin
|| hasConnectionGroupPermission(self, identifier,
Collections.singletonList(ObjectPermission.Type.ADMINISTER)))) {
// Query all child connections
Collection<APIConnection> apiConnections = new ArrayList<APIConnection>();
Directory<Connection> connectionDirectory = connectionGroup.getConnectionDirectory();
for (String childIdentifier : connectionDirectory.getIdentifiers()) {
// Pull current connection - silently ignore if connection was removed prior to read
Connection childConnection = connectionDirectory.get(childIdentifier);
if (childConnection == null)
continue;
// Filter based on permission, if requested
if (isAdmin || permissions == null || hasConnectionPermission(self, childIdentifier, permissions))
apiConnections.add(new APIConnection(childConnection));
}
// Associate child connections with current connection group
apiConnectionGroup.setChildConnections(apiConnections);
// Query all child connection groups
Collection<APIConnectionGroup> apiConnectionGroups = new ArrayList<APIConnectionGroup>();
Directory<ConnectionGroup> groupDirectory = connectionGroup.getConnectionGroupDirectory();
for (String childIdentifier : groupDirectory.getIdentifiers()) {
// Pull current connection group - silently ignore if connection group was removed prior to read
APIConnectionGroup childConnectionGroup = retrieveConnectionGroup(userContext, childIdentifier, true, permissions);
if (childConnectionGroup == null)
continue;
apiConnectionGroups.add(childConnectionGroup);
}
// Associate child groups with current connection group
apiConnectionGroup.setChildConnectionGroups(apiConnectionGroups);
}
// Return the connectiion group
return apiConnectionGroup;
}
/**
* Gets an individual connection group.
*
@@ -278,12 +97,8 @@ public class ConnectionGroupRESTService {
UserContext userContext = authenticationService.getUserContext(authToken);
// Retrieve requested connection group only
APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, false, null);
if (connectionGroup == null)
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
return connectionGroup;
// Retrieve the requested connection group
return new APIConnectionGroup(retrievalService.retrieveConnectionGroup(userContext, connectionGroupID));
}
@@ -320,16 +135,12 @@ public class ConnectionGroupRESTService {
UserContext userContext = authenticationService.getUserContext(authToken);
// Do not filter on permissions if no permissions are specified
if (permissions != null && permissions.isEmpty())
permissions = null;
// Retrieve requested connection group and all descendants
APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, true, permissions);
if (connectionGroup == null)
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
// Retrieve the requested tree, filtering by the given permissions
ConnectionGroup treeRoot = retrievalService.retrieveConnectionGroup(userContext, connectionGroupID);
ConnectionGroupTree tree = new ConnectionGroupTree(treeRoot, permissions);
return connectionGroup;
// Return tree as a connection group
return tree.getRootAPIConnectionGroup();
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2015 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.glyptodon.guacamole.net.basic.rest.connectiongroup;
import java.util.List;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
/**
* Provides access to the entire tree of connection groups and their
* connections.
*
* @author Michael Jumper
*/
public class ConnectionGroupTree {
/**
* The root connection group.
*/
private final APIConnectionGroup root;
/**
* Creates a new connection group tree using the given connection group as
* the tree root.
*
* @param root
* The connection group to use as the root of this connection group
* tree.
*
* @param permissions
* If specified and non-empty, limit the contents of the tree to only
* those connections for which the current user has any of the given
* permissions. Otherwise, all visible connections are returned.
* Connection groups are unaffected by this parameter.
*
* @throws GuacamoleException
* If an error occurs while retrieving the tree of connection groups
* and their descendants.
*/
public ConnectionGroupTree(ConnectionGroup root,
List<ObjectPermission.Type> permissions) throws GuacamoleException {
// Store root of tree
this.root = new APIConnectionGroup(root);
// STUB
}
/**
* Returns the entire connection group tree as an APIConnectionGroup. The
* returned APIConnectionGroup is the root group and will contain all
* descendant connection groups and connections, arranged hierarchically.
*
* @return
* The root connection group, containing the entire connection group
* tree and all connections.
*/
public APIConnectionGroup getRootAPIConnectionGroup() {
return root;
}
}