From 86d94d18d4c9eca32a653a006d9949f37a7f2642 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 12 Jul 2016 13:19:19 -0700 Subject: [PATCH] GUACAMOLE-5: Move permission management to own resource. --- .../PermissionSetPatch.java | 2 +- .../permission/PermissionSetResource.java | 261 ++++++++++++++++++ .../guacamole/rest/user/UserResource.java | 178 +----------- 3 files changed, 269 insertions(+), 172 deletions(-) rename guacamole/src/main/java/org/apache/guacamole/rest/{user => permission}/PermissionSetPatch.java (98%) create mode 100644 guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/PermissionSetPatch.java b/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetPatch.java similarity index 98% rename from guacamole/src/main/java/org/apache/guacamole/rest/user/PermissionSetPatch.java rename to guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetPatch.java index 653f424b4..b08d2ba3f 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/user/PermissionSetPatch.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetPatch.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.guacamole.rest.user; +package org.apache.guacamole.rest.permission; import java.util.HashSet; import java.util.Set; diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java new file mode 100644 index 000000000..e75460ccc --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/rest/permission/PermissionSetResource.java @@ -0,0 +1,261 @@ +/* + * 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.guacamole.rest.permission; + +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import org.apache.guacamole.GuacamoleClientException; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.net.auth.User; +import org.apache.guacamole.net.auth.permission.ObjectPermission; +import org.apache.guacamole.net.auth.permission.Permission; +import org.apache.guacamole.net.auth.permission.SystemPermission; +import org.apache.guacamole.rest.APIPatch; +import org.apache.guacamole.rest.PATCH; + +/** + * A REST resource which abstracts the operations available on the permissions + * granted to an existing User. + * + * @author Michael Jumper + */ +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class PermissionSetResource { + + /** + * The prefix of any path within an operation of a JSON patch which + * modifies the permissions of a user regarding a specific connection. + */ + private static final String CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/connectionPermissions/"; + + /** + * The prefix of any path within an operation of a JSON patch which + * modifies the permissions of a user regarding a specific connection group. + */ + private static final String CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX = "/connectionGroupPermissions/"; + + /** + * The prefix of any path within an operation of a JSON patch which + * modifies the permissions of a user regarding a specific active connection. + */ + private static final String ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/activeConnectionPermissions/"; + + /** + * The prefix of any path within an operation of a JSON patch which + * modifies the permissions of a user regarding another, specific user. + */ + private static final String USER_PERMISSION_PATCH_PATH_PREFIX = "/userPermissions/"; + + /** + * The path of any operation within a JSON patch which modifies the + * permissions of a user regarding the entire system. + */ + private static final String SYSTEM_PERMISSION_PATCH_PATH = "/systemPermissions"; + + /** + * The User object whose permissions are represented by this + * PermissionSetResource. + */ + private final User user; + + /** + * Creates a new PermissionSetResource which exposes the operations and + * subresources available for permissions of the given User. + * + * @param user + * The User whose permissions should be represented by this + * PermissionSetResource. + */ + public PermissionSetResource(User user) { + this.user = user; + } + + /** + * Gets a list of permissions for the user with the given username. + * + * @return + * A list of all permissions granted to the specified user. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions. + */ + @GET + public APIPermissionSet getPermissions() throws GuacamoleException { + return new APIPermissionSet(user); + } + + /** + * 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. + * + * @param operation + * The patch operation to perform. + * + * @param permissionSetPatch + * The permission set patch being modified. + * + * @param permission + * The permission being added or removed from the set. + * + * @throws GuacamoleException + * If the requested patch operation is not supported. + */ + private void updatePermissionSet( + APIPatch.Operation operation, + PermissionSetPatch permissionSetPatch, + PermissionType permission) throws GuacamoleException { + + // Add or remove permission based on operation + switch (operation) { + + // Add permission + case add: + permissionSetPatch.addPermission(permission); + break; + + // Remove permission + case remove: + permissionSetPatch.removePermission(permission); + break; + + // Unsupported patch operation + default: + throw new GuacamoleClientException("Unsupported patch operation: \"" + operation + "\""); + + } + + } + + /** + * Applies a given list of permission patches. Each patch specifies either + * an "add" or a "remove" operation for a permission type, represented by + * a string. Valid permission types depend on the path of each patch + * operation, as the path dictates the permission being modified, such as + * "/connectionPermissions/42" or "/systemPermissions". + * + * @param patches + * The permission patches to apply for this request. + * + * @throws GuacamoleException + * If a problem is encountered while modifying permissions. + */ + @PATCH + public void patchPermissions(List> patches) + throws GuacamoleException { + + // Permission patches for all types of permissions + PermissionSetPatch connectionPermissionPatch = new PermissionSetPatch(); + PermissionSetPatch connectionGroupPermissionPatch = new PermissionSetPatch(); + PermissionSetPatch activeConnectionPermissionPatch = new PermissionSetPatch(); + PermissionSetPatch userPermissionPatch = new PermissionSetPatch(); + PermissionSetPatch systemPermissionPatch = new PermissionSetPatch(); + + // Apply all patch operations individually + for (APIPatch patch : patches) { + + String path = patch.getPath(); + + // Create connection permission if path has connection prefix + if (path.startsWith(CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) { + + // Get identifier and type from patch operation + String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length()); + ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); + + // Create and update corresponding permission + ObjectPermission permission = new ObjectPermission(type, identifier); + updatePermissionSet(patch.getOp(), connectionPermissionPatch, permission); + + } + + // Create connection group permission if path has connection group prefix + else if (path.startsWith(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX)) { + + // Get identifier and type from patch operation + String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length()); + ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); + + // Create and update corresponding permission + ObjectPermission permission = new ObjectPermission(type, identifier); + updatePermissionSet(patch.getOp(), connectionGroupPermissionPatch, permission); + + } + + // Create active connection permission if path has active connection prefix + else if (path.startsWith(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) { + + // Get identifier and type from patch operation + String identifier = path.substring(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length()); + ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); + + // Create and update corresponding permission + ObjectPermission permission = new ObjectPermission(type, identifier); + updatePermissionSet(patch.getOp(), activeConnectionPermissionPatch, permission); + + } + + // Create user permission if path has user prefix + else if (path.startsWith(USER_PERMISSION_PATCH_PATH_PREFIX)) { + + // Get identifier and type from patch operation + String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length()); + ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); + + // Create and update corresponding permission + ObjectPermission permission = new ObjectPermission(type, identifier); + updatePermissionSet(patch.getOp(), userPermissionPatch, permission); + + } + + // Create system permission if path is system path + else if (path.equals(SYSTEM_PERMISSION_PATCH_PATH)) { + + // Get identifier and type from patch operation + SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue()); + + // Create and update corresponding permission + SystemPermission permission = new SystemPermission(type); + updatePermissionSet(patch.getOp(), systemPermissionPatch, permission); + + } + + // Otherwise, the path is not supported + else + throw new GuacamoleClientException("Unsupported patch path: \"" + path + "\""); + + } // end for each patch operation + + // Save the permission changes + connectionPermissionPatch.apply(user.getConnectionPermissions()); + connectionGroupPermissionPatch.apply(user.getConnectionGroupPermissions()); + activeConnectionPermissionPatch.apply(user.getActiveConnectionPermissions()); + userPermissionPatch.apply(user.getUserPermissions()); + systemPermissionPatch.apply(user.getSystemPermissions()); + + } + +} diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java index 77009b6ca..7329a0253 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java @@ -21,16 +21,13 @@ package org.apache.guacamole.rest.user; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; -import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; -import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import org.apache.guacamole.GuacamoleClientException; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleSecurityException; import org.apache.guacamole.net.auth.AuthenticationProvider; @@ -39,14 +36,9 @@ import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException; -import org.apache.guacamole.net.auth.permission.ObjectPermission; -import org.apache.guacamole.net.auth.permission.Permission; -import org.apache.guacamole.net.auth.permission.SystemPermission; -import org.apache.guacamole.rest.APIPatch; -import org.apache.guacamole.rest.PATCH; import org.apache.guacamole.rest.directory.DirectoryObjectResource; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; -import org.apache.guacamole.rest.permission.APIPermissionSet; +import org.apache.guacamole.rest.permission.PermissionSetResource; /** * A REST resource which abstracts the operations available on an existing @@ -158,172 +150,16 @@ public class UserResource } /** - * Gets a list of permissions for the user with the given username. + * Returns a resource which abstracts operations available on the overall + * permissions granted to the User represented by this UserResource. * * @return - * A list of all permissions granted to the specified user. - * - * @throws GuacamoleException - * If an error occurs while retrieving permissions. + * A resource which representing the permissions granted to the User + * represented by this UserResource. */ - @GET @Path("permissions") - public APIPermissionSet getPermissions() throws GuacamoleException { - return new APIPermissionSet(user); - } - - /** - * 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. - * - * @param operation - * The patch operation to perform. - * - * @param permissionSetPatch - * The permission set patch being modified. - * - * @param permission - * The permission being added or removed from the set. - * - * @throws GuacamoleException - * If the requested patch operation is not supported. - */ - private void updatePermissionSet( - APIPatch.Operation operation, - PermissionSetPatch permissionSetPatch, - PermissionType permission) throws GuacamoleException { - - // Add or remove permission based on operation - switch (operation) { - - // Add permission - case add: - permissionSetPatch.addPermission(permission); - break; - - // Remove permission - case remove: - permissionSetPatch.removePermission(permission); - break; - - // Unsupported patch operation - default: - throw new GuacamoleClientException("Unsupported patch operation: \"" + operation + "\""); - - } - - } - - /** - * Applies a given list of permission patches. Each patch specifies either - * an "add" or a "remove" operation for a permission type, represented by - * a string. Valid permission types depend on the path of each patch - * operation, as the path dictates the permission being modified, such as - * "/connectionPermissions/42" or "/systemPermissions". - * - * @param patches - * The permission patches to apply for this request. - * - * @throws GuacamoleException - * If a problem is encountered while modifying permissions. - */ - @PATCH - @Path("permissions") - public void patchPermissions(List> patches) - throws GuacamoleException { - - // Permission patches for all types of permissions - PermissionSetPatch connectionPermissionPatch = new PermissionSetPatch(); - PermissionSetPatch connectionGroupPermissionPatch = new PermissionSetPatch(); - PermissionSetPatch activeConnectionPermissionPatch = new PermissionSetPatch(); - PermissionSetPatch userPermissionPatch = new PermissionSetPatch(); - PermissionSetPatch systemPermissionPatch = new PermissionSetPatch(); - - // Apply all patch operations individually - for (APIPatch patch : patches) { - - String path = patch.getPath(); - - // Create connection permission if path has connection prefix - if (path.startsWith(CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) { - - // Get identifier and type from patch operation - String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length()); - ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); - - // Create and update corresponding permission - ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), connectionPermissionPatch, permission); - - } - - // Create connection group permission if path has connection group prefix - else if (path.startsWith(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX)) { - - // Get identifier and type from patch operation - String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length()); - ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); - - // Create and update corresponding permission - ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), connectionGroupPermissionPatch, permission); - - } - - // Create active connection permission if path has active connection prefix - else if (path.startsWith(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) { - - // Get identifier and type from patch operation - String identifier = path.substring(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length()); - ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); - - // Create and update corresponding permission - ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), activeConnectionPermissionPatch, permission); - - } - - // Create user permission if path has user prefix - else if (path.startsWith(USER_PERMISSION_PATCH_PATH_PREFIX)) { - - // Get identifier and type from patch operation - String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length()); - ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); - - // Create and update corresponding permission - ObjectPermission permission = new ObjectPermission(type, identifier); - updatePermissionSet(patch.getOp(), userPermissionPatch, permission); - - } - - // Create system permission if path is system path - else if (path.equals(SYSTEM_PERMISSION_PATCH_PATH)) { - - // Get identifier and type from patch operation - SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue()); - - // Create and update corresponding permission - SystemPermission permission = new SystemPermission(type); - updatePermissionSet(patch.getOp(), systemPermissionPatch, permission); - - } - - // Otherwise, the path is not supported - else - throw new GuacamoleClientException("Unsupported patch path: \"" + path + "\""); - - } // end for each patch operation - - // Save the permission changes - connectionPermissionPatch.apply(user.getConnectionPermissions()); - connectionGroupPermissionPatch.apply(user.getConnectionGroupPermissions()); - activeConnectionPermissionPatch.apply(user.getActiveConnectionPermissions()); - userPermissionPatch.apply(user.getUserPermissions()); - systemPermissionPatch.apply(user.getSystemPermissions()); - + public PermissionSetResource getPermissions() { + return new PermissionSetResource(user); } }