You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/05/04 08:26:57 UTC
[03/21] guacamole-client git commit: GUACAMOLE-220: Migrate user
management controller to ManagementPermissions.
GUACAMOLE-220: Migrate user management controller to ManagementPermissions.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/4f43ddc4
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/4f43ddc4
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/4f43ddc4
Branch: refs/heads/master
Commit: 4f43ddc4203a59c7aea6834cfd8b5961c74ba57e
Parents: 507202d
Author: Michael Jumper <mj...@apache.org>
Authored: Tue May 1 00:03:52 2018 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue May 1 00:12:58 2018 -0700
----------------------------------------------------------------------
.../manage/controllers/manageUserController.js | 464 ++++++-------------
.../webapp/app/manage/templates/manageUser.html | 18 +-
2 files changed, 153 insertions(+), 329 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/4f43ddc4/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
index c385065..388e717 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
@@ -24,14 +24,16 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
function manageUserController($scope, $injector) {
// Required types
- var PageDefinition = $injector.get('PageDefinition');
- var PermissionFlagSet = $injector.get('PermissionFlagSet');
- var PermissionSet = $injector.get('PermissionSet');
- var User = $injector.get('User');
+ var ManagementPermissions = $injector.get('ManagementPermissions');
+ var PageDefinition = $injector.get('PageDefinition');
+ var PermissionFlagSet = $injector.get('PermissionFlagSet');
+ var PermissionSet = $injector.get('PermissionSet');
+ var User = $injector.get('User');
// Required services
var $location = $injector.get('$location');
var $routeParams = $injector.get('$routeParams');
+ var $q = $injector.get('$q');
var authenticationService = $injector.get('authenticationService');
var dataSourceService = $injector.get('dataSourceService');
var guacNotification = $injector.get('guacNotification');
@@ -128,13 +130,31 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
$scope.permissionFlags = null;
/**
- * A map of data source identifiers to the set of all permissions
- * associated with the current user under that data source, or null if the
- * user's permissions have not yet been loaded.
+ * The set of permissions that will be added to the user when the user is
+ * saved. Permissions will only be present in this set if they are
+ * manually added, and not later manually removed before saving.
*
- * @type Object.<String, PermissionSet>
+ * @type PermissionSet
*/
- $scope.permissions = null;
+ $scope.permissionsAdded = new PermissionSet();
+
+ /**
+ * The set of permissions that will be removed from the user when the user
+ * is saved. Permissions will only be present in this set if they are
+ * manually removed, and not later manually added before saving.
+ *
+ * @type PermissionSet
+ */
+ $scope.permissionsRemoved = new PermissionSet();
+
+ /**
+ * The managment-related actions that the current user may perform on the
+ * user currently being created/modified, or null if the current user's
+ * permissions have not yet been loaded.
+ *
+ * @type ManagementPermissions
+ */
+ $scope.managementPermissions = null;
/**
* All available user attributes. This is only the set of attribute
@@ -162,11 +182,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
*/
$scope.isLoaded = function isLoaded() {
- return $scope.users !== null
- && $scope.permissionFlags !== null
- && $scope.rootGroups !== null
- && $scope.permissions !== null
- && $scope.attributes !== null;
+ return $scope.users !== null
+ && $scope.permissionFlags !== null
+ && $scope.managementPermissions !== null
+ && $scope.attributes !== null;
};
@@ -196,97 +215,6 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
};
/**
- * Returns whether the current user can change attributes explicitly
- * associated with the user being edited within the given data source.
- *
- * @param {String} [dataSource]
- * The identifier of the data source to check. If omitted, this will
- * default to the currently-selected data source.
- *
- * @returns {Boolean}
- * true if the current user can change attributes associated with the
- * user being edited, false otherwise.
- */
- $scope.canChangeAttributes = function canChangeAttributes(dataSource) {
-
- // Do not check if permissions are not yet loaded
- if (!$scope.permissions)
- return false;
-
- // Use currently-selected data source if unspecified
- dataSource = dataSource || $scope.dataSource;
-
- // Attributes can always be set if we are creating the user
- if (!$scope.userExists(dataSource))
- return true;
-
- // The administrator can always change attributes
- if (PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.ADMINISTER))
- return true;
-
- // Otherwise, can change attributes if we have permission to update this user
- return PermissionSet.hasUserPermission($scope.permissions[dataSource],
- PermissionSet.ObjectPermissionType.UPDATE, username);
-
- };
-
- /**
- * Returns whether the current user can change/set all user attributes for
- * the user being edited, regardless of whether those attributes are
- * already explicitly associated with that user.
- *
- * @returns {Boolean}
- * true if the current user can change all attributes for the user
- * being edited, regardless of whether those attributes are already
- * explicitly associated with that user, false otherwise.
- */
- $scope.canChangeAllAttributes = function canChangeAllAttributes() {
-
- // All attributes can be set if we are creating the user
- return !$scope.userExists($scope.dataSource);
-
- };
-
- /**
- * Returns whether the current user can change permissions of any kind
- * which are associated with the user being edited within the given data
- * source.
- *
- * @param {String} [dataSource]
- * The identifier of the data source to check. If omitted, this will
- * default to the currently-selected data source.
- *
- * @returns {Boolean}
- * true if the current user can grant or revoke permissions of any kind
- * which are associated with the user being edited, false otherwise.
- */
- $scope.canChangePermissions = function canChangePermissions(dataSource) {
-
- // Do not check if permissions are not yet loaded
- if (!$scope.permissions)
- return false;
-
- // Use currently-selected data source if unspecified
- dataSource = dataSource || $scope.dataSource;
-
- // Permissions can always be set if we are creating the user
- if (!$scope.userExists(dataSource))
- return true;
-
- // The administrator can always modify permissions
- if (PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.ADMINISTER))
- return true;
-
- // Otherwise, can only modify permissions if we have explicit
- // ADMINISTER permission
- return PermissionSet.hasUserPermission($scope.permissions[dataSource],
- PermissionSet.ObjectPermissionType.ADMINISTER, username);
-
- };
-
- /**
* Returns whether the current user can edit the username of the user being
* edited within the given data source.
*
@@ -303,151 +231,158 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
};
/**
- * Returns whether the current user can save the user being edited within
- * the given data source. Saving will create or update that user depending
- * on whether the user already exists.
+ * Loads the data associated with the user having the given username,
+ * preparing the interface for making modifications to that existing user.
*
- * @param {String} [dataSource]
- * The identifier of the data source to check. If omitted, this will
- * default to the currently-selected data source.
+ * @param {String} dataSource
+ * The unique identifier of the data source containing the user to
+ * load.
*
- * @returns {Boolean}
- * true if the current user can save changes to the user being edited,
- * false otherwise.
- */
- $scope.canSaveUser = function canSaveUser(dataSource) {
-
- // Do not check if permissions are not yet loaded
- if (!$scope.permissions)
- return false;
-
- // Use currently-selected data source if unspecified
- dataSource = dataSource || $scope.dataSource;
+ * @param {String} username
+ * The username of the user to load.
+ *
+ * @returns {Promise}
+ * A promise which is resolved when the interface has been prepared for
+ * editing the given user.
+ */
+ var loadExistingUser = function loadExistingUser(dataSource, username) {
+ return $q.all({
+ users : dataSourceService.apply(userService.getUser, dataSources, username),
+ permissions : permissionService.getPermissions(dataSource, username)
+ })
+ .then(function userDataRetrieved(values) {
- // The administrator can always save users
- if (PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.ADMINISTER))
- return true;
+ $scope.users = values.users;
+ $scope.user = values.users[dataSource];
- // If user does not exist, can only save if we have permission to create users
- if (!$scope.userExists(dataSource))
- return PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.CREATE_USER);
+ // Create skeleton user if user does not exist
+ if (!$scope.user)
+ $scope.user = new User({
+ 'username' : username
+ });
- // Otherwise, can only save if we have permission to update this user
- return PermissionSet.hasUserPermission($scope.permissions[dataSource],
- PermissionSet.ObjectPermissionType.UPDATE, username);
+ // The current user will be associated with username of the existing
+ // user in the retrieved permission set
+ $scope.selfUsername = username;
+ $scope.permissionFlags = PermissionFlagSet.fromPermissionSet(values.permissions);
+ });
};
/**
- * Returns whether the current user can clone the user being edited within
- * the given data source.
+ * Loads the data associated with the user having the given username,
+ * preparing the interface for cloning that existing user.
*
- * @param {String} [dataSource]
- * The identifier of the data source to check. If omitted, this will
- * default to the currently-selected data source.
+ * @param {String} dataSource
+ * The unique identifier of the data source containing the user to
+ * be cloned.
*
- * @returns {Boolean}
- * true if the current user can clone the user being edited, false
- * otherwise.
- */
- $scope.canCloneUser = function canCloneUser(dataSource) {
-
- // Do not check if permissions are not yet loaded
- if (!$scope.permissions)
- return false;
-
- // Use currently-selected data source if unspecified
- dataSource = dataSource || $scope.dataSource;
-
- // If we are not editing an existing user, we cannot clone
- if (!$scope.userExists($scope.dataSource))
- return false;
+ * @param {String} username
+ * The username of the user being cloned.
+ *
+ * @returns {Promise}
+ * A promise which is resolved when the interface has been prepared for
+ * cloning the given user.
+ */
+ var loadClonedUser = function loadClonedUser(dataSource, username) {
+ return $q.all({
+ users : dataSourceService.apply(userService.getUser, [dataSource], username),
+ permissions : permissionService.getPermissions(dataSource, username)
+ })
+ .then(function userDataRetrieved(values) {
- // The administrator can always clone users
- if (PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.ADMINISTER))
- return true;
+ $scope.users = {};
+ $scope.user = values.users[dataSource];
- // Otherwise we need explicit CREATE_USER permission
- return PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.CREATE_USER);
+ // The current user will be associated with cloneSourceUsername in the
+ // retrieved permission set
+ $scope.selfUsername = username;
+ $scope.permissionFlags = PermissionFlagSet.fromPermissionSet(values.permissions);
+ $scope.permissionsAdded = values.permissions;
+ });
};
/**
- * Returns whether the current user can delete the user being edited from
- * the given data source.
- *
- * @param {String} [dataSource]
- * The identifier of the data source to check. If omitted, this will
- * default to the currently-selected data source.
+ * Loads skeleton user data, preparing the interface for creating a new
+ * user.
*
- * @returns {Boolean}
- * true if the current user can delete the user being edited, false
- * otherwise.
+ * @returns {Promise}
+ * A promise which is resolved when the interface has been prepared for
+ * creating a new user.
*/
- $scope.canDeleteUser = function canDeleteUser(dataSource) {
-
- // Do not check if permissions are not yet loaded
- if (!$scope.permissions)
- return false;
+ var loadSkeletonUser = function loadSkeletonUser() {
- // Use currently-selected data source if unspecified
- dataSource = dataSource || $scope.dataSource;
+ // No users exist regardless of data source if there is no username
+ $scope.users = {};
- // Can't delete what doesn't exist
- if (!$scope.userExists(dataSource))
- return false;
+ // Use skeleton user object with no associated permissions
+ $scope.user = new User();
+ $scope.permissionFlags = new PermissionFlagSet();
- // The administrator can always delete users
- if (PermissionSet.hasSystemPermission($scope.permissions[dataSource],
- PermissionSet.SystemPermissionType.ADMINISTER))
- return true;
+ // As no permissions are yet associated with the user, it is safe to
+ // use any non-empty username as a placeholder for self-referential
+ // permissions
+ $scope.selfUsername = 'SELF';
- // Otherwise, require explicit DELETE permission on the user
- return PermissionSet.hasUserPermission($scope.permissions[dataSource],
- PermissionSet.ObjectPermissionType.DELETE, username);
+ return $q.resolve();
};
/**
- * Returns whether the user being edited within the given data source is
- * read-only, and thus cannot be modified by the current user.
- *
- * @param {String} [dataSource]
- * The identifier of the data source to check. If omitted, this will
- * default to the currently-selected data source.
+ * Loads the data requred for performing the management task requested
+ * through the route parameters given at load time, automatically preparing
+ * the interface for editing an existing user, cloning an existing user, or
+ * creating an entirely new user.
*
- * @returns {Boolean}
- * true if the user being edited is actually read-only and cannot be
- * edited at all, false otherwise.
+ * @returns {Promise}
+ * A promise which is resolved when the interface has been prepared
+ * for performing the requested management task.
*/
- $scope.isReadOnly = function isReadOnly(dataSource) {
+ var loadRequestedUser = function loadRequestedUser() {
- // Use currently-selected data source if unspecified
- dataSource = dataSource || $scope.dataSource;
+ // Pull user data and permissions if we are editing an existing user
+ if (username)
+ return loadExistingUser($scope.dataSource, username);
+
+ // If we are cloning an existing user, pull his/her data instead
+ if (cloneSourceUsername)
+ return loadClonedUser($scope.dataSource, cloneSourceUsername);
- // User is read-only if they cannot be saved
- return !$scope.canSaveUser(dataSource);
+ return loadSkeletonUser();
};
- // Update visible account pages whenever available users/permissions changes
- $scope.$watchGroup(['users', 'permissions'], function updateAccountPages() {
+ // Populate interface with requested data
+ $q.all({
+ userData : loadRequestedUser(),
+ permissions : dataSourceService.apply(permissionService.getEffectivePermissions, dataSources, currentUsername),
+ attributes : schemaService.getUserAttributes($scope.dataSource)
+ })
+ .then(function dataReceived(values) {
+
+ var managementPermissions = {};
+
+ $scope.attributes = values.attributes;
// Generate pages for each applicable data source
$scope.accountPages = [];
angular.forEach(dataSources, function addAccountPage(dataSource) {
// Determine whether data source contains this user
- var linked = $scope.userExists(dataSource);
- var readOnly = $scope.isReadOnly(dataSource);
+ var exists = (dataSource in $scope.users);
+
+ // Calculate management actions available for this specific account
+ managementPermissions[dataSource] = ManagementPermissions.fromPermissionSet(
+ values.permissions[dataSource],
+ PermissionSet.SystemPermissionType.CREATE_USER,
+ PermissionSet.hasUserPermission,
+ exists ? username : null);
// Account is not relevant if it does not exist and cannot be
// created
- if (!linked && readOnly)
+ var readOnly = !managementPermissions[dataSource].canSaveObject;
+ if (!exists && readOnly)
return;
// Only the selected data source is relevant when cloning
@@ -457,7 +392,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
// Determine class name based on read-only / linked status
var className;
if (readOnly) className = 'read-only';
- else if (linked) className = 'linked';
+ else if (exists) className = 'linked';
else className = 'unlinked';
// Add page entry
@@ -469,121 +404,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
});
- });
+ $scope.managementPermissions = managementPermissions[$scope.dataSource];
- // Pull user attribute schema
- schemaService.getUserAttributes($scope.dataSource).then(function attributesReceived(attributes) {
- $scope.attributes = attributes;
}, requestService.WARN);
- // Pull user data and permissions if we are editing an existing user
- if (username) {
-
- // Pull user data
- dataSourceService.apply(userService.getUser, dataSources, username)
- .then(function usersReceived(users) {
-
- // Get user for currently-selected data source
- $scope.users = users;
- $scope.user = users[$scope.dataSource];
-
- // Create skeleton user if user does not exist
- if (!$scope.user)
- $scope.user = new User({
- 'username' : username
- });
-
- }, requestService.WARN);
-
- // The current user will be associated with username of the existing
- // user in the retrieved permission set
- $scope.selfUsername = username;
-
- // Pull user permissions
- permissionService.getPermissions($scope.dataSource, username).then(function gotPermissions(permissions) {
- $scope.permissionFlags = PermissionFlagSet.fromPermissionSet(permissions);
- })
-
- // If permissions cannot be retrieved, use empty permissions
- ['catch'](requestService.createErrorCallback(function permissionRetrievalFailed() {
- $scope.permissionFlags = new PermissionFlagSet();
- }));
- }
-
- // If we are cloning an existing user, pull his/her data instead
- else if (cloneSourceUsername) {
-
- dataSourceService.apply(userService.getUser, dataSources, cloneSourceUsername)
- .then(function usersReceived(users) {
-
- // Get user for currently-selected data source
- $scope.users = {};
- $scope.user = users[$scope.dataSource];
-
- }, requestService.WARN);
-
- // The current user will be associated with cloneSourceUsername in the
- // retrieved permission set
- $scope.selfUsername = cloneSourceUsername;
-
- // Pull user permissions
- permissionService.getPermissions($scope.dataSource, cloneSourceUsername)
- .then(function gotPermissions(permissions) {
- $scope.permissionFlags = PermissionFlagSet.fromPermissionSet(permissions);
- $scope.permissionsAdded = permissions;
- })
-
- // If permissions cannot be retrieved, use empty permissions
- ['catch'](requestService.createErrorCallback(function permissionRetrievalFailed() {
- $scope.permissionFlags = new PermissionFlagSet();
- }));
- }
-
- // Use skeleton data if we are creating a new user
- else {
-
- // No users exist regardless of data source if there is no username
- $scope.users = {};
-
- // Use skeleton user object with no associated permissions
- $scope.user = new User();
- $scope.permissionFlags = new PermissionFlagSet();
-
- // As no permissions are yet associated with the user, it is safe to
- // use any non-empty username as a placeholder for self-referential
- // permissions
- $scope.selfUsername = 'SELF';
-
- }
-
- // Query the user's permissions for the current user
- dataSourceService.apply(
- permissionService.getEffectivePermissions,
- dataSources,
- currentUsername
- )
- .then(function permissionsReceived(permissions) {
- $scope.permissions = permissions;
- }, requestService.WARN);
-
- /**
- * The set of permissions that will be added to the user when the user is
- * saved. Permissions will only be present in this set if they are
- * manually added, and not later manually removed before saving.
- *
- * @type PermissionSet
- */
- $scope.permissionsAdded = new PermissionSet();
-
- /**
- * The set of permissions that will be removed from the user when the user
- * is saved. Permissions will only be present in this set if they are
- * manually removed, and not later manually added before saving.
- *
- * @type PermissionSet
- */
- $scope.permissionsRemoved = new PermissionSet();
-
/**
* Cancels all pending edits, returning to the management page.
*/
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/4f43ddc4/guacamole/src/main/webapp/app/manage/templates/manageUser.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageUser.html b/guacamole/src/main/webapp/app/manage/templates/manageUser.html
index 5fed148..24db74e 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageUser.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageUser.html
@@ -11,12 +11,12 @@
</div>
<!-- Warn if user is read-only -->
- <div class="section" ng-show="isReadOnly()">
+ <div class="section" ng-hide="managementPermissions.canSaveObject">
<p class="notice read-only">{{'MANAGE_USER.INFO_READ_ONLY' | translate}}</p>
</div>
<!-- Sections applicable to non-read-only users -->
- <div ng-show="!isReadOnly()">
+ <div ng-show="managementPermissions.canSaveObject">
<!-- User password section -->
<div class="section">
@@ -40,13 +40,13 @@
</div>
<!-- User attributes section -->
- <div class="attributes" ng-show="canChangeAttributes()">
+ <div class="attributes" ng-show="managementPermissions.canChangeAttributes">
<guac-form namespace="'USER_ATTRIBUTES'" content="attributes"
- model="user.attributes" model-only="!canChangeAllAttributes()"></guac-form>
+ model="user.attributes" model-only="!managementPermissions.canChangeAllAttributes"></guac-form>
</div>
<!-- System permissions section -->
- <system-permission-editor ng-show="canChangePermissions()"
+ <system-permission-editor ng-show="managementPermissions.canChangePermissions"
username="selfUsername"
data-data-source="dataSource"
permission-flags="permissionFlags"
@@ -55,7 +55,7 @@
</system-permission-editor>
<!-- Connection permissions section -->
- <connection-permission-editor ng-show="canChangePermissions()"
+ <connection-permission-editor ng-show="managementPermissions.canChangePermissions"
data-data-source="dataSource"
permission-flags="permissionFlags"
permissions-added="permissionsAdded"
@@ -64,10 +64,10 @@
<!-- Form action buttons -->
<div class="action-buttons">
- <button ng-show="canSaveUser()" ng-click="saveUser()">{{'MANAGE_USER.ACTION_SAVE' | translate}}</button>
- <button ng-show="canCloneUser()" ng-click="cloneUser()">{{'MANAGE_USER.ACTION_CLONE' | translate}}</button>
+ <button ng-show="managementPermissions.canSaveObject" ng-click="saveUser()">{{'MANAGE_USER.ACTION_SAVE' | translate}}</button>
+ <button ng-show="managementPermissions.canCloneObject" ng-click="cloneUser()">{{'MANAGE_USER.ACTION_CLONE' | translate}}</button>
<button ng-click="cancel()">{{'MANAGE_USER.ACTION_CANCEL' | translate}}</button>
- <button ng-show="canDeleteUser()" ng-click="deleteUser()" class="danger">{{'MANAGE_USER.ACTION_DELETE' | translate}}</button>
+ <button ng-show="managementPermissions.canDeleteObject" ng-click="deleteUser()" class="danger">{{'MANAGE_USER.ACTION_DELETE' | translate}}</button>
</div>
</div>