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 245321e86..aa8c56107 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 @@ -111,6 +111,40 @@ public class UserRESTService { */ @Inject private ObjectRetrievalService retrievalService; + + /** + * Determines whether the given user has at least one of the given + * permissions for the user having the given username. + * + * @param user + * The user to check permissions for. + * + * @param username + * The username of the user 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 hasUserPermission(User user, String username, + List permissions) throws GuacamoleException { + + // Determine whether user has at least one of the given permissions + for (ObjectPermission.Type permission : permissions) { + + UserPermission userPermission = new UserPermission(permission, username); + if (user.hasPermission(userPermission)) + return true; + + } + + // None of the given permissions were present + return false; + + } /** * Gets a list of users in the system, filtering the returned list by the @@ -120,10 +154,10 @@ public class UserRESTService { * The authentication token that is used to authenticate the user * performing the operation. * - * @param permission - * If specified, limit the returned list to only those users for whom - * the current user has the given permission. Otherwise, all visible - * users are returned. + * @param permissions + * The set of permissions to filter with. A user must have one or more + * of these permissions for a user to appear in the result. + * If null, no filtering will be performed. * * @return * A list of all visible users. If a permission was specified, this @@ -136,11 +170,14 @@ public class UserRESTService { @GET @AuthProviderRESTExposure public List getUsers(@QueryParam("token") String authToken, - @QueryParam("permission") UserPermission.Type permission) + @QueryParam("permission") List permissions) throws GuacamoleException { UserContext userContext = authenticationService.getUserContext(authToken); User self = userContext.self(); + + // An admin user has access to any user + boolean isAdmin = self.hasPermission(new SystemPermission(SystemPermission.Type.ADMINISTER)); // Get the directory Directory userDirectory = userContext.getUserDirectory(); @@ -150,7 +187,7 @@ public class UserRESTService { // Add all users matching the given permission filter for (String username : userDirectory.getIdentifiers()) { - if (permission == null || self.hasPermission(new UserPermission(permission, username))) + if (isAdmin || permissions == null || hasUserPermission(self, username, permissions)) users.add(new APIUser(userDirectory.get(username))); } diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageController.js b/guacamole/src/main/webapp/app/manage/controllers/manageController.js index 391efcff2..ab8ef457c 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageController.js @@ -185,8 +185,9 @@ angular.module('manage').controller('manageController', ['$scope', '$injector', $scope.rootGroup = rootGroup; }); - // Retrieve all users for whom we have UPDATE permission - userService.getUsers(PermissionSet.ObjectPermissionType.UPDATE) + // Retrieve all users for whom we have UPDATE or DELETE permission + userService.getUsers([PermissionSet.ObjectPermissionType.UPDATE, + PermissionSet.ObjectPermissionType.DELETE]) .success(function usersReceived(users) { $scope.users = users; }); diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js index dd769a933..9b2d518fe 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js @@ -34,6 +34,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto // Required services var $location = $injector.get('$location'); var $routeParams = $injector.get('$routeParams'); + var authenticationService = $injector.get('authenticationService'); var connectionGroupService = $injector.get('connectionGroupService'); var userService = $injector.get('userService'); var permissionService = $injector.get('permissionService'); @@ -77,6 +78,21 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto * @type ConnectionGroup */ $scope.rootGroup = null; + + + /** + * Whether the authenticated user has UPDATE permission for the user being edited. + * + * @type boolean + */ + $scope.hasUpdatePermission = null; + + /** + * Whether the authenticated user has DELETE permission for the user being edited. + * + * @type boolean + */ + $scope.hasDeletePermission = null; /** * Returns whether critical data has completed being loaded. @@ -87,9 +103,11 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto */ $scope.isLoaded = function isLoaded() { - return $scope.user !== null - && $scope.permissionFlags !== null - && $scope.rootGroup !== null; + return $scope.user !== null + && $scope.permissionFlags !== null + && $scope.rootGroup !== null + && $scope.hasUpdatePermission !== null + && $scope.hasDeletePermission !== null; }; @@ -108,6 +126,22 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto .success(function connectionGroupReceived(rootGroup) { $scope.rootGroup = rootGroup; }); + + // Query the user's permissions for the current connection + permissionService.getPermissions(authenticationService.getCurrentUserID()) + .success(function permissionsReceived(permissions) { + + // Check if the user has UPDATE permission + $scope.hasUpdatePermission = + PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) + || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE, username); + + // Check if the user has DELETE permission + $scope.hasDeletePermission = + PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) + || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.DELETE, username); + + }); /** * Available system permission types, as translation string / internal diff --git a/guacamole/src/main/webapp/app/manage/templates/manageUser.html b/guacamole/src/main/webapp/app/manage/templates/manageUser.html index b3dd7f5b7..3ed5f798b 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageUser.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageUser.html @@ -73,9 +73,9 @@ THE SOFTWARE.
- + - +
diff --git a/guacamole/src/main/webapp/app/rest/services/connectionGroupService.js b/guacamole/src/main/webapp/app/rest/services/connectionGroupService.js index 978fd43c4..1f959b38e 100644 --- a/guacamole/src/main/webapp/app/rest/services/connectionGroupService.js +++ b/guacamole/src/main/webapp/app/rest/services/connectionGroupService.js @@ -39,7 +39,7 @@ angular.module('rest').factory('connectionGroupService', ['$http', 'authenticati * The ID of the connection group to retrieve. If not provided, the * root connection group will be retrieved by default. * - * @param {String[]} [permissionType] + * @param {String[]} [permissionTypes] * 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. Valid values are listed diff --git a/guacamole/src/main/webapp/app/rest/services/userService.js b/guacamole/src/main/webapp/app/rest/services/userService.js index eb9062088..c4173fd1e 100644 --- a/guacamole/src/main/webapp/app/rest/services/userService.js +++ b/guacamole/src/main/webapp/app/rest/services/userService.js @@ -33,16 +33,17 @@ angular.module('rest').factory('userService', ['$http', 'authenticationService', * returning a promise that provides an array of @link{User} objects if * successful. * - * @param {String} [permissionType] - * The permission type string of the permission that the current user - * must have for a given user to appear within the list. Valid values - * are listed within PermissionSet.ObjectType. + * @param {String[]} [permissionTypes] + * The set of permissions to filter with. A user must have one or more + * of these permissions for a user to appear in the result. + * If null, no filtering will be performed. Valid values are listed + * within PermissionSet.ObjectType. * * @returns {Promise.} * A promise which will resolve with an array of @link{User} objects * upon success. */ - service.getUsers = function getUsers(permissionType) { + service.getUsers = function getUsers(permissionTypes) { // Build HTTP parameters set var httpParameters = { @@ -50,8 +51,8 @@ angular.module('rest').factory('userService', ['$http', 'authenticationService', }; // Add permission filter if specified - if (permissionType) - httpParameters.permission = permissionType; + if (permissionTypes) + httpParameters.permission = permissionTypes; // Retrieve users return $http({