From 993fbef86dba55c13598121bcff29b32bc6a293c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 18 Dec 2014 01:03:36 -0800 Subject: [PATCH] GUAC-932: Restore patch support within permission service. --- .../app/rest/services/permissionService.js | 147 ++++++++++++++---- .../webapp/app/rest/types/PermissionPatch.js | 94 +++++++++++ 2 files changed, 208 insertions(+), 33 deletions(-) create mode 100644 guacamole/src/main/webapp/app/rest/types/PermissionPatch.js diff --git a/guacamole/src/main/webapp/app/rest/services/permissionService.js b/guacamole/src/main/webapp/app/rest/services/permissionService.js index 88e42a421..f71b8cbca 100644 --- a/guacamole/src/main/webapp/app/rest/services/permissionService.js +++ b/guacamole/src/main/webapp/app/rest/services/permissionService.js @@ -23,8 +23,8 @@ /** * Service for operating on user permissions via the REST API. */ -angular.module('rest').factory('permissionService', ['$http', 'authenticationService', - function permissionService($http, authenticationService) { +angular.module('rest').factory('permissionService', ['$http', 'authenticationService', 'PermissionPatch', + function permissionService($http, authenticationService, PermissionPatch) { var service = {}; @@ -32,7 +32,6 @@ angular.module('rest').factory('permissionService', ['$http', 'authenticationSer * Makes a request to the REST API to get the list of permissions for a * given user, returning a promise that provides an array of * @link{Permission} objects if successful. - * * @param {String} userID * The ID of the user to retrieve the permissions for. @@ -42,7 +41,19 @@ angular.module('rest').factory('permissionService', ['$http', 'authenticationSer * success. */ service.getPermissions = function getPermissions(userID) { - return $http.get("api/user/" + userID + "/permissions?token=" + authenticationService.getCurrentToken()); + + // Build HTTP parameters set + var httpParameters = { + token : authenticationService.getCurrentToken() + }; + + // Retrieve user permissions + return $http({ + method : 'GET', + url : 'api/user/' + encodeURIComponent(userID) + '/permissions', + params : httpParameters + }); + }; /** @@ -50,8 +61,11 @@ angular.module('rest').factory('permissionService', ['$http', 'authenticationSer * returning a promise that can be used for processing the results of the * call. * - * @param {String} userID The ID of the user to add the permission for. - * @param {PermissionSet} permissions The permissions to add. + * @param {String} userID + * The ID of the user to modify the permissions of. + * + * @param {PermissionSet} permissions + * The set of permissions to add. * * @returns {Promise} * A promise for the HTTP call which will succeed if and only if the @@ -66,8 +80,11 @@ angular.module('rest').factory('permissionService', ['$http', 'authenticationSer * returning a promise that can be used for processing the results of the * call. * - * @param {String} userID The ID of the user to remove the permission for. - * @param {PermissionSet} permissions The permissions to remove. + * @param {String} userID + * The ID of the user to modify the permissions of. + * + * @param {PermissionSet} permissions + * The set of permissions to remove. * * @returns {Promise} * A promise for the HTTP call which will succeed if and only if the @@ -76,15 +93,88 @@ angular.module('rest').factory('permissionService', ['$http', 'authenticationSer service.removePermissions = function removePermissions(userID, permissions) { return service.patchPermissions(userID, null, permissions); }; - + + /** + * Adds patches for modifying the permissions associated with specific + * objects to the given array of patches. + * + * @param {PermissionPatch[]} patch + * The array of patches to add new patches to. + * + * @param {String} operation + * The operation to specify within each of the patches. Valid values + * for this are defined within PermissionPatch.Operation. + * + * @param {Object.} permissions + * A map of object identifiers to arrays of permission type strings, + * where each type string is a value from + * PermissionSet.ObjectPermissionType. + */ + var addObjectPatchOperations = function addObjectPatchOperations(patch, operation, path, permissions) { + + // Add object permission operations to patch + for (var identifier in permissions) { + patch.push({ + op : operation, + path : path + "/" + identifier, + value : permissions[identifier] + }); + } + + }; + + /** + * Adds patches for modifying any permission that can be stored within a + * @link{PermissionSet}. + * + * @param {PermissionPatch[]} patch + * The array of patches to add new patches to. + * + * @param {String} operation + * The operation to specify within each of the patches. Valid values + * for this are defined within PermissionPatch.Operation. + * + * @param {PermissionSet} permissions + * The set of permissions for which patches should be added. + */ + var addPatchOperations = function addPatchOperations(patch, operation, permissions) { + + // Add connection permission operations to patch + addObjectPatchOperations(patch, operation, "/connectionPermissions", + permissions.connectionPermissions); + + // Add connection group permission operations to patch + addObjectPatchOperations(patch, operation, "/connectionGroupPermissions", + permissions.connectionGroupPermissions); + + // Add user permission operations to patch + addObjectPatchOperations(patch, operation, "/userPermissions", + permissions.userPermissions); + + // Add system operations to patch + if (permissions.systemPermissions.length) { + patch.push({ + op : operation, + path : "/systemPermissions", + value : permissions.systemPermissions + }); + } + + }; + /** * Makes a request to the REST API to modify the permissions for a given * user, returning a promise that can be used for processing the results of * the call. * - * @param {String} userID The ID of the user to remove the permission for. - * @param {PermissionSet} [permissionsToAdd] The permissions to add. - * @param {PermissionSet} [permissionsToRemove] The permissions to remove. + * @param {String} userID + * The ID of the user to modify the permissions of. + * + * @param {PermissionSet} [permissionsToAdd] + * The set of permissions to add, if any. + * + * @param {PermissionSet} [permissionsToRemove] + * The set of permissions to remove, if any. * * @returns {Promise} * A promise for the HTTP call which will succeed if and only if the @@ -92,33 +182,24 @@ angular.module('rest').factory('permissionService', ['$http', 'authenticationSer */ service.patchPermissions = function patchPermissions(userID, permissionsToAdd, permissionsToRemove) { - // FIXME: This will NOT work, now that PermissionSet is used - - var i; var permissionPatch = []; + // Build HTTP parameters set + var httpParameters = { + token : authenticationService.getCurrentToken() + }; + // Add all the add operations to the patch - for (i = 0; i < permissionsToAdd.length; i++ ) { - permissionPatch.push({ - op : "add", - path : userID, - value : permissionsToAdd[i] - }); - } - + addPatchOperations(permissionPatch, PermissionPatch.Operation.ADD, permissionsToAdd); + // Add all the remove operations to the patch - for (i = 0; i < permissionsToRemove.length; i++ ) { - permissionPatch.push({ - op : "remove", - path : userID, - value : permissionsToRemove[i] - }); - } - - // Make the HTTP call + addPatchOperations(permissionPatch, PermissionPatch.Operation.REMOVE, permissionsToRemove); + + // Patch user permissions return $http({ method : 'PATCH', - url : "api/permission/?token=" + authenticationService.getCurrentToken(), + url : 'api/user/' + encodeURIComponent(userID) + '/permissions', + params : httpParameters, data : permissionPatch }); diff --git a/guacamole/src/main/webapp/app/rest/types/PermissionPatch.js b/guacamole/src/main/webapp/app/rest/types/PermissionPatch.js new file mode 100644 index 000000000..729e7a63a --- /dev/null +++ b/guacamole/src/main/webapp/app/rest/types/PermissionPatch.js @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2014 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. + */ + +/** + * Service which defines the PermissionPatch class. + */ +angular.module('rest').factory('PermissionPatch', [function definePermissionPatch() { + + /** + * The object returned by REST API calls when representing changes to the + * permissions granted to a specific user. + * + * @constructor + * @param {PermissionPatch|Object} [template={}] + * The object whose properties should be copied within the new + * PermissionPatch. + */ + var PermissionPatch = function PermissionPatch(template) { + + // Use empty object by default + template = template || {}; + + /** + * The operation to apply to the permissions indicated by the path. + * Valid operation values are defined within PermissionPatch.Operation. + * + * @type String + */ + this.op = template.op; + + /** + * The path of the permissions to modify. Depending on the type of the + * permission, this will be either "/connectionPermissions/ID", + * "/connectionGroupPermissions/ID", "/userPermissions/ID", or + * "/systemPermissions", where "ID" is the identifier of the object + * to which the permissions apply, if any. + * + * @type String + */ + this.path = template.path; + + /** + * The array of permissions. If the permission applies to an object, + * such as a connection or connection group, these will be values from + * PermissionSet.ObjectPermissionType. If the permission applies to + * the system as a whole (the path is "/systemPermissions"), these will + * be values from PermissionSet.SystemPermissionType. + * + * @type String[] + */ + this.value = template.value || []; + + }; + + /** + * All valid patch operations for permissions. Currently, only add and + * remove are supported. + */ + PermissionPatch.Operation = { + + /** + * Adds (grants) the specified permissions. + */ + ADD : "add", + + /** + * Removes (revokes) the specified permissions. + */ + REMOVE : "remove" + + }; + + return PermissionPatch; + +}]); \ No newline at end of file