mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-30 00:23:21 +00:00 
			
		
		
		
	GUAC-1132: Split non-database permission service functions into interfaces.
This commit is contained in:
		| @@ -35,7 +35,7 @@ import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | |||||||
|  * |  * | ||||||
|  * @author Michael Jumper |  * @author Michael Jumper | ||||||
|  */ |  */ | ||||||
| public class ConnectionGroupPermissionService extends ObjectPermissionService { | public class ConnectionGroupPermissionService extends ModeledObjectPermissionService { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Mapper for connection group permissions. |      * Mapper for connection group permissions. | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | |||||||
|  * |  * | ||||||
|  * @author Michael Jumper |  * @author Michael Jumper | ||||||
|  */ |  */ | ||||||
| public class ConnectionPermissionService extends ObjectPermissionService { | public class ConnectionPermissionService extends ModeledObjectPermissionService { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Mapper for connection permissions. |      * Mapper for connection permissions. | ||||||
|   | |||||||
| @@ -0,0 +1,210 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2015 Glyptodon LLC | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package org.glyptodon.guacamole.auth.jdbc.permission; | ||||||
|  |  | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; | ||||||
|  | import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | ||||||
|  | import org.glyptodon.guacamole.GuacamoleException; | ||||||
|  | import org.glyptodon.guacamole.GuacamoleSecurityException; | ||||||
|  | import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | ||||||
|  | import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Service which provides convenience methods for creating, retrieving, and | ||||||
|  |  * deleting object permissions within a backend database model. This service | ||||||
|  |  * will automatically enforce the permissions of the current user. | ||||||
|  |  * | ||||||
|  |  * @author Michael Jumper | ||||||
|  |  */ | ||||||
|  | public abstract class ModeledObjectPermissionService | ||||||
|  |     extends ModeledPermissionService<ObjectPermissionSet, ObjectPermission, ObjectPermissionModel> | ||||||
|  |     implements ObjectPermissionService { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     protected abstract ObjectPermissionMapper getPermissionMapper(); | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     protected ObjectPermission getPermissionInstance(ObjectPermissionModel model) { | ||||||
|  |         return new ObjectPermission(model.getType(), model.getObjectIdentifier()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     protected ObjectPermissionModel getModelInstance(ModeledUser targetUser, | ||||||
|  |             ObjectPermission permission) { | ||||||
|  |  | ||||||
|  |         ObjectPermissionModel model = new ObjectPermissionModel(); | ||||||
|  |  | ||||||
|  |         // Populate model object with data from user and permission | ||||||
|  |         model.setUserID(targetUser.getModel().getObjectID()); | ||||||
|  |         model.setUsername(targetUser.getModel().getIdentifier()); | ||||||
|  |         model.setType(permission.getType()); | ||||||
|  |         model.setObjectIdentifier(permission.getObjectIdentifier()); | ||||||
|  |  | ||||||
|  |         return model; | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Determines whether the current user has permission to update the given | ||||||
|  |      * target user, adding or removing the given permissions. Such permission | ||||||
|  |      * depends on whether the current user is a system administrator, whether | ||||||
|  |      * they have explicit UPDATE permission on the target user, and whether | ||||||
|  |      * they have explicit ADMINISTER permission on all affected objects. | ||||||
|  |      * | ||||||
|  |      * @param user | ||||||
|  |      *     The user who is changing permissions. | ||||||
|  |      * | ||||||
|  |      * @param targetUser | ||||||
|  |      *     The user whose permissions are being changed. | ||||||
|  |      * | ||||||
|  |      * @param permissions | ||||||
|  |      *     The permissions that are being added or removed from the target | ||||||
|  |      *     user. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     true if the user has permission to change the target users | ||||||
|  |      *     permissions as specified, false otherwise. | ||||||
|  |      * | ||||||
|  |      * @throws GuacamoleException | ||||||
|  |      *     If an error occurs while checking permission status, or if | ||||||
|  |      *     permission is denied to read the current user's permissions. | ||||||
|  |      */ | ||||||
|  |     protected boolean canAlterPermissions(AuthenticatedUser user, ModeledUser targetUser, | ||||||
|  |             Collection<ObjectPermission> permissions) | ||||||
|  |             throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // A system adminstrator can do anything | ||||||
|  |         if (user.getUser().isAdministrator()) | ||||||
|  |             return true; | ||||||
|  |          | ||||||
|  |         // Verify user has update permission on the target user | ||||||
|  |         ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions(); | ||||||
|  |         if (!userPermissionSet.hasPermission(ObjectPermission.Type.UPDATE, targetUser.getIdentifier())) | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |         // Produce collection of affected identifiers | ||||||
|  |         Collection<String> affectedIdentifiers = new HashSet(permissions.size()); | ||||||
|  |         for (ObjectPermission permission : permissions) | ||||||
|  |             affectedIdentifiers.add(permission.getObjectIdentifier()); | ||||||
|  |  | ||||||
|  |         // Determine subset of affected identifiers that we have admin access to | ||||||
|  |         ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser()); | ||||||
|  |         Collection<String> allowedSubset = affectedPermissionSet.getAccessibleObjects( | ||||||
|  |             Collections.singleton(ObjectPermission.Type.ADMINISTER), | ||||||
|  |             affectedIdentifiers | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         // The permissions can be altered if and only if the set of objects we | ||||||
|  |         // are allowed to administer is equal to the set of objects we will be | ||||||
|  |         // affecting. | ||||||
|  |  | ||||||
|  |         return affectedIdentifiers.size() == allowedSubset.size(); | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Override | ||||||
|  |     public void createPermissions(AuthenticatedUser user, ModeledUser targetUser, | ||||||
|  |             Collection<ObjectPermission> permissions) | ||||||
|  |             throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // Create permissions only if user has permission to do so | ||||||
|  |         if (canAlterPermissions(user, targetUser, permissions)) { | ||||||
|  |             Collection<ObjectPermissionModel> models = getModelInstances(targetUser, permissions); | ||||||
|  |             getPermissionMapper().insert(models); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // User lacks permission to create object permissions | ||||||
|  |         throw new GuacamoleSecurityException("Permission denied."); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void deletePermissions(AuthenticatedUser user, ModeledUser targetUser, | ||||||
|  |             Collection<ObjectPermission> permissions) | ||||||
|  |             throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // Delete permissions only if user has permission to do so | ||||||
|  |         if (canAlterPermissions(user, targetUser, permissions)) { | ||||||
|  |             Collection<ObjectPermissionModel> models = getModelInstances(targetUser, permissions); | ||||||
|  |             getPermissionMapper().delete(models); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // User lacks permission to delete object permissions | ||||||
|  |         throw new GuacamoleSecurityException("Permission denied."); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public ObjectPermission retrievePermission(AuthenticatedUser user, | ||||||
|  |             ModeledUser targetUser, ObjectPermission.Type type, | ||||||
|  |             String identifier) throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // Retrieve permissions only if allowed | ||||||
|  |         if (canReadPermissions(user, targetUser)) { | ||||||
|  |  | ||||||
|  |             // Read permission from database, return null if not found | ||||||
|  |             ObjectPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type, identifier); | ||||||
|  |             if (model == null) | ||||||
|  |                 return null; | ||||||
|  |  | ||||||
|  |             return getPermissionInstance(model); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // User cannot read this user's permissions | ||||||
|  |         throw new GuacamoleSecurityException("Permission denied."); | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Collection<String> retrieveAccessibleIdentifiers(AuthenticatedUser user, | ||||||
|  |             ModeledUser targetUser, Collection<ObjectPermission.Type> permissions, | ||||||
|  |             Collection<String> identifiers) throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // Nothing is always accessible | ||||||
|  |         if (identifiers.isEmpty()) | ||||||
|  |             return identifiers; | ||||||
|  |          | ||||||
|  |         // Retrieve permissions only if allowed | ||||||
|  |         if (canReadPermissions(user, targetUser)) { | ||||||
|  |  | ||||||
|  |             // If user is an admin, everything is accessible | ||||||
|  |             if (user.getUser().isAdministrator()) | ||||||
|  |                 return identifiers; | ||||||
|  |  | ||||||
|  |             // Otherwise, return explicitly-retrievable identifiers | ||||||
|  |             return getPermissionMapper().selectAccessibleIdentifiers(targetUser.getModel(), permissions, identifiers); | ||||||
|  |              | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // User cannot read this user's permissions | ||||||
|  |         throw new GuacamoleSecurityException("Permission denied."); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,196 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2015 Glyptodon LLC | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package org.glyptodon.guacamole.auth.jdbc.permission; | ||||||
|  |  | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Set; | ||||||
|  | import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; | ||||||
|  | import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | ||||||
|  | import org.glyptodon.guacamole.GuacamoleException; | ||||||
|  | import org.glyptodon.guacamole.GuacamoleSecurityException; | ||||||
|  | import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | ||||||
|  | import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; | ||||||
|  | import org.glyptodon.guacamole.net.auth.permission.Permission; | ||||||
|  | import org.glyptodon.guacamole.net.auth.permission.PermissionSet; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Service which provides convenience methods for creating, retrieving, and | ||||||
|  |  * deleting permissions within a backend database model, and for obtaining the | ||||||
|  |  * permission sets that contain these permissions. This service will | ||||||
|  |  * automatically enforce the permissions of the current user. | ||||||
|  |  * | ||||||
|  |  * @author Michael Jumper | ||||||
|  |  * @param <PermissionSetType> | ||||||
|  |  *     The type of permission sets this service provides access to. | ||||||
|  |  * | ||||||
|  |  * @param <PermissionType> | ||||||
|  |  *     The type of permission this service provides access to. | ||||||
|  |  * | ||||||
|  |  * @param <ModelType> | ||||||
|  |  *     The underlying model object used to represent PermissionType in the | ||||||
|  |  *     database. | ||||||
|  |  */ | ||||||
|  | public abstract class ModeledPermissionService<PermissionSetType extends PermissionSet<PermissionType>, | ||||||
|  |         PermissionType extends Permission, ModelType> | ||||||
|  |     implements PermissionService<PermissionSetType, PermissionType> { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns an instance of a mapper for the type of permission used by this | ||||||
|  |      * service. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     A mapper which provides access to the model objects associated with | ||||||
|  |      *     the permissions used by this service. | ||||||
|  |      */ | ||||||
|  |     protected abstract PermissionMapper<ModelType> getPermissionMapper(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns an instance of a permission which is based on the given model | ||||||
|  |      * object. | ||||||
|  |      * | ||||||
|  |      * @param model | ||||||
|  |      *     The model object to use to produce the returned permission. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     A permission which is based on the given model object. | ||||||
|  |      */ | ||||||
|  |     protected abstract PermissionType getPermissionInstance(ModelType model); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns a collection of permissions which are based on the models in | ||||||
|  |      * the given collection. | ||||||
|  |      * | ||||||
|  |      * @param models | ||||||
|  |      *     The model objects to use to produce the permissions within the | ||||||
|  |      *     returned set. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     A set of permissions which are based on the models in the given | ||||||
|  |      *     collection. | ||||||
|  |      */ | ||||||
|  |     protected Set<PermissionType> getPermissionInstances(Collection<ModelType> models) { | ||||||
|  |  | ||||||
|  |         // Create new collection of permissions by manually converting each model | ||||||
|  |         Set<PermissionType> permissions = new HashSet<PermissionType>(models.size()); | ||||||
|  |         for (ModelType model : models) | ||||||
|  |             permissions.add(getPermissionInstance(model)); | ||||||
|  |  | ||||||
|  |         return permissions; | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns an instance of a model object which is based on the given | ||||||
|  |      * permission and target user. | ||||||
|  |      * | ||||||
|  |      * @param targetUser | ||||||
|  |      *     The user to whom this permission is granted. | ||||||
|  |      * | ||||||
|  |      * @param permission | ||||||
|  |      *     The permission to use to produce the returned model object. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     A model object which is based on the given permission and target | ||||||
|  |      *     user. | ||||||
|  |      */ | ||||||
|  |     protected abstract ModelType getModelInstance(ModeledUser targetUser, | ||||||
|  |             PermissionType permission); | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * Returns a collection of model objects which are based on the given | ||||||
|  |      * permissions and target user. | ||||||
|  |      * | ||||||
|  |      * @param targetUser | ||||||
|  |      *     The user to whom this permission is granted. | ||||||
|  |      * | ||||||
|  |      * @param permissions | ||||||
|  |      *     The permissions to use to produce the returned model objects. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     A collection of model objects which are based on the given | ||||||
|  |      *     permissions and target user. | ||||||
|  |      */ | ||||||
|  |     protected Collection<ModelType> getModelInstances(ModeledUser targetUser, | ||||||
|  |             Collection<PermissionType> permissions) { | ||||||
|  |  | ||||||
|  |         // Create new collection of models by manually converting each permission  | ||||||
|  |         Collection<ModelType> models = new ArrayList<ModelType>(permissions.size()); | ||||||
|  |         for (PermissionType permission : permissions) | ||||||
|  |             models.add(getModelInstance(targetUser, permission)); | ||||||
|  |  | ||||||
|  |         return models; | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Determines whether the given user can read the permissions currently | ||||||
|  |      * granted to the given target user. If the reading user and the target | ||||||
|  |      * user are not the same, then explicit READ or SYSTEM_ADMINISTER access is | ||||||
|  |      * required. | ||||||
|  |      * | ||||||
|  |      * @param user | ||||||
|  |      *     The user attempting to read permissions. | ||||||
|  |      * | ||||||
|  |      * @param targetUser | ||||||
|  |      *     The user whose permissions are being read. | ||||||
|  |      * | ||||||
|  |      * @return | ||||||
|  |      *     true if permission is granted, false otherwise. | ||||||
|  |      * | ||||||
|  |      * @throws GuacamoleException  | ||||||
|  |      *     If an error occurs while checking permission status, or if | ||||||
|  |      *     permission is denied to read the current user's permissions. | ||||||
|  |      */ | ||||||
|  |     protected boolean canReadPermissions(AuthenticatedUser user, | ||||||
|  |             ModeledUser targetUser) throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // A user can always read their own permissions | ||||||
|  |         if (user.getUser().getIdentifier().equals(targetUser.getIdentifier())) | ||||||
|  |             return true; | ||||||
|  |          | ||||||
|  |         // A system adminstrator can do anything | ||||||
|  |         if (user.getUser().isAdministrator()) | ||||||
|  |             return true; | ||||||
|  |  | ||||||
|  |         // Can read permissions on target user if explicit READ is granted | ||||||
|  |         ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions(); | ||||||
|  |         return userPermissionSet.hasPermission(ObjectPermission.Type.READ, targetUser.getIdentifier()); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Set<PermissionType> retrievePermissions(AuthenticatedUser user, | ||||||
|  |             ModeledUser targetUser) throws GuacamoleException { | ||||||
|  |  | ||||||
|  |         // Retrieve permissions only if allowed | ||||||
|  |         if (canReadPermissions(user, targetUser)) | ||||||
|  |             return getPermissionInstances(getPermissionMapper().select(targetUser.getModel())); | ||||||
|  |  | ||||||
|  |         // User cannot read this user's permissions | ||||||
|  |         throw new GuacamoleSecurityException("Permission denied."); | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -23,12 +23,9 @@ | |||||||
| package org.glyptodon.guacamole.auth.jdbc.permission; | package org.glyptodon.guacamole.auth.jdbc.permission; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.HashSet; |  | ||||||
| import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; | import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; | ||||||
| import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | ||||||
| import org.glyptodon.guacamole.GuacamoleException; | import org.glyptodon.guacamole.GuacamoleException; | ||||||
| import org.glyptodon.guacamole.GuacamoleSecurityException; |  | ||||||
| import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | ||||||
| import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; | import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; | ||||||
|  |  | ||||||
| @@ -39,124 +36,8 @@ import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; | |||||||
|  * |  * | ||||||
|  * @author Michael Jumper |  * @author Michael Jumper | ||||||
|  */ |  */ | ||||||
| public abstract class ObjectPermissionService | public interface ObjectPermissionService | ||||||
|     extends PermissionService<ObjectPermissionSet, ObjectPermission, ObjectPermissionModel> { |     extends PermissionService<ObjectPermissionSet, ObjectPermission> { | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected abstract ObjectPermissionMapper getPermissionMapper(); |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected ObjectPermission getPermissionInstance(ObjectPermissionModel model) { |  | ||||||
|         return new ObjectPermission(model.getType(), model.getObjectIdentifier()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected ObjectPermissionModel getModelInstance(ModeledUser targetUser, |  | ||||||
|             ObjectPermission permission) { |  | ||||||
|  |  | ||||||
|         ObjectPermissionModel model = new ObjectPermissionModel(); |  | ||||||
|  |  | ||||||
|         // Populate model object with data from user and permission |  | ||||||
|         model.setUserID(targetUser.getModel().getObjectID()); |  | ||||||
|         model.setUsername(targetUser.getModel().getIdentifier()); |  | ||||||
|         model.setType(permission.getType()); |  | ||||||
|         model.setObjectIdentifier(permission.getObjectIdentifier()); |  | ||||||
|  |  | ||||||
|         return model; |  | ||||||
|          |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Determines whether the current user has permission to update the given |  | ||||||
|      * target user, adding or removing the given permissions. Such permission |  | ||||||
|      * depends on whether the current user is a system administrator, whether |  | ||||||
|      * they have explicit UPDATE permission on the target user, and whether |  | ||||||
|      * they have explicit ADMINISTER permission on all affected objects. |  | ||||||
|      * |  | ||||||
|      * @param user |  | ||||||
|      *     The user who is changing permissions. |  | ||||||
|      * |  | ||||||
|      * @param targetUser |  | ||||||
|      *     The user whose permissions are being changed. |  | ||||||
|      * |  | ||||||
|      * @param permissions |  | ||||||
|      *     The permissions that are being added or removed from the target |  | ||||||
|      *     user. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     true if the user has permission to change the target users |  | ||||||
|      *     permissions as specified, false otherwise. |  | ||||||
|      * |  | ||||||
|      * @throws GuacamoleException |  | ||||||
|      *     If an error occurs while checking permission status, or if |  | ||||||
|      *     permission is denied to read the current user's permissions. |  | ||||||
|      */ |  | ||||||
|     protected boolean canAlterPermissions(AuthenticatedUser user, ModeledUser targetUser, |  | ||||||
|             Collection<ObjectPermission> permissions) |  | ||||||
|             throws GuacamoleException { |  | ||||||
|  |  | ||||||
|         // A system adminstrator can do anything |  | ||||||
|         if (user.getUser().isAdministrator()) |  | ||||||
|             return true; |  | ||||||
|          |  | ||||||
|         // Verify user has update permission on the target user |  | ||||||
|         ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions(); |  | ||||||
|         if (!userPermissionSet.hasPermission(ObjectPermission.Type.UPDATE, targetUser.getIdentifier())) |  | ||||||
|             return false; |  | ||||||
|  |  | ||||||
|         // Produce collection of affected identifiers |  | ||||||
|         Collection<String> affectedIdentifiers = new HashSet(permissions.size()); |  | ||||||
|         for (ObjectPermission permission : permissions) |  | ||||||
|             affectedIdentifiers.add(permission.getObjectIdentifier()); |  | ||||||
|  |  | ||||||
|         // Determine subset of affected identifiers that we have admin access to |  | ||||||
|         ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser()); |  | ||||||
|         Collection<String> allowedSubset = affectedPermissionSet.getAccessibleObjects( |  | ||||||
|             Collections.singleton(ObjectPermission.Type.ADMINISTER), |  | ||||||
|             affectedIdentifiers |  | ||||||
|         ); |  | ||||||
|  |  | ||||||
|         // The permissions can be altered if and only if the set of objects we |  | ||||||
|         // are allowed to administer is equal to the set of objects we will be |  | ||||||
|         // affecting. |  | ||||||
|  |  | ||||||
|         return affectedIdentifiers.size() == allowedSubset.size(); |  | ||||||
|          |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     @Override |  | ||||||
|     public void createPermissions(AuthenticatedUser user, ModeledUser targetUser, |  | ||||||
|             Collection<ObjectPermission> permissions) |  | ||||||
|             throws GuacamoleException { |  | ||||||
|  |  | ||||||
|         // Create permissions only if user has permission to do so |  | ||||||
|         if (canAlterPermissions(user, targetUser, permissions)) { |  | ||||||
|             Collection<ObjectPermissionModel> models = getModelInstances(targetUser, permissions); |  | ||||||
|             getPermissionMapper().insert(models); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         // User lacks permission to create object permissions |  | ||||||
|         throw new GuacamoleSecurityException("Permission denied."); |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void deletePermissions(AuthenticatedUser user, ModeledUser targetUser, |  | ||||||
|             Collection<ObjectPermission> permissions) |  | ||||||
|             throws GuacamoleException { |  | ||||||
|  |  | ||||||
|         // Delete permissions only if user has permission to do so |  | ||||||
|         if (canAlterPermissions(user, targetUser, permissions)) { |  | ||||||
|             Collection<ObjectPermissionModel> models = getModelInstances(targetUser, permissions); |  | ||||||
|             getPermissionMapper().delete(models); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         // User lacks permission to delete object permissions |  | ||||||
|         throw new GuacamoleSecurityException("Permission denied."); |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Retrieves the permission of the given type associated with the given |      * Retrieves the permission of the given type associated with the given | ||||||
| @@ -181,26 +62,9 @@ public abstract class ObjectPermissionService | |||||||
|      * @throws GuacamoleException |      * @throws GuacamoleException | ||||||
|      *     If an error occurs while retrieving the requested permission. |      *     If an error occurs while retrieving the requested permission. | ||||||
|      */ |      */ | ||||||
|     public ObjectPermission retrievePermission(AuthenticatedUser user, |     ObjectPermission retrievePermission(AuthenticatedUser user, | ||||||
|             ModeledUser targetUser, ObjectPermission.Type type, |             ModeledUser targetUser, ObjectPermission.Type type, | ||||||
|             String identifier) throws GuacamoleException { |             String identifier) throws GuacamoleException; | ||||||
|  |  | ||||||
|         // Retrieve permissions only if allowed |  | ||||||
|         if (canReadPermissions(user, targetUser)) { |  | ||||||
|  |  | ||||||
|             // Read permission from database, return null if not found |  | ||||||
|             ObjectPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type, identifier); |  | ||||||
|             if (model == null) |  | ||||||
|                 return null; |  | ||||||
|  |  | ||||||
|             return getPermissionInstance(model); |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // User cannot read this user's permissions |  | ||||||
|         throw new GuacamoleSecurityException("Permission denied."); |  | ||||||
|          |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Retrieves the subset of the given identifiers for which the given user |      * Retrieves the subset of the given identifiers for which the given user | ||||||
| @@ -228,29 +92,8 @@ public abstract class ObjectPermissionService | |||||||
|      * @throws GuacamoleException |      * @throws GuacamoleException | ||||||
|      *     If an error occurs while retrieving permissions. |      *     If an error occurs while retrieving permissions. | ||||||
|      */ |      */ | ||||||
|     public Collection<String> retrieveAccessibleIdentifiers(AuthenticatedUser user, |     Collection<String> retrieveAccessibleIdentifiers(AuthenticatedUser user, | ||||||
|             ModeledUser targetUser, Collection<ObjectPermission.Type> permissions, |             ModeledUser targetUser, Collection<ObjectPermission.Type> permissions, | ||||||
|             Collection<String> identifiers) throws GuacamoleException { |             Collection<String> identifiers) throws GuacamoleException; | ||||||
|  |  | ||||||
|         // Nothing is always accessible |  | ||||||
|         if (identifiers.isEmpty()) |  | ||||||
|             return identifiers; |  | ||||||
|          |  | ||||||
|         // Retrieve permissions only if allowed |  | ||||||
|         if (canReadPermissions(user, targetUser)) { |  | ||||||
|  |  | ||||||
|             // If user is an admin, everything is accessible |  | ||||||
|             if (user.getUser().isAdministrator()) |  | ||||||
|                 return identifiers; |  | ||||||
|  |  | ||||||
|             // Otherwise, return explicitly-retrievable identifiers |  | ||||||
|             return getPermissionMapper().selectAccessibleIdentifiers(targetUser.getModel(), permissions, identifiers); |  | ||||||
|              |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // User cannot read this user's permissions |  | ||||||
|         throw new GuacamoleSecurityException("Permission denied."); |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -47,137 +47,9 @@ import org.glyptodon.guacamole.net.auth.permission.PermissionSet; | |||||||
|  * |  * | ||||||
|  * @param <PermissionType> |  * @param <PermissionType> | ||||||
|  *     The type of permission this service provides access to. |  *     The type of permission this service provides access to. | ||||||
|  * |  | ||||||
|  * @param <ModelType> |  | ||||||
|  *     The underlying model object used to represent PermissionType in the |  | ||||||
|  *     database. |  | ||||||
|  */ |  */ | ||||||
| public abstract class PermissionService<PermissionSetType extends PermissionSet<PermissionType>, | public interface PermissionService<PermissionSetType extends PermissionSet<PermissionType>, | ||||||
|         PermissionType extends Permission, ModelType> { |         PermissionType extends Permission> { | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns an instance of a mapper for the type of permission used by this |  | ||||||
|      * service. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     A mapper which provides access to the model objects associated with |  | ||||||
|      *     the permissions used by this service. |  | ||||||
|      */ |  | ||||||
|     protected abstract PermissionMapper<ModelType> getPermissionMapper(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns an instance of a permission which is based on the given model |  | ||||||
|      * object. |  | ||||||
|      * |  | ||||||
|      * @param model |  | ||||||
|      *     The model object to use to produce the returned permission. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     A permission which is based on the given model object. |  | ||||||
|      */ |  | ||||||
|     protected abstract PermissionType getPermissionInstance(ModelType model); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns a collection of permissions which are based on the models in |  | ||||||
|      * the given collection. |  | ||||||
|      * |  | ||||||
|      * @param models |  | ||||||
|      *     The model objects to use to produce the permissions within the |  | ||||||
|      *     returned set. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     A set of permissions which are based on the models in the given |  | ||||||
|      *     collection. |  | ||||||
|      */ |  | ||||||
|     protected Set<PermissionType> getPermissionInstances(Collection<ModelType> models) { |  | ||||||
|  |  | ||||||
|         // Create new collection of permissions by manually converting each model |  | ||||||
|         Set<PermissionType> permissions = new HashSet<PermissionType>(models.size()); |  | ||||||
|         for (ModelType model : models) |  | ||||||
|             permissions.add(getPermissionInstance(model)); |  | ||||||
|  |  | ||||||
|         return permissions; |  | ||||||
|          |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns an instance of a model object which is based on the given |  | ||||||
|      * permission and target user. |  | ||||||
|      * |  | ||||||
|      * @param targetUser |  | ||||||
|      *     The user to whom this permission is granted. |  | ||||||
|      * |  | ||||||
|      * @param permission |  | ||||||
|      *     The permission to use to produce the returned model object. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     A model object which is based on the given permission and target |  | ||||||
|      *     user. |  | ||||||
|      */ |  | ||||||
|     protected abstract ModelType getModelInstance(ModeledUser targetUser, |  | ||||||
|             PermissionType permission); |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * Returns a collection of model objects which are based on the given |  | ||||||
|      * permissions and target user. |  | ||||||
|      * |  | ||||||
|      * @param targetUser |  | ||||||
|      *     The user to whom this permission is granted. |  | ||||||
|      * |  | ||||||
|      * @param permissions |  | ||||||
|      *     The permissions to use to produce the returned model objects. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     A collection of model objects which are based on the given |  | ||||||
|      *     permissions and target user. |  | ||||||
|      */ |  | ||||||
|     protected Collection<ModelType> getModelInstances(ModeledUser targetUser, |  | ||||||
|             Collection<PermissionType> permissions) { |  | ||||||
|  |  | ||||||
|         // Create new collection of models by manually converting each permission  |  | ||||||
|         Collection<ModelType> models = new ArrayList<ModelType>(permissions.size()); |  | ||||||
|         for (PermissionType permission : permissions) |  | ||||||
|             models.add(getModelInstance(targetUser, permission)); |  | ||||||
|  |  | ||||||
|         return models; |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Determines whether the given user can read the permissions currently |  | ||||||
|      * granted to the given target user. If the reading user and the target |  | ||||||
|      * user are not the same, then explicit READ or SYSTEM_ADMINISTER access is |  | ||||||
|      * required. |  | ||||||
|      * |  | ||||||
|      * @param user |  | ||||||
|      *     The user attempting to read permissions. |  | ||||||
|      * |  | ||||||
|      * @param targetUser |  | ||||||
|      *     The user whose permissions are being read. |  | ||||||
|      * |  | ||||||
|      * @return |  | ||||||
|      *     true if permission is granted, false otherwise. |  | ||||||
|      * |  | ||||||
|      * @throws GuacamoleException  |  | ||||||
|      *     If an error occurs while checking permission status, or if |  | ||||||
|      *     permission is denied to read the current user's permissions. |  | ||||||
|      */ |  | ||||||
|     protected boolean canReadPermissions(AuthenticatedUser user, |  | ||||||
|             ModeledUser targetUser) throws GuacamoleException { |  | ||||||
|  |  | ||||||
|         // A user can always read their own permissions |  | ||||||
|         if (user.getUser().getIdentifier().equals(targetUser.getIdentifier())) |  | ||||||
|             return true; |  | ||||||
|          |  | ||||||
|         // A system adminstrator can do anything |  | ||||||
|         if (user.getUser().isAdministrator()) |  | ||||||
|             return true; |  | ||||||
|  |  | ||||||
|         // Can read permissions on target user if explicit READ is granted |  | ||||||
|         ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions(); |  | ||||||
|         return userPermissionSet.hasPermission(ObjectPermission.Type.READ, targetUser.getIdentifier()); |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Returns a permission set that can be used to retrieve and manipulate the |      * Returns a permission set that can be used to retrieve and manipulate the | ||||||
| @@ -200,7 +72,7 @@ public abstract class PermissionService<PermissionSetType extends PermissionSet< | |||||||
|      *     user, or if permission to retrieve the permissions of the given |      *     user, or if permission to retrieve the permissions of the given | ||||||
|      *     user is denied. |      *     user is denied. | ||||||
|      */ |      */ | ||||||
|     public abstract PermissionSetType getPermissionSet(AuthenticatedUser user, |     PermissionSetType getPermissionSet(AuthenticatedUser user, | ||||||
|             ModeledUser targetUser) throws GuacamoleException; |             ModeledUser targetUser) throws GuacamoleException; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -218,17 +90,8 @@ public abstract class PermissionService<PermissionSetType extends PermissionSet< | |||||||
|      * @throws GuacamoleException |      * @throws GuacamoleException | ||||||
|      *     If an error occurs while retrieving the requested permissions. |      *     If an error occurs while retrieving the requested permissions. | ||||||
|      */ |      */ | ||||||
|     public Set<PermissionType> retrievePermissions(AuthenticatedUser user, |     Set<PermissionType> retrievePermissions(AuthenticatedUser user, | ||||||
|             ModeledUser targetUser) throws GuacamoleException { |             ModeledUser targetUser) throws GuacamoleException; | ||||||
|  |  | ||||||
|         // Retrieve permissions only if allowed |  | ||||||
|         if (canReadPermissions(user, targetUser)) |  | ||||||
|             return getPermissionInstances(getPermissionMapper().select(targetUser.getModel())); |  | ||||||
|  |  | ||||||
|         // User cannot read this user's permissions |  | ||||||
|         throw new GuacamoleSecurityException("Permission denied."); |  | ||||||
|          |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Creates the given permissions within the database. If any permissions |      * Creates the given permissions within the database. If any permissions | ||||||
| @@ -247,8 +110,7 @@ public abstract class PermissionService<PermissionSetType extends PermissionSet< | |||||||
|      *     If the user lacks permission to create the permissions, or an error |      *     If the user lacks permission to create the permissions, or an error | ||||||
|      *     occurs while creating the permissions. |      *     occurs while creating the permissions. | ||||||
|      */ |      */ | ||||||
|     public abstract void createPermissions(AuthenticatedUser user, |     void createPermissions(AuthenticatedUser user, ModeledUser targetUser, | ||||||
|             ModeledUser targetUser, |  | ||||||
|             Collection<PermissionType> permissions) throws GuacamoleException; |             Collection<PermissionType> permissions) throws GuacamoleException; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -268,8 +130,7 @@ public abstract class PermissionService<PermissionSetType extends PermissionSet< | |||||||
|      *     If the user lacks permission to delete the permissions, or an error |      *     If the user lacks permission to delete the permissions, or an error | ||||||
|      *     occurs while deleting the permissions. |      *     occurs while deleting the permissions. | ||||||
|      */ |      */ | ||||||
|     public abstract void deletePermissions(AuthenticatedUser user, |     void deletePermissions(AuthenticatedUser user, ModeledUser targetUser, | ||||||
|             ModeledUser targetUser, |  | ||||||
|             Collection<PermissionType> permissions) throws GuacamoleException; |             Collection<PermissionType> permissions) throws GuacamoleException; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ import org.glyptodon.guacamole.net.auth.permission.SystemPermission; | |||||||
|  * @author Michael Jumper |  * @author Michael Jumper | ||||||
|  */ |  */ | ||||||
| public class SystemPermissionService | public class SystemPermissionService | ||||||
|     extends PermissionService<SystemPermissionSet, SystemPermission, SystemPermissionModel> { |     extends ModeledPermissionService<SystemPermissionSet, SystemPermission, SystemPermissionModel> { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Mapper for system-level permissions. |      * Mapper for system-level permissions. | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; | |||||||
|  * |  * | ||||||
|  * @author Michael Jumper |  * @author Michael Jumper | ||||||
|  */ |  */ | ||||||
| public class UserPermissionService extends ObjectPermissionService { | public class UserPermissionService extends ModeledObjectPermissionService { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Mapper for user permissions. |      * Mapper for user permissions. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user