diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/PermissionSetPatch.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/PermissionSetPatch.java new file mode 100644 index 000000000..cb887e64e --- /dev/null +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/PermissionSetPatch.java @@ -0,0 +1,98 @@ +/* + * 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.user; + +import java.util.HashSet; +import java.util.Set; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.net.auth.permission.Permission; +import org.glyptodon.guacamole.net.auth.permission.PermissionSet; + +/** + * A set of changes to be applied to a PermissionSet, describing the set of + * permissions being added and removed. + * + * @author Michael Jumper + * @param + * The type of permissions being added and removed. + */ +public class PermissionSetPatch { + + /** + * The set of all permissions being added. + */ + private final Set addedPermissions = + new HashSet(); + + /** + * The set of all permissions being removed. + */ + private final Set removedPermissions = + new HashSet(); + + /** + * Queues the given permission to be added. The add operation will be + * performed only when apply() is called. + * + * @param permission + * The permission to add. + */ + public void addPermission(PermissionType permission) { + addedPermissions.add(permission); + } + + /** + * Queues the given permission to be removed. The remove operation will be + * performed only when apply() is called. + * + * @param permission + * The permission to remove. + */ + public void removePermission(PermissionType permission) { + removedPermissions.add(permission); + } + + /** + * Applies all queued changes to the given permission set. + * + * @param permissionSet + * The permission set to add and remove permissions from. + * + * @throws GuacamoleException + * If an error occurs while manipulating the permissions of the given + * permission set. + */ + public void apply(PermissionSet permissionSet) + throws GuacamoleException { + + // Add any added permissions + if (!addedPermissions.isEmpty()) + permissionSet.addPermissions(addedPermissions); + + // Remove any removed permissions + if (!removedPermissions.isEmpty()) + permissionSet.removePermissions(removedPermissions); + + } + +} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/UserRESTService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/UserRESTService.java index 271941325..109863540 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/UserRESTService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/user/UserRESTService.java @@ -25,7 +25,6 @@ package org.glyptodon.guacamole.net.basic.rest.user; import com.google.inject.Inject; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.UUID; import javax.ws.rs.Consumes; @@ -48,7 +47,6 @@ 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.Permission; -import org.glyptodon.guacamole.net.auth.permission.PermissionSet; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet; import org.glyptodon.guacamole.net.basic.rest.APIPatch; @@ -355,8 +353,8 @@ public class UserRESTService { } /** - * Updates the given permission set by adding or removing the given - * permission based on the given patch operation. + * Updates the given permission set patch by queuing an add or remove + * operation for the given permission based on the given patch operation. * * @param * The type of permission stored within the permission set. @@ -364,31 +362,28 @@ public class UserRESTService { * @param operation * The patch operation to perform. * - * @param permissionSet - * The permission set being modified. + * @param permissionSetPatch + * The permission set patch being modified. * * @param permission * The permission being added or removed from the set. - * - * @throws GuacamoleException - * If an error occurs while modifying the permission set. */ private void updatePermissionSet( APIPatch.Operation operation, - PermissionSet permissionSet, - PermissionType permission) throws GuacamoleException { + PermissionSetPatch permissionSetPatch, + PermissionType permission) { // Add or remove permission based on operation switch (operation) { // Add permission case add: - permissionSet.addPermissions(Collections.singleton(permission)); + permissionSetPatch.addPermission(permission); break; // Remove permission case remove: - permissionSet.removePermissions(Collections.singleton(permission)); + permissionSetPatch.removePermission(permission); break; // Unsupported patch operation @@ -429,14 +424,17 @@ public class UserRESTService { UserContext userContext = authenticationService.getUserContext(authToken); - // Get the user directory - Directory userDirectory = userContext.getUserDirectory(); - // Get the user User user = userContext.getUserDirectory().get(username); if (user == null) throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\""); + // Permission patches for all types of permissions + PermissionSetPatch> connectionPermissionPatch = new PermissionSetPatch>(); + PermissionSetPatch> connectionGroupPermissionPatch = new PermissionSetPatch>(); + PermissionSetPatch> userPermissionPatch = new PermissionSetPatch>(); + PermissionSetPatch systemPermissionPatch = new PermissionSetPatch(); + // Apply all patch operations individually for (APIPatch patch : patches) { @@ -451,7 +449,7 @@ public class UserRESTService { // Create and update corresponding permission ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), user.getConnectionPermissions(), permission); + updatePermissionSet(patch.getOp(), connectionPermissionPatch, permission); } @@ -464,7 +462,7 @@ public class UserRESTService { // Create and update corresponding permission ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), user.getConnectionGroupPermissions(), permission); + updatePermissionSet(patch.getOp(), connectionGroupPermissionPatch, permission); } @@ -477,7 +475,7 @@ public class UserRESTService { // Create and update corresponding permission ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), user.getUserPermissions(), permission); + updatePermissionSet(patch.getOp(), userPermissionPatch, permission); } @@ -489,7 +487,7 @@ public class UserRESTService { // Create and update corresponding permission SystemPermission permission = new SystemPermission(type); - updatePermissionSet(patch.getOp(), user.getSystemPermissions(), permission); + updatePermissionSet(patch.getOp(), systemPermissionPatch, permission); } @@ -500,7 +498,10 @@ public class UserRESTService { } // end for each patch operation // Save the permission changes - userDirectory.update(user); + connectionPermissionPatch.apply(user.getConnectionPermissions()); + connectionGroupPermissionPatch.apply(user.getConnectionGroupPermissions()); + userPermissionPatch.apply(user.getUserPermissions()); + systemPermissionPatch.apply(user.getSystemPermissions()); }