From 97189cb991e221fd5fc4c6998c1ab943182f849f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 20 Jan 2015 20:38:59 -0800 Subject: [PATCH] GUAC-1010: Only query contents of connection groups if they are not balancing or we have admin permission. Fix rendering of balancing groups for non-admins. --- .../ConnectionGroupRESTService.java | 48 +++++++++++++++++-- .../app/groupList/types/GroupListItem.js | 16 ++++--- .../src/main/webapp/app/index/styles/ui.css | 10 ++-- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java index bbbfc9d2b..7fc93a273 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connectiongroup/ConnectionGroupRESTService.java @@ -25,6 +25,7 @@ package org.glyptodon.guacamole.net.basic.rest.connectiongroup; import com.google.inject.Inject; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -44,6 +45,7 @@ import org.glyptodon.guacamole.net.auth.ConnectionGroup; import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.UserContext; +import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission; import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission; @@ -114,7 +116,41 @@ public class ConnectionGroupRESTService { return false; } - + + /** + * Determines whether the given user has at least one of the given + * permissions for the connection group having the given identifier. + * + * @param user + * The user to check permissions for. + * + * @param identifier + * The identifier of the connection group to check permissions for. + * + * @param permissions + * The permissions to check. The given user must have one or more of + * these permissions for this function to return true. + * + * @return + * true if the user has at least one of the given permissions. + */ + private boolean hasConnectionGroupPermission(User user, String identifier, + List permissions) throws GuacamoleException { + + // Determine whether user has at least one of the given permissions + for (ObjectPermission.Type permission : permissions) { + + ConnectionGroupPermission connectionGroupPermission = new ConnectionGroupPermission(permission, identifier); + if (user.hasPermission(connectionGroupPermission)) + return true; + + } + + // None of the given permissions were present + return false; + + } + /** * Retrieves the given connection group from the user context, including * all descendant connections and groups if requested. @@ -163,8 +199,14 @@ public class ConnectionGroupRESTService { // Wrap queried connection group APIConnectionGroup apiConnectionGroup = new APIConnectionGroup(connectionGroup); - // Recursively query all descendants if necessary - if (includeDescendants) { + // Recursively query all descendants if necessary, only querying the + // descendants of balancing groups if we have admin permission on that + // group + if (includeDescendants + && (connectionGroup.getType() != ConnectionGroup.Type.BALANCING + || isAdmin + || hasConnectionGroupPermission(self, identifier, + Collections.singletonList(ObjectPermission.Type.ADMINISTER)))) { // Query all child connections Collection apiConnections = new ArrayList(); diff --git a/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js b/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js index 6e02d30f4..08a78b949 100644 --- a/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js +++ b/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js @@ -159,14 +159,18 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio var children = []; // Add any child connections - connectionGroup.childConnections.forEach(function addChildConnection(child) { - children.push(GroupListItem.fromConnection(child)); - }); + if (connectionGroup.childConnections) { + connectionGroup.childConnections.forEach(function addChildConnection(child) { + children.push(GroupListItem.fromConnection(child)); + }); + } // Add any child groups - connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) { - children.push(GroupListItem.fromConnectionGroup(child)); - }); + if (connectionGroup.childConnectionGroups) { + connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) { + children.push(GroupListItem.fromConnectionGroup(child)); + }); + } // Return item representing the given connection group return new GroupListItem({ diff --git a/guacamole/src/main/webapp/app/index/styles/ui.css b/guacamole/src/main/webapp/app/index/styles/ui.css index 7a070ed81..7f839ab01 100644 --- a/guacamole/src/main/webapp/app/index/styles/ui.css +++ b/guacamole/src/main/webapp/app/index/styles/ui.css @@ -255,16 +255,16 @@ div.section { padding-left: 6px; } +.group .icon.group.type.empty.balancer { + opacity: 1; + background-image: url('images/protocol-icons/guac-monitor.png'); +} + .group.expanded > .children { display: block; border-left: 1px dotted rgba(0, 0, 0, 0.25); } -.group.balancer:not(.empty) > .caption .icon.type { - display: inline-block; - background-image: url('images/protocol-icons/guac-monitor.png'); -} - .group > .caption .icon.group { opacity: 0.75; background-image: url('images/group-icons/guac-closed.png');