From 87b517ff3e994cd1394e041bb2d2b14e4b32686e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 20 Aug 2016 13:12:04 -0700 Subject: [PATCH 1/4] GUACAMOLE-77: Add translation strings for MySQL/PostgreSQL shared connection data source. --- .../src/main/resources/translations/en.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json index 2bf807a37..20aac1698 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/resources/translations/en.json @@ -38,10 +38,18 @@ "NAME" : "MySQL" }, + "DATA_SOURCE_MYSQL_SHARED" : { + "NAME" : "Shared Connections (MySQL)" + }, + "DATA_SOURCE_POSTGRESQL" : { "NAME" : "PostgreSQL" }, + "DATA_SOURCE_POSTGRESQL_SHARED" : { + "NAME" : "Shared Connections (PostgreSQL)" + }, + "HOME" : { "INFO_SHARED_BY" : "Shared by {USERNAME}" }, From b23dcf83cac852aaa61b3d4b34e7da612fc449c4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 20 Aug 2016 13:54:20 -0700 Subject: [PATCH 2/4] GUACAMOLE-77: Distinguish within REST between the user's identity/permissions and actual existing user objects. --- .../rest/session/UserContextResource.java | 28 ++++++++++++++++ .../rest/user/UserDirectoryResource.java | 33 ------------------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java index 31bb002dc..39be48950 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/UserContextResource.java @@ -38,6 +38,8 @@ import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.rest.activeconnection.APIActiveConnection; import org.apache.guacamole.rest.connection.APIConnection; 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.schema.SchemaResource; import org.apache.guacamole.rest.sharingprofile.APISharingProfile; @@ -57,6 +59,12 @@ public class UserContextResource { */ private final UserContext userContext; + /** + * Factory for creating DirectoryObjectResources which expose a given User. + */ + @Inject + private DirectoryObjectResourceFactory userResourceFactory; + /** * Factory for creating DirectoryResources which expose a given * ActiveConnection Directory. @@ -109,6 +117,26 @@ public class UserContextResource { 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 getSelfResource() + throws GuacamoleException { + return userResourceFactory.create(userContext, + userContext.getUserDirectory(), userContext.self()); + } + /** * Returns a new resource which represents the ActiveConnection Directory * contained within the UserContext exposed by this UserContextResource. diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserDirectoryResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserDirectoryResource.java index 04218f1b9..c2515caf9 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserDirectoryResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserDirectoryResource.java @@ -29,7 +29,6 @@ import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.Directory; 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.DirectoryObjectTranslator; import org.apache.guacamole.rest.directory.DirectoryResource; @@ -44,23 +43,6 @@ import org.apache.guacamole.rest.directory.DirectoryResource; @Consumes(MediaType.APPLICATION_JSON) public class UserDirectoryResource extends DirectoryResource { - /** - * 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 directory; - - /** - * A factory which can be used to create instances of resources representing - * Users. - */ - private final DirectoryObjectResourceFactory resourceFactory; - /** * Creates a new UserDirectoryResource which exposes the operations and * subresources available for the given User Directory. @@ -85,9 +67,6 @@ public class UserDirectoryResource extends DirectoryResource { DirectoryObjectTranslator translator, DirectoryObjectResourceFactory resourceFactory) { super(userContext, directory, translator, resourceFactory); - this.userContext = userContext; - this.directory = directory; - this.resourceFactory = resourceFactory; } @Override @@ -101,16 +80,4 @@ public class UserDirectoryResource extends DirectoryResource { } - @Override - public DirectoryObjectResource - 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); - - } - } From 36dc3750730998d1524a1ebb11e937168d9c2155 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 20 Aug 2016 13:55:00 -0700 Subject: [PATCH 3/4] GUACAMOLE-77: Users do not exist within the database auth's connection sharing system. --- .../auth/jdbc/sharing/user/SharedUserContext.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUserContext.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUserContext.java index 40f2bb5e7..672045068 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUserContext.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUserContext.java @@ -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.SimpleConnectionRecordSet; 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 @@ -114,9 +113,11 @@ public class SharedUserContext implements UserContext { this.connectionGroupDirectory = new SimpleConnectionGroupDirectory( 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.userDirectory = new SimpleUserDirectory(this.self); + + // Do not provide access to any user accounts via the directory + this.userDirectory = new SimpleDirectory(); } From 20459ecbd34fc4d215460523f59e0b2efa1936ed Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 20 Aug 2016 14:23:43 -0700 Subject: [PATCH 4/4] GUACAMOLE-77: Retrieve the current user's permissions via ".../self" rather than ".../users/{username}". The current user may not actually exist. --- .../app/rest/services/permissionService.js | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/guacamole/src/main/webapp/app/rest/services/permissionService.js b/guacamole/src/main/webapp/app/rest/services/permissionService.js index 67fceba7e..a80377566 100644 --- a/guacamole/src/main/webapp/app/rest/services/permissionService.js +++ b/guacamole/src/main/webapp/app/rest/services/permissionService.js @@ -34,6 +34,45 @@ angular.module('rest').factory('permissionService', ['$injector', 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 * given user, returning a promise that provides an array of @@ -62,7 +101,7 @@ angular.module('rest').factory('permissionService', ['$injector', return $http({ cache : cacheService.users, method : 'GET', - url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions', + url : getPermissionsResourceURL(dataSource, userID), params : httpParameters }); @@ -239,7 +278,7 @@ angular.module('rest').factory('permissionService', ['$injector', // Patch user permissions return $http({ method : 'PATCH', - url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions', + url : getPermissionsResourceURL(dataSource, userID), params : httpParameters, data : permissionPatch })