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:27:03 UTC

[09/21] guacamole-client git commit: GUACAMOLE-220: Migrate connection group management screen to common buttons and permission logic. Add required clone option.

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


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/7e1dbf7d
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/7e1dbf7d
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/7e1dbf7d

Branch: refs/heads/master
Commit: 7e1dbf7d11f51f7acd8b3ad39e30695bbda15abd
Parents: 00fee4a
Author: Michael Jumper <mj...@apache.org>
Authored: Tue May 1 11:54:38 2018 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue May 1 20:58:28 2018 -0700

----------------------------------------------------------------------
 .../manageConnectionGroupController.js          | 321 ++++++++++---------
 .../manage/templates/manageConnectionGroup.html |  14 +-
 guacamole/src/main/webapp/translations/en.json  |   1 +
 3 files changed, 174 insertions(+), 162 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/7e1dbf7d/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
index de29aff..842c395 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
@@ -24,15 +24,16 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
         function manageConnectionGroupController($scope, $injector) {
             
     // Required types
-    var ConnectionGroup = $injector.get('ConnectionGroup');
-    var PermissionSet   = $injector.get('PermissionSet');
+    var ConnectionGroup       = $injector.get('ConnectionGroup');
+    var ManagementPermissions = $injector.get('ManagementPermissions');
+    var PermissionSet         = $injector.get('PermissionSet');
 
     // Required services
     var $location              = $injector.get('$location');
+    var $q                     = $injector.get('$q');
     var $routeParams           = $injector.get('$routeParams');
     var authenticationService  = $injector.get('authenticationService');
     var connectionGroupService = $injector.get('connectionGroupService');
-    var guacNotification       = $injector.get('guacNotification');
     var permissionService      = $injector.get('permissionService');
     var requestService         = $injector.get('requestService');
     var schemaService          = $injector.get('schemaService');
@@ -46,6 +47,15 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
     $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
      * group is being created, this will not be defined.
      *
@@ -54,6 +64,23 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
     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.
      *
      * @type ConnectionGroup
@@ -68,26 +95,13 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
     $scope.connectionGroup = null;
     
     /**
-     * Whether the user has UPDATE permission for the current connection group.
-     * 
-     * @type Boolean
-     */
-    $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.
+     * The managment-related actions that the current user may perform on the
+     * connection group currently being created/modified, or null if the current
+     * 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
@@ -109,177 +123,172 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
 
         return $scope.rootGroup                !== null
             && $scope.connectionGroup          !== null
-            && $scope.permissions              !== null
-            && $scope.attributes               !== null
-            && $scope.canSaveConnectionGroup   !== null
-            && $scope.canDeleteConnectionGroup !== null;
+            && $scope.managementPermissions    !== null
+            && $scope.attributes               !== 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())
-    .then(function permissionsReceived(permissions) {
-                
-        $scope.permissions = permissions;
-                        
-        // Check if the connection group is new or if the user has UPDATE permission
-        $scope.canSaveConnectionGroup =
-              !identifier
-           || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
-           || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE, identifier);
-
-        // Check if connection group is not new and the user has DELETE permission
-        $scope.canDeleteConnectionGroup =
-           !!identifier && (
-                  PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
-              ||  PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.DELETE, identifier)
-           );
-    
-    }, requestService.WARN);
-
-
-    // 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)
+    /**
+     * Loads the data associated with the connection group having the given
+     * identifier, preparing the interface for making modifications to that
+     * existing connection group.
+     *
+     * @param {String} dataSource
+     *     The unique identifier of the data source containing the connection
+     *     group to load.
+     *
+     * @param {String} identifier
+     *     The identifier of the connection group to load.
+     *
+     * @returns {Promise}
+     *     A promise which is resolved when the interface has been prepared for
+     *     editing the given connection group.
+     */
+    var loadExistingConnectionGroup = function loadExistingConnectionGroup(dataSource, identifier) {
+        return connectionGroupService.getConnectionGroup(
+            dataSource,
+            identifier
+        )
         .then(function connectionGroupReceived(connectionGroup) {
             $scope.connectionGroup = connectionGroup;
-        }, requestService.WARN);
-    }
-
-    // If we are creating a new connection group, populate skeleton connection group data
-    else
-        $scope.connectionGroup = new ConnectionGroup({
-            parentIdentifier : $location.search().parent
         });
+    };
 
     /**
-     * Available connection group types, as translation string / internal value
-     * pairs.
-     * 
-     * @type Object[]
+     * 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.
      */
-    $scope.types = [
-        {
-            label: "MANAGE_CONNECTION_GROUP.NAME_TYPE_ORGANIZATIONAL",
-            value: ConnectionGroup.Type.ORGANIZATIONAL
-        },
-        {
-            label: "MANAGE_CONNECTION_GROUP.NAME_TYPE_BALANCING",
-            value : ConnectionGroup.Type.BALANCING
-        }
-    ];
+    var loadClonedConnectionGroup = function loadClonedConnectionGroup(dataSource, identifier) {
+        return connectionGroupService.getConnectionGroup(
+            dataSource,
+            identifier
+        )
+        .then(function connectionGroupReceived(connectionGroup) {
+            $scope.connectionGroup = connectionGroup;
+            delete $scope.connectionGroup.identifier;
+        });
+    };
 
     /**
-     * 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.
+     * Loads skeleton connection group data, preparing the interface for
+     * creating a new 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.
+     * @returns {Promise}
+     *     A promise which is resolved when the interface has been prepared for
+     *     creating a new connection group.
      */
-    $scope.canChangeAllAttributes = function canChangeAllAttributes() {
+    var loadSkeletonConnectionGroup = function loadSkeletonConnectionGroup() {
 
-        // All attributes can be set if we are creating the connection group
-        return !identifier;
+        // Use skeleton connection group object with specified parent
+        $scope.connectionGroup = new ConnectionGroup({
+            parentIdentifier : $location.search().parent
+        });
 
-    };
+        return $q.resolve();
 
-    /**
-     * Cancels all pending edits, returning to the management page.
-     */
-    $scope.cancel = function cancel() {
-        $location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections');
     };
-   
+
     /**
-     * Saves the connection group, creating a new connection group or updating
-     * the existing connection group.
+     * 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.saveConnectionGroup = function saveConnectionGroup() {
+    var loadRequestedConnectionGroup = function loadRequestedConnectionGroup() {
+
+        // If we are editing an existing connection group, pull its data
+        if (identifier)
+            return loadExistingConnectionGroup($scope.selectedDataSource, identifier);
 
-        // Save the connection
-        connectionGroupService.saveConnectionGroup($scope.selectedDataSource, $scope.connectionGroup)
-        .then(function savedConnectionGroup() {
-            $location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections');
-        }, guacNotification.SHOW_REQUEST_ERROR);
+        // 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);
+
     /**
-     * An action to be provided along with the object sent to showStatus which
-     * immediately deletes the current connection group.
+     * Cancels all pending edits, returning to the main list of connections
+     * within the selected data source.
      */
-    var DELETE_ACTION = {
-        name        : "MANAGE_CONNECTION_GROUP.ACTION_DELETE",
-        className   : "danger",
-        // Handle action
-        callback    : function deleteCallback() {
-            deleteConnectionGroupImmediately();
-            guacNotification.showStatus(false);
-        }
+    $scope.returnToConnectionList = function returnToConnectionList() {
+        $location.path('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections');
     };
 
     /**
-     * An action to be provided along with the object sent to showStatus which
-     * closes the currently-shown status dialog.
+     * Cancels all pending edits, opening an edit page for a new connection
+     * group which is prepopulated with the data from the connection group
+     * currently being edited.
      */
-    var CANCEL_ACTION = {
-        name        : "MANAGE_CONNECTION_GROUP.ACTION_CANCEL",
-        // Handle action
-        callback    : function cancelCallback() {
-            guacNotification.showStatus(false);
-        }
+    $scope.cloneConnectionGroup = function cloneConnectionGRoup() {
+        $location.path('/manage/' + encodeURIComponent($scope.selectedDataSource) + '/connectionGroups').search('clone', identifier);
     };
 
     /**
-     * Immediately deletes the current connection group, without prompting the
-     * user for confirmation.
+     * 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.
      */
-    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);
-
+    $scope.saveConnectionGroup = function saveConnectionGroup() {
+        return connectionGroupService.saveConnectionGroup($scope.selectedDataSource, $scope.connectionGroup);
     };
-
+    
     /**
-     * Deletes the connection group, prompting the user first to confirm that
-     * deletion is desired.
+     * Deletes the current connection group, returning a promise which is
+     * resolved if the delete operation succeeds and rejected if the delete
+     * operation fails.
+     *
+     * @returns {Promise}
+     *     A promise which is resolved if the delete operation succeeds and is
+     *     rejected with an {@link Error} if the delete operation fails.
      */
     $scope.deleteConnectionGroup = function deleteConnectionGroup() {
-
-        // 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]
-        });
-
+        return connectionGroupService.deleteConnectionGroup($scope.selectedDataSource, $scope.connectionGroup);
     };
 
 }]);

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/7e1dbf7d/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
index d4c6613..926dc11 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
@@ -41,14 +41,16 @@
     <!-- Connection group attributes section -->
     <div class="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>
 
     <!-- Form action buttons -->
-    <div class="action-buttons">
-        <button ng-show="canSaveConnectionGroup" ng-click="saveConnectionGroup()">{{'MANAGE_CONNECTION_GROUP.ACTION_SAVE' | translate}}</button>
-        <button ng-click="cancel()">{{'MANAGE_CONNECTION_GROUP.ACTION_CANCEL' | translate}}</button>
-        <button ng-show="canDeleteConnectionGroup" ng-click="deleteConnectionGroup()" class="danger">{{'MANAGE_CONNECTION_GROUP.ACTION_DELETE' | translate}}</button>
-    </div>
+    <management-buttons namespace="'MANAGE_CONNECTION_GROUP'"
+          permissions="managementPermissions"
+          save="saveConnectionGroup()"
+          delete="deleteConnectionGroup()"
+          clone="cloneConnectionGroup()"
+          return="returnToConnectionList()">
+    </management-buttons>
 
 </div>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/7e1dbf7d/guacamole/src/main/webapp/translations/en.json
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/translations/en.json b/guacamole/src/main/webapp/translations/en.json
index a97406e..ca8acb8 100644
--- a/guacamole/src/main/webapp/translations/en.json
+++ b/guacamole/src/main/webapp/translations/en.json
@@ -234,6 +234,7 @@
 
         "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE",
         "ACTION_CANCEL"        : "@:APP.ACTION_CANCEL",
+        "ACTION_CLONE"         : "@:APP.ACTION_CLONE",
         "ACTION_DELETE"        : "@:APP.ACTION_DELETE",
         "ACTION_SAVE"          : "@:APP.ACTION_SAVE",