GUAC-1100: Migrate REST services to new guacamole-ext API. This is partial and temporary - batch operations are not being used, and the MySQL auth has not been updated.

This commit is contained in:
Michael Jumper
2015-02-11 16:14:38 -08:00
parent 3f5d398f13
commit 9fe2eb6bbd
5 changed files with 189 additions and 198 deletions

View File

@@ -45,10 +45,10 @@ import org.glyptodon.guacamole.net.auth.ConnectionRecord;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext; import org.glyptodon.guacamole.net.auth.UserContext;
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure; import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService; import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService;
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
@@ -71,12 +71,6 @@ public class ConnectionRESTService {
*/ */
private static final Logger logger = LoggerFactory.getLogger(ConnectionRESTService.class); private static final Logger logger = LoggerFactory.getLogger(ConnectionRESTService.class);
/**
* System administration permission.
*/
private static final Permission SYSTEM_PERMISSION =
new SystemPermission(SystemPermission.Type.ADMINISTER);
/** /**
* A service for authenticating users from auth tokens. * A service for authenticating users from auth tokens.
*/ */
@@ -143,9 +137,13 @@ public class ConnectionRESTService {
UserContext userContext = authenticationService.getUserContext(authToken); UserContext userContext = authenticationService.getUserContext(authToken);
User self = userContext.self(); User self = userContext.self();
// Retrieve permission sets
SystemPermissionSet systemPermissions = self.getSystemPermissions();
ObjectPermissionSet<String> connectionPermissions = self.getConnectionPermissions();
// Deny access if adminstrative or update permission is missing // Deny access if adminstrative or update permission is missing
if (!self.hasPermission(SYSTEM_PERMISSION) if (!systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER)
&& !self.hasPermission(new ConnectionPermission(ObjectPermission.Type.UPDATE, connectionID))) && !connectionPermissions.hasPermission(ObjectPermission.Type.UPDATE, connectionID))
throw new GuacamoleSecurityException("Permission to read connection parameters denied."); throw new GuacamoleSecurityException("Permission to read connection parameters denied.");
// Retrieve the requested connection // Retrieve the requested connection

View File

@@ -45,10 +45,10 @@ import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext; 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.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure; import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService; import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService;
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
@@ -102,14 +102,14 @@ public class ConnectionGroupRESTService {
*/ */
private boolean hasConnectionPermission(User user, String identifier, private boolean hasConnectionPermission(User user, String identifier,
List<ObjectPermission.Type> permissions) throws GuacamoleException { List<ObjectPermission.Type> permissions) throws GuacamoleException {
// Retrieve connection permissions
ObjectPermissionSet<String> connectionPermissions = user.getConnectionPermissions();
// Determine whether user has at least one of the given permissions // Determine whether user has at least one of the given permissions
for (ObjectPermission.Type permission : permissions) { for (ObjectPermission.Type permission : permissions) {
if (connectionPermissions.hasPermission(permission, identifier))
ConnectionPermission connectionPermission = new ConnectionPermission(permission, identifier);
if (user.hasPermission(connectionPermission))
return true; return true;
} }
// None of the given permissions were present // None of the given permissions were present
@@ -137,13 +137,13 @@ public class ConnectionGroupRESTService {
private boolean hasConnectionGroupPermission(User user, String identifier, private boolean hasConnectionGroupPermission(User user, String identifier,
List<ObjectPermission.Type> permissions) throws GuacamoleException { List<ObjectPermission.Type> permissions) throws GuacamoleException {
// Retrieve connection group permissions
ObjectPermissionSet<String> connectionGroupPermissions = user.getConnectionGroupPermissions();
// Determine whether user has at least one of the given permissions // Determine whether user has at least one of the given permissions
for (ObjectPermission.Type permission : permissions) { for (ObjectPermission.Type permission : permissions) {
if (connectionGroupPermissions.hasPermission(permission, identifier))
ConnectionGroupPermission connectionGroupPermission = new ConnectionGroupPermission(permission, identifier);
if (user.hasPermission(connectionGroupPermission))
return true; return true;
} }
// None of the given permissions were present // None of the given permissions were present
@@ -185,7 +185,8 @@ public class ConnectionGroupRESTService {
User self = userContext.self(); User self = userContext.self();
// An admin user has access to any connection or connection group // An admin user has access to any connection or connection group
boolean isAdmin = self.hasPermission(new SystemPermission(SystemPermission.Type.ADMINISTER)); SystemPermissionSet systemPermissions = self.getSystemPermissions();
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
// Retrieve specified connection group // Retrieve specified connection group
ConnectionGroup connectionGroup; ConnectionGroup connectionGroup;

View File

@@ -24,17 +24,14 @@ package org.glyptodon.guacamole.net.basic.rest.permission;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException; import org.glyptodon.guacamole.net.auth.User;
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.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.UserPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
/** /**
* The set of permissions which are granted to a specific user, organized by * The set of permissions which are granted to a specific user, organized by
@@ -50,97 +47,26 @@ public class APIPermissionSet {
/** /**
* Map of connection ID to the set of granted permissions. * Map of connection ID to the set of granted permissions.
*/ */
private Map<String, EnumSet<ObjectPermission.Type>> connectionPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>(); private Map<String, Set<ObjectPermission.Type>> connectionPermissions =
new HashMap<String, Set<ObjectPermission.Type>>();
/** /**
* Map of connection group ID to the set of granted permissions. * Map of connection group ID to the set of granted permissions.
*/ */
private Map<String, EnumSet<ObjectPermission.Type>> connectionGroupPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>(); private Map<String, Set<ObjectPermission.Type>> connectionGroupPermissions =
new HashMap<String, Set<ObjectPermission.Type>>();
/** /**
* Map of user ID to the set of granted permissions. * Map of user ID to the set of granted permissions.
*/ */
private Map<String, EnumSet<ObjectPermission.Type>> userPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>(); private Map<String, Set<ObjectPermission.Type>> userPermissions =
new HashMap<String, Set<ObjectPermission.Type>>();
/** /**
* Set of all granted system-level permissions. * Set of all granted system-level permissions.
*/ */
private EnumSet<SystemPermission.Type> systemPermissions = EnumSet.noneOf(SystemPermission.Type.class); private Set<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 * Creates a new permission set which contains no granted permissions. Any
@@ -151,37 +77,83 @@ public class APIPermissionSet {
} }
/** /**
* Creates a new permission set having the given permissions. * Adds the system permissions from the given SystemPermissionSet to the
* Set of system permissions provided.
* *
* @param permissions * @param permissions
* The permissions to initially store within the permission set. * The Set to add system permissions to.
*
* @param permSet
* The SystemPermissionSet containing the system permissions to add.
* *
* @throws GuacamoleException * @throws GuacamoleException
* If any of the given permissions are of an unsupported type. * If an error occurs while retrieving system permissions from the
* SystemPermissionSet.
*/ */
public APIPermissionSet(Iterable<Permission> permissions) throws GuacamoleException { private void addSystemPermissions(Set<SystemPermission.Type> permissions,
SystemPermissionSet permSet) throws GuacamoleException {
// Add all provided permissions // Add all provided system permissions
for (Permission permission : permissions) for (SystemPermission permission : permSet.getPermissions())
addPermission(permission); permissions.add(permission.getType());
} }
/** /**
* Creates a new permission set having the given permissions. * Adds the object permissions from the given ObjectPermissionSet to the
* Map of object permissions provided.
* *
* @param permissions * @param permissions
* The permissions to initially store within the permission set. * The Map to add object permissions to.
*
* @param permSet
* The ObjectPermissionSet containing the object permissions to add.
* *
* @throws GuacamoleException * @throws GuacamoleException
* If any of the given permissions are of an unsupported type. * If an error occurs while retrieving object permissions from the
* ObjectPermissionSet.
*/ */
public APIPermissionSet(Permission... permissions) throws GuacamoleException { private void addObjectPermissions(Map<String, Set<ObjectPermission.Type>> permissions,
ObjectPermissionSet<String> permSet) throws GuacamoleException {
// Add all provided permissions // Add all provided object permissions
for (Permission permission : permissions) for (ObjectPermission<String> permission : permSet.getPermissions()) {
addPermission(permission);
// Get associated set of permissions
String identifier = permission.getObjectIdentifier();
Set<ObjectPermission.Type> objectPermissions = permissions.get(identifier);
// Create new set if none yet exists
if (objectPermissions == null)
permissions.put(identifier, EnumSet.of(permission.getType()));
// Otherwise add to existing set
else
objectPermissions.add(permission.getType());
}
}
/**
* Creates a new permission set containing all permissions currently
* granted to the given user.
*
* @param user
* The user whose permissions should be stored within this permission
* set.
*
* @throws GuacamoleException
* If an error occurs while retrieving the user's permissions.
*/
public APIPermissionSet(User user) throws GuacamoleException {
// Add all permissions from the provided user
addSystemPermissions(systemPermissions, user.getSystemPermissions());
addObjectPermissions(connectionPermissions, user.getConnectionPermissions());
addObjectPermissions(connectionGroupPermissions, user.getConnectionGroupPermissions());
addObjectPermissions(userPermissions, user.getUserPermissions());
} }
/** /**
@@ -195,7 +167,7 @@ public class APIPermissionSet {
* A map of connection IDs to the set of permissions granted for that * A map of connection IDs to the set of permissions granted for that
* connection. * connection.
*/ */
public Map<String, EnumSet<ObjectPermission.Type>> getConnectionPermissions() { public Map<String, Set<ObjectPermission.Type>> getConnectionPermissions() {
return connectionPermissions; return connectionPermissions;
} }
@@ -210,7 +182,7 @@ public class APIPermissionSet {
* A map of connection group IDs to the set of permissions granted for * A map of connection group IDs to the set of permissions granted for
* that connection group. * that connection group.
*/ */
public Map<String, EnumSet<ObjectPermission.Type>> getConnectionGroupPermissions() { public Map<String, Set<ObjectPermission.Type>> getConnectionGroupPermissions() {
return connectionGroupPermissions; return connectionGroupPermissions;
} }
@@ -223,7 +195,7 @@ public class APIPermissionSet {
* @return * @return
* A map of user IDs to the set of permissions granted for that user. * A map of user IDs to the set of permissions granted for that user.
*/ */
public Map<String, EnumSet<ObjectPermission.Type>> getUserPermissions() { public Map<String, Set<ObjectPermission.Type>> getUserPermissions() {
return userPermissions; return userPermissions;
} }
@@ -236,7 +208,7 @@ public class APIPermissionSet {
* @return * @return
* The set of granted system-level permissions. * The set of granted system-level permissions.
*/ */
public EnumSet<SystemPermission.Type> getSystemPermissions() { public Set<SystemPermission.Type> getSystemPermissions() {
return systemPermissions; return systemPermissions;
} }
@@ -249,7 +221,7 @@ public class APIPermissionSet {
* @param connectionPermissions * @param connectionPermissions
* The map which must replace the currently-stored map of permissions. * The map which must replace the currently-stored map of permissions.
*/ */
public void setConnectionPermissions(Map<String, EnumSet<ObjectPermission.Type>> connectionPermissions) { public void setConnectionPermissions(Map<String, Set<ObjectPermission.Type>> connectionPermissions) {
this.connectionPermissions = connectionPermissions; this.connectionPermissions = connectionPermissions;
} }
@@ -262,7 +234,7 @@ public class APIPermissionSet {
* @param connectionGroupPermissions * @param connectionGroupPermissions
* The map which must replace the currently-stored map of permissions. * The map which must replace the currently-stored map of permissions.
*/ */
public void setConnectionGroupPermissions(Map<String, EnumSet<ObjectPermission.Type>> connectionGroupPermissions) { public void setConnectionGroupPermissions(Map<String, Set<ObjectPermission.Type>> connectionGroupPermissions) {
this.connectionGroupPermissions = connectionGroupPermissions; this.connectionGroupPermissions = connectionGroupPermissions;
} }
@@ -274,7 +246,7 @@ public class APIPermissionSet {
* @param userPermissions * @param userPermissions
* The map which must replace the currently-stored map of permissions. * The map which must replace the currently-stored map of permissions.
*/ */
public void setUserPermissions(Map<String, EnumSet<ObjectPermission.Type>> userPermissions) { public void setUserPermissions(Map<String, Set<ObjectPermission.Type>> userPermissions) {
this.userPermissions = userPermissions; this.userPermissions = userPermissions;
} }
@@ -286,7 +258,7 @@ public class APIPermissionSet {
* @param systemPermissions * @param systemPermissions
* The set which must replace the currently-stored set of permissions. * The set which must replace the currently-stored set of permissions.
*/ */
public void setSystemPermissions(EnumSet<SystemPermission.Type> systemPermissions) { public void setSystemPermissions(Set<SystemPermission.Type> systemPermissions) {
this.systemPermissions = systemPermissions; this.systemPermissions = systemPermissions;
} }

View File

@@ -22,15 +22,17 @@
package org.glyptodon.guacamole.net.basic.rest.user; package org.glyptodon.guacamole.net.basic.rest.user;
import java.util.Collections;
import java.util.Set;
import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleUnsupportedException;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
/** /**
* A wrapper to make an APIConnection look like a User. Useful where a * A wrapper to make an APIUser look like a User. Useful where an
* org.glyptodon.guacamole.net.auth.User is required. * org.glyptodon.guacamole.net.auth.User is required. As a simple wrapper for
* APIUser, access to permissions is not provided. Any attempt to access or
* manipulate permissions on an APIUserWrapper will result in an exception.
* *
* @author James Muehlner * @author James Muehlner
*/ */
@@ -41,12 +43,6 @@ public class APIUserWrapper implements User {
*/ */
private final APIUser apiUser; private final APIUser apiUser;
/**
* The set of permissions for this user.
* NOTE: Not exposed by the REST endpoints.
*/
private Set<Permission> permissionSet = Collections.EMPTY_SET;
/** /**
* Wrap a given APIUser to expose as a User. * Wrap a given APIUser to expose as a User.
* @param apiUser The APIUser to wrap. * @param apiUser The APIUser to wrap.
@@ -55,16 +51,6 @@ public class APIUserWrapper implements User {
this.apiUser = apiUser; this.apiUser = apiUser;
} }
/**
* Wrap a given APIUser to expose as a User, with the given permission set.
* @param apiUser The APIUser to wrap.
* @param permissionSet The set of permissions for the wrapped user.
*/
public APIUserWrapper(APIUser apiUser, Set<Permission> permissionSet) {
this.apiUser = apiUser;
this.permissionSet = permissionSet;
}
@Override @Override
public String getUsername() { public String getUsername() {
return apiUser.getUsername(); return apiUser.getUsername();
@@ -86,23 +72,27 @@ public class APIUserWrapper implements User {
} }
@Override @Override
public Set<Permission> getPermissions() throws GuacamoleException { public SystemPermissionSet getSystemPermissions()
return permissionSet; throws GuacamoleException {
throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access.");
} }
@Override @Override
public boolean hasPermission(Permission permission) throws GuacamoleException { public ObjectPermissionSet<String> getConnectionPermissions()
return permissionSet.contains(permission); throws GuacamoleException {
throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access.");
} }
@Override @Override
public void addPermission(Permission permission) throws GuacamoleException { public ObjectPermissionSet<String> getConnectionGroupPermissions()
throw new UnsupportedOperationException("Operation not supported."); throws GuacamoleException {
throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access.");
} }
@Override @Override
public void removePermission(Permission permission) throws GuacamoleException { public ObjectPermissionSet<String> getUserPermissions()
throw new UnsupportedOperationException("Operation not supported."); throws GuacamoleException {
throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access.");
} }
} }

View File

@@ -24,6 +24,7 @@ package org.glyptodon.guacamole.net.basic.rest.user;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@@ -43,12 +44,12 @@ import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
import org.glyptodon.guacamole.net.auth.Directory; import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User; import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext; 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.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.Permission; import org.glyptodon.guacamole.net.auth.permission.Permission;
import org.glyptodon.guacamole.net.auth.permission.PermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.UserPermission; import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.net.basic.rest.APIPatch; 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.add;
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove; import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove;
@@ -132,13 +133,13 @@ public class UserRESTService {
private boolean hasUserPermission(User user, String username, private boolean hasUserPermission(User user, String username,
List<ObjectPermission.Type> permissions) throws GuacamoleException { List<ObjectPermission.Type> permissions) throws GuacamoleException {
// Retrieve user permissions
ObjectPermissionSet<String> userPermissions = user.getUserPermissions();
// Determine whether user has at least one of the given permissions // Determine whether user has at least one of the given permissions
for (ObjectPermission.Type permission : permissions) { for (ObjectPermission.Type permission : permissions) {
if (userPermissions.hasPermission(permission, username))
UserPermission userPermission = new UserPermission(permission, username);
if (user.hasPermission(userPermission))
return true; return true;
} }
// None of the given permissions were present // None of the given permissions were present
@@ -181,7 +182,8 @@ public class UserRESTService {
permissions = null; permissions = null;
// An admin user has access to any user // An admin user has access to any user
boolean isAdmin = self.hasPermission(new SystemPermission(SystemPermission.Type.ADMINISTER)); SystemPermissionSet systemPermissions = self.getSystemPermissions();
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
// Get the directory // Get the directory
Directory<String, User> userDirectory = userContext.getUserDirectory(); Directory<String, User> userDirectory = userContext.getUserDirectory();
@@ -379,7 +381,53 @@ public class UserRESTService {
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\""); throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
} }
return new APIPermissionSet(user.getPermissions()); return new APIPermissionSet(user);
}
/**
* Updates the given permission set by adding or removing the given
* permission based on the given patch operation.
*
* @param <PermissionType>
* The type of permission stored within the permission set.
*
* @param operation
* The patch operation to perform.
*
* @param permissionSet
* The permission set being modified.
*
* @param permission
* The permission being added or removed from the set.
*
* @throws GuacamoleException
* If an error occurs while modifying the permission set.
*/
private <PermissionType extends Permission> void updatePermissionSet(
APIPatch.Operation operation,
PermissionSet<PermissionType> permissionSet,
PermissionType permission) throws GuacamoleException {
// Add or remove permission based on operation
switch (operation) {
// Add permission
case add:
permissionSet.addPermissions(Collections.singleton(permission));
break;
// Remove permission
case remove:
permissionSet.removePermissions(Collections.singleton(permission));
break;
// Unsupported patch operation
default:
throw new HTTPException(Status.BAD_REQUEST,
"Unsupported patch operation: \"" + operation + "\"");
}
} }
@@ -423,8 +471,6 @@ public class UserRESTService {
// Apply all patch operations individually // Apply all patch operations individually
for (APIPatch<String> patch : patches) { for (APIPatch<String> patch : patches) {
Permission permission;
String path = patch.getPath(); String path = patch.getPath();
// Create connection permission if path has connection prefix // Create connection permission if path has connection prefix
@@ -434,8 +480,9 @@ public class UserRESTService {
String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length()); String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create corresponding permission // Create and update corresponding permission
permission = new ConnectionPermission(type, identifier); ObjectPermission<String> permission = new ObjectPermission<String>(type, identifier);
updatePermissionSet(patch.getOp(), user.getConnectionPermissions(), permission);
} }
@@ -446,8 +493,9 @@ public class UserRESTService {
String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length()); String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create corresponding permission // Create and update corresponding permission
permission = new ConnectionGroupPermission(type, identifier); ObjectPermission<String> permission = new ObjectPermission<String>(type, identifier);
updatePermissionSet(patch.getOp(), user.getConnectionGroupPermissions(), permission);
} }
@@ -458,9 +506,10 @@ public class UserRESTService {
String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length()); String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue()); ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create corresponding permission // Create and update corresponding permission
permission = new UserPermission(type, identifier); ObjectPermission<String> permission = new ObjectPermission<String>(type, identifier);
updatePermissionSet(patch.getOp(), user.getUserPermissions(), permission);
} }
// Create system permission if path is system path // Create system permission if path is system path
@@ -469,8 +518,9 @@ public class UserRESTService {
// Get identifier and type from patch operation // Get identifier and type from patch operation
SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue()); SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue());
// Create corresponding permission // Create and update corresponding permission
permission = new SystemPermission(type); SystemPermission permission = new SystemPermission(type);
updatePermissionSet(patch.getOp(), user.getSystemPermissions(), permission);
} }
@@ -478,26 +528,6 @@ public class UserRESTService {
else else
throw new HTTPException(Status.BAD_REQUEST, "Unsupported patch path: \"" + path + "\""); 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 } // end for each patch operation
// Save the permission changes // Save the permission changes