GUACAMOLE-77: Merge username fix for current vs existing users.

This commit is contained in:
James Muehlner
2016-08-20 15:07:07 -07:00
5 changed files with 81 additions and 38 deletions

View File

@@ -39,7 +39,6 @@ import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.net.auth.simple.SimpleConnectionGroupDirectory; import org.apache.guacamole.net.auth.simple.SimpleConnectionGroupDirectory;
import org.apache.guacamole.net.auth.simple.SimpleConnectionRecordSet; import org.apache.guacamole.net.auth.simple.SimpleConnectionRecordSet;
import org.apache.guacamole.net.auth.simple.SimpleDirectory; import org.apache.guacamole.net.auth.simple.SimpleDirectory;
import org.apache.guacamole.net.auth.simple.SimpleUserDirectory;
/** /**
* The user context of a SharedUser, providing access ONLY to the user * The user context of a SharedUser, providing access ONLY to the user
@@ -114,9 +113,11 @@ public class SharedUserContext implements UserContext {
this.connectionGroupDirectory = new SimpleConnectionGroupDirectory( this.connectionGroupDirectory = new SimpleConnectionGroupDirectory(
Collections.singletonList(this.rootGroup)); Collections.singletonList(this.rootGroup));
// The user directory contains only this user // Create internal pseudo-account representing the authenticated user
this.self = new SharedUser(user, this); this.self = new SharedUser(user, this);
this.userDirectory = new SimpleUserDirectory(this.self);
// Do not provide access to any user accounts via the directory
this.userDirectory = new SimpleDirectory<User>();
} }

View File

@@ -38,10 +38,18 @@
"NAME" : "MySQL" "NAME" : "MySQL"
}, },
"DATA_SOURCE_MYSQL_SHARED" : {
"NAME" : "Shared Connections (MySQL)"
},
"DATA_SOURCE_POSTGRESQL" : { "DATA_SOURCE_POSTGRESQL" : {
"NAME" : "PostgreSQL" "NAME" : "PostgreSQL"
}, },
"DATA_SOURCE_POSTGRESQL_SHARED" : {
"NAME" : "Shared Connections (PostgreSQL)"
},
"HOME" : { "HOME" : {
"INFO_SHARED_BY" : "Shared by {USERNAME}" "INFO_SHARED_BY" : "Shared by {USERNAME}"
}, },

View File

@@ -38,6 +38,8 @@ import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.rest.activeconnection.APIActiveConnection; import org.apache.guacamole.rest.activeconnection.APIActiveConnection;
import org.apache.guacamole.rest.connection.APIConnection; import org.apache.guacamole.rest.connection.APIConnection;
import org.apache.guacamole.rest.connectiongroup.APIConnectionGroup; import org.apache.guacamole.rest.connectiongroup.APIConnectionGroup;
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
import org.apache.guacamole.rest.history.HistoryResource; import org.apache.guacamole.rest.history.HistoryResource;
import org.apache.guacamole.rest.schema.SchemaResource; import org.apache.guacamole.rest.schema.SchemaResource;
import org.apache.guacamole.rest.sharingprofile.APISharingProfile; import org.apache.guacamole.rest.sharingprofile.APISharingProfile;
@@ -57,6 +59,12 @@ public class UserContextResource {
*/ */
private final UserContext userContext; private final UserContext userContext;
/**
* Factory for creating DirectoryObjectResources which expose a given User.
*/
@Inject
private DirectoryObjectResourceFactory<User, APIUser> userResourceFactory;
/** /**
* Factory for creating DirectoryResources which expose a given * Factory for creating DirectoryResources which expose a given
* ActiveConnection Directory. * ActiveConnection Directory.
@@ -109,6 +117,26 @@ public class UserContextResource {
this.userContext = userContext; this.userContext = userContext;
} }
/**
* Returns a new resource which represents the User whose access rights
* control the operations of the UserContext exposed by this
* UserContextResource.
*
* @return
* A new resource which represents the User whose access rights
* control the operations of the UserContext exposed by this
* UserContextResource.
*
* @throws GuacamoleException
* If an error occurs while retrieving the User.
*/
@Path("self")
public DirectoryObjectResource<User, APIUser> getSelfResource()
throws GuacamoleException {
return userResourceFactory.create(userContext,
userContext.getUserDirectory(), userContext.self());
}
/** /**
* Returns a new resource which represents the ActiveConnection Directory * Returns a new resource which represents the ActiveConnection Directory
* contained within the UserContext exposed by this UserContextResource. * contained within the UserContext exposed by this UserContextResource.

View File

@@ -29,7 +29,6 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory; import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
import org.apache.guacamole.rest.directory.DirectoryResource; import org.apache.guacamole.rest.directory.DirectoryResource;
@@ -44,23 +43,6 @@ import org.apache.guacamole.rest.directory.DirectoryResource;
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public class UserDirectoryResource extends DirectoryResource<User, APIUser> { public class UserDirectoryResource extends DirectoryResource<User, APIUser> {
/**
* The UserContext associated with the Directory which contains the
* User exposed by this resource.
*/
private final UserContext userContext;
/**
* The Directory exposed by this resource.
*/
private final Directory<User> directory;
/**
* A factory which can be used to create instances of resources representing
* Users.
*/
private final DirectoryObjectResourceFactory<User, APIUser> resourceFactory;
/** /**
* Creates a new UserDirectoryResource which exposes the operations and * Creates a new UserDirectoryResource which exposes the operations and
* subresources available for the given User Directory. * subresources available for the given User Directory.
@@ -85,9 +67,6 @@ public class UserDirectoryResource extends DirectoryResource<User, APIUser> {
DirectoryObjectTranslator<User, APIUser> translator, DirectoryObjectTranslator<User, APIUser> translator,
DirectoryObjectResourceFactory<User, APIUser> resourceFactory) { DirectoryObjectResourceFactory<User, APIUser> resourceFactory) {
super(userContext, directory, translator, resourceFactory); super(userContext, directory, translator, resourceFactory);
this.userContext = userContext;
this.directory = directory;
this.resourceFactory = resourceFactory;
} }
@Override @Override
@@ -101,16 +80,4 @@ public class UserDirectoryResource extends DirectoryResource<User, APIUser> {
} }
@Override
public DirectoryObjectResource<User, APIUser>
getObjectResource(String identifier) throws GuacamoleException {
// If username is own username, just use self - might not have query permissions
if (userContext.self().getIdentifier().equals(identifier))
return resourceFactory.create(userContext, directory, userContext.self());
return super.getObjectResource(identifier);
}
} }

View File

@@ -34,6 +34,45 @@ angular.module('rest').factory('permissionService', ['$injector',
var service = {}; var service = {};
/**
* Returns the URL for the REST resource most appropriate for accessing
* the permissions of the user having the given username.
*
* It is important to note that a particular data source can authenticate
* and provide permissions for a user, even if that user does not exist
* within that data source (and thus cannot be found beneath
* "api/session/data/{dataSource}/users")
*
* @param {String} dataSource
* The unique identifier of the data source containing the user whose
* permissions should be retrieved. This identifier corresponds to an
* AuthenticationProvider within the Guacamole web application.
*
* @param {String} username
* The username of the user for which the URL of the proper REST
* resource should be derived.
*
* @returns {String}
* The URL for the REST resource representing the user having the given
* username.
*/
var getPermissionsResourceURL = function getPermissionsResourceURL(dataSource, username) {
// Create base URL for data source
var base = 'api/session/data/' + encodeURIComponent(dataSource);
// If the username is that of the current user, do not rely on the
// user actually existing (they may not). Access their permissions via
// "self" rather than the collection of defined users.
if (username === authenticationService.getCurrentUsername())
return base + '/self/permissions';
// Otherwise, the user must exist for their permissions to be
// accessible. Use the collection of defined users.
return base + '/users/' + encodeURIComponent(username) + '/permissions';
};
/** /**
* Makes a request to the REST API to get the list of permissions for a * Makes a request to the REST API to get the list of permissions for a
* given user, returning a promise that provides an array of * given user, returning a promise that provides an array of
@@ -62,7 +101,7 @@ angular.module('rest').factory('permissionService', ['$injector',
return $http({ return $http({
cache : cacheService.users, cache : cacheService.users,
method : 'GET', method : 'GET',
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions', url : getPermissionsResourceURL(dataSource, userID),
params : httpParameters params : httpParameters
}); });
@@ -239,7 +278,7 @@ angular.module('rest').factory('permissionService', ['$injector',
// Patch user permissions // Patch user permissions
return $http({ return $http({
method : 'PATCH', method : 'PATCH',
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions', url : getPermissionsResourceURL(dataSource, userID),
params : httpParameters, params : httpParameters,
data : permissionPatch data : permissionPatch
}) })