From bf8957986e39bdbabd9ac7aa04f15a8df8dbf3c6 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Feb 2015 22:05:27 -0800 Subject: [PATCH] GUAC-1100: Remove old recursive tree query. Add stub of new batching tree object. --- .../ConnectionGroupRESTService.java | 203 +----------------- .../connectiongroup/ConnectionGroupTree.java | 84 ++++++++ 2 files changed, 91 insertions(+), 196 deletions(-) create mode 100644 guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupTree.java diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java index 22430bf84..cab7a3550 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java @@ -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 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 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 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 apiConnections = new ArrayList(); - Directory 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 apiConnectionGroups = new ArrayList(); - Directory 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(); } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupTree.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupTree.java new file mode 100644 index 000000000..9851710cf --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupTree.java @@ -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 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; + } + +}