GUACAMOLE-220: Manually recurse through the group membership graph if the database engine does not support recursive queries.

This commit is contained in:
Michael Jumper
2018-09-08 01:13:36 -07:00
parent 48948fc245
commit 78d5e3b9d7
6 changed files with 58 additions and 3 deletions

View File

@@ -137,4 +137,15 @@ public abstract class JDBCEnvironment extends LocalEnvironment {
*/
public abstract PasswordPolicy getPasswordPolicy();
/**
* Returns whether the database supports recursive queries. Many database
* engines support recursive queries through CTEs. If recursive queries are
* not supported, queries that are intended to be recursive may need to be
* invoked multiple times to retrieve the same data.
*
* @return
* true if the database supports recursive queries, false otherwise.
*/
public abstract boolean isRecursiveQuerySupported();
}

View File

@@ -47,6 +47,12 @@ public interface EntityMapper {
* member, taking into account the given collection of known group
* memberships which are not necessarily defined within the database.
*
* NOTE: This query is expected to handle recursion through the membership
* graph on its own. If the database engine does not support recursive
* queries (isRecursiveQuerySupported() of JDBCEnvironment returns false),
* then this query will only return one level of depth past the effective
* groups given and will need to be invoked multiple times.
*
* @param entity
* The entity whose effective groups should be returned.
*

View File

@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.jdbc.base;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
/**
* Service which provides convenience methods for creating, retrieving, and
@@ -29,6 +30,12 @@ import java.util.Set;
*/
public class EntityService {
/**
* The Guacamole server environment.
*/
@Inject
private JDBCEnvironment environment;
/**
* Mapper for Entity model objects.
*/
@@ -59,7 +66,23 @@ public class EntityService {
*/
public Set<String> retrieveEffectiveGroups(ModeledPermissions<? extends EntityModel> entity,
Collection<String> effectiveGroups) {
return entityMapper.selectEffectiveGroupIdentifiers(entity.getModel(), effectiveGroups);
// Retrieve the effective user groups of the given entity, recursively if possible
Set<String> identifiers = entityMapper.selectEffectiveGroupIdentifiers(entity.getModel(), effectiveGroups);
// If the set of user groups retrieved was not produced recursively,
// manually repeat the query to expand the set until all effective
// groups have been found
if (!environment.isRecursiveQuerySupported() && !identifiers.isEmpty()) {
Set<String> previousIdentifiers;
do {
previousIdentifiers = identifiers;
identifiers = entityMapper.selectEffectiveGroupIdentifiers(entity.getModel(), previousIdentifiers);
} while (identifiers.size() > previousIdentifiers.size());
}
return identifiers;
}
}