mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-1796: Batch updates to permissions so large permission changes can succeed.
(cherry picked from commit f2fd91ade5c75b97bbbccdef5d4ed62765ad8193)
This commit is contained in:
@@ -132,11 +132,16 @@ public abstract class ModeledObjectPermissionService
|
||||
|
||||
// Create permissions only if user has permission to do so
|
||||
if (canAlterPermissions(user, targetEntity, permissions)) {
|
||||
Collection<ObjectPermissionModel> models = getModelInstances(targetEntity, permissions);
|
||||
getPermissionMapper().insert(models);
|
||||
|
||||
batchPermissionUpdates(permissions, permissionSubset -> {
|
||||
Collection<ObjectPermissionModel> models = getModelInstances(
|
||||
targetEntity, permissionSubset);
|
||||
getPermissionMapper().insert(models);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// User lacks permission to create object permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
@@ -150,8 +155,13 @@ public abstract class ModeledObjectPermissionService
|
||||
|
||||
// Delete permissions only if user has permission to do so
|
||||
if (canAlterPermissions(user, targetEntity, permissions)) {
|
||||
Collection<ObjectPermissionModel> models = getModelInstances(targetEntity, permissions);
|
||||
getPermissionMapper().delete(models);
|
||||
|
||||
batchPermissionUpdates(permissions, permissionSubset -> {
|
||||
Collection<ObjectPermissionModel> models = getModelInstances(
|
||||
targetEntity, permissionSubset);
|
||||
getPermissionMapper().delete(models);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -23,14 +23,20 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||
import org.apache.guacamole.auth.jdbc.base.EntityModel;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
|
||||
import org.apache.guacamole.net.auth.permission.Permission;
|
||||
import org.apache.guacamole.net.auth.permission.PermissionSet;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting permissions within a backend database model, and for obtaining the
|
||||
@@ -51,6 +57,12 @@ public abstract class ModeledPermissionService<PermissionSetType extends Permiss
|
||||
PermissionType extends Permission, ModelType>
|
||||
extends AbstractPermissionService<PermissionSetType, PermissionType> {
|
||||
|
||||
/**
|
||||
* The environment of the Guacamole server.
|
||||
*/
|
||||
@Inject
|
||||
private JDBCEnvironment environment;
|
||||
|
||||
/**
|
||||
* Returns an instance of a mapper for the type of permission used by this
|
||||
* service.
|
||||
@@ -141,6 +153,38 @@ public abstract class ModeledPermissionService<PermissionSetType extends Permiss
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the provided consumer function on subsets of the original collection
|
||||
* of objects, with each subset being no larger than the maximum batch size
|
||||
* configured for the JDBC environment. Any permission update that involves
|
||||
* passing potentially-large lists of models to a mapper should use this
|
||||
* method to perform the update to ensure that the maximum number of
|
||||
* parameters for an individual query is not exceeded.
|
||||
*
|
||||
* @param <T>
|
||||
* The type of object stored in the provided objects list, and consumed
|
||||
* by the provided consumer.
|
||||
*
|
||||
* @param objects
|
||||
* A collection of objects to be partitioned.
|
||||
*
|
||||
* @param consumer
|
||||
* A function that will consume subsets of the objects from the provided
|
||||
* collection of objects, performing any update as needed.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the batch size cannot be determined for the JDBC environment.
|
||||
*/
|
||||
protected <T> void batchPermissionUpdates(
|
||||
Collection<T> objects, Consumer<Collection<T>> consumer)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Split the original collection into views, each no larger than the
|
||||
// configured batch size, and call the collector function with each
|
||||
Iterables.partition(objects, environment.getBatchSize())
|
||||
.forEach(batch -> consumer.accept(batch));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionType> retrievePermissions(ModeledAuthenticatedUser user,
|
||||
ModeledPermissions<? extends EntityModel> targetEntity,
|
||||
|
@@ -97,8 +97,13 @@ public class SystemPermissionService
|
||||
// Only privileged users (such as system administrators) can create
|
||||
// system permissions
|
||||
if (user.isPrivileged()) {
|
||||
Collection<SystemPermissionModel> models = getModelInstances(targetEntity, permissions);
|
||||
systemPermissionMapper.insert(models);
|
||||
|
||||
batchPermissionUpdates(permissions, permissionSubset -> {
|
||||
Collection<SystemPermissionModel> models = getModelInstances(
|
||||
targetEntity, permissionSubset);
|
||||
systemPermissionMapper.insert(models);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -119,9 +124,13 @@ public class SystemPermissionService
|
||||
// Do not allow users to remove their own admin powers
|
||||
if (user.getUser().getIdentifier().equals(targetEntity.getIdentifier()))
|
||||
throw new GuacamoleUnsupportedException("Removing your own administrative permissions is not allowed.");
|
||||
|
||||
Collection<SystemPermissionModel> models = getModelInstances(targetEntity, permissions);
|
||||
systemPermissionMapper.delete(models);
|
||||
|
||||
batchPermissionUpdates(permissions, permissionSubset -> {
|
||||
Collection<SystemPermissionModel> models = getModelInstances(
|
||||
targetEntity, permissionSubset);
|
||||
systemPermissionMapper.delete(models);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user