GUACAMOLE-220: Migrate connection group management screen to common buttons and permission logic. Add required clone option.

This commit is contained in:
Michael Jumper
2018-05-01 11:54:38 -07:00
parent 00fee4ac3a
commit 7e1dbf7d11
3 changed files with 185 additions and 173 deletions

View File

@@ -24,15 +24,16 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
function manageConnectionGroupController($scope, $injector) { function manageConnectionGroupController($scope, $injector) {
// Required types // Required types
var ConnectionGroup = $injector.get('ConnectionGroup'); var ConnectionGroup = $injector.get('ConnectionGroup');
var PermissionSet = $injector.get('PermissionSet'); var ManagementPermissions = $injector.get('ManagementPermissions');
var PermissionSet = $injector.get('PermissionSet');
// Required services // Required services
var $location = $injector.get('$location'); var $location = $injector.get('$location');
var $q = $injector.get('$q');
var $routeParams = $injector.get('$routeParams'); var $routeParams = $injector.get('$routeParams');
var authenticationService = $injector.get('authenticationService'); var authenticationService = $injector.get('authenticationService');
var connectionGroupService = $injector.get('connectionGroupService'); var connectionGroupService = $injector.get('connectionGroupService');
var guacNotification = $injector.get('guacNotification');
var permissionService = $injector.get('permissionService'); var permissionService = $injector.get('permissionService');
var requestService = $injector.get('requestService'); var requestService = $injector.get('requestService');
var schemaService = $injector.get('schemaService'); var schemaService = $injector.get('schemaService');
@@ -45,6 +46,15 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
*/ */
$scope.selectedDataSource = $routeParams.dataSource; $scope.selectedDataSource = $routeParams.dataSource;
/**
* The identifier of the original connection group from which this
* connection group is being cloned. Only valid if this is a new
* connection group.
*
* @type String
*/
var cloneSourceIdentifier = $location.search().clone;
/** /**
* The identifier of the connection group being edited. If a new connection * The identifier of the connection group being edited. If a new connection
* group is being created, this will not be defined. * group is being created, this will not be defined.
@@ -53,6 +63,23 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
*/ */
var identifier = $routeParams.id; var identifier = $routeParams.id;
/**
* Available connection group types, as translation string / internal value
* pairs.
*
* @type Object[]
*/
$scope.types = [
{
label: "MANAGE_CONNECTION_GROUP.NAME_TYPE_ORGANIZATIONAL",
value: ConnectionGroup.Type.ORGANIZATIONAL
},
{
label: "MANAGE_CONNECTION_GROUP.NAME_TYPE_BALANCING",
value : ConnectionGroup.Type.BALANCING
}
];
/** /**
* The root connection group of the connection group hierarchy. * The root connection group of the connection group hierarchy.
* *
@@ -68,26 +95,13 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
$scope.connectionGroup = null; $scope.connectionGroup = null;
/** /**
* Whether the user has UPDATE permission for the current connection group. * The managment-related actions that the current user may perform on the
* * connection group currently being created/modified, or null if the current
* @type Boolean * user's permissions have not yet been loaded.
*/
$scope.hasUpdatePermission = null;
/**
* Whether the user has DELETE permission for the current connection group.
*
* @type Boolean
*/
$scope.hasDeletePermission = null;
/**
* All permissions associated with the current user, or null if the user's
* permissions have not yet been loaded.
* *
* @type PermissionSet * @type ManagementPermissions
*/ */
$scope.permissions = null; $scope.managementPermissions = null;
/** /**
* All available connection group attributes. This is only the set of * All available connection group attributes. This is only the set of
@@ -109,177 +123,172 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
return $scope.rootGroup !== null return $scope.rootGroup !== null
&& $scope.connectionGroup !== null && $scope.connectionGroup !== null
&& $scope.permissions !== null && $scope.managementPermissions !== null
&& $scope.attributes !== null && $scope.attributes !== null;
&& $scope.canSaveConnectionGroup !== null
&& $scope.canDeleteConnectionGroup !== null;
}; };
// Pull connection group attribute schema
schemaService.getConnectionGroupAttributes($scope.selectedDataSource)
.then(function attributesReceived(attributes) {
$scope.attributes = attributes;
}, requestService.WARN);
// Query the user's permissions for the current connection group /**
permissionService.getEffectivePermissions($scope.selectedDataSource, authenticationService.getCurrentUsername()) * Loads the data associated with the connection group having the given
.then(function permissionsReceived(permissions) { * identifier, preparing the interface for making modifications to that
* existing connection group.
$scope.permissions = permissions; *
* @param {String} dataSource
// Check if the connection group is new or if the user has UPDATE permission * The unique identifier of the data source containing the connection
$scope.canSaveConnectionGroup = * group to load.
!identifier *
|| PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) * @param {String} identifier
|| PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE, identifier); * The identifier of the connection group to load.
*
// Check if connection group is not new and the user has DELETE permission * @returns {Promise}
$scope.canDeleteConnectionGroup = * A promise which is resolved when the interface has been prepared for
!!identifier && ( * editing the given connection group.
PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) */
|| PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.DELETE, identifier) var loadExistingConnectionGroup = function loadExistingConnectionGroup(dataSource, identifier) {
); return connectionGroupService.getConnectionGroup(
dataSource,
}, requestService.WARN); identifier
)
// Pull connection group hierarchy
connectionGroupService.getConnectionGroupTree(
$scope.selectedDataSource,
ConnectionGroup.ROOT_IDENTIFIER,
[PermissionSet.ObjectPermissionType.ADMINISTER]
)
.then(function connectionGroupReceived(rootGroup) {
$scope.rootGroup = rootGroup;
}, requestService.WARN);
// If we are editing an existing connection group, pull its data
if (identifier) {
connectionGroupService.getConnectionGroup($scope.selectedDataSource, identifier)
.then(function connectionGroupReceived(connectionGroup) { .then(function connectionGroupReceived(connectionGroup) {
$scope.connectionGroup = connectionGroup; $scope.connectionGroup = connectionGroup;
}, requestService.WARN); });
} };
// If we are creating a new connection group, populate skeleton connection group data /**
else * Loads the data associated with the connection group having the given
* identifier, preparing the interface for cloning that existing
* connection group.
*
* @param {String} dataSource
* The unique identifier of the data source containing the connection
* group to be cloned.
*
* @param {String} identifier
* The identifier of the connection group being cloned.
*
* @returns {Promise}
* A promise which is resolved when the interface has been prepared for
* cloning the given connection group.
*/
var loadClonedConnectionGroup = function loadClonedConnectionGroup(dataSource, identifier) {
return connectionGroupService.getConnectionGroup(
dataSource,
identifier
)
.then(function connectionGroupReceived(connectionGroup) {
$scope.connectionGroup = connectionGroup;
delete $scope.connectionGroup.identifier;
});
};
/**
* Loads skeleton connection group data, preparing the interface for
* creating a new connection group.
*
* @returns {Promise}
* A promise which is resolved when the interface has been prepared for
* creating a new connection group.
*/
var loadSkeletonConnectionGroup = function loadSkeletonConnectionGroup() {
// Use skeleton connection group object with specified parent
$scope.connectionGroup = new ConnectionGroup({ $scope.connectionGroup = new ConnectionGroup({
parentIdentifier : $location.search().parent parentIdentifier : $location.search().parent
}); });
/** return $q.resolve();
* Available connection group types, as translation string / internal value
* pairs.
*
* @type Object[]
*/
$scope.types = [
{
label: "MANAGE_CONNECTION_GROUP.NAME_TYPE_ORGANIZATIONAL",
value: ConnectionGroup.Type.ORGANIZATIONAL
},
{
label: "MANAGE_CONNECTION_GROUP.NAME_TYPE_BALANCING",
value : ConnectionGroup.Type.BALANCING
}
];
/**
* Returns whether the current user can change/set all connection group
* attributes for the connection group being edited, regardless of whether
* those attributes are already explicitly associated with that connection
* group.
*
* @returns {Boolean}
* true if the current user can change all attributes for the
* connection group being edited, regardless of whether those
* attributes are already explicitly associated with that connection
* group, false otherwise.
*/
$scope.canChangeAllAttributes = function canChangeAllAttributes() {
// All attributes can be set if we are creating the connection group
return !identifier;
}; };
/** /**
* Cancels all pending edits, returning to the management page. * 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 connection group, cloning an
* existing connection group, or creating an entirely new connection group.
*
* @returns {Promise}
* A promise which is resolved when the interface has been prepared
* for performing the requested management task.
*/ */
$scope.cancel = function cancel() { var loadRequestedConnectionGroup = function loadRequestedConnectionGroup() {
// If we are editing an existing connection group, pull its data
if (identifier)
return loadExistingConnectionGroup($scope.selectedDataSource, identifier);
// If we are cloning an existing connection group, pull its data
// instead
if (cloneSourceIdentifier)
return loadClonedConnectionGroup($scope.selectedDataSource, cloneSourceIdentifier);
// If we are creating a new connection group, populate skeleton
// connection group data
return loadSkeletonConnectionGroup();
};
// Query the user's permissions for the current connection group
$q.all({
connectionGroupData : loadRequestedConnectionGroup(),
attributes : schemaService.getConnectionGroupAttributes($scope.selectedDataSource),
permissions : permissionService.getEffectivePermissions($scope.selectedDataSource, authenticationService.getCurrentUsername()),
rootGroup : connectionGroupService.getConnectionGroupTree($scope.selectedDataSource, ConnectionGroup.ROOT_IDENTIFIER, [PermissionSet.ObjectPermissionType.ADMINISTER])
})
.then(function connectionGroupDataRetrieved(values) {
$scope.attributes = values.attributes;
$scope.rootGroup = values.rootGroup;
$scope.managementPermissions = ManagementPermissions.fromPermissionSet(
values.permissions,
PermissionSet.SystemPermissionType.CREATE_CONNECTION,
PermissionSet.hasConnectionPermission,
identifier);
}, requestService.WARN);
/**
* Cancels all pending edits, returning to the main list of connections
* within the selected data source.
*/
$scope.returnToConnectionList = function returnToConnectionList() {
$location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections'); $location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections');
}; };
/** /**
* Saves the connection group, creating a new connection group or updating * Cancels all pending edits, opening an edit page for a new connection
* the existing connection group. * group which is prepopulated with the data from the connection group
* currently being edited.
*/
$scope.cloneConnectionGroup = function cloneConnectionGRoup() {
$location.path('/manage/' + encodeURIComponent($scope.selectedDataSource) + '/connectionGroups').search('clone', identifier);
};
/**
* Saves the current connection group, creating a new connection group or
* updating the existing connection group, returning a promise which is
* resolved if the save operation succeeds and rejected if the save
* operation fails.
*
* @returns {Promise}
* A promise which is resolved if the save operation succeeds and is
* rejected with an {@link Error} if the save operation fails.
*/ */
$scope.saveConnectionGroup = function saveConnectionGroup() { $scope.saveConnectionGroup = function saveConnectionGroup() {
return connectionGroupService.saveConnectionGroup($scope.selectedDataSource, $scope.connectionGroup);
// Save the connection
connectionGroupService.saveConnectionGroup($scope.selectedDataSource, $scope.connectionGroup)
.then(function savedConnectionGroup() {
$location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections');
}, guacNotification.SHOW_REQUEST_ERROR);
}; };
/** /**
* An action to be provided along with the object sent to showStatus which * Deletes the current connection group, returning a promise which is
* immediately deletes the current connection group. * resolved if the delete operation succeeds and rejected if the delete
*/ * operation fails.
var DELETE_ACTION = { *
name : "MANAGE_CONNECTION_GROUP.ACTION_DELETE", * @returns {Promise}
className : "danger", * A promise which is resolved if the delete operation succeeds and is
// Handle action * rejected with an {@link Error} if the delete operation fails.
callback : function deleteCallback() {
deleteConnectionGroupImmediately();
guacNotification.showStatus(false);
}
};
/**
* An action to be provided along with the object sent to showStatus which
* closes the currently-shown status dialog.
*/
var CANCEL_ACTION = {
name : "MANAGE_CONNECTION_GROUP.ACTION_CANCEL",
// Handle action
callback : function cancelCallback() {
guacNotification.showStatus(false);
}
};
/**
* Immediately deletes the current connection group, without prompting the
* user for confirmation.
*/
var deleteConnectionGroupImmediately = function deleteConnectionGroupImmediately() {
// Delete the connection group
connectionGroupService.deleteConnectionGroup($scope.selectedDataSource, $scope.connectionGroup)
.then(function deletedConnectionGroup() {
$location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections');
}, guacNotification.SHOW_REQUEST_ERROR);
};
/**
* Deletes the connection group, prompting the user first to confirm that
* deletion is desired.
*/ */
$scope.deleteConnectionGroup = function deleteConnectionGroup() { $scope.deleteConnectionGroup = function deleteConnectionGroup() {
return connectionGroupService.deleteConnectionGroup($scope.selectedDataSource, $scope.connectionGroup);
// Confirm deletion request
guacNotification.showStatus({
'title' : 'MANAGE_CONNECTION_GROUP.DIALOG_HEADER_CONFIRM_DELETE',
'text' : {
key : 'MANAGE_CONNECTION_GROUP.TEXT_CONFIRM_DELETE'
},
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
});
}; };
}]); }]);

View File

@@ -41,14 +41,16 @@
<!-- Connection group attributes section --> <!-- Connection group attributes section -->
<div class="attributes"> <div class="attributes">
<guac-form namespace="'CONNECTION_GROUP_ATTRIBUTES'" content="attributes" <guac-form namespace="'CONNECTION_GROUP_ATTRIBUTES'" content="attributes"
model="connectionGroup.attributes" model-only="!canChangeAllAttributes()"></guac-form> model="connectionGroup.attributes" model-only="!managementPermissions.canChangeAllAttributes"></guac-form>
</div> </div>
<!-- Form action buttons --> <!-- Form action buttons -->
<div class="action-buttons"> <management-buttons namespace="'MANAGE_CONNECTION_GROUP'"
<button ng-show="canSaveConnectionGroup" ng-click="saveConnectionGroup()">{{'MANAGE_CONNECTION_GROUP.ACTION_SAVE' | translate}}</button> permissions="managementPermissions"
<button ng-click="cancel()">{{'MANAGE_CONNECTION_GROUP.ACTION_CANCEL' | translate}}</button> save="saveConnectionGroup()"
<button ng-show="canDeleteConnectionGroup" ng-click="deleteConnectionGroup()" class="danger">{{'MANAGE_CONNECTION_GROUP.ACTION_DELETE' | translate}}</button> delete="deleteConnectionGroup()"
</div> clone="cloneConnectionGroup()"
return="returnToConnectionList()">
</management-buttons>
</div> </div>

View File

@@ -234,6 +234,7 @@
"ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE", "ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE",
"ACTION_CANCEL" : "@:APP.ACTION_CANCEL", "ACTION_CANCEL" : "@:APP.ACTION_CANCEL",
"ACTION_CLONE" : "@:APP.ACTION_CLONE",
"ACTION_DELETE" : "@:APP.ACTION_DELETE", "ACTION_DELETE" : "@:APP.ACTION_DELETE",
"ACTION_SAVE" : "@:APP.ACTION_SAVE", "ACTION_SAVE" : "@:APP.ACTION_SAVE",