GUAC-932: Add permission filtering to recursive connection group query.

This commit is contained in:
Michael Jumper
2014-12-16 21:30:54 -08:00
parent 21ee9073d0
commit ef5a9f9600
2 changed files with 78 additions and 21 deletions

View File

@@ -42,7 +42,10 @@ import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
import org.glyptodon.guacamole.net.auth.Connection; import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory; 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.UserContext;
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure; import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
import org.glyptodon.guacamole.net.basic.rest.HTTPException; import org.glyptodon.guacamole.net.basic.rest.HTTPException;
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
@@ -84,6 +87,11 @@ public class ConnectionGroupRESTService {
* @param includeDescendants * @param includeDescendants
* Whether the descendant connections and groups of the given * Whether the descendant connections and groups of the given
* connection group should also be retrieved. * connection group should also be retrieved.
*
* @param permission
* The permission the current user must have for a connection or
* connection group to be returned in the results, if any. If null
* is specified, no filtering by permission will be performed.
* *
* @return * @return
* The requested connection group, or null if no such connection group * The requested connection group, or null if no such connection group
@@ -94,9 +102,10 @@ public class ConnectionGroupRESTService {
* or any of its descendants. * or any of its descendants.
*/ */
private APIConnectionGroup retrieveConnectionGroup(UserContext userContext, private APIConnectionGroup retrieveConnectionGroup(UserContext userContext,
String identifier, boolean includeDescendants) String identifier, boolean includeDescendants, ObjectPermission.Type permission)
throws GuacamoleException { throws GuacamoleException {
User self = userContext.self();
ConnectionGroup rootGroup = userContext.getRootConnectionGroup(); ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
ConnectionGroup connectionGroup; ConnectionGroup connectionGroup;
@@ -135,7 +144,9 @@ public class ConnectionGroupRESTService {
if (childConnection == null) if (childConnection == null)
continue; continue;
apiConnections.add(new APIConnection(childConnection)); // Filter based on permission, if requested
if (permission == null || self.hasPermission(new ConnectionPermission(permission, childIdentifier)))
apiConnections.add(new APIConnection(childConnection));
} }
@@ -149,7 +160,7 @@ public class ConnectionGroupRESTService {
for (String childIdentifier : groupDirectory.getIdentifiers()) { for (String childIdentifier : groupDirectory.getIdentifiers()) {
// Pull current connection group - silently ignore if connection group was removed prior to read // Pull current connection group - silently ignore if connection group was removed prior to read
APIConnectionGroup childConnectionGroup = retrieveConnectionGroup(userContext, childIdentifier, true); APIConnectionGroup childConnectionGroup = retrieveConnectionGroup(userContext, childIdentifier, true, permission);
if (childConnectionGroup == null) if (childConnectionGroup == null)
continue; continue;
@@ -170,11 +181,18 @@ public class ConnectionGroupRESTService {
/** /**
* Gets an individual connection group. * Gets an individual connection group.
* *
* @param authToken The authentication token that is used to authenticate * @param authToken
* the user performing the operation. * The authentication token that is used to authenticate the user
* @param connectionGroupID The ID of the ConnectionGroup. * performing the operation.
* @return The connection group. *
* @throws GuacamoleException If a problem is encountered while retrieving the connection group. * @param connectionGroupID
* The ID of the connection group to retrieve.
*
* @return
* The connection group, without any descendants.
*
* @throws GuacamoleException
* If a problem is encountered while retrieving the connection group.
*/ */
@GET @GET
@Path("/{connectionGroupID}") @Path("/{connectionGroupID}")
@@ -185,7 +203,7 @@ public class ConnectionGroupRESTService {
UserContext userContext = authenticationService.getUserContext(authToken); UserContext userContext = authenticationService.getUserContext(authToken);
// Retrieve requested connection group only // Retrieve requested connection group only
APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, false); APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, false, null);
if (connectionGroup == null) if (connectionGroup == null)
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\""); throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
@@ -201,10 +219,16 @@ public class ConnectionGroupRESTService {
* performing the operation. * performing the operation.
* *
* @param connectionGroupID * @param connectionGroupID
* The ID of the ConnectionGroup. * The ID of the connection group to retrieve.
* *
* @param permission
* If specified, limit the returned list to only those connections and
* connection groups for which the current user has the given
* permission. Otherwise, all visible connections and connection groups
* are returned.
*
* @return * @return
* The connection group. * The requested connection group, including all descendants.
* *
* @throws GuacamoleException * @throws GuacamoleException
* If a problem is encountered while retrieving the connection group or * If a problem is encountered while retrieving the connection group or
@@ -214,12 +238,14 @@ public class ConnectionGroupRESTService {
@Path("/{connectionGroupID}/tree") @Path("/{connectionGroupID}/tree")
@AuthProviderRESTExposure @AuthProviderRESTExposure
public APIConnectionGroup getConnectionGroupTree(@QueryParam("token") String authToken, public APIConnectionGroup getConnectionGroupTree(@QueryParam("token") String authToken,
@PathParam("connectionGroupID") String connectionGroupID) throws GuacamoleException { @PathParam("connectionGroupID") String connectionGroupID,
@QueryParam("permission") ObjectPermission.Type permission)
throws GuacamoleException {
UserContext userContext = authenticationService.getUserContext(authToken); UserContext userContext = authenticationService.getUserContext(authToken);
// Retrieve requested connection group and all descendants // Retrieve requested connection group and all descendants
APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, true); APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, true, permission);
if (connectionGroup == null) if (connectionGroup == null)
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\""); throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");

View File

@@ -32,34 +32,55 @@ angular.module('rest').factory('connectionGroupService', ['$http', 'authenticati
* Makes a request to the REST API to get an individual connection group * Makes a request to the REST API to get an individual connection group
* and all descendants, returning a promise that provides the corresponding * and all descendants, returning a promise that provides the corresponding
* @link{ConnectionGroup} if successful. Descendant groups and connections * @link{ConnectionGroup} if successful. Descendant groups and connections
* will be stored as children of that connection group. * will be stored as children of that connection group. If a permission
* type is specified, the result will be filtering by that permission.
* *
* @param {String} [connectionGroupID=ConnectionGroup.ROOT_IDENTIFIER] * @param {String} [connectionGroupID=ConnectionGroup.ROOT_IDENTIFIER]
* The ID of the connection group to retrieve. If not provided, the * The ID of the connection group to retrieve. If not provided, the
* root connection group will be retrieved by default. * root connection group will be retrieved by default.
* *
* @param {String} [permissionType]
* The permission type string of the permission that the current user
* must have for a given connection or connection group to appear
* within the result. Valid values are listed within
* PermissionSet.ObjectType.
*
* @returns {Promise.ConnectionGroup} * @returns {Promise.ConnectionGroup}
* A promise which will resolve with a @link{ConnectionGroup} upon * A promise which will resolve with a @link{ConnectionGroup} upon
* success. * success.
*/ */
service.getConnectionGroupTree = function getConnectionGroupTree(connectionGroupID) { service.getConnectionGroupTree = function getConnectionGroupTree(connectionGroupID, permissionType) {
// Use the root connection group ID if no ID is passed in // Use the root connection group ID if no ID is passed in
connectionGroupID = connectionGroupID || ConnectionGroup.ROOT_IDENTIFIER; connectionGroupID = connectionGroupID || ConnectionGroup.ROOT_IDENTIFIER;
return $http.get("api/connectionGroup/" + connectionGroupID + "/tree?token=" + authenticationService.getCurrentToken());
// Build HTTP parameters set
var httpParameters = {
token : authenticationService.getCurrentToken()
};
// Add permission filter if specified
if (permissionType)
httpParameters.permission = permissionType;
// Retrieve connection group
return $http({
method : 'GET',
url : 'api/connectionGroup/' + encodeURIComponent(connectionGroupID) + '/tree',
params : httpParameters
});
}; };
/** /**
* Makes a request to the REST API to get an individual connection group, * Makes a request to the REST API to get an individual connection group,
* returning a promise that provides the corresponding * returning a promise that provides the corresponding
* @link{ConnectionGroup} if successful. * @link{ConnectionGroup} if successful.
* *
* @param {String} [connectionGroupID=ConnectionGroup.ROOT_IDENTIFIER] * @param {String} [connectionGroupID=ConnectionGroup.ROOT_IDENTIFIER]
* The ID of the connection group to retrieve. If not provided, the * The ID of the connection group to retrieve. If not provided, the
* root connection group will be retrieved by default. * root connection group will be retrieved by default.
* *
* @returns {Promise.<ConnectionGroup>} A promise for the HTTP call. * @returns {Promise.<ConnectionGroup>} A promise for the HTTP call.
* A promise which will resolve with a @link{ConnectionGroup} upon * A promise which will resolve with a @link{ConnectionGroup} upon
* success. * success.
@@ -69,7 +90,17 @@ angular.module('rest').factory('connectionGroupService', ['$http', 'authenticati
// Use the root connection group ID if no ID is passed in // Use the root connection group ID if no ID is passed in
connectionGroupID = connectionGroupID || ConnectionGroup.ROOT_IDENTIFIER; connectionGroupID = connectionGroupID || ConnectionGroup.ROOT_IDENTIFIER;
return $http.get("api/connectionGroup/" + connectionGroupID + "?token=" + authenticationService.getCurrentToken()); // Build HTTP parameters set
var httpParameters = {
token : authenticationService.getCurrentToken()
};
// Retrieve connection group
return $http({
method : 'GET',
url : 'api/connectionGroup/' + encodeURIComponent(connectionGroupID),
params : httpParameters
});
}; };