mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUAC-932: Migrate to PermissionSet for reading permissions.
This commit is contained in:
		| @@ -25,7 +25,6 @@ package org.glyptodon.guacamole.net.basic.rest; | ||||
| import com.google.inject.AbstractModule; | ||||
| import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.permission.PermissionService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.protocol.ProtocolRetrievalService; | ||||
|  | ||||
| /** | ||||
| @@ -42,7 +41,6 @@ public class RESTModule extends AbstractModule { | ||||
|         // Bind generic low-level services | ||||
|         bind(ConnectionService.class); | ||||
|         bind(ConnectionGroupService.class); | ||||
|         bind(PermissionService.class); | ||||
|         bind(ProtocolRetrievalService.class); | ||||
|          | ||||
|     } | ||||
|   | ||||
| @@ -30,7 +30,6 @@ import org.glyptodon.guacamole.net.basic.rest.auth.TokenRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.clipboard.ClipboardRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.permission.PermissionRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.protocol.ProtocolRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.user.UserRESTService; | ||||
|  | ||||
| @@ -48,7 +47,6 @@ public class RESTServletModule extends ServletModule { | ||||
|         bind(ClipboardRESTService.class); | ||||
|         bind(ConnectionRESTService.class); | ||||
|         bind(ConnectionGroupRESTService.class); | ||||
|         bind(PermissionRESTService.class); | ||||
|         bind(ProtocolRESTService.class); | ||||
|         bind(UserRESTService.class); | ||||
|         bind(TokenRESTService.class); | ||||
|   | ||||
| @@ -1,228 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 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.net.basic.rest.permission; | ||||
|  | ||||
| import org.codehaus.jackson.annotate.JsonIgnoreProperties; | ||||
| import org.codehaus.jackson.map.annotate.JsonSerialize; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.Permission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.SystemPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.UserPermission; | ||||
|  | ||||
| /** | ||||
|  * A simple user permission to expose through the REST endpoints. | ||||
|  *  | ||||
|  * @author James Muehlner | ||||
|  */ | ||||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||||
| @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) | ||||
| public class APIPermission { | ||||
|      | ||||
|     /** | ||||
|      * Create an empty APIPermission. | ||||
|      */ | ||||
|     public APIPermission() {} | ||||
|      | ||||
|     /** | ||||
|      * The type of object that this permission refers to. | ||||
|      */ | ||||
|     private ObjectType objectType; | ||||
|      | ||||
|     /** | ||||
|      * The type of object that a permission can refer to. | ||||
|      */ | ||||
|     public enum ObjectType { | ||||
|  | ||||
|         /** | ||||
|          * A normal connection. | ||||
|          */ | ||||
|         CONNECTION, | ||||
|  | ||||
|         /** | ||||
|          * A connection group. | ||||
|          */ | ||||
|         CONNECTION_GROUP, | ||||
|  | ||||
|         /** | ||||
|          * A Guacamole user. | ||||
|          */ | ||||
|         USER, | ||||
|  | ||||
|         /** | ||||
|          * The Guacamole system itself. | ||||
|          */ | ||||
|         SYSTEM | ||||
|  | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * The identifier of the object that this permission refers to. | ||||
|      */ | ||||
|     private String objectIdentifier; | ||||
|      | ||||
|     /** | ||||
|      * The object permission type for this APIPermission, if relevant. This is | ||||
|      * only used if this.objectType is CONNECTION, CONNECTION_GROUP, or USER. | ||||
|      */ | ||||
|     private ObjectPermission.Type objectPermissionType; | ||||
|      | ||||
|     /** | ||||
|      * The system permission type for this APIPermission, if relevant. This is | ||||
|      * only used if this.objectType is SYSTEM. | ||||
|      */ | ||||
|     private SystemPermission.Type systemPermissionType; | ||||
|      | ||||
|     /** | ||||
|      * Create an APIConnection from a Connection record. | ||||
|      *  | ||||
|      * @param permission The permission to create this APIPermission from. | ||||
|      */ | ||||
|     public APIPermission(Permission permission) { | ||||
|  | ||||
|         // Connection permission | ||||
|         if (permission instanceof ConnectionPermission) { | ||||
|             this.objectType = ObjectType.CONNECTION; | ||||
|             this.objectPermissionType = ((ConnectionPermission) permission).getType(); | ||||
|             this.objectIdentifier = ((ConnectionPermission) permission).getObjectIdentifier(); | ||||
|         } | ||||
|  | ||||
|         // Connection group permission | ||||
|         else if (permission instanceof ConnectionGroupPermission) { | ||||
|             this.objectType = ObjectType.CONNECTION_GROUP; | ||||
|             this.objectPermissionType = ((ConnectionGroupPermission) permission).getType(); | ||||
|             this.objectIdentifier = ((ConnectionGroupPermission) permission).getObjectIdentifier(); | ||||
|         } | ||||
|  | ||||
|         // User permission | ||||
|         else if (permission instanceof UserPermission) { | ||||
|             this.objectType = ObjectType.USER; | ||||
|             this.objectPermissionType = ((UserPermission) permission).getType(); | ||||
|             this.objectIdentifier = ((UserPermission) permission).getObjectIdentifier(); | ||||
|         } | ||||
|  | ||||
|         // System permission | ||||
|         else if (permission instanceof SystemPermission) { | ||||
|             this.objectType = ObjectType.SYSTEM; | ||||
|             this.systemPermissionType = ((SystemPermission) permission).getType(); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the type of object that this permission refers to. | ||||
|      *  | ||||
|      * @return The type of object that this permission refers to.  | ||||
|      */ | ||||
|     public ObjectType getObjectType() { | ||||
|         return objectType; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the type of object that this permission refers to. | ||||
|      * @param objectType The type of object that this permission refers to.  | ||||
|      */ | ||||
|     public void setObjectType(ObjectType objectType) { | ||||
|         this.objectType = objectType; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a string representation of the permission type. | ||||
|      *  | ||||
|      * @return A string representation of the permission type.  | ||||
|      */ | ||||
|     public String getPermissionType() { | ||||
|         switch(this.objectType) { | ||||
|             case CONNECTION: | ||||
|             case CONNECTION_GROUP: | ||||
|             case USER: | ||||
|                 return this.objectPermissionType.toString(); | ||||
|             case SYSTEM: | ||||
|                 return this.systemPermissionType.toString(); | ||||
|             default: | ||||
|                 return null; | ||||
|         }  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the permission type from a string representation of that type. | ||||
|      * Since it's not clear at this point whether this is an object permission or | ||||
|      * system permission, try to set both of them. | ||||
|      *  | ||||
|      * @param permissionType The string representation of the permission type. | ||||
|      */ | ||||
|     public void setPermissionType(String permissionType) { | ||||
|         try { | ||||
|             this.objectPermissionType = ObjectPermission.Type.valueOf(permissionType); | ||||
|         } catch(IllegalArgumentException e) {} | ||||
|          | ||||
|         try { | ||||
|             this.systemPermissionType = SystemPermission.Type.valueOf(permissionType); | ||||
|         } catch(IllegalArgumentException e) {} | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the identifier of the object that this permission refers to. | ||||
|      *  | ||||
|      * @return The identifier of the object that this permission refers to.  | ||||
|      */ | ||||
|     public String getObjectIdentifier() { | ||||
|         return objectIdentifier; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the identifier of the object that this permission refers to. | ||||
|      *  | ||||
|      * @param objectIdentifier The identifier of the object that this permission refers to.  | ||||
|      */ | ||||
|     public void setObjectIdentifier(String objectIdentifier) { | ||||
|         this.objectIdentifier = objectIdentifier; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Returns an org.glyptodon.guacamole.net.auth.permission.Permission  | ||||
|      * representation of this APIPermission. | ||||
|      *  | ||||
|      * @return An org.glyptodon.guacamole.net.auth.permission.Permission | ||||
|      * representation of this APIPermission. | ||||
|      */ | ||||
|     public Permission toPermission() { | ||||
|         switch(this.objectType) { | ||||
|             case CONNECTION: | ||||
|                 return new ConnectionPermission | ||||
|                         (this.objectPermissionType, this.objectIdentifier); | ||||
|             case CONNECTION_GROUP: | ||||
|                 return new ConnectionGroupPermission | ||||
|                         (this.objectPermissionType, this.objectIdentifier); | ||||
|             case USER: | ||||
|                 return new UserPermission | ||||
|                         (this.objectPermissionType, this.objectIdentifier); | ||||
|             case SYSTEM: | ||||
|                 return new SystemPermission(this.systemPermissionType); | ||||
|             default: | ||||
|                 return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,293 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 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.net.basic.rest.permission; | ||||
|  | ||||
| import java.util.EnumSet; | ||||
| import java.util.HashMap; | ||||
| import java.util.HashSet; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import org.glyptodon.guacamole.GuacamoleException; | ||||
| import org.glyptodon.guacamole.GuacamoleServerException; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.Permission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.SystemPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.UserPermission; | ||||
|  | ||||
| /** | ||||
|  * The set of permissions which are granted to a specific user, organized by | ||||
|  * object type and, if applicable, identifier. This object can be constructed | ||||
|  * with arbitrary permissions present, or manipulated after creation through | ||||
|  * the manipulation or replacement of its collections of permissions, but is | ||||
|  * otherwise not intended for internal use as a data structure for permissions. | ||||
|  * Its primary purpose is as a hierarchical format for exchanging granted | ||||
|  * permissions with REST clients. | ||||
|  */ | ||||
| public class APIPermissionSet { | ||||
|  | ||||
|     /** | ||||
|      * Map of connection ID to the set of granted permissions. | ||||
|      */ | ||||
|     private Map<String, EnumSet<ObjectPermission.Type>> connectionPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>(); | ||||
|  | ||||
|     /** | ||||
|      * Map of connection group ID to the set of granted permissions. | ||||
|      */ | ||||
|     private Map<String, EnumSet<ObjectPermission.Type>> connectionGroupPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>(); | ||||
|  | ||||
|     /** | ||||
|      * Map of user ID to the set of granted permissions. | ||||
|      */ | ||||
|     private Map<String, EnumSet<ObjectPermission.Type>> userPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>(); | ||||
|  | ||||
|     /** | ||||
|      * Set of all granted system-level permissions. | ||||
|      */ | ||||
|     private EnumSet<SystemPermission.Type> systemPermissions = EnumSet.noneOf(SystemPermission.Type.class); | ||||
|  | ||||
|     /** | ||||
|      * Adds the given object permission to the given map of object identifier | ||||
|      * to permission set. | ||||
|      * | ||||
|      * @param permissions | ||||
|      *     The map to add the given permission to. | ||||
|      * | ||||
|      * @param permission | ||||
|      *     The permission to add. | ||||
|      */ | ||||
|     private void addPermission(Map<String, EnumSet<ObjectPermission.Type>> permissions, ObjectPermission<String> permission) { | ||||
|  | ||||
|         // Pull set of permissions for given object | ||||
|         String id = permission.getObjectIdentifier(); | ||||
|         EnumSet<ObjectPermission.Type> types = permissions.get(id); | ||||
|  | ||||
|         // If set does not yet exist, create it | ||||
|         if (types == null) { | ||||
|             types = EnumSet.of(permission.getType()); | ||||
|             permissions.put(id, types); | ||||
|         } | ||||
|  | ||||
|         // Otherwise, add the specified permission | ||||
|         else | ||||
|             types.add(permission.getType()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds the given system-level permission to the given set of granted | ||||
|      * system permissions. | ||||
|      * | ||||
|      * @param permissions | ||||
|      *     The set of system permissions to add the given permission to. | ||||
|      * | ||||
|      * @param permission | ||||
|      *     The permission to add. | ||||
|      */ | ||||
|     private void addPermission(EnumSet<SystemPermission.Type> permissions, SystemPermission permission) { | ||||
|         permissions.add(permission.getType()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds the given permission to the appropriate type-specific set or map of | ||||
|      * permissions based on the permission class. Only connection, connection | ||||
|      * group, user, and system permissions are supported. Unsupported | ||||
|      * permission types will result in a GuacamoleException being thrown. | ||||
|      * | ||||
|      * @param permission The permission to add. | ||||
|      * @throws GuacamoleException If the permission is of an unsupported type. | ||||
|      */ | ||||
|     private void addPermission(Permission<?> permission) throws GuacamoleException { | ||||
|  | ||||
|         // Connection permissions | ||||
|         if (permission instanceof ConnectionPermission) | ||||
|             addPermission(connectionPermissions, (ConnectionPermission) permission); | ||||
|  | ||||
|         // Connection group permissions | ||||
|         else if (permission instanceof ConnectionGroupPermission) | ||||
|             addPermission(connectionGroupPermissions, (ConnectionGroupPermission) permission); | ||||
|  | ||||
|         // User permissions | ||||
|         else if (permission instanceof UserPermission) | ||||
|             addPermission(userPermissions, (UserPermission) permission); | ||||
|  | ||||
|         // System permissions | ||||
|         else if (permission instanceof SystemPermission) | ||||
|             addPermission(systemPermissions, (SystemPermission) permission); | ||||
|  | ||||
|         // Unknown / unsupported permission type | ||||
|         else | ||||
|             throw new GuacamoleServerException("Serialization of permission type \"" + permission.getClass() + "\" not implemented."); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new permission set which contains no granted permissions. Any | ||||
|      * permissions must be added by manipulating or replacing the applicable | ||||
|      * permission collection. | ||||
|      */ | ||||
|     public APIPermissionSet() { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new permission set having the given permissions. | ||||
|      * | ||||
|      * @param permissions | ||||
|      *     The permissions to initially store within the permission set. | ||||
|      * | ||||
|      * @throws GuacamoleException | ||||
|      *     If any of the given permissions are of an unsupported type. | ||||
|      */ | ||||
|     public APIPermissionSet(Iterable<Permission> permissions) throws GuacamoleException { | ||||
|  | ||||
|         // Add all provided permissions  | ||||
|         for (Permission permission : permissions) | ||||
|             addPermission(permission); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new permission set having the given permissions. | ||||
|      * | ||||
|      * @param permissions | ||||
|      *     The permissions to initially store within the permission set. | ||||
|      * | ||||
|      * @throws GuacamoleException | ||||
|      *     If any of the given permissions are of an unsupported type. | ||||
|      */ | ||||
|     public APIPermissionSet(Permission... permissions) throws GuacamoleException { | ||||
|  | ||||
|         // Add all provided permissions  | ||||
|         for (Permission permission : permissions) | ||||
|             addPermission(permission); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a map of connection IDs to the set of permissions granted for | ||||
|      * that connection. If no permissions are granted to a particular | ||||
|      * connection, its ID will not be present as a key in the map. This map is | ||||
|      * mutable, and changes to this map will affect the permission set | ||||
|      * directly. | ||||
|      * | ||||
|      * @return | ||||
|      *     A map of connection IDs to the set of permissions granted for that | ||||
|      *     connection. | ||||
|      */ | ||||
|     public Map<String, EnumSet<ObjectPermission.Type>> getConnectionPermissions() { | ||||
|         return connectionPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a map of connection group IDs to the set of permissions granted | ||||
|      * for that connection group. If no permissions are granted to a particular | ||||
|      * connection group, its ID will not be present as a key in the map. This | ||||
|      * map is mutable, and changes to this map will affect the permission set | ||||
|      * directly. | ||||
|      * | ||||
|      * @return | ||||
|      *     A map of connection group IDs to the set of permissions granted for | ||||
|      *     that connection group. | ||||
|      */ | ||||
|     public Map<String, EnumSet<ObjectPermission.Type>> getConnectionGroupPermissions() { | ||||
|         return connectionGroupPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a map of user IDs to the set of permissions granted for that | ||||
|      * user. If no permissions are granted to a particular user, its ID will | ||||
|      * not be present as a key in the map. This map is mutable, and changes to | ||||
|      * to this map will affect the permission set directly. | ||||
|      * | ||||
|      * @return | ||||
|      *     A map of user IDs to the set of permissions granted for that user. | ||||
|      */ | ||||
|     public Map<String, EnumSet<ObjectPermission.Type>> getUserPermissions() { | ||||
|         return userPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the set of granted system-level permissions. If no permissions | ||||
|      * are granted at the system level, this will be an empty set. This set is | ||||
|      * mutable, and changes to this set will affect the permission set | ||||
|      * directly. | ||||
|      * | ||||
|      * @return | ||||
|      *     The set of granted system-level permissions. | ||||
|      */ | ||||
|     public EnumSet<SystemPermission.Type> getSystemPermissions() { | ||||
|         return systemPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Replaces the current map of connection permissions with the given map, | ||||
|      * which must map connection ID to its corresponding set of granted | ||||
|      * permissions. If a connection has no permissions, its ID must not be | ||||
|      * present as a key in the map. | ||||
|      * | ||||
|      * @param connectionPermissions | ||||
|      *     The map which must replace the currently-stored map of permissions. | ||||
|      */ | ||||
|     public void setConnectionPermissions(Map<String, EnumSet<ObjectPermission.Type>> connectionPermissions) { | ||||
|         this.connectionPermissions = connectionPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Replaces the current map of connection group permissions with the given | ||||
|      * map, which must map connection group ID to its corresponding set of | ||||
|      * granted permissions. If a connection group has no permissions, its ID | ||||
|      * must not be present as a key in the map. | ||||
|      * | ||||
|      * @param connectionGroupPermissions | ||||
|      *     The map which must replace the currently-stored map of permissions. | ||||
|      */ | ||||
|     public void setConnectionGroupPermissions(Map<String, EnumSet<ObjectPermission.Type>> connectionGroupPermissions) { | ||||
|         this.connectionGroupPermissions = connectionGroupPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Replaces the current map of user permissions with the given map, which | ||||
|      * must map user ID to its corresponding set of granted permissions. If a | ||||
|      * user has no permissions, its ID must not be present as a key in the map. | ||||
|      * | ||||
|      * @param userPermissions | ||||
|      *     The map which must replace the currently-stored map of permissions. | ||||
|      */ | ||||
|     public void setUserPermissions(Map<String, EnumSet<ObjectPermission.Type>> userPermissions) { | ||||
|         this.userPermissions = userPermissions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Replaces the current set of system-level permissions with the given set. | ||||
|      * If no system-level permissions are granted, the empty set must be | ||||
|      * specified. | ||||
|      * | ||||
|      * @param systemPermissions | ||||
|      *     The set which must replace the currently-stored set of permissions. | ||||
|      */ | ||||
|     public void setSystemPermissions(EnumSet<SystemPermission.Type> systemPermissions) { | ||||
|         this.systemPermissions = systemPermissions; | ||||
|     } | ||||
|      | ||||
| } | ||||
| @@ -1,157 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 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.net.basic.rest.permission; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import javax.ws.rs.Consumes; | ||||
| import javax.ws.rs.GET; | ||||
| import javax.ws.rs.Path; | ||||
| import javax.ws.rs.PathParam; | ||||
| import javax.ws.rs.Produces; | ||||
| import javax.ws.rs.QueryParam; | ||||
| import javax.ws.rs.core.MediaType; | ||||
| import javax.ws.rs.core.Response.Status; | ||||
| import org.glyptodon.guacamole.GuacamoleException; | ||||
| import org.glyptodon.guacamole.net.auth.Directory; | ||||
| import org.glyptodon.guacamole.net.auth.User; | ||||
| import org.glyptodon.guacamole.net.auth.UserContext; | ||||
| import org.glyptodon.guacamole.net.auth.permission.Permission; | ||||
| import org.glyptodon.guacamole.net.basic.rest.APIPatch; | ||||
| import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure; | ||||
| import org.glyptodon.guacamole.net.basic.rest.HTTPException; | ||||
| import org.glyptodon.guacamole.net.basic.rest.PATCH; | ||||
| import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| /** | ||||
|  * A REST Service for handling connection CRUD operations. | ||||
|  *  | ||||
|  * @author James Muehlner | ||||
|  */ | ||||
| @Path("/permission") | ||||
| @Produces(MediaType.APPLICATION_JSON) | ||||
| @Consumes(MediaType.APPLICATION_JSON) | ||||
| public class PermissionRESTService { | ||||
|  | ||||
|     /** | ||||
|      * Logger for this class. | ||||
|      */ | ||||
|     private static final Logger logger = LoggerFactory.getLogger(PermissionRESTService.class); | ||||
|      | ||||
|     /** | ||||
|      * A service for authenticating users from auth tokens. | ||||
|      */ | ||||
|     @Inject | ||||
|     private AuthenticationService authenticationService; | ||||
|      | ||||
|     /** | ||||
|      * A service for managing the REST endpoint APIPermission objects.  | ||||
|      */ | ||||
|     @Inject | ||||
|     private PermissionService permissionService; | ||||
|      | ||||
|     /** | ||||
|      * Gets a list of permissions for the user with the given userID. | ||||
|      *  | ||||
|      * @param authToken The authentication token that is used to authenticate | ||||
|      *                  the user performing the operation. | ||||
|      * @param userID The ID of the user to retrieve permissions for. | ||||
|      * @return The permission list. | ||||
|      * @throws GuacamoleException If a problem is encountered while listing permissions. | ||||
|      */ | ||||
|     @GET | ||||
|     @Path("/{userID}") | ||||
|     @AuthProviderRESTExposure | ||||
|     public List<APIPermission> getPermissions(@QueryParam("token") String authToken, @PathParam("userID") String userID)  | ||||
|             throws GuacamoleException { | ||||
|  | ||||
|         UserContext userContext = authenticationService.getUserContext(authToken); | ||||
|  | ||||
|         // Get the user | ||||
|         User user = userContext.getUserDirectory().get(userID); | ||||
|         if (user == null) | ||||
|             throw new HTTPException(Status.NOT_FOUND, "User not found with the provided userID."); | ||||
|  | ||||
|         return permissionService.convertPermissionList(user.getPermissions()); | ||||
|  | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Applies a given list of permission patches. | ||||
|      *  | ||||
|      * @param authToken The authentication token that is used to authenticate | ||||
|      *                  the user performing the operation. | ||||
|      * @param patches   The permission patches to apply for this request. | ||||
|      * @throws GuacamoleException If a problem is encountered while removing the permission. | ||||
|      */ | ||||
|     @PATCH | ||||
|     @AuthProviderRESTExposure | ||||
|     public void patchPermissions(@QueryParam("token") String authToken,  | ||||
|             List<APIPatch<APIPermission>> patches) throws GuacamoleException { | ||||
|  | ||||
|         UserContext userContext = authenticationService.getUserContext(authToken); | ||||
|          | ||||
|         // Get the user directory | ||||
|         Directory<String, User> userDirectory = userContext.getUserDirectory(); | ||||
|          | ||||
|         // All users who have had permissions added or removed | ||||
|         Map<String, User> modifiedUsers = new HashMap<String, User>(); | ||||
|          | ||||
|         for (APIPatch<APIPermission> patch : patches) { | ||||
|  | ||||
|             String userID = patch.getPath(); | ||||
|             Permission permission = patch.getValue().toPermission(); | ||||
|              | ||||
|             // See if we've already modified this user in this request | ||||
|             User user = modifiedUsers.get(userID); | ||||
|             if (user == null) | ||||
|                 user = userDirectory.get(userID); | ||||
|              | ||||
|             if (user == null) | ||||
|                 throw new HTTPException(Status.NOT_FOUND, "User not found with userID " + userID + "."); | ||||
|              | ||||
|             // Only the add and remove operations are supported for permissions | ||||
|             switch(patch.getOp()) { | ||||
|                 case add: | ||||
|                     user.addPermission(permission); | ||||
|                     modifiedUsers.put(userID, user); | ||||
|                     break; | ||||
|                 case remove: | ||||
|                     user.removePermission(permission); | ||||
|                     modifiedUsers.put(userID, user); | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|          | ||||
|         // Save the permission changes for all modified users | ||||
|         for (User user : modifiedUsers.values()) | ||||
|             userDirectory.update(user); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 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.net.basic.rest.permission; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import org.glyptodon.guacamole.net.auth.permission.Permission; | ||||
|  | ||||
| /** | ||||
|  * A service for performing useful manipulations on REST Permissions. | ||||
|  *  | ||||
|  * @author James Muehlner | ||||
|  */ | ||||
| public class PermissionService { | ||||
|      | ||||
|     /** | ||||
|      * Converts a list of Permission to a list of APIPermission objects for  | ||||
|      * exposing with the REST endpoints. | ||||
|      *  | ||||
|      * @param permissions The Connections to convert for REST endpoint use. | ||||
|      * @return A List of APIPermission objects for use with the REST endpoint. | ||||
|      */ | ||||
|     public List<APIPermission> convertPermissionList(Iterable<? extends Permission> permissions) { | ||||
|  | ||||
|         List<APIPermission> restPermissions = new ArrayList<APIPermission>(); | ||||
|          | ||||
|         for(Permission permission : permissions) | ||||
|             restPermissions.add(new APIPermission(permission)); | ||||
|              | ||||
|         return restPermissions; | ||||
|  | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Converts a list of APIPermission to a set of Permission objects for internal | ||||
|      * Guacamole use. | ||||
|      *  | ||||
|      * @param restPermissions The APIPermission objects from the REST endpoints. | ||||
|      * @return a List of Permission objects for internal Guacamole use. | ||||
|      */ | ||||
|     public Set<Permission> convertAPIPermissionList(Iterable<APIPermission> restPermissions) { | ||||
|  | ||||
|         Set<Permission> permissions = new HashSet<Permission>(); | ||||
|          | ||||
|         for(APIPermission restPermission : restPermissions) | ||||
|             permissions.add(restPermission.toPermission()); | ||||
|          | ||||
|         return permissions; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -36,14 +36,25 @@ import javax.ws.rs.Produces; | ||||
| import javax.ws.rs.QueryParam; | ||||
| import javax.ws.rs.core.MediaType; | ||||
| import javax.ws.rs.core.Response; | ||||
| import javax.ws.rs.core.Response.Status; | ||||
| import org.glyptodon.guacamole.GuacamoleException; | ||||
| import org.glyptodon.guacamole.net.auth.Directory; | ||||
| import org.glyptodon.guacamole.net.auth.User; | ||||
| import org.glyptodon.guacamole.net.auth.UserContext; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.Permission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.SystemPermission; | ||||
| import org.glyptodon.guacamole.net.auth.permission.UserPermission; | ||||
| import org.glyptodon.guacamole.net.basic.rest.APIPatch; | ||||
| import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.add; | ||||
| import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove; | ||||
| import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure; | ||||
| import org.glyptodon.guacamole.net.basic.rest.HTTPException; | ||||
| import org.glyptodon.guacamole.net.basic.rest.PATCH; | ||||
| import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.permission.APIPermissionSet; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| @@ -61,6 +72,30 @@ public class UserRESTService { | ||||
|      * Logger for this class. | ||||
|      */ | ||||
|     private static final Logger logger = LoggerFactory.getLogger(UserRESTService.class); | ||||
|  | ||||
|     /** | ||||
|      * The prefix of any path within an operation of a JSON patch which | ||||
|      * modifies the permissions of a user regarding a specific connection. | ||||
|      */ | ||||
|     private static final String CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/connectionPermissions/"; | ||||
|      | ||||
|     /** | ||||
|      * The prefix of any path within an operation of a JSON patch which | ||||
|      * modifies the permissions of a user regarding a specific connection group. | ||||
|      */ | ||||
|     private static final String CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX = "/connectionGroupPermissions/"; | ||||
|  | ||||
|     /** | ||||
|      * The prefix of any path within an operation of a JSON patch which | ||||
|      * modifies the permissions of a user regarding another, specific user. | ||||
|      */ | ||||
|     private static final String USER_PERMISSION_PATCH_PATH_PREFIX = "/userPermissions/"; | ||||
|  | ||||
|     /** | ||||
|      * The path of any operation within a JSON patch which modifies the | ||||
|      * permissions of a user regarding the entire system. | ||||
|      */ | ||||
|     private static final String SYSTEM_PERMISSION_PATCH_PATH = "/systemPermissions"; | ||||
|      | ||||
|     /** | ||||
|      * A service for authenticating users from auth tokens. | ||||
| @@ -239,4 +274,152 @@ public class UserRESTService { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of permissions for the user with the given userID. | ||||
|      *  | ||||
|      * @param authToken The authentication token that is used to authenticate | ||||
|      *                  the user performing the operation. | ||||
|      * @param userID The ID of the user to retrieve permissions for. | ||||
|      * @return The permission list. | ||||
|      * @throws GuacamoleException If a problem is encountered while listing permissions. | ||||
|      */ | ||||
|     @GET | ||||
|     @Path("/{userID}/permissions") | ||||
|     @AuthProviderRESTExposure | ||||
|     public APIPermissionSet getPermissions(@QueryParam("token") String authToken, @PathParam("userID") String userID)  | ||||
|             throws GuacamoleException { | ||||
|  | ||||
|         UserContext userContext = authenticationService.getUserContext(authToken); | ||||
|  | ||||
|         // Get the user | ||||
|         User user = userContext.getUserDirectory().get(userID); | ||||
|         if (user == null) | ||||
|             throw new HTTPException(Status.NOT_FOUND, "User not found with the provided userID."); | ||||
|  | ||||
|         return new APIPermissionSet(user.getPermissions()); | ||||
|  | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Applies a given list of permission patches. Each patch specifies either | ||||
|      * an "add" or a "remove" operation for a permission type, represented by | ||||
|      * a string. Valid permission types depend on the path of each patch | ||||
|      * operation, as the path dictates the permission being modified, such as | ||||
|      * "/connectionPermissions/42" or "/systemPermissions". | ||||
|      *  | ||||
|      * @param authToken | ||||
|      *     The authentication token that is used to authenticate the user | ||||
|      *     performing the operation. | ||||
|      *  | ||||
|      * @param userID | ||||
|      *     The ID of the user to modify the permissions of. | ||||
|      * | ||||
|      * @param patches | ||||
|      *     The permission patches to apply for this request. | ||||
|      * | ||||
|      * @throws GuacamoleException | ||||
|      *     If a problem is encountered while modifying permissions. | ||||
|      */ | ||||
|     @PATCH | ||||
|     @Path("/{userID}/permissions") | ||||
|     @AuthProviderRESTExposure | ||||
|     public void patchPermissions(@QueryParam("token") String authToken, | ||||
|             @PathParam("userID") String userID, | ||||
|             List<APIPatch<String>> patches) throws GuacamoleException { | ||||
|  | ||||
|         UserContext userContext = authenticationService.getUserContext(authToken); | ||||
|          | ||||
|         // Get the user directory | ||||
|         Directory<String, User> userDirectory = userContext.getUserDirectory(); | ||||
|  | ||||
|         // Get the user | ||||
|         User user = userContext.getUserDirectory().get(userID); | ||||
|         if (user == null) | ||||
|             throw new HTTPException(Status.NOT_FOUND, "User not found with the provided userID."); | ||||
|  | ||||
|         // Apply all patch operations individually | ||||
|         for (APIPatch<String> patch : patches) { | ||||
|  | ||||
|             Permission permission; | ||||
|  | ||||
|             String path = patch.getPath(); | ||||
|  | ||||
|             // Create connection permission if path has connection prefix | ||||
|             if (path.startsWith(CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) { | ||||
|  | ||||
|                 // Get identifier and type from patch operation | ||||
|                 String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length()); | ||||
|                 ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); | ||||
|  | ||||
|                 // Create corresponding permission | ||||
|                 permission = new ConnectionPermission(type, identifier); | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             // Create connection group permission if path has connection group prefix | ||||
|             else if (path.startsWith(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX)) { | ||||
|  | ||||
|                 // Get identifier and type from patch operation | ||||
|                 String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length()); | ||||
|                 ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); | ||||
|  | ||||
|                 // Create corresponding permission | ||||
|                 permission = new ConnectionGroupPermission(type, identifier); | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             // Create user permission if path has user prefix | ||||
|             else if (path.startsWith(USER_PERMISSION_PATCH_PATH_PREFIX)) { | ||||
|  | ||||
|                 // Get identifier and type from patch operation | ||||
|                 String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length()); | ||||
|                 ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); | ||||
|  | ||||
|                 // Create corresponding permission | ||||
|                 permission = new UserPermission(type, identifier); | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             // Create system permission if path is system path | ||||
|             else if (path.startsWith(SYSTEM_PERMISSION_PATCH_PATH)) { | ||||
|  | ||||
|                 // Get identifier and type from patch operation | ||||
|                 SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue()); | ||||
|  | ||||
|                 // Create corresponding permission | ||||
|                 permission = new SystemPermission(type); | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             // Otherwise, the path is not supported | ||||
|             else | ||||
|                 throw new HTTPException(Status.BAD_REQUEST, "Unsupported patch path: \"" + path + "\""); | ||||
|  | ||||
|             // Add or remove permission based on operation | ||||
|             switch (patch.getOp()) { | ||||
|  | ||||
|                 // Add permission | ||||
|                 case add: | ||||
|                     user.addPermission(permission); | ||||
|                     break; | ||||
|  | ||||
|                 // Remove permission | ||||
|                 case remove: | ||||
|                     user.removePermission(permission); | ||||
|                     break; | ||||
|  | ||||
|                 // Unsupported patch operation | ||||
|                 default: | ||||
|                     throw new HTTPException(Status.BAD_REQUEST, "Unsupported patch operation: \"" + patch.getOp() + "\""); | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } // end for each patch operation | ||||
|          | ||||
|         // Save the permission changes | ||||
|         userDirectory.update(user); | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user