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 820873a4f..fd70f6ac1 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 @@ -132,11 +132,16 @@ public abstract class ModeledObjectPermissionService // Create permissions only if user has permission to do so if (canAlterPermissions(user, targetEntity, permissions)) { - Collection models = getModelInstances(targetEntity, permissions); - getPermissionMapper().insert(models); + + batchPermissionUpdates(permissions, permissionSubset -> { + Collection 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 models = getModelInstances(targetEntity, permissions); - getPermissionMapper().delete(models); + + batchPermissionUpdates(permissions, permissionSubset -> { + Collection models = getModelInstances( + targetEntity, permissionSubset); + getPermissionMapper().delete(models); + }); + return; } 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 a102f3434..6f8c09f73 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 @@ -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 extends AbstractPermissionService { + /** + * 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 + * 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 void batchPermissionUpdates( + Collection objects, Consumer> 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 retrievePermissions(ModeledAuthenticatedUser user, ModeledPermissions targetEntity, 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 4b8269f6b..1a0f1523c 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 @@ -97,8 +97,13 @@ public class SystemPermissionService // Only privileged users (such as system administrators) can create // system permissions if (user.isPrivileged()) { - Collection models = getModelInstances(targetEntity, permissions); - systemPermissionMapper.insert(models); + + batchPermissionUpdates(permissions, permissionSubset -> { + Collection 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 models = getModelInstances(targetEntity, permissions); - systemPermissionMapper.delete(models); + + batchPermissionUpdates(permissions, permissionSubset -> { + Collection models = getModelInstances( + targetEntity, permissionSubset); + systemPermissionMapper.delete(models); + }); + return; }