diff --git a/guacamole/src/main/webapp/app/manage/types/ManageableUser.js b/guacamole/src/main/webapp/app/manage/types/ManageableUser.js new file mode 100644 index 000000000..8f2e43aef --- /dev/null +++ b/guacamole/src/main/webapp/app/manage/types/ManageableUser.js @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/** + * A service for defining the ManageableUser class. + */ +angular.module('manage').factory('ManageableUser', [function defineManageableUser() { + + /** + * A pairing of an @link{User} with the identifier of its corresponding + * data source. + * + * @constructor + * @param {Object|ManageableUser} template + */ + var ManageableUser = function ManageableUser(template) { + + /** + * The unique identifier of the data source containing this user. + * + * @type String + */ + this.dataSource = template.dataSource; + + /** + * The @link{User} object represented by this ManageableUser and + * contained within the associated data source. + * + * @type User + */ + this.user = template.user; + + }; + + return ManageableUser; + +}]); diff --git a/guacamole/src/main/webapp/app/settings/directives/guacSettingsUsers.js b/guacamole/src/main/webapp/app/settings/directives/guacSettingsUsers.js index 420409196..494148888 100644 --- a/guacamole/src/main/webapp/app/settings/directives/guacSettingsUsers.js +++ b/guacamole/src/main/webapp/app/settings/directives/guacSettingsUsers.js @@ -37,8 +37,8 @@ angular.module('settings').directive('guacSettingsUsers', [function guacSettings controller: ['$scope', '$injector', function settingsUsersController($scope, $injector) { // Required types + var ManageableUser = $injector.get('ManageableUser'); var PermissionSet = $injector.get('PermissionSet'); - var User = $injector.get('User'); // Required services var $location = $injector.get('$location'); @@ -63,36 +63,19 @@ angular.module('settings').directive('guacSettingsUsers', [function guacSettings }; /** - * The data source from which the list of users should be pulled. - * For the time being, this is just the data source which - * authenticated the current user. + * The identifiers of all data sources accessible by the current + * user. * - * @type String + * @type String[] */ - $scope.dataSource = authenticationService.getDataSource(); + var dataSources = authenticationService.getAvailableDataSources(); /** - * All visible users. + * All visible users, along with their corresponding data sources. * - * @type User[] + * @type ManageableUser[] */ - $scope.users = null; - - /** - * Whether the current user can manage users. If the current - * permissions have not yet been loaded, this will be null. - * - * @type Boolean - */ - $scope.canManageUsers = null; - - /** - * Whether the current user can create new users. If the current - * permissions have not yet been loaded, this will be null. - * - * @type Boolean - */ - $scope.canCreateUsers = null; + $scope.manageableUsers = null; /** * The name of the new user to create, if any, when user creation @@ -103,10 +86,11 @@ angular.module('settings').directive('guacSettingsUsers', [function guacSettings $scope.newUsername = ""; /** - * All permissions associated with the current user, or null if the + * Map of data source identifiers to all permissions associated + * with the current user within that data source, or null if the * user's permissions have not yet been loaded. * - * @type PermissionSet + * @type Object. */ $scope.permissions = null; @@ -119,82 +103,144 @@ angular.module('settings').directive('guacSettingsUsers', [function guacSettings */ $scope.isLoaded = function isLoaded() { - return $scope.users !== null - && $scope.permissions !== null - && $scope.canManageUsers !== null - && $scope.canCreateUsers !== null; + return $scope.manageableUsers !== null + && $scope.permissions !== null; + + }; + + /** + * Returns the identifier of the data source that should be used by + * default when creating a new user. + * + * @return {String} + * The identifier of the data source that should be used by + * default when creating a new user, or null if user creation + * is not allowed. + */ + var getDefaultDataSource = function getDefaultDataSource() { + + // Abort if permissions have not yet loaded + if (!$scope.permissions) + return null; + + // For each data source + for (var dataSource in $scope.permissions) { + + // Retrieve corresponding permission set + var permissionSet = $scope.permissions[dataSource]; + + // Can create users if adminstrator or have explicit permission + if (PermissionSet.hasSystemPermission(permissionSet, PermissionSet.SystemPermissionType.ADMINISTER) + || PermissionSet.hasSystemPermission(permissionSet, PermissionSet.SystemPermissionType.CREATE_USER)) + return dataSource; + + } + + // No data sources allow user creation + return null; + + }; + + /** + * Returns whether the current user can create new users within at + * least one data source. + * + * @return {Boolean} + * true if the current user can create new users within at + * least one data source, false otherwise. + */ + $scope.canCreateUsers = function canCreateUsers() { + return getDefaultDataSource() !== null; + }; + + /** + * Returns whether the current user can create new users or make + * changes to existing users within at least one data source. The + * user management interface as a whole is useless if this function + * returns false. + * + * @return {Boolean} + * true if the current user can create new users or make + * changes to existing users within at least one data source, + * false otherwise. + */ + var canManageUsers = function canManageUsers() { + + // Abort if permissions have not yet loaded + if (!$scope.permissions) + return false; + + // Creating users counts as management + if ($scope.canCreateUsers()) + return true; + + // For each data source + for (var dataSource in $scope.permissions) { + + // Retrieve corresponding permission set + var permissionSet = $scope.permissions[dataSource]; + + // Can manage users if granted explicit update or delete + if (PermissionSet.hasUserPermission(permissionSet, PermissionSet.ObjectPermissionType.UPDATE) + || PermissionSet.hasUserPermission(permissionSet, PermissionSet.ObjectPermissionType.DELETE)) + return true; + + } + + // No data sources allow management of users + return false; }; // Retrieve current permissions - permissionService.getPermissions($scope.dataSource, currentUsername) - .success(function permissionsRetrieved(permissions) { + permissionService.getAllPermissions(dataSources, currentUsername) + .then(function permissionsRetrieved(permissions) { + // Store retrieved permissions $scope.permissions = permissions; - // Determine whether the current user can create new users - $scope.canCreateUsers = - PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) - || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_USER); - - // Determine whether the current user can manage other users - $scope.canManageUsers = - $scope.canCreateUsers - || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) - || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.DELETE); - // Return to home if there's nothing to do here - if (!$scope.canManageUsers) + if (!canManageUsers()) $location.path('/'); - + }); // Retrieve all users for whom we have UPDATE or DELETE permission - userService.getUsers($scope.dataSource, [ + userService.getAllUsers(dataSources, [ PermissionSet.ObjectPermissionType.UPDATE, PermissionSet.ObjectPermissionType.DELETE ]) - .success(function usersReceived(users) { + .then(function usersReceived(userArrays) { - // Display only other users, not self - $scope.users = users.filter(function isNotSelf(user) { - return user.username !== currentUsername; + var addedUsers = {}; + $scope.manageableUsers = []; + + // For each user in each data source + angular.forEach(dataSources, function addUserList(dataSource) { + angular.forEach(userArrays[dataSource], function addUser(user) { + + // Do not add the same user twice + if (addedUsers[user.username]) + return; + + // Add user to overall list + addedUsers[user.username] = user; + $scope.manageableUsers.push(new ManageableUser ({ + 'dataSource' : dataSource, + 'user' : user + })); + + }); }); }); /** - * Creates a new user having the username specified in the user - * creation interface. + * Navigates to an interface for creating a new user having the + * username specified. */ $scope.newUser = function newUser() { - - // Create user skeleton - var user = new User({ - username: $scope.newUsername || '' - }); - - // Create specified user - userService.createUser($scope.dataSource, user) - - // Add user to visible list upon success - .success(function userCreated() { - $scope.users.push(user); - }) - - // Notify of any errors - .error(function userCreationFailed(error) { - guacNotification.showStatus({ - 'className' : 'error', - 'title' : 'SETTINGS_USERS.DIALOG_HEADER_ERROR', - 'text' : error.message, - 'actions' : [ ACKNOWLEDGE_ACTION ] - }); - }); - - // Reset username - $scope.newUsername = ""; - + $location.url('/manage/' + encodeURIComponent(getDefaultDataSource()) + '/users/' + encodeURIComponent($scope.newUsername)); }; }] diff --git a/guacamole/src/main/webapp/app/settings/templates/settingsUsers.html b/guacamole/src/main/webapp/app/settings/templates/settingsUsers.html index 430f57912..e1932bfb4 100644 --- a/guacamole/src/main/webapp/app/settings/templates/settingsUsers.html +++ b/guacamole/src/main/webapp/app/settings/templates/settingsUsers.html @@ -25,24 +25,25 @@

{{'SETTINGS_USERS.HELP_USERS' | translate}}

-
+
\ No newline at end of file