mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	Merge pull request #159 from glyptodon/session-storage
GUAC-1161: Implement session-local storage.
This commit is contained in:
		| @@ -30,18 +30,34 @@ angular.module('client').factory('guacClientManager', ['$injector', | ||||
|     var ManagedClient = $injector.get('ManagedClient'); | ||||
|  | ||||
|     // Required services | ||||
|     var $window    = $injector.get('$window'); | ||||
|     var $rootScope = $injector.get('$rootScope'); | ||||
|     var $window               = $injector.get('$window'); | ||||
|     var sessionStorageFactory = $injector.get('sessionStorageFactory'); | ||||
|  | ||||
|     var service = {}; | ||||
|  | ||||
|     /** | ||||
|      * Map of all active managed clients. Each key is the ID of the connection | ||||
|      * used by that client. | ||||
|      * Getter/setter which retrieves or sets the map of all active managed | ||||
|      * clients. Each key is the ID of the connection used by that client. | ||||
|      * | ||||
|      * @type Object.<String, ManagedClient> | ||||
|      * @type Function | ||||
|      */ | ||||
|     service.managedClients = {}; | ||||
|     var storedManagedClients = sessionStorageFactory.create({}, function destroyClientStorage() { | ||||
|  | ||||
|         // Disconnect all clients when storage is destroyed | ||||
|         service.clear(); | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     /** | ||||
|      * Returns a map of all active managed clients. Each key is the ID of the | ||||
|      * connection used by that client. | ||||
|      * | ||||
|      * @returns {Object.<String, ManagedClient>} | ||||
|      *     A map of all active managed clients. | ||||
|      */ | ||||
|     service.getManagedClients = function getManagedClients() { | ||||
|         return storedManagedClients(); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Removes the existing ManagedClient associated with the connection having | ||||
| @@ -55,13 +71,15 @@ angular.module('client').factory('guacClientManager', ['$injector', | ||||
|      *     true if an existing client was removed, false otherwise. | ||||
|      */ | ||||
|     service.removeManagedClient = function replaceManagedClient(id) { | ||||
|          | ||||
|  | ||||
|         var managedClients = storedManagedClients(); | ||||
|  | ||||
|         // Remove client if it exists | ||||
|         if (id in service.managedClients) { | ||||
|         if (id in managedClients) { | ||||
|  | ||||
|             // Disconnect and remove | ||||
|             service.managedClients[id].client.disconnect(); | ||||
|             delete service.managedClients[id]; | ||||
|             managedClients[id].client.disconnect(); | ||||
|             delete managedClients[id]; | ||||
|  | ||||
|             // A client was removed | ||||
|             return true; | ||||
| @@ -96,7 +114,7 @@ angular.module('client').factory('guacClientManager', ['$injector', | ||||
|         service.removeManagedClient(id); | ||||
|  | ||||
|         // Set new client | ||||
|         return service.managedClients[id] = ManagedClient.getInstance(id, connectionParameters); | ||||
|         return storedManagedClients()[id] = ManagedClient.getInstance(id, connectionParameters); | ||||
|  | ||||
|     }; | ||||
|  | ||||
| @@ -119,12 +137,14 @@ angular.module('client').factory('guacClientManager', ['$injector', | ||||
|      */ | ||||
|     service.getManagedClient = function getManagedClient(id, connectionParameters) { | ||||
|  | ||||
|         var managedClients = storedManagedClients(); | ||||
|  | ||||
|         // Create new managed client if it doesn't already exist | ||||
|         if (!(id in service.managedClients)) | ||||
|             service.managedClients[id] = ManagedClient.getInstance(id, connectionParameters); | ||||
|         if (!(id in managedClients)) | ||||
|             managedClients[id] = ManagedClient.getInstance(id, connectionParameters); | ||||
|  | ||||
|         // Return existing client | ||||
|         return service.managedClients[id]; | ||||
|         return managedClients[id]; | ||||
|  | ||||
|     }; | ||||
|  | ||||
| @@ -133,23 +153,20 @@ angular.module('client').factory('guacClientManager', ['$injector', | ||||
|      */ | ||||
|     service.clear = function clear() { | ||||
|  | ||||
|         var managedClients = storedManagedClients(); | ||||
|  | ||||
|         // Disconnect each managed client | ||||
|         for (var id in service.managedClients) | ||||
|             service.managedClients[id].client.disconnect(); | ||||
|         for (var id in managedClients) | ||||
|             managedClients[id].client.disconnect(); | ||||
|  | ||||
|         // Clear managed clients | ||||
|         service.managedClients = {}; | ||||
|         storedManagedClients({}); | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     // Disconnect all clients when window is unloaded | ||||
|     $window.addEventListener('unload', service.clear); | ||||
|  | ||||
|     // Clear clients on logout | ||||
|     $rootScope.$on('guacLogout', function handleLogout() { | ||||
|         service.clear(); | ||||
|     }); | ||||
|  | ||||
|     return service; | ||||
|  | ||||
| }]); | ||||
|   | ||||
| @@ -137,11 +137,13 @@ angular.module('home').directive('guacRecentConnections', [function guacRecentCo | ||||
|                 if (rootGroup) | ||||
|                     addVisibleConnectionGroup(rootGroup); | ||||
|  | ||||
|                 var managedClients = guacClientManager.getManagedClients(); | ||||
|  | ||||
|                 // Add all active connections | ||||
|                 for (var id in guacClientManager.managedClients) { | ||||
|                 for (var id in managedClients) { | ||||
|  | ||||
|                     // Get corresponding managed client | ||||
|                     var client = guacClientManager.managedClients[id]; | ||||
|                     var client = managedClients[id]; | ||||
|  | ||||
|                     // Add active connections for clients with associated visible objects | ||||
|                     if (id in visibleObjects) { | ||||
| @@ -157,7 +159,7 @@ angular.module('home').directive('guacRecentConnections', [function guacRecentCo | ||||
|                 guacHistory.recentConnections.forEach(function addRecentConnection(historyEntry) { | ||||
|  | ||||
|                     // Add recent connections for history entries with associated visible objects | ||||
|                     if (historyEntry.id in visibleObjects && !(historyEntry.id in guacClientManager.managedClients)) { | ||||
|                     if (historyEntry.id in visibleObjects && !(historyEntry.id in managedClients)) { | ||||
|  | ||||
|                         var object = visibleObjects[historyEntry.id]; | ||||
|                         $scope.recentConnections.push(new RecentConnection(object.name, historyEntry)); | ||||
|   | ||||
| @@ -23,4 +23,6 @@ | ||||
| /** | ||||
|  * The module for code used to display arbitrary notifications. | ||||
|  */ | ||||
| angular.module('notification', []); | ||||
| angular.module('notification', [ | ||||
|     'storage' | ||||
| ]); | ||||
|   | ||||
| @@ -23,34 +23,33 @@ | ||||
| /** | ||||
|  * Service for displaying notifications and modal status dialogs. | ||||
|  */ | ||||
| angular.module('notification').factory('guacNotification', ['$rootScope', | ||||
|         function guacNotification($rootScope) { | ||||
| angular.module('notification').factory('guacNotification', ['$injector', | ||||
|         function guacNotification($injector) { | ||||
|  | ||||
|     // Required services | ||||
|     var $rootScope            = $injector.get('$rootScope'); | ||||
|     var sessionStorageFactory = $injector.get('sessionStorageFactory'); | ||||
|  | ||||
|     var service = {}; | ||||
|  | ||||
|     /** | ||||
|      * The current status notification, or false if no status is currently | ||||
|      * shown. | ||||
|      * Getter/setter which retrieves or sets the current status notification, | ||||
|      * which may simply be false if no status is currently shown. | ||||
|      *  | ||||
|      * @type Function | ||||
|      */ | ||||
|     var storedStatus = sessionStorageFactory.create(false); | ||||
|  | ||||
|     /** | ||||
|      * Retrieves the current status notification, which may simply be false if | ||||
|      * no status is currently shown. | ||||
|      *  | ||||
|      * @type Notification|Boolean | ||||
|      */ | ||||
|     service.status = false; | ||||
|     service.getStatus = function getStatus() { | ||||
|         return storedStatus(); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * All currently-visible notifications. | ||||
|      *  | ||||
|      * @type Notification[] | ||||
|      */ | ||||
|     service.notifications = []; | ||||
|  | ||||
|     /** | ||||
|      * The ID of the most recently shown notification, or 0 if no notifications | ||||
|      * have yet been shown. | ||||
|      * | ||||
|      * @type Number | ||||
|      */ | ||||
|     var notificationUniqueID = 0; | ||||
|      | ||||
|     /** | ||||
|      * Shows or hides the given notification as a modal status. If a status | ||||
|      * notification is currently shown, no further statuses will be shown | ||||
| @@ -77,59 +76,10 @@ angular.module('notification').factory('guacNotification', ['$rootScope', | ||||
|      * guacNotification.showStatus(false); | ||||
|      */ | ||||
|     service.showStatus = function showStatus(status) { | ||||
|         if (!service.status || !status) | ||||
|             service.status = status; | ||||
|         if (!storedStatus() || !status) | ||||
|             storedStatus(status); | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * Adds a notification to the the list of notifications shown. | ||||
|      *  | ||||
|      * @param {Notification|Object} notification | ||||
|      *     The notification to add. | ||||
|      * | ||||
|      * @returns {Number} | ||||
|      *     A unique ID for the notification that's just been added. | ||||
|      *  | ||||
|      * @example | ||||
|      *  | ||||
|      * var id = guacNotification.addNotification({ | ||||
|      *     'title'      : 'Download', | ||||
|      *     'text'       : 'You have a file ready for download!', | ||||
|      *     'actions'    : { | ||||
|      *         'name'       : 'download', | ||||
|      *         'callback'   : function () { | ||||
|      *             // download the file and remove the notification here | ||||
|      *         } | ||||
|      *     } | ||||
|      * }); | ||||
|      */ | ||||
|     service.addNotification = function addNotification(notification) { | ||||
|         var id = ++notificationUniqueID; | ||||
|  | ||||
|         service.notifications.push({ | ||||
|             notification    : notification, | ||||
|             id              : id | ||||
|         }); | ||||
|          | ||||
|         return id; | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * Remove a notification by unique ID. | ||||
|      *  | ||||
|      * @param {Number} id | ||||
|      *     The unique ID of the notification to remove. This ID is retrieved | ||||
|      *     from the initial call to addNotification. | ||||
|      */ | ||||
|     service.removeNotification = function removeNotification(id) { | ||||
|         for (var i = 0; i < service.notifications.length; i++) { | ||||
|             if (service.notifications[i].id === id) { | ||||
|                 service.notifications.splice(i, 1); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|             | ||||
|     // Hide status upon navigation | ||||
|     $rootScope.$on('$routeChangeSuccess', function() { | ||||
|         service.showStatus(false); | ||||
|   | ||||
| @@ -0,0 +1,134 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 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. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Factory for session-local storage. Creating session-local storage creates a | ||||
|  * getter/setter with semantics tied to the user's session. If a user is logged | ||||
|  * in, the storage is consistent. If the user logs out, the storage will not | ||||
|  * persist new values, and attempts to retrieve the existing value will result | ||||
|  * only in the default value. | ||||
|  */ | ||||
| angular.module('storage').factory('sessionStorageFactory', ['$injector', function sessionStorageFactory($injector) { | ||||
|  | ||||
|     // Required services | ||||
|     var $rootScope            = $injector.get('$rootScope'); | ||||
|     var authenticationService = $injector.get('authenticationService'); | ||||
|  | ||||
|     var service = {}; | ||||
|  | ||||
|     /** | ||||
|      * Creates session-local storage that uses the provided default value or | ||||
|      * getter to obtain new values as necessary. Beware that if the default is | ||||
|      * an object, the resulting getter provide deep copies for new values. | ||||
|      * | ||||
|      * @param {Function|*} [template] | ||||
|      *     The default value for new users, or a getter which returns a newly- | ||||
|      *     created default value. | ||||
|      * | ||||
|      * @param {Function} [destructor] | ||||
|      *     Function which will be called just before the stored value is | ||||
|      *     destroyed on logout, if a value is stored. | ||||
|      * | ||||
|      * @returns {Function} | ||||
|      *     A getter/setter which returns or sets the current value of the new | ||||
|      *     session-local storage. Newly-set values will only persist of the | ||||
|      *     user is actually logged in. | ||||
|      */ | ||||
|     service.create = function create(template, destructor) { | ||||
|  | ||||
|         /** | ||||
|          * Whether new values may be stored and retrieved. | ||||
|          * | ||||
|          * @type Boolean | ||||
|          */ | ||||
|         var enabled = !!authenticationService.getCurrentToken(); | ||||
|  | ||||
|         /** | ||||
|          * Getter which returns the default value for this storage. | ||||
|          * | ||||
|          * @type Function | ||||
|          */ | ||||
|         var getter; | ||||
|  | ||||
|         // If getter provided, use that | ||||
|         if (typeof template === 'function') | ||||
|             getter = template; | ||||
|  | ||||
|         // Otherwise, always create a deep copy | ||||
|         else | ||||
|             getter = function getCopy() { | ||||
|                 return angular.copy(template); | ||||
|             }; | ||||
|  | ||||
|         /** | ||||
|          * The current value of this storage, or undefined if not yet set. | ||||
|          */ | ||||
|         var value = undefined; | ||||
|  | ||||
|         // Reset value and allow storage when the user is logged in | ||||
|         $rootScope.$on('guacLogin', function userLoggedIn() { | ||||
|             enabled = true; | ||||
|             value = undefined; | ||||
|         }); | ||||
|  | ||||
|         // Reset value and disallow storage when the user is logged out | ||||
|         $rootScope.$on('guacLogout', function userLoggedOut() { | ||||
|  | ||||
|             // Call destructor before storage is teared down | ||||
|             if (angular.isDefined(value) && destructor) | ||||
|                 destructor(value); | ||||
|  | ||||
|             // Destroy storage | ||||
|             enabled = false; | ||||
|             value = undefined; | ||||
|  | ||||
|         }); | ||||
|  | ||||
|         // Return getter/setter for value | ||||
|         return function sessionLocalGetterSetter(newValue) { | ||||
|  | ||||
|             // Only actually store/retrieve values if enabled | ||||
|             if (enabled) { | ||||
|  | ||||
|                 // Set value if provided | ||||
|                 if (angular.isDefined(newValue)) | ||||
|                     value = newValue; | ||||
|  | ||||
|                 // Obtain new value if unset | ||||
|                 if (!angular.isDefined(value)) | ||||
|                     value = getter(); | ||||
|  | ||||
|                 // Return current value | ||||
|                 return value; | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // Otherwise, just pretend to store/retrieve | ||||
|             return angular.isDefined(newValue) ? newValue : getter(); | ||||
|  | ||||
|         }; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     return service; | ||||
|  | ||||
| }]); | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright (C) 2013 Glyptodon LLC | ||||
|  * Copyright (C) 2015 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 | ||||
| @@ -20,30 +20,9 @@ | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #notificationArea { | ||||
|     position: fixed; | ||||
|     right: 0.5em; | ||||
|     bottom: 0.5em; | ||||
|     max-width: 25%; | ||||
|     width: 2in; | ||||
| } | ||||
| 
 | ||||
| #notificationArea .notification { | ||||
|     font-size: 0.7em; | ||||
|     text-align: center; | ||||
|     width: 100%; | ||||
|     overflow: hidden; | ||||
| } | ||||
| 
 | ||||
| #notificationArea .notification .text { | ||||
|     width: 100%; | ||||
|     white-space: nowrap; | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
| } | ||||
| 
 | ||||
| #notificationArea .notification.error .text { | ||||
|     white-space: normal; | ||||
|     text-overflow: clip; | ||||
|     text-align: left; | ||||
| } | ||||
| /** | ||||
|  * Module which provides generic storage services. | ||||
|  */ | ||||
| angular.module('storage', [ | ||||
|     'auth' | ||||
| ]); | ||||
		Reference in New Issue
	
	Block a user