You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/10/01 17:36:37 UTC

[04/37] guacamole-client git commit: GUACAMOLE-220: Inherit from groups even if not determined by database.

GUACAMOLE-220: Inherit from groups even if not determined by database.


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

Branch: refs/heads/staging/1.0.0
Commit: 14d10fb42abb59515bd58ce04245bd655be3b056
Parents: 6e71f33
Author: Michael Jumper <mj...@apache.org>
Authored: Fri Apr 6 14:10:52 2018 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Sep 19 23:56:51 2018 -0700

----------------------------------------------------------------------
 .../ActiveConnectionPermissionService.java      | 18 +++--
 .../jdbc/base/ModeledDirectoryObjectMapper.java | 14 +++-
 .../base/ModeledDirectoryObjectService.java     |  6 +-
 .../auth/jdbc/connection/ConnectionMapper.java  | 10 ++-
 .../jdbc/connection/ConnectionRecordMapper.java |  9 ++-
 .../auth/jdbc/connection/ConnectionService.java |  9 ++-
 .../connectiongroup/ConnectionGroupMapper.java  | 10 ++-
 .../connectiongroup/ConnectionGroupService.java |  4 +-
 .../ConnectionGroupPermissionService.java       |  6 +-
 .../permission/ConnectionPermissionService.java |  6 +-
 .../ModeledObjectPermissionService.java         | 15 +++--
 .../permission/ModeledPermissionService.java    |  5 +-
 .../jdbc/permission/ObjectPermissionMapper.java | 22 +++---
 .../permission/ObjectPermissionService.java     | 23 ++++---
 .../jdbc/permission/ObjectPermissionSet.java    | 25 +++----
 .../auth/jdbc/permission/PermissionMapper.java  | 11 +--
 .../auth/jdbc/permission/PermissionService.java | 24 ++++---
 .../SharingProfilePermissionService.java        |  6 +-
 .../jdbc/permission/SystemPermissionMapper.java | 12 ++--
 .../permission/SystemPermissionService.java     | 18 ++---
 .../jdbc/permission/SystemPermissionSet.java    | 23 +++----
 .../jdbc/permission/UserPermissionService.java  |  6 +-
 .../tunnel/AbstractGuacamoleTunnelService.java  |  4 +-
 .../guacamole/auth/jdbc/user/ModeledUser.java   | 52 +++++++++-----
 .../guacamole/auth/jdbc/user/UserMapper.java    | 24 ++++++-
 .../auth/jdbc/user/UserRecordMapper.java        |  9 ++-
 .../guacamole/auth/jdbc/user/UserService.java   | 29 +++++++-
 .../guacamole/auth/jdbc/base/EntityMapper.xml   | 49 +++++++++-----
 .../auth/jdbc/connection/ConnectionMapper.xml   | 55 +++++++--------
 .../jdbc/connection/ConnectionRecordMapper.xml  | 22 +++---
 .../connectiongroup/ConnectionGroupMapper.xml   | 66 +++++++++---------
 .../ConnectionGroupPermissionMapper.xml         | 33 +++++----
 .../permission/ConnectionPermissionMapper.xml   | 33 +++++----
 .../SharingProfilePermissionMapper.xml          | 34 +++++-----
 .../jdbc/permission/SystemPermissionMapper.xml  | 22 +++---
 .../jdbc/permission/UserPermissionMapper.xml    | 33 +++++----
 .../sharingprofile/SharingProfileMapper.xml     | 33 +++++----
 .../guacamole/auth/jdbc/user/UserMapper.xml     | 71 +++++++++++++++-----
 .../auth/jdbc/user/UserRecordMapper.xml         | 11 ++-
 39 files changed, 514 insertions(+), 348 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
index 405b237..a0511b8 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
@@ -59,10 +59,11 @@ public class ActiveConnectionPermissionService
     @Override
     public boolean hasPermission(ModeledAuthenticatedUser user,
             ModeledUser targetUser, ObjectPermission.Type type,
-            String identifier, boolean inherit) throws GuacamoleException {
+            String identifier, Set<String> effectiveGroups) throws GuacamoleException {
 
         // Retrieve permissions
-        Set<ObjectPermission> permissions = retrievePermissions(user, targetUser, inherit);
+        Set<ObjectPermission> permissions = retrievePermissions(user,
+                targetUser, effectiveGroups);
 
         // Permission is granted if retrieved permissions contains the
         // requested permission
@@ -73,7 +74,8 @@ public class ActiveConnectionPermissionService
 
     @Override
     public Set<ObjectPermission> retrievePermissions(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Retrieve permissions only if allowed
         if (canReadPermissions(user, targetUser)) {
@@ -109,9 +111,10 @@ public class ActiveConnectionPermissionService
     @Override
     public Collection<String> retrieveAccessibleIdentifiers(ModeledAuthenticatedUser user,
             ModeledUser targetUser, Collection<ObjectPermission.Type> permissionTypes,
-            Collection<String> identifiers, boolean inherit) throws GuacamoleException {
+            Collection<String> identifiers, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
-        Set<ObjectPermission> permissions = retrievePermissions(user, targetUser, inherit);
+        Set<ObjectPermission> permissions = retrievePermissions(user, targetUser, effectiveGroups);
         Collection<String> accessibleObjects = new ArrayList<String>(permissions.size());
 
         // For each identifier/permission combination
@@ -134,11 +137,12 @@ public class ActiveConnectionPermissionService
 
     @Override
     public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
     
         // Create permission set for requested user
         ActiveConnectionPermissionSet permissionSet = activeConnectionPermissionSetProvider.get();
-        permissionSet.init(user, targetUser, inherit);
+        permissionSet.init(user, targetUser, effectiveGroups);
 
         return permissionSet;
  

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
index 4431e8f..8ff0cc1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
@@ -57,10 +57,15 @@ public interface ModeledDirectoryObjectMapper<ModelType> {
      *    The user whose permissions should determine whether an identifier
      *    is returned.
      *
+     * @param effectiveGroups
+     *     The identifiers of any known effective groups that should be taken
+     *     into account, such as those defined externally to the database.
+     *
      * @return
      *     A Set containing all identifiers of all readable objects.
      */
-    Set<String> selectReadableIdentifiers(@Param("user") UserModel user);
+    Set<String> selectReadableIdentifiers(@Param("user") UserModel user,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
     
     /**
      * Selects all objects which have the given identifiers. If an identifier
@@ -91,11 +96,16 @@ public interface ModeledDirectoryObjectMapper<ModelType> {
      * @param identifiers
      *     The identifiers of the objects to return.
      *
+     * @param effectiveGroups
+     *     The identifiers of any known effective groups that should be taken
+     *     into account, such as those defined externally to the database.
+     *
      * @return 
      *     A Collection of all objects having the given identifiers.
      */
     Collection<ModelType> selectReadable(@Param("user") UserModel user,
-            @Param("identifiers") Collection<String> identifiers);
+            @Param("identifiers") Collection<String> identifiers,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
     /**
      * Inserts the given object into the database. If the object already

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
index e87d664..edbb67e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
@@ -401,7 +401,8 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
 
         // Otherwise only return explicitly readable identifiers
         else
-            objects = getObjectMapper().selectReadable(user.getUser().getModel(), identifiers);
+            objects = getObjectMapper().selectReadable(user.getUser().getModel(),
+                    identifiers, user.getEffectiveUserGroups());
         
         // Return collection of requested objects
         return getObjectInstances(user, objects);
@@ -512,7 +513,8 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
 
         // Otherwise only return explicitly readable identifiers
         else
-            return getObjectMapper().selectReadableIdentifiers(user.getUser().getModel());
+            return getObjectMapper().selectReadableIdentifiers(user.getUser().getModel(),
+                    user.getEffectiveUserGroups());
 
     }
 

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
index 9a49132..3cd542f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
@@ -19,6 +19,7 @@
 
 package org.apache.guacamole.auth.jdbc.connection;
 
+import java.util.Collection;
 import java.util.Set;
 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
 import org.apache.guacamole.auth.jdbc.user.UserModel;
@@ -61,11 +62,18 @@ public interface ConnectionMapper extends ModeledDirectoryObjectMapper<Connectio
      *     The identifier of the parent connection group, or null if the root
      *     connection group is to be queried.
      *
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
+     *
      * @return
      *     A Set containing all identifiers of all readable objects.
      */
     Set<String> selectReadableIdentifiersWithin(@Param("user") UserModel user,
-            @Param("parentIdentifier") String parentIdentifier);
+            @Param("parentIdentifier") String parentIdentifier,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
     /**
      * Selects the connection within the given parent group and having the

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
index 637fd0f..7380b21 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
@@ -102,12 +102,19 @@ public interface ConnectionRecordMapper {
      * @param limit
      *     The maximum number of records that should be returned.
      *
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
+     *
      * @return
      *     The results of the search performed with the given parameters.
      */
     List<ConnectionRecordModel> searchReadable(@Param("user") UserModel user,
             @Param("terms") Collection<ActivityRecordSearchTerm> terms,
             @Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
-            @Param("limit") int limit);
+            @Param("limit") int limit,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
index 11e3792..8dcf6f5 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
@@ -303,7 +303,9 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
 
         // Otherwise only return explicitly readable identifiers
         else
-            return connectionMapper.selectReadableIdentifiersWithin(user.getUser().getModel(), identifier);
+            return connectionMapper.selectReadableIdentifiersWithin(
+                    user.getUser().getModel(), identifier,
+                    user.getEffectiveUserGroups());
 
     }
 
@@ -475,8 +477,9 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
 
         // Otherwise only return explicitly readable history records
         else
-            searchResults = connectionRecordMapper.searchReadable(user.getUser().getModel(),
-                    requiredContents, sortPredicates, limit);
+            searchResults = connectionRecordMapper.searchReadable(
+                    user.getUser().getModel(), requiredContents, sortPredicates,
+                    limit, user.getEffectiveUserGroups());
 
         return getObjectInstances(searchResults);
 

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.java
index c82069a..a54a151 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.java
@@ -19,6 +19,7 @@
 
 package org.apache.guacamole.auth.jdbc.connectiongroup;
 
+import java.util.Collection;
 import java.util.Set;
 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
 import org.apache.guacamole.auth.jdbc.user.UserModel;
@@ -61,11 +62,18 @@ public interface ConnectionGroupMapper extends ModeledDirectoryObjectMapper<Conn
      *     The identifier of the parent connection group, or null if the root
      *     connection group is to be queried.
      *
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
+     *
      * @return
      *     A Set containing all identifiers of all readable objects.
      */
     Set<String> selectReadableIdentifiersWithin(@Param("user") UserModel user,
-            @Param("parentIdentifier") String parentIdentifier);
+            @Param("parentIdentifier") String parentIdentifier,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
     /**
      * Selects the connection group within the given parent group and having

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
index 34d039c..01119b9 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
@@ -223,7 +223,9 @@ public class ConnectionGroupService extends ModeledChildDirectoryObjectService<M
 
         // Otherwise only return explicitly readable identifiers
         else
-            return connectionGroupMapper.selectReadableIdentifiersWithin(user.getUser().getModel(), identifier);
+            return connectionGroupMapper.selectReadableIdentifiersWithin(
+                    user.getUser().getModel(), identifier,
+                    user.getEffectiveUserGroups());
 
     }
 

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
index 3027d81..afabbc7 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.permission;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
@@ -51,11 +52,12 @@ public class ConnectionGroupPermissionService extends ModeledObjectPermissionSer
 
     @Override
     public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Create permission set for requested user
         ObjectPermissionSet permissionSet = connectionGroupPermissionSetProvider.get();
-        permissionSet.init(user, targetUser, inherit);
+        permissionSet.init(user, targetUser, effectiveGroups);
 
         return permissionSet;
         

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
index 19c30c0..0cc69df 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.permission;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
@@ -51,11 +52,12 @@ public class ConnectionPermissionService extends ModeledObjectPermissionService
 
     @Override
     public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Create permission set for requested user
         ObjectPermissionSet permissionSet = connectionPermissionSetProvider.get();
-        permissionSet.init(user, targetUser, inherit);
+        permissionSet.init(user, targetUser, effectiveGroups);
 
         return permissionSet;
         

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
index b1229ae..f1105ed 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.jdbc.permission;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
 import org.apache.guacamole.GuacamoleException;
@@ -106,7 +107,7 @@ public abstract class ModeledObjectPermissionService
             affectedIdentifiers.add(permission.getObjectIdentifier());
 
         // Determine subset of affected identifiers that we have admin access to
-        ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser(), true);
+        ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser(), user.getEffectiveUserGroups());
         Collection<String> allowedSubset = affectedPermissionSet.getAccessibleObjects(
             Collections.singleton(ObjectPermission.Type.ADMINISTER),
             affectedIdentifiers
@@ -157,11 +158,13 @@ public abstract class ModeledObjectPermissionService
     @Override
     public boolean hasPermission(ModeledAuthenticatedUser user,
             ModeledUser targetUser, ObjectPermission.Type type,
-            String identifier, boolean inherit) throws GuacamoleException {
+            String identifier, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Retrieve permissions only if allowed
         if (canReadPermissions(user, targetUser))
-            return getPermissionMapper().selectOne(targetUser.getModel(), type, identifier, inherit) != null;
+            return getPermissionMapper().selectOne(targetUser.getModel(), type,
+                    identifier, effectiveGroups) != null;
 
         // User cannot read this user's permissions
         throw new GuacamoleSecurityException("Permission denied.");
@@ -171,7 +174,7 @@ public abstract class ModeledObjectPermissionService
     @Override
     public Collection<String> retrieveAccessibleIdentifiers(ModeledAuthenticatedUser user,
             ModeledUser targetUser, Collection<ObjectPermission.Type> permissions,
-            Collection<String> identifiers, boolean inherit)
+            Collection<String> identifiers, Set<String> effectiveGroups)
             throws GuacamoleException {
 
         // Nothing is always accessible
@@ -186,7 +189,9 @@ public abstract class ModeledObjectPermissionService
                 return identifiers;
 
             // Otherwise, return explicitly-retrievable identifiers
-            return getPermissionMapper().selectAccessibleIdentifiers(targetUser.getModel(), permissions, identifiers, inherit);
+            return getPermissionMapper().selectAccessibleIdentifiers(
+                    targetUser.getModel(), permissions, identifiers,
+                    effectiveGroups);
             
         }
 

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
index 4d0fcf6..dadaea6 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
@@ -140,11 +140,12 @@ public abstract class ModeledPermissionService<PermissionSetType extends Permiss
 
     @Override
     public Set<PermissionType> retrievePermissions(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Retrieve permissions only if allowed
         if (canReadPermissions(user, targetUser))
-            return getPermissionInstances(getPermissionMapper().select(targetUser.getModel(), inherit));
+            return getPermissionInstances(getPermissionMapper().select(targetUser.getModel(), effectiveGroups));
 
         // User cannot read this user's permissions
         throw new GuacamoleSecurityException("Permission denied.");

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
index e5efad0..b6f9801 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
@@ -43,10 +43,11 @@ public interface ObjectPermissionMapper extends PermissionMapper<ObjectPermissio
      * @param identifier
      *     The identifier of the object affected by the permission to return.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     The requested permission, or null if no such permission is granted
@@ -55,7 +56,7 @@ public interface ObjectPermissionMapper extends PermissionMapper<ObjectPermissio
     ObjectPermissionModel selectOne(@Param("entity") EntityModel entity,
             @Param("type") ObjectPermission.Type type,
             @Param("identifier") String identifier,
-            @Param("inherit") boolean inherit);
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
     /**
      * Retrieves the subset of the given identifiers for which the given entity
@@ -73,10 +74,11 @@ public interface ObjectPermissionMapper extends PermissionMapper<ObjectPermissio
      *     The identifiers of the objects affected by the permissions being
      *     checked.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     A collection containing the subset of identifiers for which at least
@@ -85,6 +87,6 @@ public interface ObjectPermissionMapper extends PermissionMapper<ObjectPermissio
     Collection<String> selectAccessibleIdentifiers(@Param("entity") EntityModel entity,
             @Param("permissions") Collection<ObjectPermission.Type> permissions,
             @Param("identifiers") Collection<String> identifiers,
-            @Param("inherit") boolean inherit);
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
index fa1ee2d..3f39881 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
@@ -20,6 +20,7 @@
 package org.apache.guacamole.auth.jdbc.permission;
 
 import java.util.Collection;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
 import org.apache.guacamole.GuacamoleException;
@@ -50,10 +51,11 @@ public interface ObjectPermissionService
      * @param identifier
      *     The identifier of the object affected by the permission to return.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     true if permission of the given type and associated with the given
@@ -64,7 +66,7 @@ public interface ObjectPermissionService
      */
     boolean hasPermission(ModeledAuthenticatedUser user,
             ModeledUser targetUser, ObjectPermission.Type type,
-            String identifier, boolean inherit) throws GuacamoleException;
+            String identifier, Set<String> effectiveGroups) throws GuacamoleException;
 
     /**
      * Retrieves the subset of the given identifiers for which the given user
@@ -85,10 +87,11 @@ public interface ObjectPermissionService
      *     The identifiers of the objects affected by the permissions being
      *     checked.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     A collection containing the subset of identifiers for which at least
@@ -99,7 +102,7 @@ public interface ObjectPermissionService
      */
     Collection<String> retrieveAccessibleIdentifiers(ModeledAuthenticatedUser user,
             ModeledUser targetUser, Collection<ObjectPermission.Type> permissions,
-            Collection<String> identifiers, boolean inherit)
+            Collection<String> identifiers, Set<String> effectiveGroups)
             throws GuacamoleException;
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
index cedb45d..c15b1af 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
@@ -42,11 +42,7 @@ public abstract class ObjectPermissionSet extends RestrictedObject
      */
     private ModeledUser user;
 
-    /**
-     * Whether permissions inherited through user groups should be taken into
-     * account. If false, only permissions granted directly will be included.
-     */
-    boolean inherit;
+    private Set<String> effectiveGroups;
 
     /**
      * Creates a new ObjectPermissionSet. The resulting permission set
@@ -67,16 +63,17 @@ public abstract class ObjectPermissionSet extends RestrictedObject
      * @param user
      *     The user to whom the permissions in this set are granted.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      */
     public void init(ModeledAuthenticatedUser currentUser, ModeledUser user,
-            boolean inherit) {
+            Set<String> effectiveGroups) {
         super.init(currentUser);
         this.user = user;
-        this.inherit = inherit;
+        this.effectiveGroups = effectiveGroups;
     }
 
     /**
@@ -91,13 +88,13 @@ public abstract class ObjectPermissionSet extends RestrictedObject
 
     @Override
     public Set<ObjectPermission> getPermissions() throws GuacamoleException {
-        return getObjectPermissionService().retrievePermissions(getCurrentUser(), user, inherit);
+        return getObjectPermissionService().retrievePermissions(getCurrentUser(), user, effectiveGroups);
     }
 
     @Override
     public boolean hasPermission(ObjectPermission.Type permission,
             String identifier) throws GuacamoleException {
-        return getObjectPermissionService().hasPermission(getCurrentUser(), user, permission, identifier, inherit);
+        return getObjectPermissionService().hasPermission(getCurrentUser(), user, permission, identifier, effectiveGroups);
     }
 
     @Override
@@ -115,7 +112,7 @@ public abstract class ObjectPermissionSet extends RestrictedObject
     @Override
     public Collection<String> getAccessibleObjects(Collection<ObjectPermission.Type> permissions,
             Collection<String> identifiers) throws GuacamoleException {
-        return getObjectPermissionService().retrieveAccessibleIdentifiers(getCurrentUser(), user, permissions, identifiers, inherit);
+        return getObjectPermissionService().retrieveAccessibleIdentifiers(getCurrentUser(), user, permissions, identifiers, effectiveGroups);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
index 1c2d23b..edd66f4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
@@ -38,16 +38,17 @@ public interface PermissionMapper<PermissionType> {
      * @param entity
      *     The entity to retrieve permissions for.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     All permissions associated with the given entity.
      */
     Collection<PermissionType> select(@Param("entity") EntityModel entity,
-            @Param("inherit") boolean inherit);
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
     /**
      * Inserts the given permissions into the database. If any permissions

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
index 6e59634..3caa587 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
@@ -54,10 +54,11 @@ public interface PermissionService<PermissionSetType extends PermissionSet<Permi
      *     The user to whom the permissions in the returned permission set are
      *     granted.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     A permission set that contains all permissions associated with the
@@ -69,7 +70,8 @@ public interface PermissionService<PermissionSetType extends PermissionSet<Permi
      *     user is denied.
      */
     PermissionSetType getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException;
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException;
 
     /**
      * Retrieves all permissions associated with the given user.
@@ -80,10 +82,11 @@ public interface PermissionService<PermissionSetType extends PermissionSet<Permi
      * @param targetUser
      *     The user associated with the permissions to be retrieved.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     The permissions associated with the given user.
@@ -92,7 +95,8 @@ public interface PermissionService<PermissionSetType extends PermissionSet<Permi
      *     If an error occurs while retrieving the requested permissions.
      */
     Set<PermissionType> retrievePermissions(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException;
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException;
 
     /**
      * Creates the given permissions within the database. If any permissions

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java
index 3cdf9d1..3018b29 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.permission;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
@@ -51,11 +52,12 @@ public class SharingProfilePermissionService extends ModeledObjectPermissionServ
 
     @Override
     public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Create permission set for requested user
         ObjectPermissionSet permissionSet = sharingProfilePermissionSetProvider.get();
-        permissionSet.init(user, targetUser, inherit);
+        permissionSet.init(user, targetUser, effectiveGroups);
 
         return permissionSet;
         

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
index c05f405..c676b72 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
@@ -19,6 +19,7 @@
 
 package org.apache.guacamole.auth.jdbc.permission;
 
+import java.util.Collection;
 import org.apache.guacamole.auth.jdbc.base.EntityModel;
 import org.apache.ibatis.annotations.Param;
 import org.apache.guacamole.net.auth.permission.SystemPermission;
@@ -38,10 +39,11 @@ public interface SystemPermissionMapper extends PermissionMapper<SystemPermissio
      * @param type
      *     The type of permission to return.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     The requested permission, or null if no such permission is granted
@@ -49,6 +51,6 @@ public interface SystemPermissionMapper extends PermissionMapper<SystemPermissio
      */
     SystemPermissionModel selectOne(@Param("entity") EntityModel entity,
             @Param("type") SystemPermission.Type type,
-            @Param("inherit") boolean inherit);
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
index 5909569..b534ad3 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.jdbc.permission;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import java.util.Collection;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
 import org.apache.guacamole.GuacamoleException;
@@ -75,11 +76,11 @@ public class SystemPermissionService
 
     @Override
     public SystemPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups) throws GuacamoleException {
 
         // Create permission set for requested user
         SystemPermissionSet permissionSet = systemPermissionSetProvider.get();
-        permissionSet.init(user, targetUser, inherit);
+        permissionSet.init(user, targetUser, effectiveGroups);
 
         return permissionSet;
         
@@ -136,10 +137,11 @@ public class SystemPermissionService
      * @param type
      *     The type of permission to retrieve.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      *
      * @return
      *     true if permission of the given type has been granted to the given
@@ -150,11 +152,11 @@ public class SystemPermissionService
      */
     public boolean hasPermission(ModeledAuthenticatedUser user,
             ModeledUser targetUser, SystemPermission.Type type,
-            boolean inherit) throws GuacamoleException {
+            Set<String> effectiveGroups) throws GuacamoleException {
 
         // Retrieve permissions only if allowed
         if (canReadPermissions(user, targetUser))
-            return getPermissionMapper().selectOne(targetUser.getModel(), type, inherit) != null;
+            return getPermissionMapper().selectOne(targetUser.getModel(), type, effectiveGroups) != null;
 
         // User cannot read this user's permissions
         throw new GuacamoleSecurityException("Permission denied.");

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
index bb5af11..dd88879 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
@@ -42,11 +42,7 @@ public class SystemPermissionSet extends RestrictedObject
      */
     private ModeledUser user;
 
-    /**
-     * Whether permissions inherited through user groups should be taken into
-     * account. If false, only permissions granted directly will be included.
-     */
-    private boolean inherit;
+    private Set<String> effectiveGroups;
 
     /**
      * Service for reading and manipulating system permissions.
@@ -73,27 +69,28 @@ public class SystemPermissionSet extends RestrictedObject
      * @param user
      *     The user to whom the permissions in this set are granted.
      *
-     * @param inherit
-     *     Whether permissions inherited through user groups should be taken
-     *     into account. If false, only permissions granted directly will be
-     *     included.
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
      */
     public void init(ModeledAuthenticatedUser currentUser, ModeledUser user,
-            boolean inherit) {
+            Set<String> effectiveGroups) {
         super.init(currentUser);
         this.user = user;
-        this.inherit = inherit;
+        this.effectiveGroups = effectiveGroups;
     }
 
     @Override
     public Set<SystemPermission> getPermissions() throws GuacamoleException {
-        return systemPermissionService.retrievePermissions(getCurrentUser(), user, inherit);
+        return systemPermissionService.retrievePermissions(getCurrentUser(), user, effectiveGroups);
     }
 
     @Override
     public boolean hasPermission(SystemPermission.Type permission)
             throws GuacamoleException {
-        return systemPermissionService.hasPermission(getCurrentUser(), user, permission, inherit);
+        return systemPermissionService.hasPermission(getCurrentUser(), user, permission, effectiveGroups);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
index 8e65862..fabbf72 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.permission;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.user.ModeledUser;
@@ -51,11 +52,12 @@ public class UserPermissionService extends ModeledObjectPermissionService {
 
     @Override
     public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
-            ModeledUser targetUser, boolean inherit) throws GuacamoleException {
+            ModeledUser targetUser, Set<String> effectiveGroups)
+            throws GuacamoleException {
 
         // Create permission set for requested user
         ObjectPermissionSet permissionSet = userPermissionSetProvider.get();
-        permissionSet.init(user, targetUser, inherit);
+        permissionSet.init(user, targetUser, effectiveGroups);
 
         return permissionSet;
         

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
index fe3a45b..5f7fc1b 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
@@ -628,7 +628,9 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
             identifiers.add(record.getConnection().getIdentifier());
 
         // Produce collection of readable connection identifiers
-        Collection<ConnectionModel> connections = connectionMapper.selectReadable(user.getUser().getModel(), identifiers);
+        Collection<ConnectionModel> connections =
+                connectionMapper.selectReadable(user.getUser().getModel(),
+                        identifiers, user.getEffectiveUserGroups());
 
         // Ensure set contains only identifiers of readable connections
         identifiers.clear();

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
index 0628d74..0bb199e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
@@ -351,37 +351,43 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
     @Override
     public SystemPermissionSet getSystemPermissions()
             throws GuacamoleException {
-        return systemPermissionService.getPermissionSet(getCurrentUser(), this, false);
+        return systemPermissionService.getPermissionSet(getCurrentUser(), this,
+                Collections.<String>emptySet());
     }
 
     @Override
     public ObjectPermissionSet getConnectionPermissions()
             throws GuacamoleException {
-        return connectionPermissionService.getPermissionSet(getCurrentUser(), this, false);
+        return connectionPermissionService.getPermissionSet(getCurrentUser(),
+                this, Collections.<String>emptySet());
     }
 
     @Override
     public ObjectPermissionSet getConnectionGroupPermissions()
             throws GuacamoleException {
-        return connectionGroupPermissionService.getPermissionSet(getCurrentUser(), this, false);
+        return connectionGroupPermissionService.getPermissionSet(
+                getCurrentUser(), this, Collections.<String>emptySet());
     }
 
     @Override
     public ObjectPermissionSet getSharingProfilePermissions()
             throws GuacamoleException {
-        return sharingProfilePermissionService.getPermissionSet(getCurrentUser(), this, false);
+        return sharingProfilePermissionService.getPermissionSet(
+                getCurrentUser(), this, Collections.<String>emptySet());
     }
 
     @Override
     public ObjectPermissionSet getActiveConnectionPermissions()
             throws GuacamoleException {
-        return activeConnectionPermissionService.getPermissionSet(getCurrentUser(), this, false);
+        return activeConnectionPermissionService.getPermissionSet(
+                getCurrentUser(), this, Collections.<String>emptySet());
     }
 
     @Override
     public ObjectPermissionSet getUserPermissions()
             throws GuacamoleException {
-        return userPermissionService.getPermissionSet(getCurrentUser(), this, false);
+        return userPermissionService.getPermissionSet(getCurrentUser(), this,
+                Collections.<String>emptySet());
     }
 
     @Override
@@ -864,50 +870,64 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
      *     apply to this user.
      */
     public Set<String> getEffectiveUserGroups() {
-
-        // FIXME: STUB
-        return /*retrieveEffectiveIdentifiers(this, */Collections.<String>emptySet()/*)*/;
-
+        return userService.retrieveEffectiveGroups(this,
+                Collections.<String>emptySet());
     }
 
     @Override
     public Permissions getEffectivePermissions() throws GuacamoleException {
+
+        final ModeledAuthenticatedUser authenticatedUser = getCurrentUser();
+        final Set<String> effectiveGroups;
+
+        // If this user is the currently-authenticated user, include any
+        // additional effective groups declared by the authentication system
+        if (authenticatedUser.getIdentifier().equals(getIdentifier()))
+            effectiveGroups = userService.retrieveEffectiveGroups(this,
+                    authenticatedUser.getEffectiveUserGroups());
+
+        // Otherwise, just include effective groups from the database
+        else
+            effectiveGroups = getEffectiveUserGroups();
+
+        // Return a permissions object which describes all effective
+        // permissions, including any permissions inherited via user groups
         return new Permissions() {
 
             @Override
             public ObjectPermissionSet getActiveConnectionPermissions()
                     throws GuacamoleException {
-                return activeConnectionPermissionService.getPermissionSet(getCurrentUser(), ModeledUser.this, true);
+                return activeConnectionPermissionService.getPermissionSet(authenticatedUser, ModeledUser.this, effectiveGroups);
             }
 
             @Override
             public ObjectPermissionSet getConnectionGroupPermissions()
                     throws GuacamoleException {
-                return connectionGroupPermissionService.getPermissionSet(getCurrentUser(), ModeledUser.this, true);
+                return connectionGroupPermissionService.getPermissionSet(authenticatedUser, ModeledUser.this, effectiveGroups);
             }
 
             @Override
             public ObjectPermissionSet getConnectionPermissions()
                     throws GuacamoleException {
-                return connectionPermissionService.getPermissionSet(getCurrentUser(), ModeledUser.this, true);
+                return connectionPermissionService.getPermissionSet(authenticatedUser, ModeledUser.this, effectiveGroups);
             }
 
             @Override
             public ObjectPermissionSet getSharingProfilePermissions()
                     throws GuacamoleException {
-                return sharingProfilePermissionService.getPermissionSet(getCurrentUser(), ModeledUser.this, true);
+                return sharingProfilePermissionService.getPermissionSet(authenticatedUser, ModeledUser.this, effectiveGroups);
             }
 
             @Override
             public SystemPermissionSet getSystemPermissions()
                     throws GuacamoleException {
-                return systemPermissionService.getPermissionSet(getCurrentUser(), ModeledUser.this, true);
+                return systemPermissionService.getPermissionSet(authenticatedUser, ModeledUser.this, effectiveGroups);
             }
 
             @Override
             public ObjectPermissionSet getUserPermissions()
                     throws GuacamoleException {
-                return userPermissionService.getPermissionSet(getCurrentUser(), ModeledUser.this, true);
+                return userPermissionService.getPermissionSet(authenticatedUser, ModeledUser.this, effectiveGroups);
             }
 
             @Override

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserMapper.java
index 251445b..6b51105 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserMapper.java
@@ -19,6 +19,8 @@
 
 package org.apache.guacamole.auth.jdbc.user;
 
+import java.util.Collection;
+import java.util.Set;
 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -38,5 +40,25 @@ public interface UserMapper extends ModeledDirectoryObjectMapper<UserModel> {
      *     The user having the given username, or null if no such user exists.
      */
     UserModel selectOne(@Param("username") String username);
-    
+
+    /**
+     * Returns the set of all group identifiers of which the given user is a
+     * member, taking into account the given collection of known group
+     * memberships which are not necessarily defined within the database.
+     *
+     * @param user
+     *     The user whose effective groups should be returned.
+     *
+     * @param effectiveGroups
+     *     The identifiers of any known effective groups that should be taken
+     *     into account, such as those defined externally to the database.
+     *
+     * @return
+     *     The set of identifiers of all groups that the given user is a
+     *     member of, including those where membership is inherited through
+     *     membership in other groups.
+     */
+    Set<String> selectEffectiveGroupIdentifiers(@Param("user") UserModel user,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordMapper.java
index b2177bf..92501ab 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordMapper.java
@@ -113,12 +113,19 @@ public interface UserRecordMapper {
      * @param limit
      *     The maximum number of records that should be returned.
      *
+     * @param effectiveGroups
+     *     The identifiers of all groups that should be taken into account
+     *     when determining the permissions effectively granted to the user. If
+     *     no groups are given, only permissions directly granted to the user
+     *     will be used.
+     *
      * @return
      *     The results of the search performed with the given parameters.
      */
     List<ActivityRecordModel> searchReadable(@Param("user") UserModel user,
             @Param("terms") Collection<ActivityRecordSearchTerm> terms,
             @Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
-            @Param("limit") int limit);
+            @Param("limit") int limit,
+            @Param("effectiveGroups") Collection<String> effectiveGroups);
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
index 2c70e22..6d89125 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 import javax.servlet.http.HttpServletRequest;
 import org.apache.guacamole.net.auth.Credentials;
 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
@@ -591,11 +592,37 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
         // Otherwise only return explicitly readable history records
         else
             searchResults = userRecordMapper.searchReadable(user.getUser().getModel(),
-                    requiredContents, sortPredicates, limit);
+                    requiredContents, sortPredicates, limit, user.getEffectiveUserGroups());
 
         return getObjectInstances(searchResults);
 
     }
 
+    /**
+     * Returns the set of all group identifiers of which the given user is a
+     * member, taking into account the given collection of known group
+     * memberships which are not necessarily defined within the database.
+     * 
+     * Note that group visibility with respect to the queried user is NOT taken
+     * into account. If the user is a member of a group, the identifier of that
+     * group will be included in the returned set even if the current user lacks
+     * "READ" permission for that group.
+     *
+     * @param user
+     *     The user whose effective groups should be returned.
+     *
+     * @param effectiveGroups
+     *     The identifiers of any known effective groups that should be taken
+     *     into account, such as those defined externally to the database.
+     *
+     * @return
+     *     The set of identifiers of all groups that the given user is a
+     *     member of, including those where membership is inherited through
+     *     membership in other groups.
+     */
+    public Set<String> retrieveEffectiveGroups(ModeledUser user,
+            Collection<String> effectiveGroups) {
+        return userMapper.selectEffectiveGroupIdentifiers(user.getModel(), effectiveGroups);
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/base/EntityMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/base/EntityMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/base/EntityMapper.xml
index dd262d1..01830d7 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/base/EntityMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/base/EntityMapper.xml
@@ -23,21 +23,40 @@
 
 <mapper namespace="org.apache.guacamole.auth.jdbc.base.EntityMapper" >
 
-    <!-- Retrieves the ID of the given entity. If inheritance is enabled, the
-    IDs of the entities for all applicable user groups are retrieved, as well. -->
-    <sql id="relatedEntities">
-        <if test="!${inheritFlag}">${entityID}</if>
-        <if test="${inheritFlag}">
-            WITH RECURSIVE related_entity(entity_id) AS (
-                    VALUES (${entityID})
-                UNION
-                    SELECT guacamole_user_group.entity_id
-                    FROM related_entity
-                    JOIN guacamole_user_group_member ON related_entity.entity_id = guacamole_user_group_member.member_entity_id
-                    JOIN guacamole_user_group ON guacamole_user_group.user_group_id = guacamole_user_group_member.user_group_id
-            )
-            SELECT entity_id FROM related_entity
-        </if>
+    <!--
+      * SQL fragment which tests whether the value of the given column matches
+      * the given entity ID. If group identifiers are provided, the IDs of the
+      * entities for all groups having those identifiers are tested, as well.
+      *
+      * @param column
+      *     The name of the column to test. This column MUST contain an entity
+      *     ID (a foreign key into the guacamole_entity table).
+      *
+      * @param entityID
+      *     The ID of the specific entity to test the column against.
+      *
+      * @param groups
+      *     A collection of group identifiers to additionally test the column
+      *     against. Though this functionality is optional, a collection must
+      *     always be given, even if that collection is empty.
+      -->
+    <sql id="isRelatedEntity">
+        (
+            ${column} = ${entityID}
+            <if test="!${groups}.isEmpty()">
+                OR ${column} IN (
+                    SELECT entity_id
+                    FROM guacamole_entity
+                    WHERE
+                        type = 'USER_GROUP'::guacamole_entity_type
+                        AND name IN
+                            <foreach collection="${groups}" item="effectiveGroup"
+                                     open="(" separator="," close=")">
+                                #{effectiveGroup,jdbcType=VARCHAR}
+                            </foreach>
+                )
+            </if>
+        )
     </sql>
 
     <!-- Insert single entity -->

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
index 94855e1..859cec5 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -68,12 +68,11 @@
         SELECT connection_id
         FROM guacamole_connection_permission
         WHERE
-            entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND permission = 'READ'
     </select>
 
@@ -94,12 +93,11 @@
         WHERE
             <if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}::integer</if>
             <if test="parentIdentifier == null">parent_id IS NULL</if>
-            AND entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            AND <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND permission = 'READ'
     </select>
 
@@ -175,12 +173,11 @@
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=INTEGER}::integer
             </foreach>
-            AND guacamole_connection_permission.entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            AND <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="guacamole_connection_permission.entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND permission = 'READ'
         GROUP BY guacamole_connection.connection_id;
 
@@ -192,12 +189,11 @@
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=INTEGER}::integer
             </foreach>
-            AND entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            AND <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND permission = 'READ';
 
         SELECT
@@ -211,12 +207,11 @@
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=INTEGER}::integer
             </foreach>
-            AND entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            AND <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND permission = 'READ';
 
     </select>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/14d10fb4/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
index b04c9ca..e8e8876 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
@@ -166,23 +166,21 @@
         <!-- Restrict to readable connections -->
         JOIN guacamole_connection_permission ON
                 guacamole_connection_history.connection_id = guacamole_connection_permission.connection_id
-            AND guacamole_connection_permission.entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            AND <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="guacamole_connection_permission.entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND guacamole_connection_permission.permission = 'READ'
 
         <!-- Restrict to readable users -->
         JOIN guacamole_user_permission ON
                 guacamole_connection_history.user_id = guacamole_user_permission.affected_user_id
-            AND guacamole_user_permission.entity_id IN (
-                <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.relatedEntities">
-                    <property name="inheritFlag" value="true"/>
-                    <property name="entityID"    value="#{user.entityID,jdbcType=INTEGER}"/>
-                </include>
-            )
+            AND <include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
+                <property name="column"   value="guacamole_user_permission.entity_id"/>
+                <property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
+                <property name="groups"   value="effectiveGroups"/>
+            </include>
             AND guacamole_user_permission.permission = 'READ'
 
         <!-- Search terms -->