You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by jm...@apache.org on 2016/08/05 04:01:31 UTC

[1/9] incubator-guacamole-client git commit: GUACAMOLE-5: Fix CSS selector match of open/closed groups.

Repository: incubator-guacamole-client
Updated Branches:
  refs/heads/master 841bc4761 -> 989ad3951


GUACAMOLE-5: Fix CSS selector match of open/closed groups.

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

Branch: refs/heads/master
Commit: 031763af05508c95556ae07b2d39b6b09fe247ab
Parents: f4ad97e
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 19:18:30 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 guacamole/src/main/webapp/app/index/styles/ui.css | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/031763af/guacamole/src/main/webapp/app/index/styles/ui.css
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/styles/ui.css b/guacamole/src/main/webapp/app/index/styles/ui.css
index d517445..62db41f 100644
--- a/guacamole/src/main/webapp/app/index/styles/ui.css
+++ b/guacamole/src/main/webapp/app/index/styles/ui.css
@@ -178,11 +178,11 @@ div.section {
     background-position: center center;
 }
 
-.group .icon {
+.group > .caption .icon {
     background-image: url('images/folder-closed.png');
 }
 
-.group.expanded .icon {
+.group.expanded > .caption .icon {
     background-image: url('images/folder-open.png');
 }
 
@@ -253,11 +253,11 @@ div.section {
     background-image: url('images/group-icons/guac-closed.png');
 }
 
-.expandable.expanded .icon.expand {
+.expandable.expanded > .caption .icon.expand {
     background-image: url('images/group-icons/guac-open.png');
 }
 
-.expandable.empty .icon.expand {
+.expandable.empty > .caption .icon.expand {
     opacity: 0.25;
     background-image: url('images/group-icons/guac-open.png');
 }


[8/9] incubator-guacamole-client git commit: GUACAMOLE-5: Rename permission granted/revoked flag sensibly.

Posted by jm...@apache.org.
GUACAMOLE-5: Rename permission granted/revoked flag sensibly.


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

Branch: refs/heads/master
Commit: f3a201a4152504388063387ac11d77dbf582eb51
Parents: 031763a
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 20:42:19 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 20:42:19 2016 -0700

----------------------------------------------------------------------
 .../manage/controllers/manageUserController.js  | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/f3a201a4/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 36d00c6..7a4db92 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
@@ -709,10 +709,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
     $scope.systemPermissionChanged = function systemPermissionChanged(type) {
 
         // Determine current permission setting
-        var value = $scope.permissionFlags.systemPermissions[type];
+        var granted = $scope.permissionFlags.systemPermissions[type];
 
         // Add/remove permission depending on flag state
-        if (value)
+        if (granted)
             addSystemPermission(type);
         else
             removeSystemPermission(type);
@@ -779,10 +779,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
     $scope.userPermissionChanged = function userPermissionChanged(type, identifier) {
 
         // Determine current permission setting
-        var value = $scope.permissionFlags.userPermissions[type][identifier];
+        var granted = $scope.permissionFlags.userPermissions[type][identifier];
 
         // Add/remove permission depending on flag state
-        if (value)
+        if (granted)
             addUserPermission(type, identifier);
         else
             removeUserPermission(type, identifier);
@@ -931,10 +931,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
         connectionPermissionChanged : function connectionPermissionChanged(identifier) {
 
             // Determine current permission setting
-            var value = $scope.permissionFlags.connectionPermissions.READ[identifier];
+            var granted = $scope.permissionFlags.connectionPermissions.READ[identifier];
 
             // Add/remove permission depending on flag state
-            if (value)
+            if (granted)
                 addConnectionPermission(identifier);
             else
                 removeConnectionPermission(identifier);
@@ -953,10 +953,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
         connectionGroupPermissionChanged : function connectionGroupPermissionChanged(identifier) {
 
             // Determine current permission setting
-            var value = $scope.permissionFlags.connectionGroupPermissions.READ[identifier];
+            var granted = $scope.permissionFlags.connectionGroupPermissions.READ[identifier];
 
             // Add/remove permission depending on flag state
-            if (value)
+            if (granted)
                 addConnectionGroupPermission(identifier);
             else
                 removeConnectionGroupPermission(identifier);
@@ -975,10 +975,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
         sharingProfilePermissionChanged : function sharingProfilePermissionChanged(identifier) {
 
             // Determine current permission setting
-            var value = $scope.permissionFlags.sharingProfilePermissions.READ[identifier];
+            var granted = $scope.permissionFlags.sharingProfilePermissions.READ[identifier];
 
             // Add/remove permission depending on flag state
-            if (value)
+            if (granted)
                 addSharingProfilePermission(identifier);
             else
                 removeSharingProfilePermission(identifier);


[5/9] incubator-guacamole-client git commit: GUACAMOLE-5: Switch to nice rendering of connection tree lines.

Posted by jm...@apache.org.
GUACAMOLE-5: Switch to nice rendering of connection tree lines.

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

Branch: refs/heads/master
Commit: f4ad97e73286b972ef33b9fa4f3a761daeb74061
Parents: e3db19d
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 18:54:17 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 .../src/main/webapp/app/index/styles/ui.css     | 33 +++++++++++++++++---
 1 file changed, 29 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/f4ad97e7/guacamole/src/main/webapp/app/index/styles/ui.css
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/styles/ui.css b/guacamole/src/main/webapp/app/index/styles/ui.css
index 67e34e4..d517445 100644
--- a/guacamole/src/main/webapp/app/index/styles/ui.css
+++ b/guacamole/src/main/webapp/app/index/styles/ui.css
@@ -214,17 +214,42 @@ div.section {
 }
  
 .group.empty.balancer .icon {
-    opacity: 1;
     background-image: url('images/protocol-icons/guac-monitor.png');
 }
 
-.expandable.expanded > .children {
+.expandable.expanded > .children > .list-item {
+    position: relative;
+}
+
+.expandable.expanded > .children > .list-item:before,
+.expandable.expanded > .children > .list-item:after {
+    display: block;
+    content: ' ';
+    position: absolute;
+    z-index: -1;
+}
+
+.expandable.expanded > .children > .list-item:before {
+    border-left: 1px solid #BBB;
+    left: -13px;
+    top: -0.75em;
+    bottom: 0;
+}
+
+.expandable.expanded > .children > .list-item:last-child:before {
+    height: 1.5em;
+}
+
+.expandable.expanded > .children > .list-item:after {
     display: block;
-    border-left: 1px dotted rgba(0, 0, 0, 0.25);
+    content: ' ';
+    border-bottom: 1px solid #BBB;
+    left: -13px;
+    width: 13px;
+    top: 0.75em;
 }
 
 .expandable > .caption .icon.expand {
-    opacity: 0.75;
     background-image: url('images/group-icons/guac-closed.png');
 }
 


[2/9] incubator-guacamole-client git commit: GUACAMOLE-5: Add support for sharing profile permissions to JavaScript implementations of REST API objects.

Posted by jm...@apache.org.
GUACAMOLE-5: Add support for sharing profile permissions to JavaScript implementations of REST API objects.

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

Branch: refs/heads/master
Commit: 8a8ae8496cee67f055266d63d64eae2c5d24f9e0
Parents: 85f15b7
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 18:15:28 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 .../app/rest/services/permissionService.js      |  4 +
 .../webapp/app/rest/types/PermissionFlagSet.js  | 22 +++++
 .../main/webapp/app/rest/types/PermissionSet.js | 88 +++++++++++++++++++-
 3 files changed, 113 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/8a8ae849/guacamole/src/main/webapp/app/rest/services/permissionService.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/rest/services/permissionService.js b/guacamole/src/main/webapp/app/rest/services/permissionService.js
index 8a41845..67fceba 100644
--- a/guacamole/src/main/webapp/app/rest/services/permissionService.js
+++ b/guacamole/src/main/webapp/app/rest/services/permissionService.js
@@ -175,6 +175,10 @@ angular.module('rest').factory('permissionService', ['$injector',
         addObjectPatchOperations(patch, operation, "/connectionGroupPermissions",
             permissions.connectionGroupPermissions);
 
+        // Add sharing profile permission operations to patch
+        addObjectPatchOperations(patch, operation, "/sharingProfilePermissions",
+            permissions.sharingProfilePermissions);
+
         // Add active connection permission operations to patch
         addObjectPatchOperations(patch, operation, "/activeConnectionPermissions",
             permissions.activeConnectionPermissions);

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/8a8ae849/guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js b/guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js
index be2771c..64b942b 100644
--- a/guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js
+++ b/guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js
@@ -88,6 +88,25 @@ angular.module('rest').factory('PermissionFlagSet', ['PermissionSet',
         };
 
         /**
+         * The granted state of each permission for each sharing profile, as a
+         * map of object permission type string to permission map. The
+         * permission map is, in turn, a map of sharing profile identifier to
+         * boolean value. A particular permission is granted if its
+         * corresponding boolean value is set to true. Valid permission type
+         * strings are defined within PermissionSet.ObjectPermissionType.
+         * Permissions which are not granted may be set to false, but this is
+         * not required.
+         *
+         * @type Object.<String, Object.<String, Boolean>>
+         */
+        this.sharingProfilePermissions = template.sharingProfilePermissions || {
+            'READ'       : {},
+            'UPDATE'     : {},
+            'DELETE'     : {},
+            'ADMINISTER' : {}
+        };
+
+        /**
          * The granted state of each permission for each active connection, as
          * a map of object permission type string to permission map. The
          * permission map is, in turn, a map of active connection identifier to
@@ -188,6 +207,9 @@ angular.module('rest').factory('PermissionFlagSet', ['PermissionSet',
         // Add all granted connection group permissions
         addObjectPermissions(permissionSet.connectionGroupPermissions, permissionFlagSet.connectionGroupPermissions);
 
+        // Add all granted sharing profile permissions
+        addObjectPermissions(permissionSet.sharingProfilePermissions, permissionFlagSet.sharingProfilePermissions);
+
         // Add all granted active connection permissions
         addObjectPermissions(permissionSet.activeConnectionPermissions, permissionFlagSet.activeConnectionPermissions);
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/8a8ae849/guacamole/src/main/webapp/app/rest/types/PermissionSet.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/rest/types/PermissionSet.js b/guacamole/src/main/webapp/app/rest/types/PermissionSet.js
index 2ac418e..8fd1ef6 100644
--- a/guacamole/src/main/webapp/app/rest/types/PermissionSet.js
+++ b/guacamole/src/main/webapp/app/rest/types/PermissionSet.js
@@ -53,6 +53,15 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
          * @type Object.<String, String[]>
          */
         this.connectionGroupPermissions = template.connectionGroupPermissions || {};
+
+        /**
+         * Map of sharing profile identifiers to the corresponding array of
+         * granted permissions. Each permission is represented by a string
+         * listed within PermissionSet.ObjectPermissionType.
+         *
+         * @type Object.<String, String[]>
+         */
+        this.sharingProfilePermissions = template.sharingProfilePermissions || {};
         
         /**
          * Map of active connection identifiers to the corresponding array of
@@ -132,7 +141,12 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
         /**
          * Permission to create new connection groups.
          */
-        CREATE_CONNECTION_GROUP : "CREATE_CONNECTION_GROUP"
+        CREATE_CONNECTION_GROUP : "CREATE_CONNECTION_GROUP",
+
+        /**
+         * Permission to create new sharing profiles.
+         */
+        CREATE_SHARING_PROFILE : "CREATE_SHARING_PROFILE"
 
     };
 
@@ -248,6 +262,28 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
     };
 
     /**
+     * Returns whether the given permission is granted for the sharing profile
+     * having the given ID.
+     *
+     * @param {PermissionSet|Object} permSet
+     *     The permission set to check.
+     *
+     * @param {String} type
+     *     The permission to search for, as defined by
+     *     PermissionSet.ObjectPermissionType.
+     *
+     * @param {String} identifier
+     *     The identifier of the sharing profile to which the permission
+     *     applies.
+     *
+     * @returns {Boolean}
+     *     true if the permission is present (granted), false otherwise.
+     */
+    PermissionSet.hasSharingProfilePermission = function hasSharingProfilePermission(permSet, type, identifier) {
+        return hasPermission(permSet.sharingProfilePermissions, type, identifier);
+    };
+
+    /**
      * Returns whether the given permission is granted for the active
      * connection having the given ID.
      *
@@ -549,6 +585,56 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
     };
 
     /**
+     * Adds the given sharing profile permission applying to the sharing profile
+     * with the given ID to the given permission set, if not already present. If
+     * the permission is already present, this function has no effect.
+     *
+     * @param {PermissionSet} permSet
+     *     The permission set to modify.
+     *
+     * @param {String} type
+     *     The permission to add, as defined by
+     *     PermissionSet.ObjectPermissionType.
+     *
+     * @param {String} identifier
+     *     The identifier of the sharing profile to which the permission
+     *     applies.
+     *
+     * @returns {Boolean}
+     *     true if the permission was added, false if the permission was
+     *     already present in the given permission set.
+     */
+    PermissionSet.addSharingProfilePermission = function addSharingProfilePermission(permSet, type, identifier) {
+        permSet.sharingProfilePermissions = permSet.sharingProfilePermissions || {};
+        return addObjectPermission(permSet.sharingProfilePermissions, type, identifier);
+    };
+
+    /**
+     * Removes the given sharing profile permission applying to the sharing
+     * profile with the given ID from the given permission set, if present. If
+     * the permission is not present, this function has no effect.
+     *
+     * @param {PermissionSet} permSet
+     *     The permission set to modify.
+     *
+     * @param {String} type
+     *     The permission to remove, as defined by
+     *     PermissionSet.ObjectPermissionType.
+     *
+     * @param {String} identifier
+     *     The identifier of the sharing profile to which the permission
+     *     applies.
+     *
+     * @returns {Boolean}
+     *     true if the permission was removed, false if the permission was not
+     *     present in the given permission set.
+     */
+    PermissionSet.removeSharingProfilePermission = function removeSharingProfilePermission(permSet, type, identifier) {
+        permSet.sharingProfilePermissions = permSet.sharingProfilePermissions || {};
+        return removeObjectPermission(permSet.sharingProfilePermissions, type, identifier);
+    };
+
+    /**
      * Adds the given active connection permission applying to the connection
      * group with the given ID to the given permission set, if not already
      * present. If the permission is already present, this function has no


[4/9] incubator-guacamole-client git commit: GUACAMOLE-5: Include sharing profiles within connection tree.

Posted by jm...@apache.org.
GUACAMOLE-5: Include sharing profiles within connection tree.


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

Branch: refs/heads/master
Commit: 60152e38411e40fc9d059dda9bf9f8c33eb91773
Parents: 841bc47
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 14:05:32 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 .../rest/connection/APIConnection.java          |  32 ++++
 .../connectiongroup/ConnectionGroupTree.java    | 172 ++++++++++++++++---
 .../main/webapp/app/rest/types/Connection.js    |   9 +
 3 files changed, 193 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/60152e38/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnection.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnection.java b/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnection.java
index 639318f..cd04413 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnection.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnection.java
@@ -19,12 +19,14 @@
 
 package org.apache.guacamole.rest.connection;
 
+import java.util.Collection;
 import java.util.Map;
 import org.codehaus.jackson.annotate.JsonIgnoreProperties;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.Connection;
 import org.apache.guacamole.protocol.GuacamoleConfiguration;
+import org.apache.guacamole.rest.sharingprofile.APISharingProfile;
 
 /**
  * A simple connection to expose through the REST endpoints.
@@ -66,6 +68,12 @@ public class APIConnection {
     private Map<String, String> attributes;
 
     /**
+     * All associated sharing profiles. If sharing profiles are not being
+     * queried, this may be omitted.
+     */
+    private Collection<APISharingProfile> sharingProfiles;
+
+    /**
      * The count of currently active connections using this connection.
      */
     private int activeConnections;
@@ -227,4 +235,28 @@ public class APIConnection {
         this.attributes = attributes;
     }
 
+    /**
+     * Returns a collection of all associated sharing profiles, or null if
+     * sharing profiles have not been queried.
+     *
+     * @return
+     *     A collection of all associated sharing profiles, or null if sharing
+     *     profiles have not been queried.
+     */
+    public Collection<APISharingProfile> getSharingProfiles() {
+        return sharingProfiles;
+    }
+
+    /**
+     * Sets the collection of all associated sharing profiles to the given
+     * collection, which may be null if sharing profiles have not been queried.
+     *
+     * @param sharingProfiles
+     *     The collection containing all sharing profiles associated with this
+     *     connection, or null if sharing profiles have not been queried.
+     */
+    public void setSharingProfiles(Collection<APISharingProfile> sharingProfiles) {
+        this.sharingProfiles = sharingProfiles;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/60152e38/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupTree.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupTree.java b/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupTree.java
index d2f6f6f..2541fa2 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupTree.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupTree.java
@@ -28,16 +28,20 @@ import java.util.Map;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.Connection;
 import org.apache.guacamole.net.auth.ConnectionGroup;
+import org.apache.guacamole.net.auth.Directory;
+import org.apache.guacamole.net.auth.SharingProfile;
+import org.apache.guacamole.net.auth.User;
 import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.net.auth.permission.ObjectPermission;
 import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
 import org.apache.guacamole.rest.connection.APIConnection;
+import org.apache.guacamole.rest.sharingprofile.APISharingProfile;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Provides access to the entire tree of connection groups and their
- * connections.
+ * Provides access to the entire tree of connection groups, their
+ * connections, and any associated sharing profiles.
  *
  * @author Michael Jumper
  */
@@ -49,16 +53,38 @@ public class ConnectionGroupTree {
     private static final Logger logger = LoggerFactory.getLogger(ConnectionGroupTree.class);
 
     /**
-     * The context of the user obtaining this tree.
-     */
-    private final UserContext userContext;
-    
-    /**
      * The root connection group as an APIConnectionGroup.
      */
     private final APIConnectionGroup rootAPIGroup;
 
     /**
+     * All connection permissions granted to the user obtaining this tree.
+     */
+    private final ObjectPermissionSet connectionPermissions;
+
+    /**
+     * All sharing profile permissions granted to the user obtaining this tree.
+     */
+    private final ObjectPermissionSet sharingProfilePermissions;
+
+    /**
+     * The directory of all connections visible to the user obtaining this tree.
+     */
+    private final Directory<Connection> connectionDirectory;
+
+    /**
+     * The directory of all connection groups visible to the user obtaining this
+     * tree.
+     */
+    private final Directory<ConnectionGroup> connectionGroupDirectory;
+
+    /**
+     * The directory of all sharing profiles visible to the user obtaining this
+     * tree.
+     */
+    private final Directory<SharingProfile> sharingProfileDirectory;
+
+    /**
      * All connection groups that have been retrieved, stored by their
      * identifiers.
      */
@@ -66,6 +92,12 @@ public class ConnectionGroupTree {
             new HashMap<String, APIConnectionGroup>();
 
     /**
+     * All connections that have been retrieved, stored by their identifiers.
+     */
+    private final Map<String, APIConnection> retrievedConnections =
+            new HashMap<String, APIConnection>();
+
+    /**
      * Adds each of the provided connections to the current tree as children
      * of their respective parents. The parent connection groups must already
      * be added.
@@ -95,7 +127,9 @@ public class ConnectionGroupTree {
                 }
 
                 // Add child
-                children.add(new APIConnection(connection));
+                APIConnection apiConnection = new APIConnection(connection);
+                retrievedConnections.put(connection.getIdentifier(), apiConnection);
+                children.add(apiConnection);
                 
             }
 
@@ -150,7 +184,55 @@ public class ConnectionGroupTree {
         } // end for each connection group
         
     }
-    
+
+    /**
+     * Adds each of the provided sharing profiles to the current tree as
+     * children of their respective primary connections. The primary connections
+     * must already be added.
+     *
+     * @param sharingProfiles
+     *     The sharing profiles to add to the tree.
+     *
+     * @throws GuacamoleException
+     *     If an error occurs while adding the sharing profiles to the tree.
+     */
+    private void addSharingProfiles(Collection<SharingProfile> sharingProfiles)
+        throws GuacamoleException {
+
+        // Add each sharing profile to the tree
+        for (SharingProfile sharingProfile : sharingProfiles) {
+
+            // Retrieve the sharing profile's associated connection
+            String primaryConnectionIdentifier = sharingProfile.getPrimaryConnectionIdentifier();
+            APIConnection primaryConnection = retrievedConnections.get(primaryConnectionIdentifier);
+
+            // Add the sharing profile as a child of the primary connection
+            if (primaryConnection != null) {
+
+                Collection<APISharingProfile> children = primaryConnection.getSharingProfiles();
+
+                // Create child collection if it does not yet exist
+                if (children == null) {
+                    children = new ArrayList<APISharingProfile>();
+                    primaryConnection.setSharingProfiles(children);
+                }
+
+                // Add child
+                children.add(new APISharingProfile(sharingProfile));
+
+            }
+
+            // Warn of internal consistency issues
+            else
+                logger.debug("Sharing profile \"{}\" cannot be added to the "
+                        + "tree: primary connection \"{}\" does not actually "
+                        + "exist.", sharingProfile.getIdentifier(),
+                        primaryConnectionIdentifier);
+
+        } // end for each sharing profile
+
+    }
+
     /**
      * Adds all descendants of the given parent groups to their corresponding
      * parents already stored under root.
@@ -167,7 +249,7 @@ public class ConnectionGroupTree {
      * @throws GuacamoleException
      *     If an error occurs while retrieving the descendants.
      */
-    private void addDescendants(Collection<ConnectionGroup> parents,
+    private void addConnectionGroupDescendants(Collection<ConnectionGroup> parents,
             List<ObjectPermission.Type> permissions)
         throws GuacamoleException {
 
@@ -185,22 +267,64 @@ public class ConnectionGroupTree {
         }
 
         // Filter identifiers based on permissions, if requested
-        if (permissions != null && !permissions.isEmpty()) {
-            ObjectPermissionSet permissionSet = userContext.self().getConnectionPermissions();
-            childConnectionIdentifiers = permissionSet.getAccessibleObjects(permissions, childConnectionIdentifiers);
-        }
+        if (permissions != null && !permissions.isEmpty())
+            childConnectionIdentifiers = connectionPermissions.getAccessibleObjects(
+                    permissions, childConnectionIdentifiers);
         
         // Retrieve child connections
         if (!childConnectionIdentifiers.isEmpty()) {
-            Collection<Connection> childConnections = userContext.getConnectionDirectory().getAll(childConnectionIdentifiers);
+            Collection<Connection> childConnections = connectionDirectory.getAll(childConnectionIdentifiers);
             addConnections(childConnections);
+            addConnectionDescendants(childConnections, permissions);
         }
 
         // Retrieve child connection groups
         if (!childConnectionGroupIdentifiers.isEmpty()) {
-            Collection<ConnectionGroup> childConnectionGroups = userContext.getConnectionGroupDirectory().getAll(childConnectionGroupIdentifiers);
+            Collection<ConnectionGroup> childConnectionGroups = connectionGroupDirectory.getAll(childConnectionGroupIdentifiers);
             addConnectionGroups(childConnectionGroups);
-            addDescendants(childConnectionGroups, permissions);
+            addConnectionGroupDescendants(childConnectionGroups, permissions);
+        }
+
+    }
+
+    /**
+     * Adds all descendant sharing profiles of the given connections to their
+     * corresponding primary connections already stored under root.
+     *
+     * @param connections
+     *     The connections whose descendant sharing profiles should be added to
+     *     the tree.
+     *
+     * @param permissions
+     *     If specified and non-empty, limit added sharing profiles to only
+     *     those for which the current user has any of the given
+     *     permissions. Otherwise, all visible sharing profiles are added.
+     *
+     * @throws GuacamoleException
+     *     If an error occurs while retrieving the descendants.
+     */
+    private void addConnectionDescendants(Collection<Connection> connections,
+            List<ObjectPermission.Type> permissions)
+        throws GuacamoleException {
+
+        // If no connections, nothing to do
+        if (connections.isEmpty())
+            return;
+
+        // Build lists of sharing profile identifiers for retrieval
+        Collection<String> identifiers = new ArrayList<String>();
+        for (Connection connection : connections)
+            identifiers.addAll(connection.getSharingProfileIdentifiers());
+
+        // Filter identifiers based on permissions, if requested
+        if (permissions != null && !permissions.isEmpty())
+            identifiers = sharingProfilePermissions.getAccessibleObjects(
+                    permissions, identifiers);
+
+        // Retrieve and add all associated sharing profiles
+        if (!identifiers.isEmpty()) {
+            Collection<SharingProfile> sharingProfiles = sharingProfileDirectory.getAll(identifiers);
+            addSharingProfiles(sharingProfiles);
         }
 
     }
@@ -229,14 +353,22 @@ public class ConnectionGroupTree {
     public ConnectionGroupTree(UserContext userContext, ConnectionGroup root,
             List<ObjectPermission.Type> permissions) throws GuacamoleException {
 
-        this.userContext = userContext;
-        
         // Store root of tree
         this.rootAPIGroup = new APIConnectionGroup(root);
         retrievedGroups.put(root.getIdentifier(), this.rootAPIGroup);
 
+        // Store user's current permissions
+        User self = userContext.self();
+        this.connectionPermissions = self.getConnectionPermissions();
+        this.sharingProfilePermissions = self.getSharingProfilePermissions();
+
+        // Store required directories
+        this.connectionDirectory = userContext.getConnectionDirectory();
+        this.connectionGroupDirectory = userContext.getConnectionGroupDirectory();
+        this.sharingProfileDirectory = userContext.getSharingProfileDirectory();
+
         // Add all descendants
-        addDescendants(Collections.singleton(root), permissions);
+        addConnectionGroupDescendants(Collections.singleton(root), permissions);
         
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/60152e38/guacamole/src/main/webapp/app/rest/types/Connection.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/rest/types/Connection.js b/guacamole/src/main/webapp/app/rest/types/Connection.js
index e000761..b4639b2 100644
--- a/guacamole/src/main/webapp/app/rest/types/Connection.js
+++ b/guacamole/src/main/webapp/app/rest/types/Connection.js
@@ -95,6 +95,15 @@ angular.module('rest').factory('Connection', [function defineConnection() {
          */
         this.activeConnections = template.activeConnections;
 
+        /**
+         * An array of all associated sharing profiles, if known. This property
+         * may be null or undefined if sharing profiles have not been queried,
+         * and thus the sharing profiles are unknown.
+         *
+         * @type SharingProfile[]
+         */
+        this.sharingProfiles = template.sharingProfiles;
+
     };
 
     return Connection;


[6/9] incubator-guacamole-client git commit: GUACAMOLE-5: Implement management interface for sharing profile permissions.

Posted by jm...@apache.org.
GUACAMOLE-5: Implement management interface for sharing profile permissions.

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

Branch: refs/heads/master
Commit: e3db19d633c1123ec0e071c8a998a7dca6ad54d3
Parents: 8a8ae84
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 18:21:32 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 .../src/main/webapp/app/index/styles/ui.css     |  7 ++-
 .../manage/controllers/manageUserController.js  | 65 ++++++++++++++++++++
 .../webapp/app/manage/templates/manageUser.html |  1 +
 .../templates/sharingProfilePermission.html     | 13 ++++
 guacamole/src/main/webapp/translations/en.json  |  1 +
 5 files changed, 86 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/e3db19d6/guacamole/src/main/webapp/app/index/styles/ui.css
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/styles/ui.css b/guacamole/src/main/webapp/app/index/styles/ui.css
index f324e3d..67e34e4 100644
--- a/guacamole/src/main/webapp/app/index/styles/ui.css
+++ b/guacamole/src/main/webapp/app/index/styles/ui.css
@@ -165,7 +165,8 @@ div.section {
 }
 
 .connection .icon,
-.connection-group .icon {
+.connection-group .icon,
+.sharing-profile .icon {
     display: inline-block;
     width: 24px;
     height: 24px;
@@ -199,6 +200,10 @@ div.section {
     background-image: url('images/protocol-icons/guac-monitor.png');
 }
 
+.sharing-profile .icon {
+    background-image: url('images/share.png');
+}
+
 /*
  * Groups
  */

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/e3db19d6/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 2a308f1..36d00c6 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
@@ -633,6 +633,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
         {
             label: "MANAGE_USER.FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS",
             value: PermissionSet.SystemPermissionType.CREATE_CONNECTION_GROUP
+        },
+        {
+            label: "MANAGE_USER.FIELD_HEADER_CREATE_NEW_SHARING_PROFILES",
+            value: PermissionSet.SystemPermissionType.CREATE_SHARING_PROFILE
         }
     ];
 
@@ -861,6 +865,45 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
 
     };
 
+    /**
+     * Updates the permissionsAdded and permissionsRemoved permission sets to
+     * reflect the addition of the given sharing profile permission.
+     *
+     * @param {String} identifier
+     *     The identifier of the sharing profile to add READ permission for.
+     */
+    var addSharingProfilePermission = function addSharingProfilePermission(identifier) {
+
+        // If permission was previously removed, simply un-remove it
+        if (PermissionSet.hasSharingProfilePermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier))
+            PermissionSet.removeSharingProfilePermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
+
+        // Otherwise, explicitly add the permission
+        else
+            PermissionSet.addSharingProfilePermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
+
+    };
+
+    /**
+     * Updates the permissionsAdded and permissionsRemoved permission sets to
+     * reflect the removal of the given sharing profile permission.
+     *
+     * @param {String} identifier
+     *     The identifier of the sharing profile to remove READ permission for.
+     */
+    var removeSharingProfilePermission = function removeSharingProfilePermission(identifier) {
+
+        // If permission was previously added, simply un-add it
+        if (PermissionSet.hasSharingProfilePermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier))
+            PermissionSet.removeSharingProfilePermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
+
+        // Otherwise, explicitly remove the permission
+        else
+            PermissionSet.addSharingProfilePermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
+
+    };
+
+
     // Expose permission query and modification functions to group list template
     $scope.groupListContext = {
 
@@ -918,6 +961,28 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
             else
                 removeConnectionGroupPermission(identifier);
 
+        },
+
+        /**
+         * Notifies the controller that a change has been made to the given
+         * sharing profile permission for the user being edited. This only
+         * applies to READ permissions.
+         *
+         * @param {String} identifier
+         *     The identifier of the sharing profile affected by the changed
+         *     permission.
+         */
+        sharingProfilePermissionChanged : function sharingProfilePermissionChanged(identifier) {
+
+            // Determine current permission setting
+            var value = $scope.permissionFlags.sharingProfilePermissions.READ[identifier];
+
+            // Add/remove permission depending on flag state
+            if (value)
+                addSharingProfilePermission(identifier);
+            else
+                removeSharingProfilePermission(identifier);
+
         }
 
     };

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/e3db19d6/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 14edccd..82bc1e9 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageUser.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageUser.html
@@ -79,6 +79,7 @@
                     context="groupListContext"
                     connection-groups="filteredRootGroups"
                     connection-template="'app/manage/templates/connectionPermission.html'"
+                    sharing-profile-template="'app/manage/templates/sharingProfilePermission.html'"
                     connection-group-template="'app/manage/templates/connectionGroupPermission.html'"
                     page-size="20"/>
             </div>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/e3db19d6/guacamole/src/main/webapp/app/manage/templates/sharingProfilePermission.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/templates/sharingProfilePermission.html b/guacamole/src/main/webapp/app/manage/templates/sharingProfilePermission.html
new file mode 100644
index 0000000..bc2b130
--- /dev/null
+++ b/guacamole/src/main/webapp/app/manage/templates/sharingProfilePermission.html
@@ -0,0 +1,13 @@
+<div class="choice">
+
+    <!-- Sharing profile icon -->
+    <div class="icon type"></div>
+
+    <!-- Permission checkbox -->
+    <input type="checkbox" ng-model="context.getPermissionFlags().sharingProfilePermissions.READ[item.identifier]"
+                           ng-change="context.sharingProfilePermissionChanged(item.identifier)"/>
+
+    <!-- Sharing profile name -->
+    <span class="name">{{item.name}}</span>
+
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/e3db19d6/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 3c9ce9c..e991436 100644
--- a/guacamole/src/main/webapp/translations/en.json
+++ b/guacamole/src/main/webapp/translations/en.json
@@ -256,6 +256,7 @@
         "FIELD_HEADER_CREATE_NEW_USERS"              : "Create new users:",
         "FIELD_HEADER_CREATE_NEW_CONNECTIONS"        : "Create new connections:",
         "FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS"  : "Create new connection groups:",
+        "FIELD_HEADER_CREATE_NEW_SHARING_PROFILES"   : "Create new sharing profiles:",
         "FIELD_HEADER_PASSWORD"                      : "@:APP.FIELD_HEADER_PASSWORD",
         "FIELD_HEADER_PASSWORD_AGAIN"                : "@:APP.FIELD_HEADER_PASSWORD_AGAIN",
         "FIELD_HEADER_USERNAME"                      : "Username:",


[7/9] incubator-guacamole-client git commit: GUACAMOLE-5: Add support for sharing profiles to the guacGroupList directive.

Posted by jm...@apache.org.
GUACAMOLE-5: Add support for sharing profiles to the guacGroupList directive.

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

Branch: refs/heads/master
Commit: da9ddf7683d3cbeb24fae5bdeb87258298467764
Parents: 60152e3
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 17:28:26 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 .../app/groupList/directives/guacGroupList.js   |  30 +++++-
 .../app/groupList/templates/guacGroupList.html  |  40 +++++--
 .../webapp/app/groupList/types/GroupListItem.js | 105 +++++++++++++++----
 3 files changed, 147 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/da9ddf76/guacamole/src/main/webapp/app/groupList/directives/guacGroupList.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/groupList/directives/guacGroupList.js b/guacamole/src/main/webapp/app/groupList/directives/guacGroupList.js
index 0b5ed6f..d5404c7 100644
--- a/guacamole/src/main/webapp/app/groupList/directives/guacGroupList.js
+++ b/guacamole/src/main/webapp/app/groupList/directives/guacGroupList.js
@@ -68,6 +68,17 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
             connectionGroupTemplate : '=',
 
             /**
+             * The URL or ID of the Angular template to use when rendering a
+             * sharing profile. The @link{GroupListItem} associated with that
+             * sharing profile will be exposed within the scope of the template
+             * as <code>item</code>, and the arbitrary context object, if any,
+             * will be exposed as <code>context</code>.
+             *
+             * @type String
+             */
+            sharingProfileTemplate : '=',
+
+            /**
              * Whether the root of the connection group hierarchy given should
              * be shown. If false (the default), only the descendants of the
              * given connection group will be listed.
@@ -165,6 +176,22 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
                 return item.isConnectionGroup && !!$scope.connectionGroupTemplate;
             };
 
+            /**
+             * Returns whether the given item represents a sharing profile that
+             * can be displayed. If there is no sharing profile template, then
+             * no sharing profile is visible.
+             *
+             * @param {GroupListItem} item
+             *     The item to check.
+             *
+             * @returns {Boolean}
+             *     true if the given item is a sharing profile that can be
+             *     displayed, false otherwise.
+             */
+            $scope.isVisibleSharingProfile = function isVisibleSharingProfile(item) {
+                return item.isSharingProfile && !!$scope.sharingProfileTemplate;
+            };
+
             // Set contents whenever the connection group is assigned or changed
             $scope.$watch('connectionGroups', function setContents(connectionGroups) {
 
@@ -185,7 +212,8 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
 
                         // Create root item for current connection group
                         var rootItem = GroupListItem.fromConnectionGroup(dataSource, connectionGroup,
-                            !!$scope.connectionTemplate, countActiveConnections);
+                            !!$scope.connectionTemplate, !!$scope.sharingProfileTemplate,
+                            countActiveConnections);
 
                         // If root group is to be shown, add it as a root item
                         if ($scope.showRootGroup)

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/da9ddf76/guacamole/src/main/webapp/app/groupList/templates/guacGroupList.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/groupList/templates/guacGroupList.html b/guacamole/src/main/webapp/app/groupList/templates/guacGroupList.html
index 19d9fd5..df9b5b6 100644
--- a/guacamole/src/main/webapp/app/groupList/templates/guacGroupList.html
+++ b/guacamole/src/main/webapp/app/groupList/templates/guacGroupList.html
@@ -1,38 +1,60 @@
 <div class="group-list">
 
-    <script type="text/ng-template" id="nestedGroup.html">
+    <script type="text/ng-template" id="nestedItem.html">
 
         <!-- Connection -->
-        <div class="connection" ng-show="isVisibleConnection(item)">
+        <div class="connection expandable" ng-if="isVisibleConnection(item)"
+            ng-class="{expanded: item.isExpanded, empty: !item.children.length}">
             <div class="caption">
+
+                <!-- Expand/collapse icon -->
+                <div class="icon expand" ng-click="toggleExpanded(item)"
+                    ng-if="sharingProfileTemplate"></div>
+
                 <ng-include src="connectionTemplate"/>
+
+            </div>
+
+            <!-- Children of this connection -->
+            <div class="children" ng-show="item.isExpanded">
+                <div class="list-item" ng-repeat="item in item.children | orderBy : 'name'"
+                    ng-include="'nestedItem.html'"></div>
             </div>
+
         </div>
 
         <!-- Connection group -->
-        <div class="group" ng-show="isVisibleConnectionGroup(item)">
+        <div class="group expandable" ng-if="isVisibleConnectionGroup(item)"
+            ng-class="{expanded: item.isExpanded, empty: !item.children.length, balancer: item.isBalancing}">
             <div class="caption">
 
-                <!-- Connection group icon -->
-                <div class="icon group type" ng-click="toggleExpanded(item)"
-                     ng-class="{expanded: item.isExpanded, empty: !item.children.length, balancer: item.isBalancing}"></div>
+                <!-- Expand/collapse icon -->
+                <div class="icon expand" ng-click="toggleExpanded(item)"></div>
 
                 <ng-include src="connectionGroupTemplate"/>
 
             </div>
 
             <!-- Children of this group -->
-            <div class="children" ng-show="item.isExpanded">
-                <div class="list-item" ng-repeat="item in item.children | orderBy : 'name'" ng-include="'nestedGroup.html'">
+            <div class="children" ng-if="item.isExpanded">
+                <div class="list-item" ng-repeat="item in item.children | orderBy : 'name'"
+                    ng-include="'nestedItem.html'"></div>
             </div>
 
         </div>
 
+        <!-- Sharing profile -->
+        <div class="sharing-profile" ng-show="isVisibleSharingProfile(item)">
+            <div class="caption">
+                <ng-include src="sharingProfileTemplate"/>
+            </div>
+        </div>
+
     </script>
 
     <!-- Root-level connections / groups -->
     <div class="group-list-page">
-        <div class="list-item" ng-repeat="item in childrenPage" ng-include="'nestedGroup.html'"></div>
+        <div class="list-item" ng-repeat="item in childrenPage" ng-include="'nestedItem.html'"></div>
     </div>
 
     <!-- Pager for connections / groups -->

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/da9ddf76/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js b/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js
index a46eb20..2fc9cf5 100644
--- a/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js
+++ b/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js
@@ -37,16 +37,16 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
         template = template || {};
 
         /**
-         * The identifier of the data source associated with the connection or
-         * connection group this item represents.
+         * The identifier of the data source associated with the connection,
+         * connection group, or sharing profile this item represents.
          *
          * @type String
          */
         this.dataSource = template.dataSource;
 
         /**
-         * The unique identifier associated with the connection or connection
-         * group this item represents.
+         * The unique identifier associated with the connection, connection
+         * group, or sharing profile this item represents.
          *
          * @type String
          */
@@ -78,7 +78,7 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
 
         /**
          * Whether this item represents a connection. If this item represents
-         * a connection group, this MUST be false.
+         * a connection group or sharing profile, this MUST be false.
          *
          * @type Boolean
          */
@@ -86,13 +86,21 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
 
         /**
          * Whether this item represents a connection group. If this item
-         * represents a connection, this MUST be false.
+         * represents a connection or sharing profile, this MUST be false.
          *
          * @type Boolean
          */
         this.isConnectionGroup = template.isConnectionGroup;
 
         /**
+         * Whether this item represents a sharing profile. If this item
+         * represents a connection or connection group, this MUST be false.
+         *
+         * @type Boolean
+         */
+        this.isSharingProfile = template.isSharingProfile;
+
+        /**
          * Whether this item represents a balancing connection group.
          *
          * @type Boolean
@@ -107,8 +115,8 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
         this.isExpanded = template.isExpanded;
         
         /**
-         * Returns the number of currently active users for this connection or
-         * connection group, if known.
+         * Returns the number of currently active users for this connection,
+         * connection group, or sharing profile, if known.
          * 
          * @type Number
          */
@@ -117,10 +125,10 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
         });
 
         /**
-         * The connection or connection group whose data is exposed within
-         * this GroupListItem.
+         * The connection, connection group, or sharing profile whose data is
+         * exposed within this GroupListItem.
          *
-         * @type Connection|ConnectionGroup
+         * @type Connection|ConnectionGroup|SharingProfile
          */
         this.wrappedItem = template.wrappedItem;
 
@@ -137,6 +145,10 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
      *     The connection whose contents should be represented by the new
      *     GroupListItem.
      *
+     * @param {Boolean} [includeSharingProfiles=true]
+     *     Whether sharing profiles should be included in the contents of the
+     *     resulting GroupListItem. By default, sharing profiles are included.
+     *
      * @param {Function} [countActiveConnections]
      *     A getter which returns the current number of active connections for
      *     the given connection. If omitted, the number of active connections
@@ -148,7 +160,17 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
      *     A new GroupListItem which represents the given connection.
      */
     GroupListItem.fromConnection = function fromConnection(dataSource,
-        connection, countActiveConnections) {
+        connection, includeSharingProfiles, countActiveConnections) {
+
+        var children = [];
+
+        // Add any sharing profiles
+        if (connection.sharingProfiles && includeSharingProfiles !== false) {
+            connection.sharingProfiles.forEach(function addSharingProfile(child) {
+                children.push(GroupListItem.fromSharingProfile(dataSource,
+                    child, countActiveConnections));
+            });
+        }
 
         // Return item representing the given connection
         return new GroupListItem({
@@ -162,7 +184,11 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
             // Type information
             isConnection      : true,
             isConnectionGroup : false,
-            
+            isSharingProfile  : false,
+
+            // Already-converted children
+            children : children,
+
             // Count of currently active connections using this connection
             getActiveConnections : function getActiveConnections() {
 
@@ -197,6 +223,10 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
      *     Whether connections should be included in the contents of the
      *     resulting GroupListItem. By default, connections are included.
      *
+     * @param {Boolean} [includeSharingProfiles=true]
+     *     Whether sharing profiles should be included in the contents of the
+     *     resulting GroupListItem. By default, sharing profiles are included.
+     *
      * @param {Function} [countActiveConnections]
      *     A getter which returns the current number of active connections for
      *     the given connection. If omitted, the number of active connections
@@ -216,8 +246,8 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
      *     including all descendants.
      */
     GroupListItem.fromConnectionGroup = function fromConnectionGroup(dataSource,
-        connectionGroup, includeConnections, countActiveConnections,
-        countActiveConnectionGroups) {
+        connectionGroup, includeConnections, includeSharingProfiles,
+        countActiveConnections, countActiveConnectionGroups) {
 
         var children = [];
 
@@ -225,7 +255,7 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
         if (connectionGroup.childConnections && includeConnections !== false) {
             connectionGroup.childConnections.forEach(function addChildConnection(child) {
                 children.push(GroupListItem.fromConnection(dataSource, child,
-                    countActiveConnections));
+                    includeSharingProfiles, countActiveConnections));
             });
         }
 
@@ -233,8 +263,8 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
         if (connectionGroup.childConnectionGroups) {
             connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) {
                 children.push(GroupListItem.fromConnectionGroup(dataSource,
-                    child, includeConnections, countActiveConnections,
-                    countActiveConnectionGroups));
+                    child, includeConnections, includeSharingProfiles,
+                    countActiveConnections, countActiveConnectionGroups));
             });
         }
 
@@ -249,6 +279,7 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
             // Type information
             isConnection      : false,
             isConnectionGroup : true,
+            isSharingProfile  : false,
             isBalancing       : connectionGroup.type === ConnectionGroup.Type.BALANCING,
 
             // Already-converted children
@@ -273,6 +304,44 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
 
     };
 
+    /**
+     * Creates a new GroupListItem using the contents of the given sharing
+     * profile.
+     *
+     * @param {String} dataSource
+     *     The identifier of the data source containing the given sharing
+     *     profile.
+     *
+     * @param {SharingProfile} sharingProfile
+     *     The sharing profile whose contents should be represented by the new
+     *     GroupListItem.
+     *
+     * @returns {GroupListItem}
+     *     A new GroupListItem which represents the given sharing profile.
+     */
+    GroupListItem.fromSharingProfile = function fromSharingProfile(dataSource,
+        sharingProfile) {
+
+        // Return item representing the given sharing profile
+        return new GroupListItem({
+
+            // Identifying information
+            name       : sharingProfile.name,
+            identifier : sharingProfile.identifier,
+            dataSource : dataSource,
+
+            // Type information
+            isConnection      : false,
+            isConnectionGroup : false,
+            isSharingProfile  : true,
+
+            // Wrapped item
+            wrappedItem : sharingProfile
+
+        });
+
+    };
+
     return GroupListItem;
 
 }]);


[9/9] incubator-guacamole-client git commit: GUACAMOLE-5: Merge sharing profile permission editing change.

Posted by jm...@apache.org.
GUACAMOLE-5: Merge sharing profile permission editing change.


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

Branch: refs/heads/master
Commit: 989ad395132f319a18bfb2b6cf6ed2ff8c0152b1
Parents: 841bc47 f3a201a
Author: James Muehlner <ja...@guac-dev.org>
Authored: Thu Aug 4 21:00:21 2016 -0700
Committer: James Muehlner <ja...@guac-dev.org>
Committed: Thu Aug 4 21:00:21 2016 -0700

----------------------------------------------------------------------
 .../rest/connection/APIConnection.java          |  32 ++++
 .../connectiongroup/ConnectionGroupTree.java    | 172 ++++++++++++++++---
 .../app/groupList/directives/guacGroupList.js   |  30 +++-
 .../app/groupList/templates/guacGroupList.html  |  40 ++++-
 .../webapp/app/groupList/types/GroupListItem.js | 105 +++++++++--
 .../webapp/app/home/templates/connection.html   |  24 ++-
 .../src/main/webapp/app/index/styles/lists.css  |  15 +-
 .../src/main/webapp/app/index/styles/ui.css     |  78 +++++++--
 .../manage/controllers/manageUserController.js  |  81 ++++++++-
 .../templates/connectionGroupPermission.html    |   6 +
 .../manage/templates/connectionPermission.html  |   6 +-
 .../webapp/app/manage/templates/manageUser.html |   1 +
 .../templates/sharingProfilePermission.html     |  13 ++
 .../app/rest/services/permissionService.js      |   4 +
 .../main/webapp/app/rest/types/Connection.js    |   9 +
 .../webapp/app/rest/types/PermissionFlagSet.js  |  22 +++
 .../main/webapp/app/rest/types/PermissionSet.js |  88 +++++++++-
 .../app/settings/templates/connection.html      |  24 ++-
 guacamole/src/main/webapp/translations/en.json  |   1 +
 19 files changed, 632 insertions(+), 119 deletions(-)
----------------------------------------------------------------------



[3/9] incubator-guacamole-client git commit: GUACAMOLE-5: Correct and simply guacGroupList styling/structure.

Posted by jm...@apache.org.
GUACAMOLE-5: Correct and simply guacGroupList styling/structure.


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

Branch: refs/heads/master
Commit: 85f15b7cd1378ff4572e05567c1b09d87e1a0331
Parents: da9ddf7
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Aug 4 17:50:33 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Aug 4 19:48:58 2016 -0700

----------------------------------------------------------------------
 .../webapp/app/home/templates/connection.html   | 24 +++++------
 .../src/main/webapp/app/index/styles/lists.css  | 15 ++-----
 .../src/main/webapp/app/index/styles/ui.css     | 42 ++++++++++++--------
 .../templates/connectionGroupPermission.html    |  6 +++
 .../manage/templates/connectionPermission.html  |  6 +--
 .../app/settings/templates/connection.html      | 24 +++++------
 6 files changed, 58 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/85f15b7c/guacamole/src/main/webapp/app/home/templates/connection.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/home/templates/connection.html b/guacamole/src/main/webapp/app/home/templates/connection.html
index 01f58bb..8e8ccc2 100644
--- a/guacamole/src/main/webapp/app/home/templates/connection.html
+++ b/guacamole/src/main/webapp/app/home/templates/connection.html
@@ -1,19 +1,15 @@
-<a ng-href="#/client/{{context.getClientIdentifier(item)}}">
+<a ng-href="#/client/{{context.getClientIdentifier(item)}}"
+   ng-class="{active: item.getActiveConnections()}">
 
-    <div class="caption" ng-class="{active: item.getActiveConnections()}">
+    <!-- Connection icon -->
+    <div class="icon type" ng-class="item.protocol"></div>
 
-        <!-- Connection icon -->
-        <div class="protocol">
-            <div class="icon type" ng-class="item.protocol"></div>
-        </div>
+    <!-- Connection name -->
+    <span class="name">{{item.name}}</span>
 
-        <!-- Connection name -->
-        <span class="name">{{item.name}}</span>
-        
-        <!-- Active user count -->
-        <span class="activeUserCount" ng-show="item.getActiveConnections()"
-            translate="HOME.INFO_ACTIVE_USER_COUNT"
-            translate-values="{USERS: item.getActiveConnections()}"></span>
+    <!-- Active user count -->
+    <span class="activeUserCount" ng-show="item.getActiveConnections()"
+        translate="HOME.INFO_ACTIVE_USER_COUNT"
+        translate-values="{USERS: item.getActiveConnections()}"></span>
 
-    </div>
 </a>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/85f15b7c/guacamole/src/main/webapp/app/index/styles/lists.css
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/styles/lists.css b/guacamole/src/main/webapp/app/index/styles/lists.css
index 536169f..5ce162a 100644
--- a/guacamole/src/main/webapp/app/index/styles/lists.css
+++ b/guacamole/src/main/webapp/app/index/styles/lists.css
@@ -44,15 +44,16 @@
     color: black;
 }
 
-.connection:hover {
+.recent-connections .connection:hover {
     background: #CDA;
 }
 
-.connection .thumbnail {
+.recent-connections .connection .thumbnail {
+    display: block;
     margin: 0.5em;
 }
 
-.connection .thumbnail > * {
+.recent-connections .connection .thumbnail > * {
     border: 1px solid black;
     background: black;
     box-shadow: 1px 1px 5px black;
@@ -60,14 +61,6 @@
     display: inline-block;
 }
 
-div.recent-connections .connection .thumbnail {
-    display: block;
-}
-
-div.recent-connections .protocol {
-    display: none;
-}
-
 .caption * {
     vertical-align: middle;
 }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/85f15b7c/guacamole/src/main/webapp/app/index/styles/ui.css
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/index/styles/ui.css b/guacamole/src/main/webapp/app/index/styles/ui.css
index d91becf..f324e3d 100644
--- a/guacamole/src/main/webapp/app/index/styles/ui.css
+++ b/guacamole/src/main/webapp/app/index/styles/ui.css
@@ -164,14 +164,11 @@ div.section {
     background-image: url('images/action-icons/guac-monitor-add.png');
 }
 
-.protocol {
+.connection .icon,
+.connection-group .icon {
     display: inline-block;
-}
-
-.protocol .icon {
     width: 24px;
     height: 24px;
-    background-image: url('images/protocol-icons/guac-plug.png');
     background-size: 16px 16px;
     -moz-background-size: 16px 16px;
     -webkit-background-size: 16px 16px;
@@ -180,44 +177,57 @@ div.section {
     background-position: center center;
 }
 
-.protocol .icon.ssh,
-.protocol .icon.telnet {
+.group .icon {
+    background-image: url('images/folder-closed.png');
+}
+
+.group.expanded .icon {
+    background-image: url('images/folder-open.png');
+}
+
+.connection .icon {
+    background-image: url('images/protocol-icons/guac-plug.png');
+}
+
+.connection .icon.ssh,
+.connection .icon.telnet {
     background-image: url('images/protocol-icons/guac-text.png');
 }
 
-.protocol .icon.vnc,
-.protocol .icon.rdp {
+.connection .icon.vnc,
+.connection .icon.rdp {
     background-image: url('images/protocol-icons/guac-monitor.png');
 }
+
 /*
  * Groups
  */
 
-.group > .children {
+.expandable > .children {
     margin-left: 13px;
-    padding-left: 6px;
+    padding-left: 13px;
 }
  
-.group .icon.group.type.empty.balancer {
+.group.empty.balancer .icon {
     opacity: 1;
     background-image: url('images/protocol-icons/guac-monitor.png');
 }
 
-.group.expanded > .children {
+.expandable.expanded > .children {
     display: block;
     border-left: 1px dotted rgba(0, 0, 0, 0.25);
 }
 
-.group > .caption .icon.group {
+.expandable > .caption .icon.expand {
     opacity: 0.75;
     background-image: url('images/group-icons/guac-closed.png');
 }
 
-.group .icon.type.group.expanded {
+.expandable.expanded .icon.expand {
     background-image: url('images/group-icons/guac-open.png');
 }
 
-.group .icon.type.group.empty {
+.expandable.empty .icon.expand {
     opacity: 0.25;
     background-image: url('images/group-icons/guac-open.png');
 }

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/85f15b7c/guacamole/src/main/webapp/app/manage/templates/connectionGroupPermission.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/templates/connectionGroupPermission.html b/guacamole/src/main/webapp/app/manage/templates/connectionGroupPermission.html
index b43376b..6b27055 100644
--- a/guacamole/src/main/webapp/app/manage/templates/connectionGroupPermission.html
+++ b/guacamole/src/main/webapp/app/manage/templates/connectionGroupPermission.html
@@ -1,7 +1,13 @@
 <div class="choice">
 
+    <!-- Connection group icon -->
+    <div class="icon type"></div>
+
+    <!-- Permission checkbox -->
     <input type="checkbox" ng-model="context.getPermissionFlags().connectionGroupPermissions.READ[item.identifier]"
                            ng-change="context.connectionGroupPermissionChanged(item.identifier)"/>
 
+    <!-- Connection group name -->
     <span class="name">{{item.name}}</span>
+
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/85f15b7c/guacamole/src/main/webapp/app/manage/templates/connectionPermission.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/manage/templates/connectionPermission.html b/guacamole/src/main/webapp/app/manage/templates/connectionPermission.html
index 8ccaf44..8f1bb8b 100644
--- a/guacamole/src/main/webapp/app/manage/templates/connectionPermission.html
+++ b/guacamole/src/main/webapp/app/manage/templates/connectionPermission.html
@@ -1,11 +1,9 @@
 <div class="choice">
 
     <!-- Connection icon -->
-    <div class="protocol">
-        <div class="icon type" ng-class="item.protocol"></div>
-    </div>
+    <div class="icon type" ng-class="item.protocol"></div>
 
-    <!-- Checkbox -->
+    <!-- Permission checkbox -->
     <input type="checkbox" ng-model="context.getPermissionFlags().connectionPermissions.READ[item.identifier]"
                            ng-change="context.connectionPermissionChanged(item.identifier)"/>
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/85f15b7c/guacamole/src/main/webapp/app/settings/templates/connection.html
----------------------------------------------------------------------
diff --git a/guacamole/src/main/webapp/app/settings/templates/connection.html b/guacamole/src/main/webapp/app/settings/templates/connection.html
index 0a6001c..7db6835 100644
--- a/guacamole/src/main/webapp/app/settings/templates/connection.html
+++ b/guacamole/src/main/webapp/app/settings/templates/connection.html
@@ -1,19 +1,15 @@
-<a ng-href="#/manage/{{item.dataSource}}/connections/{{item.identifier}}">
+<a ng-href="#/manage/{{item.dataSource}}/connections/{{item.identifier}}"
+   ng-class="{active: item.getActiveConnections()}">
 
-    <div class="caption" ng-class="{active: item.getActiveConnections()}">
+    <!-- Connection icon -->
+    <div class="icon type" ng-class="item.protocol"></div>
 
-        <!-- Connection icon -->
-        <div class="protocol">
-            <div class="icon type" ng-class="item.protocol"></div>
-        </div>
+    <!-- Connection name -->
+    <span class="name">{{item.name}}</span>
 
-        <!-- Connection name -->
-        <span class="name">{{item.name}}</span>
+    <!-- Active user count -->
+    <span class="activeUserCount" ng-show="item.getActiveConnections()"
+        translate="SETTINGS_CONNECTIONS.INFO_ACTIVE_USER_COUNT"
+        translate-values="{USERS: item.getActiveConnections()}"></span>
 
-        <!-- Active user count -->
-        <span class="activeUserCount" ng-show="item.getActiveConnections()"
-            translate="SETTINGS_CONNECTIONS.INFO_ACTIVE_USER_COUNT"
-            translate-values="{USERS: item.getActiveConnections()}"></span>
-        
-    </div>
 </a>