diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProvider.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProvider.java index e3f0bbd44..b431ad10e 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProvider.java +++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProvider.java @@ -37,6 +37,11 @@ import org.apache.guacamole.token.TokenFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Class providing the necessary hooks into the Guacamole Client authentication + * process so that the QuickConnect functionality can be initialized and be used + * throughout the web client. + */ public class QuickConnectAuthenticationProvider extends SimpleAuthenticationProvider { /** @@ -44,17 +49,16 @@ public class QuickConnectAuthenticationProvider extends SimpleAuthenticationProv */ private final Logger logger = LoggerFactory.getLogger(QuickConnectAuthenticationProvider.class); - private UserContext userContext = null; - - @Inject - private Provider userContextProvider; + /** + * userContext for this authentication provider. + */ + private UserContext userContext; @Override public String getIdentifier() { return "quickconnect"; } - /** * For QuickConnect, authenticateUser simply returns null because this * extension is designed to provide only a connection directory to users @@ -71,14 +75,10 @@ public class QuickConnectAuthenticationProvider extends SimpleAuthenticationProv public AuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { - logger.debug(">>>QuickConnect<<< authenticateUser running for user {}.", credentials.getUsername()); - String username = credentials.getUsername(); - if(username == null || username.isEmpty()) + if (username == null || username.isEmpty()) throw new GuacamoleInvalidCredentialsException("You must login.", CredentialsInfo.USERNAME_PASSWORD); - userContext = new QuickConnectUserContext(this, credentials.getUsername()); - return null; } @@ -88,67 +88,14 @@ public class QuickConnectAuthenticationProvider extends SimpleAuthenticationProv getAuthorizedConfigurations(Credentials credentials) throws GuacamoleException { - logger.debug(">>>QuickConnect<<< Retrieving configurations for user {}", credentials.getUsername()); - - if(userContext == null) - userContext = new QuickConnectUserContext(this, credentials.getUsername()); - return Collections.emptyMap(); } - private Map - getFilteredAuthorizedConfigurations(Credentials credentials) - throws GuacamoleException { - - logger.debug(">>>QuickConnect<<< Filtering configurations."); - - // Get configurations - Map configs = - getAuthorizedConfigurations(credentials); - - // Return as unauthorized if not authorized to retrieve configs - if (configs == null) - return null; - - // Build credential TokenFilter - TokenFilter tokenFilter = new TokenFilter(); - StandardTokens.addStandardTokens(tokenFilter, credentials); - - // Filter each configuration - for (GuacamoleConfiguration config : configs.values()) - tokenFilter.filterValues(config.getParameters()); - - return configs; - - } - - private Map - getFilteredAuthorizedConfigurations(AuthenticatedUser authenticatedUser) - throws GuacamoleException { - - // Pull using credentials - return getFilteredAuthorizedConfigurations(authenticatedUser.getCredentials()); - - } - @Override public UserContext getUserContext(AuthenticatedUser authenticatedUser) throws GuacamoleException { - logger.debug(">>>QuickConnect<<< getUserContext for {}", authenticatedUser.getCredentials().getUsername()); - - // Get configurations - // Map configs = - // getFilteredAuthorizedConfigurations(authenticatedUser); - - // Return as unauthorized if not authorized to retrieve configs - // if (configs == null) - // return null; - - // Return user context restricted to authorized configs - // return new QuickConnectUserContext(this, authenticatedUser.getIdentifier(), configs); - return new QuickConnectUserContext(this, authenticatedUser.getIdentifier()); } diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProviderModule.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProviderModule.java index 54f7c4163..397de5aa9 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectAuthenticationProviderModule.java @@ -71,8 +71,10 @@ public class QuickConnectAuthenticationProviderModule extends AbstractModule { bind(Environment.class).toInstance(environment); // Bind QuickConnect-specific classes; + bind(QuickConnectConnectionGroup.class); bind(QuickConnectDirectory.class); bind(QuickConnectUserContext.class); + bind(QuickConnection.class); } diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectConnectionGroup.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectConnectionGroup.java index 94d00d7c6..df10ba13d 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectConnectionGroup.java +++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectConnectionGroup.java @@ -31,6 +31,11 @@ import org.apache.guacamole.net.auth.AbstractConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.protocol.GuacamoleClientInformation; +/** + * Provides a very simple, single-level connection group used + * for temporarily storing the QuickConnections created by + * users. + */ class QuickConnectConnectionGroup extends AbstractConnectionGroup { /** @@ -38,6 +43,15 @@ class QuickConnectConnectionGroup extends AbstractConnectionGroup { */ private Set connectionIdentifiers; + /** + * Set up a QuickConnectConnectionGroup with a name and identifier, and + * an empty set of child connections. + * + * @param name + * The name of the QuickConnectConnectionGroup. + * @param identifier + * The identifier of the QuickConnectConnectionGroup. + */ public QuickConnectConnectionGroup(String name, String identifier) { setName(name); @@ -48,15 +62,20 @@ class QuickConnectConnectionGroup extends AbstractConnectionGroup { } - public QuickConnectConnectionGroup(String name, String identifier, - Collection connectionIdentifiers) { - - setName(name); - setIdentifier(identifier); - setType(ConnectionGroup.Type.ORGANIZATIONAL); - - this.connectionIdentifiers = new HashSet(connectionIdentifiers); - + /** + * Add a connection identifier to this connection group, and + * return the identifier if the add succeeds, else return null. + * + * @param identifier + * The identifier of the connection to add to the group. + * @return + * The String identifier of the connection if the add + * operation was successful; otherwise null. + */ + public String addConnectionIdentifier(String identifier) { + if (connectionIdentifiers.add(identifier)) + return identifier; + return null; } @Override @@ -90,10 +109,4 @@ class QuickConnectConnectionGroup extends AbstractConnectionGroup { throw new GuacamoleSecurityException("Permission denied."); } - public String addConnectionIdentifier(String identifier) { - if (connectionIdentifiers.add(identifier)) - return identifier; - return null; - } - } diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectDirectory.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectDirectory.java index f77a5a78c..370961c0c 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectDirectory.java +++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectDirectory.java @@ -68,35 +68,38 @@ public class QuickConnectDirectory extends SimpleConnectionDirectory { public QuickConnectDirectory(Collection connections, ConnectionGroup rootGroup) { super(connections); this.rootGroup = (QuickConnectConnectionGroup)rootGroup; - logger.debug(">>>QuickConnect<<< Created new directory."); - } + /** + * Returns the current counter and then increments it. + * + * @returns + * An Integer representing the next available connection + * ID to get used when adding connections. + */ private Integer getNextConnectionID() { return CONNECTION_ID++; } @Override public void add(Connection object) throws GuacamoleException { - logger.debug(">>>QuickConnect<<< Adding connection object."); + + // Get the next connection ID. String connectionId = getNextConnectionID().toString(); + + // Set up identifier and parent on original object. object.setIdentifier(connectionId); object.setParentIdentifier(ROOT_IDENTIFIER); - /* - SimpleConnection newConn = new SimpleConnection( - object.getName(), - connectionId, - object.getConfiguration() - ); - newConn.setParentIdentifier(ROOT_IDENTIFIER); - */ + + // Add connection to the directory putConnection(new QuickConnection(object)); + + // Add connection to the tree this.rootGroup.addConnectionIdentifier(connectionId); } @Override public void update(Connection object) throws GuacamoleException { - logger.debug(">>>QuickConnect<<< Updating connection object."); putConnection(object); } diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectUserContext.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectUserContext.java index 9d12eaab2..4fe4b38d2 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectUserContext.java +++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnectUserContext.java @@ -47,9 +47,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * An extremely simple UserContext implementation which provides access to - * a defined and restricted set of GuacamoleConfigurations. Access to - * querying or modifying either users or permissions is denied. + * A simple implementation of UserContext to support the QuickConnect + * extension, primarily used for storing connections the user has + * created using the QuickConnect bar in the webapp. */ public class QuickConnectUserContext implements UserContext { @@ -98,107 +98,41 @@ public class QuickConnectUserContext implements UserContext { private final ConnectionGroup rootGroup; /** - * Creates a new SimpleUserContext which provides access to only those - * configurations within the given Map. The username is assigned - * arbitrarily. + * Construct a QuickConnectUserContext using the authProvider and + * the username. * * @param authProvider - * The AuthenticationProvider creating this UserContext. - * - * @param configs - * A Map of all configurations for which the user associated with this - * UserContext has read access. - */ - public QuickConnectUserContext(AuthenticationProvider authProvider, - Map configs) { - this(authProvider, UUID.randomUUID().toString(), configs); - logger.debug(">>>QuickConnect<<< Constructor with authProvider and configs."); - } - - /** - * Creates a new SimpleUserContext for the user with the given username - * which provides access to only those configurations within the given Map. - * - * @param authProvider - * The AuthenticationProvider creating this UserContext. - * + * The authentication provider module instantiating this + * this class. * @param username - * The username of the user associated with this UserContext. - * - * @param configs - * A Map of all configurations for which the user associated with - * this UserContext has read access. + * The name of the user logging in and using this class. */ - public QuickConnectUserContext(AuthenticationProvider authProvider, - String username, Map configs) { - - Collection connectionIdentifiers = new ArrayList(configs.size()); - Collection connectionGroupIdentifiers = Collections.singleton(ROOT_IDENTIFIER); - - // Produce collection of connections from given configs - Collection connections = new ArrayList(configs.size()); - for (Map.Entry configEntry : configs.entrySet()) { - - // Get connection identifier and configuration - String identifier = configEntry.getKey(); - GuacamoleConfiguration config = configEntry.getValue(); - - // Add as simple connection - Connection connection = new SimpleConnection(identifier, identifier, config); - connection.setParentIdentifier(ROOT_IDENTIFIER); - connections.add(connection); - - // Add identifier to overall set of identifiers - connectionIdentifiers.add(identifier); - - } - - // Add root group that contains only the given configurations - this.rootGroup = new QuickConnectConnectionGroup( - ROOT_IDENTIFIER, ROOT_IDENTIFIER, - connectionIdentifiers - ); - - // Build new user from credentials - this.self = new SimpleUser(username, connectionIdentifiers, - connectionGroupIdentifiers); - - // Create directories for new user - this.userDirectory = new SimpleUserDirectory(self); - this.connectionDirectory = new QuickConnectDirectory(connections,this.rootGroup); - this.connectionGroupDirectory = new SimpleConnectionGroupDirectory(Collections.singleton(this.rootGroup)); - - // Associate provided AuthenticationProvider - this.authProvider = authProvider; - - } - public QuickConnectUserContext(AuthenticationProvider authProvider, String username) { + // Initialize the rootGroup to a basic connection group with a + // single root identifier. this.rootGroup = new QuickConnectConnectionGroup( ROOT_IDENTIFIER, ROOT_IDENTIFIER ); + // Initialize the user to a SimpleUser with the username, no + // preexisting connections, and the single root group. this.self = new SimpleUser(username, Collections.emptyList(), Collections.singleton(ROOT_IDENTIFIER) ); + // Initialize each of the directories associated with the userContext. this.userDirectory = new SimpleUserDirectory(self); this.connectionDirectory = new QuickConnectDirectory(Collections.emptyList(), this.rootGroup); this.connectionGroupDirectory = new SimpleConnectionGroupDirectory(Collections.singleton(this.rootGroup)); + // Set the authProvider to the calling authProvider object. this.authProvider = authProvider; } - public void setConfigs(Map configs) { - - return; - - } - @Override public User self() { return self; @@ -217,35 +151,23 @@ public class QuickConnectUserContext implements UserContext { @Override public Directory getUserDirectory() throws GuacamoleException { - - logger.debug(">>>QuickConnect<<< Returning the entire user directory: {}", userDirectory.getIdentifiers()); - return userDirectory; } @Override public Directory getConnectionDirectory() throws GuacamoleException { - - logger.debug(">>>QuickConnect<<< Returning the entire connection directory: {}", connectionDirectory.getIdentifiers()); - return connectionDirectory; } @Override public Directory getConnectionGroupDirectory() throws GuacamoleException { - - logger.debug(">>>QuickConnect<<< Returning the entire group directory: {}", connectionGroupDirectory.getIdentifiers()); - return connectionGroupDirectory; } @Override public ConnectionGroup getRootConnectionGroup() throws GuacamoleException { - - logger.debug(">>>QuickConnect<<< Returning the entire root Connection Group: {}", rootGroup); - return rootGroup; } diff --git a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnection.java b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnection.java index f675057b6..cbcdd4fa0 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnection.java +++ b/extensions/guacamole-auth-quickconnect/src/main/java/org/apache/guacamole/auth/quickconnect/QuickConnection.java @@ -39,6 +39,9 @@ import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket; import org.apache.guacamole.protocol.GuacamoleClientInformation; import org.apache.guacamole.protocol.GuacamoleConfiguration; +/** + * A type of Connection specific to this authentication extension. + */ public class QuickConnection extends AbstractConnection { /** @@ -51,10 +54,26 @@ public class QuickConnection extends AbstractConnection { */ private int activeConnections; + /** + * Empty connection constructor. + */ public QuickConnection() { } + /** + * Constructor that takes a name, identifier, and GuacamoleConfiguration + * and builds a QuickConnection from it. + * + * @param name + * The name of the connection. + * @param identifier + * The unique identifier of this connection within this + * authentication module. + * @param config + * The GuacamoleConfiguration object to store in this + * QuickConnection. + */ public QuickConnection(String name, String identifier, GuacamoleConfiguration config) { @@ -69,6 +88,14 @@ public class QuickConnection extends AbstractConnection { } + /** + * Constructs a QuickConnection from a generic Connection + * object, copying over the relevant data and initializing + * the rest. + * + * @param object + * The generic Connection object to be copied. + */ public QuickConnection(Connection object) { setName(object.getName()); diff --git a/extensions/guacamole-auth-quickconnect/src/main/resources/controllers/quickconnectController.js b/extensions/guacamole-auth-quickconnect/src/main/resources/controllers/quickconnectController.js index 1a120a89a..156a84d5e 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/resources/controllers/quickconnectController.js +++ b/extensions/guacamole-auth-quickconnect/src/main/resources/controllers/quickconnectController.js @@ -23,8 +23,6 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope', '$injector', '$log', function manageConnectionController($scope, $injector, $log) { - $log.debug('In quickconnectController...'); - // Required types var ClientIdentifier = $injector.get('ClientIdentifier'); var Connection = $injector.get('Connection'); @@ -58,8 +56,6 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope */ $scope.quickConnect = function quickConnect() { - $log.debug('Got saveConnection() call.'); - // Construct parameters from URI... /** * Parse URL into the following components: @@ -75,14 +71,10 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope * [17] - JS Route */ var regexURL = /^(((rdp|ssh|telnet|vnc)?):\/)?\/?((.*?)(:(.*?)|)@)?([^:\/\s]+)(:([^\/]*))?((\/\w+\/)*)([-\w.\/]+[^#?\s]*)?(\?([^#]*))?(#(.*))?$/g; - $log.debug(regexURL); var urlArray = regexURL.exec($scope.uri); - $log.debug($scope.uri); - $log.debug(urlArray); var gettingProtocols = schemaService.getProtocols('quickconnect'); gettingProtocols.success(function checkProtocol(supportedProtocols) { - $log.debug(supportedProtocols); if (!(urlArray[3] in supportedProtocols)) { guacNotification.showStatus({ 'className' : 'error', @@ -94,6 +86,8 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope } var port = 0; var urlParams = Array(); + + // Default port assignments for various protocols. switch(urlArray[3]) { case 'rdp': port = 3389; @@ -111,23 +105,29 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope port = 0; } + // If the port is explicitly set, overwrite the default if (!isNaN(urlArray[10])) port = parseInt(urlArray[10]); + // Parse out any additional URI parameters on the connection string into an array. if (!(typeof urlArray[15] === 'undefined')) urlParams = JSON.parse('{"' + decodeURI(urlArray[15]).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'); - console.log(urlParams); - var connParams = {}; + + // If hostname is undefined, assume localhost if (!(typeof urlArray[8] === 'undefined')) connParams['hostname'] = urlArray[8]; else connParams['hostname'] = 'localhost'; + + // Username and password if (!(typeof urlArray[5] === 'undefined')) connParams['username'] = urlArray[5]; if (!(typeof urlArray[7] === 'undefined')) connParams['password'] = urlArray[7]; + + // Additional connection parameters connParams['port'] = port; connParams['read-only'] = 'read-only' in urlParams ? urlParams['read-only'] : ''; connParams['swap-red-blue'] = 'swap-red-blue' in urlParams ? urlParams['swap-red-blue'] : ''; @@ -145,21 +145,23 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope connParams['private-key'] = 'private-key' in urlParams ? urlParams['private-key'] : ''; connParams['passphrase'] = 'passphrase' in urlParams ? urlParams['passphrase'] : ''; + // Set up the name of the connection based on various parts of the URI var connName = urlArray[3] + '://'; if(!(typeof connParams['username'] === 'undefined')) connName += connParams['username'] + '@'; connName += connParams['hostname'] + ':' + connParams['port']; - + + // Create the new connection $scope.connection = new Connection({ name : connName, protocol : urlArray[3], parameters: connParams }); - console.log($scope.connection); + // Save the new connection into the QuickConnect datasource. connectionService.saveConnection($scope.selectedDataSource, $scope.connection) .success(function runConnection(newConnection) { - $log.debug('Connection saved - we should run it, now: ' + newConnection.identifier); + // If the save succeeds, launch the new connection. $location.url('/client/' + ClientIdentifier.toString({ dataSource : $scope.selectedDataSource, type : ClientIdentifier.Types.CONNECTION, @@ -177,31 +179,8 @@ angular.module('guacQuickConnect').controller('quickconnectController', ['$scope }); - - return; - /* - $scope.connection.parameters = $scope.parameters; - - // Save the connection - connectionService.saveConnection($scope.selectedDataSource, $scope.connection) - .success(function savedConnection(newConnection) { - $log.debug('Connection saved successfully: ' + newConnection); - // $location.url('/settings/' + encodeURIComponent($scope.selectedDataSource) + '/connections'); - }) - - // Notify of any errors - .error(function connectionSaveFailed(error) { - guacNotification.showStatus({ - 'className' : 'error', - 'title' : 'MANAGE_CONNECTION.DIALOG_HEADER_ERROR', - 'text' : error.translatableMessage, - 'actions' : [ ACKNOWLEDGE_ACTION ] - }); - }); - */ - }; }]); diff --git a/extensions/guacamole-auth-quickconnect/src/main/resources/quickconnectModule.js b/extensions/guacamole-auth-quickconnect/src/main/resources/quickconnectModule.js index 7635a1ed2..ed397a6ed 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/resources/quickconnectModule.js +++ b/extensions/guacamole-auth-quickconnect/src/main/resources/quickconnectModule.js @@ -18,7 +18,7 @@ */ /** - * Module which provides Adhoc connection capability + * Module which provides QuickConnect capability */ angular.module('guacQuickConnect', [ 'form' diff --git a/extensions/guacamole-auth-quickconnect/src/main/resources/templates/quickconnectField.html b/extensions/guacamole-auth-quickconnect/src/main/resources/templates/quickconnectField.html index 0f53379f8..75daf4bf8 100644 --- a/extensions/guacamole-auth-quickconnect/src/main/resources/templates/quickconnectField.html +++ b/extensions/guacamole-auth-quickconnect/src/main/resources/templates/quickconnectField.html @@ -1,7 +1,9 @@
- +
+ +