Repository: guacamole-client
Updated Branches:
  refs/heads/staging/1.0.0 d6ecfaa36 -> c36d33321


GUACAMOLE-220: Display only selected connection permissions by default.


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

Branch: refs/heads/staging/1.0.0
Commit: edcb2af21f4982f8054f0292fb4265854baaf77b
Parents: dd65bf6
Author: Michael Jumper <mjum...@apache.org>
Authored: Sat Jul 21 00:00:52 2018 -0700
Committer: Michael Jumper <mjum...@apache.org>
Committed: Sat Jul 21 14:22:50 2018 -0700

----------------------------------------------------------------------
 .../directives/connectionPermissionEditor.js    | 216 ++++++++++++++-----
 .../templates/connectionPermissionEditor.html   |   5 +-
 2 files changed, 171 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/edcb2af2/guacamole/src/main/webapp/app/manage/directives/connectionPermissionEditor.js
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/webapp/app/manage/directives/connectionPermissionEditor.js 
b/guacamole/src/main/webapp/app/manage/directives/connectionPermissionEditor.js
index 43e80c2..632de49 100644
--- 
a/guacamole/src/main/webapp/app/manage/directives/connectionPermissionEditor.js
+++ 
b/guacamole/src/main/webapp/app/manage/directives/connectionPermissionEditor.js
@@ -85,6 +85,38 @@ 
angular.module('manage').directive('connectionPermissionEditor', ['$injector',
     directive.controller = ['$scope', function 
connectionPermissionEditorController($scope) {
 
         /**
+         * A map of data source identifiers to all root connection groups
+         * within those data sources, regardless of the permissions granted for
+         * the items within those groups. As only one data source is applicable
+         * to any particular permission set being edited/created, this will 
only
+         * contain a single key. If the data necessary to produce this map has
+         * not yet been loaded, this will be null.
+         *
+         * @type Object.<String, GroupListItem>
+         */
+        var allRootGroups = null;
+
+        /**
+         * A map of data source identifiers to the root connection groups 
within
+         * those data sources, excluding all items which are not explicitly
+         * readable according to $scope.permissionFlags. As only one data
+         * source is applicable to any particular permission set being
+         * edited/created, this will only contain a single key. If the data
+         * necessary to produce this map has not yet been loaded, this will be
+         * null.
+         *
+         * @type Object.<String, GroupListItem>
+         */
+        var readableRootGroups = null;
+
+        /**
+         * Whether the items displayed within the connection permission editor
+         * should be limited to those which had explicit READ permission at the
+         * time the editor was loaded.
+         */
+        $scope.displayReadableOnly = false;
+
+        /**
          * Array of all connection properties that are filterable.
          *
          * @type String[]
@@ -104,31 +136,53 @@ 
angular.module('manage').directive('connectionPermissionEditor', ['$injector',
         ];
 
         /**
-         * A map of data source identifiers to the root connection groups 
within
-         * thost data sources. As only one data source is applicable to any
-         * particular permission set being edited/created, this will only
-         * contain a single key.
+         * Returns the root groups which should be displayed within the
+         * connection permission editor.
          *
-         * @type Object.<String, GroupListItem>
+         * @returns {Object.<String, GroupListItem>}
+         *     The root groups which should be displayed within the connection
+         *     permission editor as a map of data source identifiers to the
+         *     root connection groups within those data sources.
          */
-        $scope.rootGroups = null;
+        $scope.getRootGroups = function getRootGroups() {
+            return $scope.displayReadableOnly ? readableRootGroups : 
allRootGroups;
+        };
 
-        // Retrieve all connections for which we have ADMINISTER permission
-        dataSourceService.apply(
-            connectionGroupService.getConnectionGroupTree,
-            [$scope.dataSource],
-            ConnectionGroup.ROOT_IDENTIFIER,
-            [PermissionSet.ObjectPermissionType.ADMINISTER]
-        )
-        .then(function connectionGroupReceived(rootGroups) {
+        /**
+         * Returns whether the given PermissionFlagSet declares explicit READ
+         * permission for the connection, connection group, or sharing profile
+         * represented by the given GroupListItem.
+         *
+         * @param {GroupListItem} item
+         *     The GroupListItem which should be checked against the
+         *     PermissionFlagSet.
+         *
+         * @param {PemissionFlagSet} flags
+         *     The set of permissions which should be used to determine whether
+         *     explicit READ permission is granted for the given item.
+         *
+         * @returns {Boolean}
+         *     true if explicit READ permission is granted for the given item
+         *     according to the given permission set, false otherwise.
+         */
+        var isReadable = function isReadable(item, flags) {
 
-            // Convert all received ConnectionGroup objects into GroupListItems
-            $scope.rootGroups = {};
-            angular.forEach(rootGroups, function addGroupListItem(rootGroup, 
dataSource) {
-                $scope.rootGroups[dataSource] = 
GroupListItem.fromConnectionGroup(dataSource, rootGroup);
-            });
+            switch (item.type) {
 
-        }, requestService.WARN);
+                case GroupListItem.Type.CONNECTION:
+                    return flags.connectionPermissions.READ[item.identifier];
+
+                case GroupListItem.Type.CONNECTION_GROUP:
+                    return 
flags.connectionGroupPermissions.READ[item.identifier];
+
+                case GroupListItem.Type.SHARING_PROFILE:
+                    return 
flags.sharingProfilePermissions.READ[item.identifier];
+
+            }
+
+            return false;
+
+        };
 
         /**
          * Expands all items within the tree descending from the given
@@ -144,6 +198,9 @@ 
angular.module('manage').directive('connectionPermissionEditor', ['$injector',
          * @param {PemissionFlagSet} flags
          *     The set of permissions which should be used to determine whether
          *     the given item and its descendants are expanded.
+         *
+         * @returns {Boolean}
+         *     true if the given item has been expanded, false otherwise.
          */
         var expandReadable = function expandReadable(item, flags) {
 
@@ -152,53 +209,114 @@ 
angular.module('manage').directive('connectionPermissionEditor', ['$injector',
             if (item.expandable && item.children) {
                 angular.forEach(item.children, function 
expandReadableChild(child) {
 
-                    // Determine whether the permission set contains READ
-                    // permission for the current child object
-                    var readable = false;
-                    switch (child.type) {
+                    // The parent should be expanded by default if the child is
+                    // expanded by default OR the permission set contains READ
+                    // permission on the child
+                    item.expanded |= expandReadable(child, flags) || 
isReadable(child, flags);
 
-                        case GroupListItem.Type.CONNECTION:
-                            readable = 
flags.connectionPermissions.READ[child.identifier];
-                            break;
+                });
+            }
 
-                        case GroupListItem.Type.CONNECTION_GROUP:
-                            readable = 
flags.connectionGroupPermissions.READ[child.identifier];
-                            break;
+            return item.expanded;
+
+        };
+
+        /**
+         * Creates a deep copy of all items within the tree descending from the
+         * given GroupListItem which have at least one descendant for which
+         * explicit READ permission is granted. Items which lack explicit READ
+         * permission and which have no descendants having explicit READ
+         * permission are omitted from the copy.
+         *
+         * @param {GroupListItem} item
+         *     The GroupListItem which should be conditionally copied
+         *     depending on whether READ permission is granted for any of its
+         *     descendants.
+         *
+         * @param {PemissionFlagSet} flags
+         *     The set of permissions which should be used to determine whether
+         *     the given item or any of its descendants are copied.
+         *
+         * @returns {GroupListItem}
+         *     A new GroupListItem containing a deep copy of the given item,
+         *     omitting any items which lack explicit READ permission and whose
+         *     descendants also lack explicit READ permission, or null if even
+         *     the given item would not be copied.
+         */
+        var copyReadable = function copyReadable(item, flags) {
 
-                        case GroupListItem.Type.SHARING_PROFILE:
-                            readable = 
flags.sharingProfilePermissions.READ[child.identifier];
-                            break;
+            // Produce initial shallow copy of given item
+            item = new GroupListItem(item);
 
-                    }
+            // Replace children array with an array containing only readable
+            // children (or children with at least one readable descendant),
+            // flagging the current item for copying if any such children exist
+            if (item.children) {
 
-                    // The parent should be expanded by default if the child is
-                    // expanded by default OR the permission set contains READ
-                    // permission on the child
-                    item.expanded |= expandReadable(child, flags) || readable;
+                var children = [];
+                angular.forEach(item.children, function 
copyReadableChildren(child) {
+
+                    // Reduce child tree to only explicitly readable items and
+                    // their parents
+                    child = copyReadable(child, flags);
+
+                    // Include child only if they are explicitly readable or
+                    // they have explicitly readable descendants
+                    if ((child.children && child.children.length) || 
isReadable(child, flags))
+                        children.push(child);
 
                 });
+
+                item.children = children;
+
             }
 
-            return item.expanded;
+            return item;
 
         };
 
-        // Update default expanded state whenever connection groups and
-        // associated permissions change
-        $scope.$watchGroup(['rootGroups', 'permissionFlags'], function 
updateDefaultExpandedStates() {
+        // Retrieve all connections for which we have ADMINISTER permission
+        dataSourceService.apply(
+            connectionGroupService.getConnectionGroupTree,
+            [$scope.dataSource],
+            ConnectionGroup.ROOT_IDENTIFIER,
+            [PermissionSet.ObjectPermissionType.ADMINISTER]
+        )
+        .then(function connectionGroupReceived(rootGroups) {
+
+            // Update default expanded state and the all / readable-only views
+            // when associated permissions change
+            $scope.$watchGroup(['permissionFlags'], function 
updateDefaultExpandedStates() {
+
+                if (!$scope.permissionFlags)
+                    return;
+
+                allRootGroups = {};
+                readableRootGroups = {};
 
-            if (!$scope.rootGroups || !$scope.permissionFlags)
-                return;
+                angular.forEach(rootGroups, function 
addGroupListItem(rootGroup, dataSource) {
 
-            angular.forEach($scope.rootGroups, function 
updateExpandedStates(rootGroup) {
+                    // Convert all received ConnectionGroup objects into 
GroupListItems
+                    var item = GroupListItem.fromConnectionGroup(dataSource, 
rootGroup);
+                    allRootGroups[dataSource] = item;
 
-                // Automatically expand all objects with any descendants for
-                // which the permission set contains READ permission
-                expandReadable(rootGroup, $scope.permissionFlags);
+                    // Automatically expand all objects with any descendants 
for
+                    // which the permission set contains READ permission
+                    expandReadable(item, $scope.permissionFlags);
+
+                    // Create a duplicate view which contains only readable
+                    // items
+                    readableRootGroups[dataSource] = copyReadable(item, 
$scope.permissionFlags);
+
+                });
+
+                // Display only readable connections by default if at least one
+                // readable connection exists
+                $scope.displayReadableOnly = 
!!readableRootGroups[$scope.dataSource].children.length;
 
             });
 
-        });
+        }, requestService.WARN);
 
         /**
          * Updates the permissionsAdded and permissionsRemoved permission sets

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/edcb2af2/guacamole/src/main/webapp/app/manage/templates/connectionPermissionEditor.html
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/webapp/app/manage/templates/connectionPermissionEditor.html
 
b/guacamole/src/main/webapp/app/manage/templates/connectionPermissionEditor.html
index 61d3804..0e3a373 100644
--- 
a/guacamole/src/main/webapp/app/manage/templates/connectionPermissionEditor.html
+++ 
b/guacamole/src/main/webapp/app/manage/templates/connectionPermissionEditor.html
@@ -1,7 +1,10 @@
 <div class="connection-permissions">
     <div class="header">
         <h2>{{'MANAGE_USER.SECTION_HEADER_CONNECTIONS' | translate}}</h2>
-        <guac-group-list-filter connection-groups="rootGroups"
+        <div class="filter">
+            <label><input type="checkbox" ng-model="displayReadableOnly"> 
{{'MANAGE_USER.' | translate}}</label>
+        </div>
+        <guac-group-list-filter connection-groups="getRootGroups()"
             filtered-connection-groups="filteredRootGroups"
             placeholder="'MANAGE_USER.FIELD_PLACEHOLDER_FILTER' | translate"
             connection-properties="filteredConnectionProperties"

Reply via email to