mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 09:03:21 +00:00 
			
		
		
		
	Merge pull request #149 from glyptodon/settings-page
GUAC-1053: Move manage sections into tabbed settings page
This commit is contained in:
		| @@ -104,6 +104,10 @@ angular.module('form').directive('guacForm', [function form() { | |||||||
|              */ |              */ | ||||||
|             $scope.getSectionHeader = function getSectionHeader(form) { |             $scope.getSectionHeader = function getSectionHeader(form) { | ||||||
|  |  | ||||||
|  |                 // If no form, or no name, then no header | ||||||
|  |                 if (!form || !form.name) | ||||||
|  |                     return ''; | ||||||
|  |  | ||||||
|                 return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') |                 return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') | ||||||
|                         + '.SECTION_HEADER_' + translationStringService.canonicalize(form.name); |                         + '.SECTION_HEADER_' + translationStringService.canonicalize(form.name); | ||||||
|  |  | ||||||
| @@ -128,6 +132,10 @@ angular.module('form').directive('guacForm', [function form() { | |||||||
|              */ |              */ | ||||||
|             $scope.getFieldHeader = function getFieldHeader(field) { |             $scope.getFieldHeader = function getFieldHeader(field) { | ||||||
|  |  | ||||||
|  |                 // If no field, or no name, then no header | ||||||
|  |                 if (!field || !field.name) | ||||||
|  |                     return ''; | ||||||
|  |  | ||||||
|                 return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') |                 return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') | ||||||
|                         + '.FIELD_HEADER_' + translationStringService.canonicalize(field.name); |                         + '.FIELD_HEADER_' + translationStringService.canonicalize(field.name); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -131,8 +131,8 @@ angular.module('form').directive('guacFormField', [function formField() { | |||||||
|              */ |              */ | ||||||
|             $scope.getFieldOption = function getFieldOption(value) { |             $scope.getFieldOption = function getFieldOption(value) { | ||||||
|  |  | ||||||
|                 // Don't bother if the model is not yet defined |                 // If no field, or no value, then no corresponding translation string | ||||||
|                 if (!$scope.field) |                 if (!$scope.field || !$scope.field.name || !value) | ||||||
|                     return ''; |                     return ''; | ||||||
|  |  | ||||||
|                 return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') |                 return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE') | ||||||
|   | |||||||
| @@ -125,30 +125,12 @@ angular.module('index').config(['$routeProvider', '$locationProvider', | |||||||
|             resolve       : { routeToUserHomePage: routeToUserHomePage } |             resolve       : { routeToUserHomePage: routeToUserHomePage } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|         // Connection management screen |         // Management screen | ||||||
|         .when('/manage/modules/connections/', { |         .when('/settings/:tab', { | ||||||
|             title         : 'APP.NAME', |             title         : 'APP.NAME', | ||||||
|             bodyClassName : 'manage', |             bodyClassName : 'settings', | ||||||
|             templateUrl   : 'app/manage/templates/manageConnections.html', |             templateUrl   : 'app/settings/templates/settings.html', | ||||||
|             controller    : 'manageConnectionsController', |             controller    : 'settingsController', | ||||||
|             resolve       : { updateCurrentToken: updateCurrentToken } |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|         // User management screen |  | ||||||
|         .when('/manage/modules/users/', { |  | ||||||
|             title         : 'APP.NAME', |  | ||||||
|             bodyClassName : 'manage', |  | ||||||
|             templateUrl   : 'app/manage/templates/manageUsers.html', |  | ||||||
|             controller    : 'manageUsersController', |  | ||||||
|             resolve       : { updateCurrentToken: updateCurrentToken } |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|         // Session management screen |  | ||||||
|         .when('/manage/modules/sessions/', { |  | ||||||
|             title         : 'APP.NAME', |  | ||||||
|             bodyClassName : 'manage', |  | ||||||
|             templateUrl   : 'app/manage/templates/manageSessions.html', |  | ||||||
|             controller    : 'manageSessionsController', |  | ||||||
|             resolve       : { updateCurrentToken: updateCurrentToken } |             resolve       : { updateCurrentToken: updateCurrentToken } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,5 +34,6 @@ angular.module('index', [ | |||||||
|     'ngTouch', |     'ngTouch', | ||||||
|     'notification', |     'notification', | ||||||
|     'pascalprecht.translate', |     'pascalprecht.translate', | ||||||
|     'rest' |     'rest', | ||||||
|  |     'settings' | ||||||
| ]); | ]); | ||||||
|   | |||||||
| @@ -317,7 +317,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i | |||||||
|      * Cancels all pending edits, returning to the management page. |      * Cancels all pending edits, returning to the management page. | ||||||
|      */ |      */ | ||||||
|     $scope.cancel = function cancel() { |     $scope.cancel = function cancel() { | ||||||
|         $location.path('/manage/modules/connections/'); |         $location.path('/settings/connections'); | ||||||
|     }; |     }; | ||||||
|      |      | ||||||
|     /** |     /** | ||||||
| @@ -339,7 +339,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i | |||||||
|         // Save the connection |         // Save the connection | ||||||
|         connectionService.saveConnection($scope.connection) |         connectionService.saveConnection($scope.connection) | ||||||
|         .success(function savedConnection() { |         .success(function savedConnection() { | ||||||
|             $location.path('/manage/modules/connections/'); |             $location.path('/settings/connections'); | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|         // Notify of any errors |         // Notify of any errors | ||||||
| @@ -389,7 +389,7 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i | |||||||
|         // Delete the connection |         // Delete the connection | ||||||
|         connectionService.deleteConnection($scope.connection) |         connectionService.deleteConnection($scope.connection) | ||||||
|         .success(function deletedConnection() { |         .success(function deletedConnection() { | ||||||
|             $location.path('/manage/modules/connections/'); |             $location.path('/settings/connections'); | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|         // Notify of any errors |         // Notify of any errors | ||||||
|   | |||||||
| @@ -1,156 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2014 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. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * The controller for the connection and connection group administration page. |  | ||||||
|  */ |  | ||||||
| angular.module('manage').controller('manageConnectionsController', ['$scope', '$injector',  |  | ||||||
|         function manageConnectionsController($scope, $injector) { |  | ||||||
|  |  | ||||||
|     // Required types |  | ||||||
|     var ConnectionGroup = $injector.get('ConnectionGroup'); |  | ||||||
|     var PermissionSet   = $injector.get('PermissionSet'); |  | ||||||
|  |  | ||||||
|     // Required services |  | ||||||
|     var $location              = $injector.get('$location'); |  | ||||||
|     var authenticationService  = $injector.get('authenticationService'); |  | ||||||
|     var connectionGroupService = $injector.get('connectionGroupService'); |  | ||||||
|     var guacNotification       = $injector.get('guacNotification'); |  | ||||||
|     var permissionService      = $injector.get('permissionService'); |  | ||||||
|  |  | ||||||
|     // Identifier of the current user |  | ||||||
|     var currentUserID = authenticationService.getCurrentUserID(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * An action to be provided along with the object sent to showStatus which |  | ||||||
|      * closes the currently-shown status dialog. |  | ||||||
|      */ |  | ||||||
|     var ACKNOWLEDGE_ACTION = { |  | ||||||
|         name        : "MANAGE_CONNECTION.ACTION_ACKNOWLEDGE", |  | ||||||
|         // Handle action |  | ||||||
|         callback    : function acknowledgeCallback() { |  | ||||||
|             guacNotification.showStatus(false); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * The root connection group of the connection group hierarchy. |  | ||||||
|      * |  | ||||||
|      * @type ConnectionGroup |  | ||||||
|      */ |  | ||||||
|     $scope.rootGroup = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Whether the current user can manage connections. If the current |  | ||||||
|      * permissions have not yet been loaded, this will be null. |  | ||||||
|      * |  | ||||||
|      * @type Boolean |  | ||||||
|      */ |  | ||||||
|     $scope.canManageConnections = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Whether the current user can create new connections. If the current |  | ||||||
|      * permissions have not yet been loaded, this will be null. |  | ||||||
|      * |  | ||||||
|      * @type Boolean |  | ||||||
|      */ |  | ||||||
|     $scope.canCreateConnections = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Whether the current user can create new connection groups. If the |  | ||||||
|      * current permissions have not yet been loaded, this will be null. |  | ||||||
|      * |  | ||||||
|      * @type Boolean |  | ||||||
|      */ |  | ||||||
|     $scope.canCreateConnectionGroups = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * All permissions associated with the current user, or null if the user's |  | ||||||
|      * permissions have not yet been loaded. |  | ||||||
|      * |  | ||||||
|      * @type PermissionSet |  | ||||||
|      */ |  | ||||||
|     $scope.permissions = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns whether critical data has completed being loaded. |  | ||||||
|      * |  | ||||||
|      * @returns {Boolean} |  | ||||||
|      *     true if enough data has been loaded for the user interface to be |  | ||||||
|      *     useful, false otherwise. |  | ||||||
|      */ |  | ||||||
|     $scope.isLoaded = function isLoaded() { |  | ||||||
|  |  | ||||||
|         return $scope.rootGroup                 !== null |  | ||||||
|             && $scope.permissions               !== null |  | ||||||
|             && $scope.canManageConnections      !== null |  | ||||||
|             && $scope.canCreateConnections      !== null |  | ||||||
|             && $scope.canCreateConnectionGroups !== null; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // Retrieve current permissions |  | ||||||
|     permissionService.getPermissions(currentUserID) |  | ||||||
|     .success(function permissionsRetrieved(permissions) { |  | ||||||
|  |  | ||||||
|         $scope.permissions = permissions; |  | ||||||
|                          |  | ||||||
|         // Ignore permission to update root group |  | ||||||
|         PermissionSet.removeConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE, ConnectionGroup.ROOT_IDENTIFIER); |  | ||||||
|  |  | ||||||
|         // Determine whether the current user can create new users |  | ||||||
|         $scope.canCreateConnections = |  | ||||||
|                PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) |  | ||||||
|             || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_CONNECTION); |  | ||||||
|  |  | ||||||
|         // Determine whether the current user can create new users |  | ||||||
|         $scope.canCreateConnectionGroups = |  | ||||||
|                PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) |  | ||||||
|             || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_CONNECTION_GROUP); |  | ||||||
|  |  | ||||||
|         // Determine whether the current user can manage other connections or groups |  | ||||||
|         $scope.canManageConnections = |  | ||||||
|  |  | ||||||
|             // Permission to manage connections |  | ||||||
|                $scope.canCreateConnections |  | ||||||
|             || PermissionSet.hasConnectionPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) |  | ||||||
|             || PermissionSet.hasConnectionPermission(permissions, PermissionSet.ObjectPermissionType.DELETE) |  | ||||||
|  |  | ||||||
|             // Permission to manage groups |  | ||||||
|             || $scope.canCreateConnectionGroups |  | ||||||
|             || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) |  | ||||||
|             || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.DELETE); |  | ||||||
|  |  | ||||||
|         // Return to home if there's nothing to do here |  | ||||||
|         if (!$scope.canManageConnections) |  | ||||||
|             $location.path('/'); |  | ||||||
|          |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     // Retrieve all connections for which we have UPDATE or DELETE permission |  | ||||||
|     connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER,  |  | ||||||
|         [PermissionSet.ObjectPermissionType.UPDATE, PermissionSet.ObjectPermissionType.DELETE]) |  | ||||||
|     .success(function connectionGroupReceived(rootGroup) { |  | ||||||
|         $scope.rootGroup = rootGroup; |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
| }]); |  | ||||||
| @@ -1,349 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * The controller for the user session administration page. |  | ||||||
|  */ |  | ||||||
| angular.module('manage').controller('manageSessionsController', ['$scope', '$injector',  |  | ||||||
|         function manageSessionsController($scope, $injector) { |  | ||||||
|  |  | ||||||
|     // Required types |  | ||||||
|     var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper'); |  | ||||||
|     var ConnectionGroup         = $injector.get('ConnectionGroup'); |  | ||||||
|     var SortOrder               = $injector.get('SortOrder'); |  | ||||||
|  |  | ||||||
|     // Required services |  | ||||||
|     var $filter                 = $injector.get('$filter'); |  | ||||||
|     var $translate              = $injector.get('$translate'); |  | ||||||
|     var activeConnectionService = $injector.get('activeConnectionService'); |  | ||||||
|     var authenticationService   = $injector.get('authenticationService'); |  | ||||||
|     var connectionGroupService  = $injector.get('connectionGroupService'); |  | ||||||
|     var guacNotification        = $injector.get('guacNotification'); |  | ||||||
|     var permissionService       = $injector.get('permissionService'); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * All permissions associated with the current user, or null if the user's |  | ||||||
|      * permissions have not yet been loaded. |  | ||||||
|      * |  | ||||||
|      * @type PermissionSet |  | ||||||
|      */ |  | ||||||
|     $scope.permissions = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * The ActiveConnectionWrappers of all active sessions accessible by the |  | ||||||
|      * current user, or null if the active sessions have not yet been loaded. |  | ||||||
|      * |  | ||||||
|      * @type ActiveConnectionWrapper[] |  | ||||||
|      */ |  | ||||||
|     $scope.wrappers = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * SortOrder instance which maintains the sort order of the visible |  | ||||||
|      * connection wrappers. |  | ||||||
|      * |  | ||||||
|      * @type SortOrder |  | ||||||
|      */ |  | ||||||
|     $scope.wrapperOrder = new SortOrder([ |  | ||||||
|         'activeConnection.username', |  | ||||||
|         'startDate', |  | ||||||
|         'activeConnection.remoteHost', |  | ||||||
|         'name' |  | ||||||
|     ]); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Array of all wrapper properties that are filterable. |  | ||||||
|      * |  | ||||||
|      * @type String[] |  | ||||||
|      */ |  | ||||||
|     $scope.filteredWrapperProperties = [ |  | ||||||
|         'activeConnection.username', |  | ||||||
|         'startDate', |  | ||||||
|         'activeConnection.remoteHost', |  | ||||||
|         'name' |  | ||||||
|     ]; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * All active connections, if known, or null if active connections have not |  | ||||||
|      * yet been loaded. |  | ||||||
|      * |  | ||||||
|      * @type ActiveConnection |  | ||||||
|      */ |  | ||||||
|     var activeConnections = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Map of all visible connections by object identifier, or null if visible |  | ||||||
|      * connections have not yet been loaded. |  | ||||||
|      * |  | ||||||
|      * @type Object.<String, Connection> |  | ||||||
|      */ |  | ||||||
|     var connections = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * The date format for use for session-related dates. |  | ||||||
|      * |  | ||||||
|      * @type String |  | ||||||
|      */ |  | ||||||
|     var sessionDateFormat = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Map of all currently-selected active connection wrappers by identifier. |  | ||||||
|      *  |  | ||||||
|      * @type Object.<String, ActiveConnectionWrapper> |  | ||||||
|      */ |  | ||||||
|     var selectedWrappers = {}; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Adds the given connection to the internal set of visible |  | ||||||
|      * connections. |  | ||||||
|      *  |  | ||||||
|      * @param {Connection} connection |  | ||||||
|      *     The connection to add to the internal set of visible connections. |  | ||||||
|      */ |  | ||||||
|     var addConnection = function addConnection(connection) { |  | ||||||
|  |  | ||||||
|         // Add given connection to set of visible connections |  | ||||||
|         connections[connection.identifier] = connection; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Adds all descendant connections of the given connection group to the |  | ||||||
|      * internal set of connections. |  | ||||||
|      *  |  | ||||||
|      * @param {ConnectionGroup} connectionGroup |  | ||||||
|      *     The connection group whose descendant connections should be added to |  | ||||||
|      *     the internal set of connections. |  | ||||||
|      */ |  | ||||||
|     var addDescendantConnections = function addDescendantConnections(connectionGroup) { |  | ||||||
|  |  | ||||||
|         // Add all child connections |  | ||||||
|         if (connectionGroup.childConnections) |  | ||||||
|             connectionGroup.childConnections.forEach(addConnection); |  | ||||||
|  |  | ||||||
|         // Add all child connection groups |  | ||||||
|         if (connectionGroup.childConnectionGroups) |  | ||||||
|             connectionGroup.childConnectionGroups.forEach(addDescendantConnections); |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Wraps all loaded active connections, storing the resulting array within |  | ||||||
|      * the scope. If required data has not yet finished loading, this function |  | ||||||
|      * has no effect. |  | ||||||
|      */ |  | ||||||
|     var wrapActiveConnections = function wrapActiveConnections() { |  | ||||||
|  |  | ||||||
|         // Abort if not all required data is available |  | ||||||
|         if (!activeConnections || !connections || !sessionDateFormat) |  | ||||||
|             return; |  | ||||||
|  |  | ||||||
|         // Wrap all active connections for sake of display |  | ||||||
|         $scope.wrappers = []; |  | ||||||
|         for (var identifier in activeConnections) { |  | ||||||
|  |  | ||||||
|             var activeConnection = activeConnections[identifier]; |  | ||||||
|             var connection = connections[activeConnection.connectionIdentifier]; |  | ||||||
|  |  | ||||||
|             $scope.wrappers.push(new ActiveConnectionWrapper( |  | ||||||
|                 connection.name, |  | ||||||
|                 $filter('date')(activeConnection.startDate, sessionDateFormat), |  | ||||||
|                 activeConnection |  | ||||||
|             ));  |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // Query the user's permissions |  | ||||||
|     permissionService.getPermissions(authenticationService.getCurrentUserID()) |  | ||||||
|             .success(function permissionsReceived(retrievedPermissions) { |  | ||||||
|         $scope.permissions = retrievedPermissions; |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Retrieve all connections  |  | ||||||
|     connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER) |  | ||||||
|     .success(function connectionGroupReceived(retrievedRootGroup) { |  | ||||||
|  |  | ||||||
|         // Load connections from retrieved group tree |  | ||||||
|         connections = {}; |  | ||||||
|         addDescendantConnections(retrievedRootGroup); |  | ||||||
|  |  | ||||||
|         // Attempt to produce wrapped list of active connections |  | ||||||
|         wrapActiveConnections(); |  | ||||||
|  |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     // Query active sessions |  | ||||||
|     activeConnectionService.getActiveConnections().success(function sessionsRetrieved(retrievedActiveConnections) { |  | ||||||
|  |  | ||||||
|         // Store received list |  | ||||||
|         activeConnections = retrievedActiveConnections; |  | ||||||
|  |  | ||||||
|         // Attempt to produce wrapped list of active connections |  | ||||||
|         wrapActiveConnections(); |  | ||||||
|  |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Get session date format |  | ||||||
|     $translate('MANAGE_SESSION.FORMAT_STARTDATE').then(function sessionDateFormatReceived(retrievedSessionDateFormat) { |  | ||||||
|  |  | ||||||
|         // Store received date format |  | ||||||
|         sessionDateFormat = retrievedSessionDateFormat; |  | ||||||
|  |  | ||||||
|         // Attempt to produce wrapped list of active connections |  | ||||||
|         wrapActiveConnections(); |  | ||||||
|  |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns whether critical data has completed being loaded. |  | ||||||
|      * |  | ||||||
|      * @returns {Boolean} |  | ||||||
|      *     true if enough data has been loaded for the user interface to be |  | ||||||
|      *     useful, false otherwise. |  | ||||||
|      */ |  | ||||||
|     $scope.isLoaded = function isLoaded() { |  | ||||||
|  |  | ||||||
|         return $scope.wrappers          !== null |  | ||||||
|             && $scope.sessionDateFormat !== null |  | ||||||
|             && $scope.permissions       !== null; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * An action to be provided along with the object sent to showStatus which |  | ||||||
|      * closes the currently-shown status dialog. |  | ||||||
|      */ |  | ||||||
|     var ACKNOWLEDGE_ACTION = { |  | ||||||
|         name        : "MANAGE_SESSION.ACTION_ACKNOWLEDGE", |  | ||||||
|         // Handle action |  | ||||||
|         callback    : function acknowledgeCallback() { |  | ||||||
|             guacNotification.showStatus(false); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * An action to be provided along with the object sent to showStatus which |  | ||||||
|      * closes the currently-shown status dialog. |  | ||||||
|      */ |  | ||||||
|     var CANCEL_ACTION = { |  | ||||||
|         name        : "MANAGE_SESSION.ACTION_CANCEL", |  | ||||||
|         // Handle action |  | ||||||
|         callback    : function cancelCallback() { |  | ||||||
|             guacNotification.showStatus(false); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * An action to be provided along with the object sent to showStatus which |  | ||||||
|      * immediately deletes the currently selected sessions. |  | ||||||
|      */ |  | ||||||
|     var DELETE_ACTION = { |  | ||||||
|         name        : "MANAGE_SESSION.ACTION_DELETE", |  | ||||||
|         className   : "danger", |  | ||||||
|         // Handle action |  | ||||||
|         callback    : function deleteCallback() { |  | ||||||
|             deleteSessionsImmediately(); |  | ||||||
|             guacNotification.showStatus(false); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * Immediately deletes the selected sessions, without prompting the user for |  | ||||||
|      * confirmation. |  | ||||||
|      */ |  | ||||||
|     var deleteSessionsImmediately = function deleteSessionsImmediately() { |  | ||||||
|  |  | ||||||
|         // Perform deletion |  | ||||||
|         activeConnectionService.deleteActiveConnections(Object.keys(selectedWrappers)) |  | ||||||
|         .success(function activeConnectionsDeleted() { |  | ||||||
|  |  | ||||||
|             // Remove deleted connections from wrapper array |  | ||||||
|             $scope.wrappers = $scope.wrappers.filter(function activeConnectionStillExists(wrapper) { |  | ||||||
|                 return !(wrapper.activeConnection.identifier in selectedWrappers); |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             // Clear selection |  | ||||||
|             selectedWrappers = {}; |  | ||||||
|  |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|         // Notify of any errors |  | ||||||
|         .error(function activeConnectionDeletionFailed(error) { |  | ||||||
|             guacNotification.showStatus({ |  | ||||||
|                 'className'  : 'error', |  | ||||||
|                 'title'      : 'MANAGE_SESSION.DIALOG_HEADER_ERROR', |  | ||||||
|                 'text'       : error.message, |  | ||||||
|                 'actions'    : [ ACKNOWLEDGE_ACTION ] |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|     };  |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * Delete all selected sessions, prompting the user first to confirm that  |  | ||||||
|      * deletion is desired. |  | ||||||
|      */ |  | ||||||
|     $scope.deleteSessions = function deleteSessions() { |  | ||||||
|         // Confirm deletion request |  | ||||||
|         guacNotification.showStatus({ |  | ||||||
|             'title'      : 'MANAGE_SESSION.DIALOG_HEADER_CONFIRM_DELETE', |  | ||||||
|             'text'       : 'MANAGE_SESSION.TEXT_CONFIRM_DELETE', |  | ||||||
|             'actions'    : [ DELETE_ACTION, CANCEL_ACTION] |  | ||||||
|         }); |  | ||||||
|     }; |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * Returns whether the selected sessions can be deleted. |  | ||||||
|      *  |  | ||||||
|      * @returns {Boolean} |  | ||||||
|      *     true if selected sessions can be deleted, false otherwise. |  | ||||||
|      */ |  | ||||||
|     $scope.canDeleteSessions = function canDeleteSessions() { |  | ||||||
|  |  | ||||||
|         // We can delete sessions if at least one is selected |  | ||||||
|         for (var identifier in selectedWrappers) |  | ||||||
|             return true; |  | ||||||
|  |  | ||||||
|         return false; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|      |  | ||||||
|     /** |  | ||||||
|      * Called whenever an active connection wrapper changes selected status. |  | ||||||
|      *  |  | ||||||
|      * @param {ActiveConnectionWrapper} wrapper |  | ||||||
|      *     The wrapper whose selected status has changed. |  | ||||||
|      */ |  | ||||||
|     $scope.wrapperSelectionChange = function wrapperSelectionChange(wrapper) { |  | ||||||
|  |  | ||||||
|         // Add wrapper to map if selected |  | ||||||
|         if (wrapper.checked) |  | ||||||
|             selectedWrappers[wrapper.activeConnection.identifier] = wrapper; |  | ||||||
|  |  | ||||||
|         // Otherwise, remove wrapper from map |  | ||||||
|         else |  | ||||||
|             delete selectedWrappers[wrapper.activeConnection.identifier]; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|      |  | ||||||
| }]); |  | ||||||
| @@ -472,7 +472,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto | |||||||
|      * Cancels all pending edits, returning to the management page. |      * Cancels all pending edits, returning to the management page. | ||||||
|      */ |      */ | ||||||
|     $scope.cancel = function cancel() { |     $scope.cancel = function cancel() { | ||||||
|         $location.path('/manage/modules/users/'); |         $location.path('/settings/users'); | ||||||
|     }; |     }; | ||||||
|              |              | ||||||
|     /** |     /** | ||||||
| @@ -498,7 +498,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto | |||||||
|             // Upon success, save any changed permissions |             // Upon success, save any changed permissions | ||||||
|             permissionService.patchPermissions($scope.user.username, permissionsAdded, permissionsRemoved) |             permissionService.patchPermissions($scope.user.username, permissionsAdded, permissionsRemoved) | ||||||
|             .success(function patchedUserPermissions() { |             .success(function patchedUserPermissions() { | ||||||
|                 $location.path('/manage/modules/users/'); |                 $location.path('/settings/users'); | ||||||
|             }) |             }) | ||||||
|  |  | ||||||
|             // Notify of any errors |             // Notify of any errors | ||||||
| @@ -560,7 +560,7 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto | |||||||
|         // Delete the user  |         // Delete the user  | ||||||
|         userService.deleteUser($scope.user) |         userService.deleteUser($scope.user) | ||||||
|         .success(function deletedUser() { |         .success(function deletedUser() { | ||||||
|             $location.path('/manage/modules/users/'); |             $location.path('/settings/users'); | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|         // Notify of any errors |         // Notify of any errors | ||||||
|   | |||||||
| @@ -1,179 +0,0 @@ | |||||||
| /* |  | ||||||
|  * 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. |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * The controller for the user administration page. |  | ||||||
|  */ |  | ||||||
| angular.module('manage').controller('manageUsersController', ['$scope', '$injector',  |  | ||||||
|         function manageUsersController($scope, $injector) { |  | ||||||
|  |  | ||||||
|     // Required types |  | ||||||
|     var PermissionSet   = $injector.get('PermissionSet'); |  | ||||||
|     var User            = $injector.get('User'); |  | ||||||
|  |  | ||||||
|     // Required services |  | ||||||
|     var $location              = $injector.get('$location'); |  | ||||||
|     var authenticationService  = $injector.get('authenticationService'); |  | ||||||
|     var guacNotification       = $injector.get('guacNotification'); |  | ||||||
|     var permissionService      = $injector.get('permissionService'); |  | ||||||
|     var userService            = $injector.get('userService'); |  | ||||||
|  |  | ||||||
|     // Identifier of the current user |  | ||||||
|     var currentUserID = authenticationService.getCurrentUserID(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * An action to be provided along with the object sent to showStatus which |  | ||||||
|      * closes the currently-shown status dialog. |  | ||||||
|      */ |  | ||||||
|     var ACKNOWLEDGE_ACTION = { |  | ||||||
|         name        : "MANAGE_USER.ACTION_ACKNOWLEDGE", |  | ||||||
|         // Handle action |  | ||||||
|         callback    : function acknowledgeCallback() { |  | ||||||
|             guacNotification.showStatus(false); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * All visible users. |  | ||||||
|      * |  | ||||||
|      * @type User[] |  | ||||||
|      */ |  | ||||||
|     $scope.users = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Whether the current user can manage users. If the current permissions |  | ||||||
|      * have not yet been loaded, this will be null. |  | ||||||
|      * |  | ||||||
|      * @type Boolean |  | ||||||
|      */ |  | ||||||
|     $scope.canManageUsers = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Whether the current user can create new users. If the current |  | ||||||
|      * permissions have not yet been loaded, this will be null. |  | ||||||
|      * |  | ||||||
|      * @type Boolean |  | ||||||
|      */ |  | ||||||
|     $scope.canCreateUsers = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * The name of the new user to create, if any, when user creation is |  | ||||||
|      * requested via newUser(). |  | ||||||
|      * |  | ||||||
|      * @type String |  | ||||||
|      */ |  | ||||||
|     $scope.newUsername = ""; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * All permissions associated with the current user, or null if the user's |  | ||||||
|      * permissions have not yet been loaded. |  | ||||||
|      * |  | ||||||
|      * @type PermissionSet |  | ||||||
|      */ |  | ||||||
|     $scope.permissions = null; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Returns whether critical data has completed being loaded. |  | ||||||
|      * |  | ||||||
|      * @returns {Boolean} |  | ||||||
|      *     true if enough data has been loaded for the user interface to be |  | ||||||
|      *     useful, false otherwise. |  | ||||||
|      */ |  | ||||||
|     $scope.isLoaded = function isLoaded() { |  | ||||||
|  |  | ||||||
|         return $scope.users                     !== null |  | ||||||
|             && $scope.permissions               !== null |  | ||||||
|             && $scope.canManageUsers            !== null |  | ||||||
|             && $scope.canCreateUsers            !== null; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // Retrieve current permissions |  | ||||||
|     permissionService.getPermissions(currentUserID) |  | ||||||
|     .success(function permissionsRetrieved(permissions) { |  | ||||||
|  |  | ||||||
|         $scope.permissions = permissions; |  | ||||||
|  |  | ||||||
|         // Determine whether the current user can create new users |  | ||||||
|         $scope.canCreateUsers = |  | ||||||
|                PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) |  | ||||||
|             || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_USER); |  | ||||||
|  |  | ||||||
|         // Determine whether the current user can manage other users |  | ||||||
|         $scope.canManageUsers = |  | ||||||
|                $scope.canCreateUsers |  | ||||||
|             || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) |  | ||||||
|             || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.DELETE); |  | ||||||
|  |  | ||||||
|         // Return to home if there's nothing to do here |  | ||||||
|         if (!$scope.canManageUsers) |  | ||||||
|             $location.path('/'); |  | ||||||
|          |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Retrieve all users for whom we have UPDATE or DELETE permission |  | ||||||
|     userService.getUsers([PermissionSet.ObjectPermissionType.UPDATE,  |  | ||||||
|         PermissionSet.ObjectPermissionType.DELETE]) |  | ||||||
|     .success(function usersReceived(users) { |  | ||||||
|  |  | ||||||
|         // Display only other users, not self |  | ||||||
|         $scope.users = users.filter(function isNotSelf(user) { |  | ||||||
|             return user.username !== currentUserID; |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Creates a new user having the username specified in the user creation |  | ||||||
|      * interface. |  | ||||||
|      */ |  | ||||||
|     $scope.newUser = function newUser() { |  | ||||||
|  |  | ||||||
|         // Create user skeleton |  | ||||||
|         var user = new User({ |  | ||||||
|             username: $scope.newUsername || '' |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         // Create specified user |  | ||||||
|         userService.createUser(user) |  | ||||||
|  |  | ||||||
|         // Add user to visible list upon success |  | ||||||
|         .success(function userCreated() { |  | ||||||
|             $scope.users.push(user); |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|         // Notify of any errors |  | ||||||
|         .error(function userCreationFailed(error) { |  | ||||||
|             guacNotification.showStatus({ |  | ||||||
|                 'className'  : 'error', |  | ||||||
|                 'title'      : 'MANAGE_USER.DIALOG_HEADER_ERROR', |  | ||||||
|                 'text'       : error.message, |  | ||||||
|                 'actions'    : [ ACKNOWLEDGE_ACTION ] |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         // Reset username |  | ||||||
|         $scope.newUsername = ""; |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|      |  | ||||||
| }]); |  | ||||||
| @@ -1,57 +0,0 @@ | |||||||
| <!-- |  | ||||||
| Copyright 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. |  | ||||||
| --> |  | ||||||
|  |  | ||||||
| <div class="view" ng-class="{loading: !isLoaded()}"> |  | ||||||
|  |  | ||||||
|     <div class="header"> |  | ||||||
|         <h2>{{'MANAGE_CONNECTION.SECTION_HEADER_CONNECTIONS' | translate}}</h2> |  | ||||||
|         <guac-user-menu></guac-user-menu> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
|     <!-- Connection management --> |  | ||||||
|     <div class="settings section connections"> |  | ||||||
|         <p>{{'MANAGE_CONNECTION.HELP_CONNECTIONS' | translate}}</p> |  | ||||||
|  |  | ||||||
|         <!-- Form action buttons --> |  | ||||||
|         <div class="action-buttons"> |  | ||||||
|  |  | ||||||
|             <a class="add-connection button" |  | ||||||
|                ng-show="canCreateConnections" |  | ||||||
|                href="#/manage/connections/">{{'MANAGE_CONNECTION.ACTION_NEW_CONNECTION' | translate}}</a> |  | ||||||
|  |  | ||||||
|             <a class="add-connection-group button" |  | ||||||
|                ng-show="canCreateConnectionGroups" |  | ||||||
|                href="#/manage/connectionGroups/">{{'MANAGE_CONNECTION.ACTION_NEW_CONNECTION_GROUP' | translate}}</a> |  | ||||||
|  |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <!-- List of accessible connections and groups --> |  | ||||||
|         <div class="connection-list"> |  | ||||||
|             <guac-group-list |  | ||||||
|                 page-size="25" |  | ||||||
|                 connection-group="rootGroup" |  | ||||||
|                 connection-template="'app/manage/templates/connection.html'" |  | ||||||
|                 connection-group-template="'app/manage/templates/connectionGroup.html'"/> |  | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
| </div> |  | ||||||
| @@ -1,86 +0,0 @@ | |||||||
| <!-- |  | ||||||
| Copyright 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. |  | ||||||
| --> |  | ||||||
|  |  | ||||||
| <div class="view" ng-class="{loading: !isLoaded()}"> |  | ||||||
|  |  | ||||||
|     <div class="header"> |  | ||||||
|         <h2>{{'MANAGE_SESSION.SECTION_HEADER_SESSIONS' | translate}}</h2> |  | ||||||
|         <guac-user-menu></guac-user-menu> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
|     <!-- User Session management --> |  | ||||||
|     <div class="settings section sessions"> |  | ||||||
|         <p>{{'MANAGE_SESSION.HELP_SESSIONS' | translate}}</p> |  | ||||||
|  |  | ||||||
|         <!-- Form action buttons --> |  | ||||||
|         <div class="action-buttons"> |  | ||||||
|             <button class="delete-sessions danger" ng-disabled="!canDeleteSessions()" ng-click="deleteSessions()">{{'MANAGE_SESSION.ACTION_DELETE' | translate}}</button> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <!-- Session filter --> |  | ||||||
|         <guac-filter filtered-items="filteredWrappers" items="wrappers" |  | ||||||
|                      placeholder="'MANAGE_SESSION.FIELD_PLACEHOLDER_FILTER' | translate" |  | ||||||
|                      properties="filteredWrapperProperties"></guac-filter> |  | ||||||
|  |  | ||||||
|         <!-- List of current user sessions --> |  | ||||||
|         <table class="sorted session-list"> |  | ||||||
|             <thead> |  | ||||||
|                 <tr> |  | ||||||
|                     <th class="select-session"></th> |  | ||||||
|                     <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.username'"> |  | ||||||
|                         {{'MANAGE_SESSION.TABLE_HEADER_SESSION_USERNAME' | translate}} |  | ||||||
|                     </th> |  | ||||||
|                     <th guac-sort-order="wrapperOrder" guac-sort-property="'startDate'"> |  | ||||||
|                         {{'MANAGE_SESSION.TABLE_HEADER_SESSION_STARTDATE' | translate}} |  | ||||||
|                     </th> |  | ||||||
|                     <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.remoteHost'"> |  | ||||||
|                         {{'MANAGE_SESSION.TABLE_HEADER_SESSION_REMOTEHOST' | translate}} |  | ||||||
|                     </th> |  | ||||||
|                     <th guac-sort-order="wrapperOrder" guac-sort-property="'name'"> |  | ||||||
|                         {{'MANAGE_SESSION.TABLE_HEADER_SESSION_CONNECTION_NAME' | translate}} |  | ||||||
|                     </th> |  | ||||||
|                 </tr> |  | ||||||
|             </thead> |  | ||||||
|             <tbody> |  | ||||||
|                 <tr ng-repeat="wrapper in wrapperPage" class="session"> |  | ||||||
|                     <td class="select-session"> |  | ||||||
|                         <input ng-change="wrapperSelectionChange(wrapper)" type="checkbox" ng-model="wrapper.checked" /> |  | ||||||
|                     </td> |  | ||||||
|                     <td>{{wrapper.activeConnection.username}}</td> |  | ||||||
|                     <td>{{wrapper.startDate}}</td> |  | ||||||
|                     <td>{{wrapper.activeConnection.remoteHost}}</td> |  | ||||||
|                     <td>{{wrapper.name}}</td> |  | ||||||
|                 </tr> |  | ||||||
|             </tbody> |  | ||||||
|         </table> |  | ||||||
|  |  | ||||||
|         <!-- Text displayed if no sessions exist --> |  | ||||||
|         <p class="placeholder" ng-hide="wrapperPage.length"> |  | ||||||
|             {{'MANAGE_SESSION.INFO_NO_SESSIONS' | translate}} |  | ||||||
|         </p> |  | ||||||
|  |  | ||||||
|         <!-- Pager for session list --> |  | ||||||
|         <guac-pager page="wrapperPage" page-size="25" |  | ||||||
|                     items="filteredWrappers | orderBy : wrapperOrder.predicate"></guac-pager> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
| </div> |  | ||||||
| @@ -1,56 +0,0 @@ | |||||||
| <!-- |  | ||||||
| Copyright 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. |  | ||||||
| --> |  | ||||||
|  |  | ||||||
| <div class="view" ng-class="{loading: !isLoaded()}"> |  | ||||||
|  |  | ||||||
|     <div class="header"> |  | ||||||
|         <h2>{{'MANAGE_USER.SECTION_HEADER_USERS' | translate}}</h2> |  | ||||||
|         <guac-user-menu></guac-user-menu> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
|     <!-- User management --> |  | ||||||
|     <div class="settings section users"> |  | ||||||
|         <p>{{'MANAGE_USER.HELP_USERS' | translate}}</p> |  | ||||||
|  |  | ||||||
|         <!-- Form action buttons --> |  | ||||||
|         <div class="action-buttons" ng-show="canCreateUsers"> |  | ||||||
|             <input type="text" ng-model="newUsername" class="name username" autocorrect="off" autocapitalize="off"/> |  | ||||||
|             <button class="add-user" ng-click="newUser()">{{'MANAGE_USER.ACTION_NEW_USER' | translate}}</button> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <!-- List of users this user has access to --> |  | ||||||
|         <div class="user-list"> |  | ||||||
|             <div ng-repeat="user in userPage" class="user list-item"> |  | ||||||
|                 <a ng-href="#/manage/users/{{user.username}}"> |  | ||||||
|                     <div class="caption"> |  | ||||||
|                         <div class="icon user"></div> |  | ||||||
|                         <span class="name">{{user.username}}</span> |  | ||||||
|                     </div> |  | ||||||
|                 </a> |  | ||||||
|             </div> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <!-- Pager controls for user list --> |  | ||||||
|         <guac-pager page="userPage" page-size="25" items="users | orderBy : 'username'"></guac-pager> |  | ||||||
|     </div> |  | ||||||
|  |  | ||||||
| </div> |  | ||||||
| @@ -0,0 +1,74 @@ | |||||||
|  | /* | ||||||
|  |  * 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A directive which provides a list of links to specific pages. | ||||||
|  |  */ | ||||||
|  | angular.module('navigation').directive('guacPageList', [function guacPageList() { | ||||||
|  |  | ||||||
|  |     return { | ||||||
|  |         restrict: 'E', | ||||||
|  |         replace: true, | ||||||
|  |         scope: { | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * The array of pages to display. | ||||||
|  |              * | ||||||
|  |              * @type Page[] | ||||||
|  |              */ | ||||||
|  |             pages : '=' | ||||||
|  |  | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         templateUrl: 'app/navigation/templates/guacPageList.html', | ||||||
|  |         controller: ['$scope', '$injector', function guacPageListController($scope, $injector) { | ||||||
|  |  | ||||||
|  |             // Get required services | ||||||
|  |             var $location = $injector.get('$location'); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Navigate to the given page. | ||||||
|  |              *  | ||||||
|  |              * @param {Page} page | ||||||
|  |              *     The page to navigate to. | ||||||
|  |              */ | ||||||
|  |             $scope.navigateToPage = function navigateToPage(page) { | ||||||
|  |                 $location.path(page.url); | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * Tests whether the given page is the page currently being viewed. | ||||||
|  |              * | ||||||
|  |              * @param {Page} page | ||||||
|  |              *     The page to test. | ||||||
|  |              * | ||||||
|  |              * @returns {Boolean} | ||||||
|  |              *     true if the given page is the current page, false otherwise. | ||||||
|  |              */ | ||||||
|  |             $scope.isCurrentPage = function isCurrentPage(page) { | ||||||
|  |                 return $location.url() === page.url; | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |         }] // end controller | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  | }]); | ||||||
| @@ -214,29 +214,6 @@ angular.module('navigation').directive('guacUserMenu', [function guacUserMenu() | |||||||
|                  |                  | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             /** |  | ||||||
|              * Navigate to the given page. |  | ||||||
|              *  |  | ||||||
|              * @param {Page} page |  | ||||||
|              *     The page to navigate to. |  | ||||||
|              */ |  | ||||||
|             $scope.navigateToPage = function navigateToPage(page) { |  | ||||||
|                 $location.path(page.url); |  | ||||||
|             }; |  | ||||||
|              |  | ||||||
|             /** |  | ||||||
|              * Tests whether the given page should be disabled. |  | ||||||
|              * |  | ||||||
|              * @param {Page} page |  | ||||||
|              *     The page to test. |  | ||||||
|              * |  | ||||||
|              * @returns {Boolean} |  | ||||||
|              *     true if the given page should be disabled, false otherwise. |  | ||||||
|              */ |  | ||||||
|             $scope.isPageDisabled = function isPageDisabled(page) { |  | ||||||
|                 return $location.url() === page.url; |  | ||||||
|             }; |  | ||||||
|              |  | ||||||
|             /** |             /** | ||||||
|              * Logs out the current user, redirecting them to back to the login |              * Logs out the current user, redirecting them to back to the login | ||||||
|              * screen after logout completes. |              * screen after logout completes. | ||||||
|   | |||||||
| @@ -137,20 +137,16 @@ angular.module('navigation').factory('userPageService', ['$injector', | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Returns all the main pages that the current user can visit. This can  |      * Returns all settings pages that the current user can visit. This can | ||||||
|      * include the home page, manage pages, etc. In the case that there are no  |      * include any of the various manage pages. | ||||||
|      * applicable pages of this sort, it may return a client page. |  | ||||||
|      *  |  | ||||||
|      * @param {ConnectionGroup} rootGroup |  | ||||||
|      *     The root of the connection group tree for the current user. |  | ||||||
|      *  |      *  | ||||||
|      * @param {PermissionSet} permissions |      * @param {PermissionSet} permissions | ||||||
|      *     The permissions for the current user. |      *     The permissions for the current user. | ||||||
|      *  |      *  | ||||||
|      * @returns {Page[]}  |      * @returns {Page[]}  | ||||||
|      *     An array of all main pages that the current user can visit. |      *     An array of all settings pages that the current user can visit. | ||||||
|      */ |      */ | ||||||
|     var generateMainPages = function generateMainPages(rootGroup, permissions) { |     var generateSettingsPages = function generateSettingsPages(permissions) { | ||||||
|          |          | ||||||
|         var pages = []; |         var pages = []; | ||||||
|          |          | ||||||
| @@ -203,17 +199,19 @@ angular.module('navigation').factory('userPageService', ['$injector', | |||||||
|                 // A user must be a system administrator to manage sessions |                 // A user must be a system administrator to manage sessions | ||||||
|                 PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER); |                 PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER); | ||||||
|  |  | ||||||
|         // Only include the home page in the list of main pages if the user |         // If user can manage sessions, add link to sessions management page | ||||||
|         // can navigate elsewhere. |         if (canManageSessions) { | ||||||
|         var homePage = generateHomePage(rootGroup); |             pages.push(new Page( | ||||||
|         if (homePage === SYSTEM_HOME_PAGE) |                 'USER_MENU.ACTION_MANAGE_SESSIONS', | ||||||
|             pages.push(homePage); |                 '/settings/sessions' | ||||||
|  |             )); | ||||||
|  |         } | ||||||
|          |          | ||||||
|         // If user can manage users, add link to user management page |         // If user can manage users, add link to user management page | ||||||
|         if (canManageUsers) { |         if (canManageUsers) { | ||||||
|             pages.push(new Page( |             pages.push(new Page( | ||||||
|                 'USER_MENU.ACTION_MANAGE_USERS', |                 'USER_MENU.ACTION_MANAGE_USERS', | ||||||
|                 '/manage/modules/users/' |                 '/settings/users' | ||||||
|             )); |             )); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -221,15 +219,69 @@ angular.module('navigation').factory('userPageService', ['$injector', | |||||||
|         if (canManageConnections) { |         if (canManageConnections) { | ||||||
|             pages.push(new Page( |             pages.push(new Page( | ||||||
|                 'USER_MENU.ACTION_MANAGE_CONNECTIONS', |                 'USER_MENU.ACTION_MANAGE_CONNECTIONS', | ||||||
|                 '/manage/modules/connections/' |                 '/settings/connections' | ||||||
|             )); |             )); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // If user can manage sessions, add link to sessions management page |         return pages; | ||||||
|         if (canManageSessions) { |     }; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns a promise which resolves to an array of all settings pages that | ||||||
|  |      * the current user can visit. This can include any of the various manage | ||||||
|  |      * pages. | ||||||
|  |      * | ||||||
|  |      * @returns {Promise.<Page[]>}  | ||||||
|  |      *     A promise which resolves to an array of all settings pages that the | ||||||
|  |      *     current user can visit. | ||||||
|  |      */ | ||||||
|  |     service.getSettingsPages = function getSettingsPages() { | ||||||
|  |  | ||||||
|  |         var deferred = $q.defer(); | ||||||
|  |  | ||||||
|  |         // Retrieve current permissions, resolving main pages if possible | ||||||
|  |         // Resolve promise using settings pages derived from permissions | ||||||
|  |         permissionService.getPermissions(authenticationService.getCurrentUserID()) | ||||||
|  |         .success(function permissionsRetrieved(permissions) { | ||||||
|  |             deferred.resolve(generateSettingsPages(permissions)); | ||||||
|  |         }); | ||||||
|  |          | ||||||
|  |         return deferred.promise; | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  |     | ||||||
|  |     /** | ||||||
|  |      * Returns all the main pages that the current user can visit. This can  | ||||||
|  |      * include the home page, manage pages, etc. In the case that there are no  | ||||||
|  |      * applicable pages of this sort, it may return a client page. | ||||||
|  |      *  | ||||||
|  |      * @param {ConnectionGroup} rootGroup | ||||||
|  |      *     The root of the connection group tree for the current user. | ||||||
|  |      *      | ||||||
|  |      * @param {PermissionSet} permissions | ||||||
|  |      *     The permissions for the current user. | ||||||
|  |      *  | ||||||
|  |      * @returns {Page[]}  | ||||||
|  |      *     An array of all main pages that the current user can visit. | ||||||
|  |      */ | ||||||
|  |     var generateMainPages = function generateMainPages(rootGroup, permissions) { | ||||||
|  |          | ||||||
|  |         var pages = []; | ||||||
|  |  | ||||||
|  |         // Get home page and settings pages | ||||||
|  |         var homePage = generateHomePage(rootGroup); | ||||||
|  |         var settingsPages = generateSettingsPages(permissions); | ||||||
|  |  | ||||||
|  |         // Only include the home page in the list of main pages if the user | ||||||
|  |         // can navigate elsewhere. | ||||||
|  |         if (homePage === SYSTEM_HOME_PAGE || settingsPages.length) | ||||||
|  |             pages.push(homePage); | ||||||
|  |  | ||||||
|  |         // Add generic link to the first-available settings page | ||||||
|  |         if (settingsPages.length) { | ||||||
|             pages.push(new Page( |             pages.push(new Page( | ||||||
|                 'USER_MENU.ACTION_MANAGE_SESSIONS', |                 'USER_MENU.ACTION_MANAGE_SETTINGS', | ||||||
|                 '/manage/modules/sessions/' |                 settingsPages[0].url | ||||||
|             )); |             )); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|   | |||||||
| @@ -139,8 +139,6 @@ | |||||||
|     top: 100%; |     top: 100%; | ||||||
|     right: 0; |     right: 0; | ||||||
|     left: -1px; |     left: -1px; | ||||||
|     margin: 0; |  | ||||||
|     padding: 0; |  | ||||||
|  |  | ||||||
|     background: #EEE; |     background: #EEE; | ||||||
|     box-shadow: 0 2px 2px rgba(0, 0, 0, 0.125); |     box-shadow: 0 2px 2px rgba(0, 0, 0, 0.125); | ||||||
| @@ -151,6 +149,11 @@ | |||||||
|      |      | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .user-menu .options ul { | ||||||
|  |     margin: 0; | ||||||
|  |     padding: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| .user-menu .user-menu-dropdown.open .options { | .user-menu .user-menu-dropdown.open .options { | ||||||
|     visibility: visible; |     visibility: visible; | ||||||
| } | } | ||||||
| @@ -161,50 +164,40 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .user-menu .options li a { | .user-menu .options li a { | ||||||
|  |  | ||||||
|     display: block; |     display: block; | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|     color: black; |     color: black; | ||||||
|     text-decoration: none; |     text-decoration: none; | ||||||
|     padding: 0.75em; |     padding: 0.75em; | ||||||
|  |  | ||||||
|  |     background-repeat: no-repeat; | ||||||
|  |     background-size: 1em; | ||||||
|  |     background-position: 0.75em center; | ||||||
|  |     padding-left: 2.5em; | ||||||
|  |     background-image: url('images/protocol-icons/guac-monitor.png'); | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| .user-menu .options li a:hover { | .user-menu .options li a:hover { | ||||||
|     background-color: #CDA; |     background-color: #CDA; | ||||||
| } | } | ||||||
|  |  | ||||||
| .user-menu .options li a.disabled, | .user-menu .options li a.current, | ||||||
| .user-menu .options li a.disabled:hover { | .user-menu .options li a.current:hover { | ||||||
|     background-color: transparent; |     background-color: transparent; | ||||||
|     cursor: default; |     cursor: default; | ||||||
|     opacity: 0.25; |     opacity: 0.25; | ||||||
| } | } | ||||||
|  |  | ||||||
| .user-menu .options li a.home, |  | ||||||
| .user-menu .options li a.manage-users, |  | ||||||
| .user-menu .options li a.manage-connections, |  | ||||||
| .user-menu .options li a.manage-sessions, |  | ||||||
| .user-menu .options li a.change-password, |  | ||||||
| .user-menu .options li a.logout { |  | ||||||
|     background-repeat: no-repeat; |  | ||||||
|     background-size: 1em; |  | ||||||
|     background-position: 0.75em center; |  | ||||||
|     padding-left: 2.5em; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .user-menu .options li a[href="#/"] { | .user-menu .options li a[href="#/"] { | ||||||
|     background-image: url('images/action-icons/guac-home-dark.png'); |     background-image: url('images/action-icons/guac-home-dark.png'); | ||||||
| } | } | ||||||
|  |  | ||||||
| .user-menu .options li a[href="#/manage/modules/users/"] { | .user-menu .options li a[href="#/settings/users"], | ||||||
|     background-image: url('images/user-icons/guac-user.png'); | .user-menu .options li a[href="#/settings/connections"], | ||||||
| } | .user-menu .options li a[href="#/settings/sessions"] { | ||||||
|  |     background-image: url('images/action-icons/guac-config-dark.png'); | ||||||
| .user-menu .options li a[href="#/manage/modules/connections/"] { |  | ||||||
|     background-image: url('images/protocol-icons/guac-monitor.png'); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .user-menu .options li a[href="#/manage/modules/sessions/"] { |  | ||||||
|     background-image: url('images/protocol-icons/guac-plug.png'); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| .user-menu .options li a.change-password { | .user-menu .options li a.change-password { | ||||||
|   | |||||||
| @@ -0,0 +1,32 @@ | |||||||
|  | <ul class="page-list"> | ||||||
|  |     <!-- | ||||||
|  |        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. | ||||||
|  |     --> | ||||||
|  |  | ||||||
|  |     <!-- Navigation links --> | ||||||
|  |     <li ng-repeat="page in pages"> | ||||||
|  |         <a class="home" ng-click="navigateToPage(page)" | ||||||
|  |            ng-class="{current: isCurrentPage(page)}" href="#{{page.url}}"> | ||||||
|  |             {{page.name | translate}} | ||||||
|  |         </a> | ||||||
|  |     </li> | ||||||
|  |  | ||||||
|  | </ul> | ||||||
| @@ -26,31 +26,30 @@ | |||||||
|         <div class="menu-indicator"></div> |         <div class="menu-indicator"></div> | ||||||
|          |          | ||||||
|         <!-- Menu options --> |         <!-- Menu options --> | ||||||
|         <ul class="options"> |         <div class="options"> | ||||||
|              |              | ||||||
|             <!-- Local actions --> |             <!-- Local actions --> | ||||||
|             <li ng-repeat="action in localActions"> |             <ul class="action-list"> | ||||||
|                 <a ng-class="action.className" ng-click="action.callback()"> |                 <li ng-repeat="action in localActions"> | ||||||
|                     {{action.name | translate}} |                     <a ng-class="action.className" ng-click="action.callback()"> | ||||||
|                 </a> |                         {{action.name | translate}} | ||||||
|             </li> |                     </a> | ||||||
|  |                 </li> | ||||||
|  |             </ul> | ||||||
|  |  | ||||||
|             <!-- Navigation links --> |             <!-- Navigation links --> | ||||||
|             <li ng-repeat="page in pages"> |             <guac-page-list pages="pages"></guac-page-list> | ||||||
|                 <a class="home" ng-click="navigateToPage(page)" |  | ||||||
|                    ng-class="{disabled: isPageDisabled(page)}" href="#{{page.url}}"> |  | ||||||
|                     {{page.name | translate}} |  | ||||||
|                 </a> |  | ||||||
|             </li> |  | ||||||
|  |  | ||||||
|             <!-- Actions --> |             <!-- Actions --> | ||||||
|             <li ng-repeat="action in actions"> |             <ul class="action-list"> | ||||||
|                 <a ng-class="action.className" ng-click="action.callback()"> |                 <li ng-repeat="action in actions"> | ||||||
|                     {{action.name | translate}} |                     <a ng-class="action.className" ng-click="action.callback()"> | ||||||
|                 </a> |                         {{action.name | translate}} | ||||||
|             </li> |                     </a> | ||||||
|  |                 </li> | ||||||
|  |             </ul> | ||||||
|  |  | ||||||
|         </ul> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <!-- Password dialog --> |     <!-- Password dialog --> | ||||||
|   | |||||||
| @@ -0,0 +1,55 @@ | |||||||
|  | /* | ||||||
|  |  * 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The controller for the general settings page. | ||||||
|  |  */ | ||||||
|  | angular.module('manage').controller('settingsController', ['$scope', '$injector',  | ||||||
|  |         function settingsController($scope, $injector) { | ||||||
|  |  | ||||||
|  |     // Required services | ||||||
|  |     var $routeParams    = $injector.get('$routeParams'); | ||||||
|  |     var userPageService = $injector.get('userPageService'); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The array of settings pages available to the current user, or null if | ||||||
|  |      * not yet known. | ||||||
|  |      * | ||||||
|  |      * @type Page[] | ||||||
|  |      */ | ||||||
|  |     $scope.settingsPages = null; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The currently-selected settings tab. This may be 'users', 'connections', | ||||||
|  |      * or 'sessions'. | ||||||
|  |      * | ||||||
|  |      * @type String | ||||||
|  |      */ | ||||||
|  |     $scope.activeTab = $routeParams.tab; | ||||||
|  |  | ||||||
|  |     // Retrieve settings pages | ||||||
|  |     userPageService.getSettingsPages() | ||||||
|  |     .then(function settingsPagesRetrieved(pages) { | ||||||
|  |         $scope.settingsPages = pages; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | }]); | ||||||
| @@ -0,0 +1,170 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2014 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A directive for managing all connections and connection groups in the system. | ||||||
|  |  */ | ||||||
|  | angular.module('settings').directive('guacSettingsConnections', [function guacSettingsConnections() { | ||||||
|  |      | ||||||
|  |     return { | ||||||
|  |         // Element only | ||||||
|  |         restrict: 'E', | ||||||
|  |         replace: true, | ||||||
|  |  | ||||||
|  |         scope: { | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         templateUrl: 'app/settings/templates/settingsConnections.html', | ||||||
|  |         controller: ['$scope', '$injector', function settingsConnectionsController($scope, $injector) { | ||||||
|  |  | ||||||
|  |             // Required types | ||||||
|  |             var ConnectionGroup = $injector.get('ConnectionGroup'); | ||||||
|  |             var PermissionSet   = $injector.get('PermissionSet'); | ||||||
|  |  | ||||||
|  |             // Required services | ||||||
|  |             var $location              = $injector.get('$location'); | ||||||
|  |             var authenticationService  = $injector.get('authenticationService'); | ||||||
|  |             var connectionGroupService = $injector.get('connectionGroupService'); | ||||||
|  |             var guacNotification       = $injector.get('guacNotification'); | ||||||
|  |             var permissionService      = $injector.get('permissionService'); | ||||||
|  |  | ||||||
|  |             // Identifier of the current user | ||||||
|  |             var currentUserID = authenticationService.getCurrentUserID(); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * An action to be provided along with the object sent to | ||||||
|  |              * showStatus which closes the currently-shown status dialog. | ||||||
|  |              */ | ||||||
|  |             var ACKNOWLEDGE_ACTION = { | ||||||
|  |                 name        : "SETTINGS_CONNECTIONS.ACTION_ACKNOWLEDGE", | ||||||
|  |                 // Handle action | ||||||
|  |                 callback    : function acknowledgeCallback() { | ||||||
|  |                     guacNotification.showStatus(false); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * The root connection group of the connection group hierarchy. | ||||||
|  |              * | ||||||
|  |              * @type ConnectionGroup | ||||||
|  |              */ | ||||||
|  |             $scope.rootGroup = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Whether the current user can manage connections. If the current | ||||||
|  |              * permissions have not yet been loaded, this will be null. | ||||||
|  |              * | ||||||
|  |              * @type Boolean | ||||||
|  |              */ | ||||||
|  |             $scope.canManageConnections = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Whether the current user can create new connections. If the | ||||||
|  |              * current permissions have not yet been loaded, this will be null. | ||||||
|  |              * | ||||||
|  |              * @type Boolean | ||||||
|  |              */ | ||||||
|  |             $scope.canCreateConnections = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Whether the current user can create new connection groups. If | ||||||
|  |              * the current permissions have not yet been loaded, this will be | ||||||
|  |              * null. | ||||||
|  |              * | ||||||
|  |              * @type Boolean | ||||||
|  |              */ | ||||||
|  |             $scope.canCreateConnectionGroups = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * All permissions associated with the current user, or null if the | ||||||
|  |              * user's permissions have not yet been loaded. | ||||||
|  |              * | ||||||
|  |              * @type PermissionSet | ||||||
|  |              */ | ||||||
|  |             $scope.permissions = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Returns whether critical data has completed being loaded. | ||||||
|  |              * | ||||||
|  |              * @returns {Boolean} | ||||||
|  |              *     true if enough data has been loaded for the user interface | ||||||
|  |              *     to be useful, false otherwise. | ||||||
|  |              */ | ||||||
|  |             $scope.isLoaded = function isLoaded() { | ||||||
|  |  | ||||||
|  |                 return $scope.rootGroup                 !== null | ||||||
|  |                     && $scope.permissions               !== null | ||||||
|  |                     && $scope.canManageConnections      !== null | ||||||
|  |                     && $scope.canCreateConnections      !== null | ||||||
|  |                     && $scope.canCreateConnectionGroups !== null; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             // Retrieve current permissions | ||||||
|  |             permissionService.getPermissions(currentUserID) | ||||||
|  |             .success(function permissionsRetrieved(permissions) { | ||||||
|  |  | ||||||
|  |                 $scope.permissions = permissions; | ||||||
|  |                                  | ||||||
|  |                 // Ignore permission to update root group | ||||||
|  |                 PermissionSet.removeConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE, ConnectionGroup.ROOT_IDENTIFIER); | ||||||
|  |  | ||||||
|  |                 // Determine whether the current user can create new users | ||||||
|  |                 $scope.canCreateConnections = | ||||||
|  |                        PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) | ||||||
|  |                     || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_CONNECTION); | ||||||
|  |  | ||||||
|  |                 // Determine whether the current user can create new users | ||||||
|  |                 $scope.canCreateConnectionGroups = | ||||||
|  |                        PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) | ||||||
|  |                     || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_CONNECTION_GROUP); | ||||||
|  |  | ||||||
|  |                 // Determine whether the current user can manage other connections or groups | ||||||
|  |                 $scope.canManageConnections = | ||||||
|  |  | ||||||
|  |                     // Permission to manage connections | ||||||
|  |                        $scope.canCreateConnections | ||||||
|  |                     || PermissionSet.hasConnectionPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) | ||||||
|  |                     || PermissionSet.hasConnectionPermission(permissions, PermissionSet.ObjectPermissionType.DELETE) | ||||||
|  |  | ||||||
|  |                     // Permission to manage groups | ||||||
|  |                     || $scope.canCreateConnectionGroups | ||||||
|  |                     || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) | ||||||
|  |                     || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.DELETE); | ||||||
|  |  | ||||||
|  |                 // Return to home if there's nothing to do here | ||||||
|  |                 if (!$scope.canManageConnections) | ||||||
|  |                     $location.path('/'); | ||||||
|  |                  | ||||||
|  |             }); | ||||||
|  |              | ||||||
|  |             // Retrieve all connections for which we have UPDATE or DELETE permission | ||||||
|  |             connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER,  | ||||||
|  |                 [PermissionSet.ObjectPermissionType.UPDATE, PermissionSet.ObjectPermissionType.DELETE]) | ||||||
|  |             .success(function connectionGroupReceived(rootGroup) { | ||||||
|  |                 $scope.rootGroup = rootGroup; | ||||||
|  |             }); | ||||||
|  |              | ||||||
|  |         }] | ||||||
|  |     }; | ||||||
|  |      | ||||||
|  | }]); | ||||||
| @@ -0,0 +1,367 @@ | |||||||
|  | /* | ||||||
|  |  * 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A directive for managing all active Guacamole sessions. | ||||||
|  |  */ | ||||||
|  | angular.module('settings').directive('guacSettingsSessions', [function guacSettingsSessions() { | ||||||
|  |      | ||||||
|  |     return { | ||||||
|  |         // Element only | ||||||
|  |         restrict: 'E', | ||||||
|  |         replace: true, | ||||||
|  |  | ||||||
|  |         scope: { | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         templateUrl: 'app/settings/templates/settingsSessions.html', | ||||||
|  |         controller: ['$scope', '$injector', function settingsSessionsController($scope, $injector) { | ||||||
|  |  | ||||||
|  |             // Required types | ||||||
|  |             var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper'); | ||||||
|  |             var ConnectionGroup         = $injector.get('ConnectionGroup'); | ||||||
|  |             var SortOrder               = $injector.get('SortOrder'); | ||||||
|  |  | ||||||
|  |             // Required services | ||||||
|  |             var $filter                 = $injector.get('$filter'); | ||||||
|  |             var $translate              = $injector.get('$translate'); | ||||||
|  |             var activeConnectionService = $injector.get('activeConnectionService'); | ||||||
|  |             var authenticationService   = $injector.get('authenticationService'); | ||||||
|  |             var connectionGroupService  = $injector.get('connectionGroupService'); | ||||||
|  |             var guacNotification        = $injector.get('guacNotification'); | ||||||
|  |             var permissionService       = $injector.get('permissionService'); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * All permissions associated with the current user, or null if the | ||||||
|  |              * user's permissions have not yet been loaded. | ||||||
|  |              * | ||||||
|  |              * @type PermissionSet | ||||||
|  |              */ | ||||||
|  |             $scope.permissions = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * The ActiveConnectionWrappers of all active sessions accessible | ||||||
|  |              * by the current user, or null if the active sessions have not yet | ||||||
|  |              * been loaded. | ||||||
|  |              * | ||||||
|  |              * @type ActiveConnectionWrapper[] | ||||||
|  |              */ | ||||||
|  |             $scope.wrappers = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * SortOrder instance which maintains the sort order of the visible | ||||||
|  |              * connection wrappers. | ||||||
|  |              * | ||||||
|  |              * @type SortOrder | ||||||
|  |              */ | ||||||
|  |             $scope.wrapperOrder = new SortOrder([ | ||||||
|  |                 'activeConnection.username', | ||||||
|  |                 'startDate', | ||||||
|  |                 'activeConnection.remoteHost', | ||||||
|  |                 'name' | ||||||
|  |             ]); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Array of all wrapper properties that are filterable. | ||||||
|  |              * | ||||||
|  |              * @type String[] | ||||||
|  |              */ | ||||||
|  |             $scope.filteredWrapperProperties = [ | ||||||
|  |                 'activeConnection.username', | ||||||
|  |                 'startDate', | ||||||
|  |                 'activeConnection.remoteHost', | ||||||
|  |                 'name' | ||||||
|  |             ]; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * All active connections, if known, or null if active connections | ||||||
|  |              * have not yet been loaded. | ||||||
|  |              * | ||||||
|  |              * @type ActiveConnection | ||||||
|  |              */ | ||||||
|  |             var activeConnections = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Map of all visible connections by object identifier, or null if | ||||||
|  |              * visible connections have not yet been loaded. | ||||||
|  |              * | ||||||
|  |              * @type Object.<String, Connection> | ||||||
|  |              */ | ||||||
|  |             var connections = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * The date format for use for session-related dates. | ||||||
|  |              * | ||||||
|  |              * @type String | ||||||
|  |              */ | ||||||
|  |             var sessionDateFormat = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Map of all currently-selected active connection wrappers by | ||||||
|  |              * identifier. | ||||||
|  |              *  | ||||||
|  |              * @type Object.<String, ActiveConnectionWrapper> | ||||||
|  |              */ | ||||||
|  |             var selectedWrappers = {}; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Adds the given connection to the internal set of visible | ||||||
|  |              * connections. | ||||||
|  |              *  | ||||||
|  |              * @param {Connection} connection | ||||||
|  |              *     The connection to add to the internal set of visible | ||||||
|  |              *     connections. | ||||||
|  |              */ | ||||||
|  |             var addConnection = function addConnection(connection) { | ||||||
|  |  | ||||||
|  |                 // Add given connection to set of visible connections | ||||||
|  |                 connections[connection.identifier] = connection; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Adds all descendant connections of the given connection group to | ||||||
|  |              * the internal set of connections. | ||||||
|  |              *  | ||||||
|  |              * @param {ConnectionGroup} connectionGroup | ||||||
|  |              *     The connection group whose descendant connections should be | ||||||
|  |              *     added to the internal set of connections. | ||||||
|  |              */ | ||||||
|  |             var addDescendantConnections = function addDescendantConnections(connectionGroup) { | ||||||
|  |  | ||||||
|  |                 // Add all child connections | ||||||
|  |                 if (connectionGroup.childConnections) | ||||||
|  |                     connectionGroup.childConnections.forEach(addConnection); | ||||||
|  |  | ||||||
|  |                 // Add all child connection groups | ||||||
|  |                 if (connectionGroup.childConnectionGroups) | ||||||
|  |                     connectionGroup.childConnectionGroups.forEach(addDescendantConnections); | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Wraps all loaded active connections, storing the resulting array | ||||||
|  |              * within the scope. If required data has not yet finished loading, | ||||||
|  |              * this function has no effect. | ||||||
|  |              */ | ||||||
|  |             var wrapActiveConnections = function wrapActiveConnections() { | ||||||
|  |  | ||||||
|  |                 // Abort if not all required data is available | ||||||
|  |                 if (!activeConnections || !connections || !sessionDateFormat) | ||||||
|  |                     return; | ||||||
|  |  | ||||||
|  |                 // Wrap all active connections for sake of display | ||||||
|  |                 $scope.wrappers = []; | ||||||
|  |                 for (var identifier in activeConnections) { | ||||||
|  |  | ||||||
|  |                     var activeConnection = activeConnections[identifier]; | ||||||
|  |                     var connection = connections[activeConnection.connectionIdentifier]; | ||||||
|  |  | ||||||
|  |                     $scope.wrappers.push(new ActiveConnectionWrapper( | ||||||
|  |                         connection.name, | ||||||
|  |                         $filter('date')(activeConnection.startDate, sessionDateFormat), | ||||||
|  |                         activeConnection | ||||||
|  |                     ));  | ||||||
|  |  | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             // Query the user's permissions | ||||||
|  |             permissionService.getPermissions(authenticationService.getCurrentUserID()) | ||||||
|  |                     .success(function permissionsReceived(retrievedPermissions) { | ||||||
|  |                 $scope.permissions = retrievedPermissions; | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             // Retrieve all connections  | ||||||
|  |             connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER) | ||||||
|  |             .success(function connectionGroupReceived(retrievedRootGroup) { | ||||||
|  |  | ||||||
|  |                 // Load connections from retrieved group tree | ||||||
|  |                 connections = {}; | ||||||
|  |                 addDescendantConnections(retrievedRootGroup); | ||||||
|  |  | ||||||
|  |                 // Attempt to produce wrapped list of active connections | ||||||
|  |                 wrapActiveConnections(); | ||||||
|  |  | ||||||
|  |             }); | ||||||
|  |              | ||||||
|  |             // Query active sessions | ||||||
|  |             activeConnectionService.getActiveConnections().success(function sessionsRetrieved(retrievedActiveConnections) { | ||||||
|  |  | ||||||
|  |                 // Store received list | ||||||
|  |                 activeConnections = retrievedActiveConnections; | ||||||
|  |  | ||||||
|  |                 // Attempt to produce wrapped list of active connections | ||||||
|  |                 wrapActiveConnections(); | ||||||
|  |  | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             // Get session date format | ||||||
|  |             $translate('SETTINGS_SESSIONS.FORMAT_STARTDATE').then(function sessionDateFormatReceived(retrievedSessionDateFormat) { | ||||||
|  |  | ||||||
|  |                 // Store received date format | ||||||
|  |                 sessionDateFormat = retrievedSessionDateFormat; | ||||||
|  |  | ||||||
|  |                 // Attempt to produce wrapped list of active connections | ||||||
|  |                 wrapActiveConnections(); | ||||||
|  |  | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Returns whether critical data has completed being loaded. | ||||||
|  |              * | ||||||
|  |              * @returns {Boolean} | ||||||
|  |              *     true if enough data has been loaded for the user interface | ||||||
|  |              *     to be useful, false otherwise. | ||||||
|  |              */ | ||||||
|  |             $scope.isLoaded = function isLoaded() { | ||||||
|  |  | ||||||
|  |                 return $scope.wrappers          !== null | ||||||
|  |                     && $scope.sessionDateFormat !== null | ||||||
|  |                     && $scope.permissions       !== null; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * An action to be provided along with the object sent to | ||||||
|  |              * showStatus which closes the currently-shown status dialog. | ||||||
|  |              */ | ||||||
|  |             var ACKNOWLEDGE_ACTION = { | ||||||
|  |                 name        : "SETTINGS_SESSIONS.ACTION_ACKNOWLEDGE", | ||||||
|  |                 // Handle action | ||||||
|  |                 callback    : function acknowledgeCallback() { | ||||||
|  |                     guacNotification.showStatus(false); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * An action to be provided along with the object sent to | ||||||
|  |              * showStatus which closes the currently-shown status dialog. | ||||||
|  |              */ | ||||||
|  |             var CANCEL_ACTION = { | ||||||
|  |                 name        : "SETTINGS_SESSIONS.ACTION_CANCEL", | ||||||
|  |                 // Handle action | ||||||
|  |                 callback    : function cancelCallback() { | ||||||
|  |                     guacNotification.showStatus(false); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * An action to be provided along with the object sent to | ||||||
|  |              * showStatus which immediately deletes the currently selected | ||||||
|  |              * sessions. | ||||||
|  |              */ | ||||||
|  |             var DELETE_ACTION = { | ||||||
|  |                 name        : "SETTINGS_SESSIONS.ACTION_DELETE", | ||||||
|  |                 className   : "danger", | ||||||
|  |                 // Handle action | ||||||
|  |                 callback    : function deleteCallback() { | ||||||
|  |                     deleteSessionsImmediately(); | ||||||
|  |                     guacNotification.showStatus(false); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * Immediately deletes the selected sessions, without prompting the | ||||||
|  |              * user for confirmation. | ||||||
|  |              */ | ||||||
|  |             var deleteSessionsImmediately = function deleteSessionsImmediately() { | ||||||
|  |  | ||||||
|  |                 // Perform deletion | ||||||
|  |                 activeConnectionService.deleteActiveConnections(Object.keys(selectedWrappers)) | ||||||
|  |                 .success(function activeConnectionsDeleted() { | ||||||
|  |  | ||||||
|  |                     // Remove deleted connections from wrapper array | ||||||
|  |                     $scope.wrappers = $scope.wrappers.filter(function activeConnectionStillExists(wrapper) { | ||||||
|  |                         return !(wrapper.activeConnection.identifier in selectedWrappers); | ||||||
|  |                     }); | ||||||
|  |  | ||||||
|  |                     // Clear selection | ||||||
|  |                     selectedWrappers = {}; | ||||||
|  |  | ||||||
|  |                 }) | ||||||
|  |  | ||||||
|  |                 // Notify of any errors | ||||||
|  |                 .error(function activeConnectionDeletionFailed(error) { | ||||||
|  |                     guacNotification.showStatus({ | ||||||
|  |                         'className'  : 'error', | ||||||
|  |                         'title'      : 'SETTINGS_SESSIONS.DIALOG_HEADER_ERROR', | ||||||
|  |                         'text'       : error.message, | ||||||
|  |                         'actions'    : [ ACKNOWLEDGE_ACTION ] | ||||||
|  |                     }); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             };  | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * Delete all selected sessions, prompting the user first to | ||||||
|  |              * confirm that deletion is desired. | ||||||
|  |              */ | ||||||
|  |             $scope.deleteSessions = function deleteSessions() { | ||||||
|  |                 // Confirm deletion request | ||||||
|  |                 guacNotification.showStatus({ | ||||||
|  |                     'title'      : 'SETTINGS_SESSIONS.DIALOG_HEADER_CONFIRM_DELETE', | ||||||
|  |                     'text'       : 'SETTINGS_SESSIONS.TEXT_CONFIRM_DELETE', | ||||||
|  |                     'actions'    : [ DELETE_ACTION, CANCEL_ACTION] | ||||||
|  |                 }); | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * Returns whether the selected sessions can be deleted. | ||||||
|  |              *  | ||||||
|  |              * @returns {Boolean} | ||||||
|  |              *     true if selected sessions can be deleted, false otherwise. | ||||||
|  |              */ | ||||||
|  |             $scope.canDeleteSessions = function canDeleteSessions() { | ||||||
|  |  | ||||||
|  |                 // We can delete sessions if at least one is selected | ||||||
|  |                 for (var identifier in selectedWrappers) | ||||||
|  |                     return true; | ||||||
|  |  | ||||||
|  |                 return false; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * Called whenever an active connection wrapper changes selected | ||||||
|  |              * status. | ||||||
|  |              *  | ||||||
|  |              * @param {ActiveConnectionWrapper} wrapper | ||||||
|  |              *     The wrapper whose selected status has changed. | ||||||
|  |              */ | ||||||
|  |             $scope.wrapperSelectionChange = function wrapperSelectionChange(wrapper) { | ||||||
|  |  | ||||||
|  |                 // Add wrapper to map if selected | ||||||
|  |                 if (wrapper.checked) | ||||||
|  |                     selectedWrappers[wrapper.activeConnection.identifier] = wrapper; | ||||||
|  |  | ||||||
|  |                 // Otherwise, remove wrapper from map | ||||||
|  |                 else | ||||||
|  |                     delete selectedWrappers[wrapper.activeConnection.identifier]; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |         }] | ||||||
|  |     }; | ||||||
|  |      | ||||||
|  | }]); | ||||||
| @@ -0,0 +1,192 @@ | |||||||
|  | /* | ||||||
|  |  * 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A directive for managing all users in the system. | ||||||
|  |  */ | ||||||
|  | angular.module('settings').directive('guacSettingsUsers', [function guacSettingsUsers() { | ||||||
|  |      | ||||||
|  |     return { | ||||||
|  |         // Element only | ||||||
|  |         restrict: 'E', | ||||||
|  |         replace: true, | ||||||
|  |  | ||||||
|  |         scope: { | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         templateUrl: 'app/settings/templates/settingsUsers.html', | ||||||
|  |         controller: ['$scope', '$injector', function settingsUsersController($scope, $injector) { | ||||||
|  |  | ||||||
|  |             // Required types | ||||||
|  |             var PermissionSet   = $injector.get('PermissionSet'); | ||||||
|  |             var User            = $injector.get('User'); | ||||||
|  |  | ||||||
|  |             // Required services | ||||||
|  |             var $location              = $injector.get('$location'); | ||||||
|  |             var authenticationService  = $injector.get('authenticationService'); | ||||||
|  |             var guacNotification       = $injector.get('guacNotification'); | ||||||
|  |             var permissionService      = $injector.get('permissionService'); | ||||||
|  |             var userService            = $injector.get('userService'); | ||||||
|  |  | ||||||
|  |             // Identifier of the current user | ||||||
|  |             var currentUserID = authenticationService.getCurrentUserID(); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * An action to be provided along with the object sent to | ||||||
|  |              * showStatus which closes the currently-shown status dialog. | ||||||
|  |              */ | ||||||
|  |             var ACKNOWLEDGE_ACTION = { | ||||||
|  |                 name        : "SETTINGS_USERS.ACTION_ACKNOWLEDGE", | ||||||
|  |                 // Handle action | ||||||
|  |                 callback    : function acknowledgeCallback() { | ||||||
|  |                     guacNotification.showStatus(false); | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * All visible users. | ||||||
|  |              * | ||||||
|  |              * @type User[] | ||||||
|  |              */ | ||||||
|  |             $scope.users = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Whether the current user can manage users. If the current | ||||||
|  |              * permissions have not yet been loaded, this will be null. | ||||||
|  |              * | ||||||
|  |              * @type Boolean | ||||||
|  |              */ | ||||||
|  |             $scope.canManageUsers = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Whether the current user can create new users. If the current | ||||||
|  |              * permissions have not yet been loaded, this will be null. | ||||||
|  |              * | ||||||
|  |              * @type Boolean | ||||||
|  |              */ | ||||||
|  |             $scope.canCreateUsers = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * The name of the new user to create, if any, when user creation | ||||||
|  |              * is requested via newUser(). | ||||||
|  |              * | ||||||
|  |              * @type String | ||||||
|  |              */ | ||||||
|  |             $scope.newUsername = ""; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * All permissions associated with the current user, or null if the | ||||||
|  |              * user's permissions have not yet been loaded. | ||||||
|  |              * | ||||||
|  |              * @type PermissionSet | ||||||
|  |              */ | ||||||
|  |             $scope.permissions = null; | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Returns whether critical data has completed being loaded. | ||||||
|  |              * | ||||||
|  |              * @returns {Boolean} | ||||||
|  |              *     true if enough data has been loaded for the user interface | ||||||
|  |              *     to be useful, false otherwise. | ||||||
|  |              */ | ||||||
|  |             $scope.isLoaded = function isLoaded() { | ||||||
|  |  | ||||||
|  |                 return $scope.users                     !== null | ||||||
|  |                     && $scope.permissions               !== null | ||||||
|  |                     && $scope.canManageUsers            !== null | ||||||
|  |                     && $scope.canCreateUsers            !== null; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             // Retrieve current permissions | ||||||
|  |             permissionService.getPermissions(currentUserID) | ||||||
|  |             .success(function permissionsRetrieved(permissions) { | ||||||
|  |  | ||||||
|  |                 $scope.permissions = permissions; | ||||||
|  |  | ||||||
|  |                 // Determine whether the current user can create new users | ||||||
|  |                 $scope.canCreateUsers = | ||||||
|  |                        PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER) | ||||||
|  |                     || PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.CREATE_USER); | ||||||
|  |  | ||||||
|  |                 // Determine whether the current user can manage other users | ||||||
|  |                 $scope.canManageUsers = | ||||||
|  |                        $scope.canCreateUsers | ||||||
|  |                     || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE) | ||||||
|  |                     || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.DELETE); | ||||||
|  |  | ||||||
|  |                 // Return to home if there's nothing to do here | ||||||
|  |                 if (!$scope.canManageUsers) | ||||||
|  |                     $location.path('/'); | ||||||
|  |                  | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             // Retrieve all users for whom we have UPDATE or DELETE permission | ||||||
|  |             userService.getUsers([PermissionSet.ObjectPermissionType.UPDATE,  | ||||||
|  |                 PermissionSet.ObjectPermissionType.DELETE]) | ||||||
|  |             .success(function usersReceived(users) { | ||||||
|  |  | ||||||
|  |                 // Display only other users, not self | ||||||
|  |                 $scope.users = users.filter(function isNotSelf(user) { | ||||||
|  |                     return user.username !== currentUserID; | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * Creates a new user having the username specified in the user | ||||||
|  |              * creation interface. | ||||||
|  |              */ | ||||||
|  |             $scope.newUser = function newUser() { | ||||||
|  |  | ||||||
|  |                 // Create user skeleton | ||||||
|  |                 var user = new User({ | ||||||
|  |                     username: $scope.newUsername || '' | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 // Create specified user | ||||||
|  |                 userService.createUser(user) | ||||||
|  |  | ||||||
|  |                 // Add user to visible list upon success | ||||||
|  |                 .success(function userCreated() { | ||||||
|  |                     $scope.users.push(user); | ||||||
|  |                 }) | ||||||
|  |  | ||||||
|  |                 // Notify of any errors | ||||||
|  |                 .error(function userCreationFailed(error) { | ||||||
|  |                     guacNotification.showStatus({ | ||||||
|  |                         'className'  : 'error', | ||||||
|  |                         'title'      : 'SETTINGS_USERS.DIALOG_HEADER_ERROR', | ||||||
|  |                         'text'       : error.message, | ||||||
|  |                         'actions'    : [ ACKNOWLEDGE_ACTION ] | ||||||
|  |                     }); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 // Reset username | ||||||
|  |                 $scope.newUsername = ""; | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |         }] | ||||||
|  |     }; | ||||||
|  |      | ||||||
|  | }]); | ||||||
							
								
								
									
										33
									
								
								guacamole/src/main/webapp/app/settings/settingsModule.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								guacamole/src/main/webapp/app/settings/settingsModule.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2014 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The module for manipulation of general settings. This is distinct from the | ||||||
|  |  * "manage" module, which deals only with administrator-level system management. | ||||||
|  |  */ | ||||||
|  | angular.module('settings', [ | ||||||
|  |     'groupList', | ||||||
|  |     'list', | ||||||
|  |     'navigation', | ||||||
|  |     'notification', | ||||||
|  |     'rest' | ||||||
|  | ]); | ||||||
| @@ -20,15 +20,15 @@ | |||||||
|  * THE SOFTWARE. |  * THE SOFTWARE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| .manage table.session-list { | .settings table.session-list { | ||||||
|     width: 100%; |     width: 100%; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .manage table.session-list tr.session:hover { | .settings table.session-list tr.session:hover { | ||||||
|     background: #CDA; |     background: #CDA; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .manage table.session-list .select-session { | .settings table.session-list .select-session { | ||||||
|     min-width: 2em; |     min-width: 2em; | ||||||
|     text-align: center; |     text-align: center; | ||||||
| } | } | ||||||
							
								
								
									
										69
									
								
								guacamole/src/main/webapp/app/settings/styles/settings.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								guacamole/src/main/webapp/app/settings/styles/settings.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | /* | ||||||
|  |  * 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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | .settings .header { | ||||||
|  |     margin-bottom: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings table.properties th { | ||||||
|  |     text-align: left; | ||||||
|  |     font-weight: normal; | ||||||
|  |     padding-right: 1em; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings .action-buttons { | ||||||
|  |     text-align: center; | ||||||
|  |     margin-bottom: 1em; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings-tabs .page-list { | ||||||
|  |     margin: 0; | ||||||
|  |     padding: 0; | ||||||
|  |     background: rgba(0, 0, 0, 0.0125); | ||||||
|  |     border-bottom: 1px solid rgba(0, 0, 0, 0.05); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings-tabs .page-list li { | ||||||
|  |     display: inline-block; | ||||||
|  |     list-style: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings-tabs .page-list li a[href] { | ||||||
|  |     display: block; | ||||||
|  |     color: black; | ||||||
|  |     text-decoration: none; | ||||||
|  |     padding: 0.75em 1em; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings-tabs .page-list li a[href]:visited { | ||||||
|  |     color: black; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings-tabs .page-list li a[href]:hover { | ||||||
|  |     background-color: #CDA; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .settings-tabs .page-list li a[href].current, | ||||||
|  | .settings-tabs .page-list li a[href].current:hover { | ||||||
|  |     background: rgba(0,0,0,0.3); | ||||||
|  |     cursor: default; | ||||||
|  | } | ||||||
| @@ -33,7 +33,7 @@ | |||||||
| 
 | 
 | ||||||
|         <!-- Active user count --> |         <!-- Active user count --> | ||||||
|         <span class="activeUserCount" ng-show="item.getActiveConnections()"> |         <span class="activeUserCount" ng-show="item.getActiveConnections()"> | ||||||
|             {{'MANAGE_CONNECTION.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.getActiveConnections()}'}} |             {{'SETTINGS_CONNECTIONS.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.getActiveConnections()}'}} | ||||||
|         </span> |         </span> | ||||||
|          |          | ||||||
|     </div> |     </div> | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | <!-- | ||||||
|  | Copyright 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. | ||||||
|  | --> | ||||||
|  |  | ||||||
|  | <div class="view"> | ||||||
|  |  | ||||||
|  |     <div class="header"> | ||||||
|  |         <h2>{{'SETTINGS.SECTION_HEADER_SETTINGS' | translate}}</h2> | ||||||
|  |         <guac-user-menu></guac-user-menu> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- Available tabs --> | ||||||
|  |     <div class="settings-tabs"> | ||||||
|  |         <guac-page-list pages="settingsPages"></guac-page-list> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- Selected tab --> | ||||||
|  |     <guac-settings-users       ng-if="activeTab === 'users'"></guac-settings-users> | ||||||
|  |     <guac-settings-connections ng-if="activeTab === 'connections'"></guac-settings-connections> | ||||||
|  |     <guac-settings-sessions    ng-if="activeTab === 'sessions'"></guac-settings-sessions> | ||||||
|  |  | ||||||
|  | </div> | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | <div class="settings section connections" ng-class="{loading: !isLoaded()}"> | ||||||
|  |     <!-- | ||||||
|  |     Copyright 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. | ||||||
|  |     --> | ||||||
|  |  | ||||||
|  |     <!-- Connection management --> | ||||||
|  |     <p>{{'SETTINGS_CONNECTIONS.HELP_CONNECTIONS' | translate}}</p> | ||||||
|  |  | ||||||
|  |     <!-- Form action buttons --> | ||||||
|  |     <div class="action-buttons"> | ||||||
|  |  | ||||||
|  |         <a class="add-connection button" | ||||||
|  |            ng-show="canCreateConnections" | ||||||
|  |            href="#/manage/connections/">{{'SETTINGS_CONNECTIONS.ACTION_NEW_CONNECTION' | translate}}</a> | ||||||
|  |  | ||||||
|  |         <a class="add-connection-group button" | ||||||
|  |            ng-show="canCreateConnectionGroups" | ||||||
|  |            href="#/manage/connectionGroups/">{{'SETTINGS_CONNECTIONS.ACTION_NEW_CONNECTION_GROUP' | translate}}</a> | ||||||
|  |  | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- List of accessible connections and groups --> | ||||||
|  |     <div class="connection-list"> | ||||||
|  |         <guac-group-list | ||||||
|  |             page-size="25" | ||||||
|  |             connection-group="rootGroup" | ||||||
|  |             connection-template="'app/settings/templates/connection.html'" | ||||||
|  |             connection-group-template="'app/settings/templates/connectionGroup.html'"/> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
| @@ -0,0 +1,77 @@ | |||||||
|  | <div class="settings section sessions" ng-class="{loading: !isLoaded()}"> | ||||||
|  |     <!-- | ||||||
|  |     Copyright 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. | ||||||
|  |     --> | ||||||
|  |  | ||||||
|  |     <!-- User Session management --> | ||||||
|  |     <p>{{'SETTINGS_SESSIONS.HELP_SESSIONS' | translate}}</p> | ||||||
|  |  | ||||||
|  |     <!-- Form action buttons --> | ||||||
|  |     <div class="action-buttons"> | ||||||
|  |         <button class="delete-sessions danger" ng-disabled="!canDeleteSessions()" ng-click="deleteSessions()">{{'SETTINGS_SESSIONS.ACTION_DELETE' | translate}}</button> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- Session filter --> | ||||||
|  |     <guac-filter filtered-items="filteredWrappers" items="wrappers" | ||||||
|  |                  placeholder="'SETTINGS_SESSIONS.FIELD_PLACEHOLDER_FILTER' | translate" | ||||||
|  |                  properties="filteredWrapperProperties"></guac-filter> | ||||||
|  |  | ||||||
|  |     <!-- List of current user sessions --> | ||||||
|  |     <table class="sorted session-list"> | ||||||
|  |         <thead> | ||||||
|  |             <tr> | ||||||
|  |                 <th class="select-session"></th> | ||||||
|  |                 <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.username'"> | ||||||
|  |                     {{'SETTINGS_SESSIONS.TABLE_HEADER_SESSION_USERNAME' | translate}} | ||||||
|  |                 </th> | ||||||
|  |                 <th guac-sort-order="wrapperOrder" guac-sort-property="'startDate'"> | ||||||
|  |                     {{'SETTINGS_SESSIONS.TABLE_HEADER_SESSION_STARTDATE' | translate}} | ||||||
|  |                 </th> | ||||||
|  |                 <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.remoteHost'"> | ||||||
|  |                     {{'SETTINGS_SESSIONS.TABLE_HEADER_SESSION_REMOTEHOST' | translate}} | ||||||
|  |                 </th> | ||||||
|  |                 <th guac-sort-order="wrapperOrder" guac-sort-property="'name'"> | ||||||
|  |                     {{'SETTINGS_SESSIONS.TABLE_HEADER_SESSION_CONNECTION_NAME' | translate}} | ||||||
|  |                 </th> | ||||||
|  |             </tr> | ||||||
|  |         </thead> | ||||||
|  |         <tbody> | ||||||
|  |             <tr ng-repeat="wrapper in wrapperPage" class="session"> | ||||||
|  |                 <td class="select-session"> | ||||||
|  |                     <input ng-change="wrapperSelectionChange(wrapper)" type="checkbox" ng-model="wrapper.checked" /> | ||||||
|  |                 </td> | ||||||
|  |                 <td>{{wrapper.activeConnection.username}}</td> | ||||||
|  |                 <td>{{wrapper.startDate}}</td> | ||||||
|  |                 <td>{{wrapper.activeConnection.remoteHost}}</td> | ||||||
|  |                 <td>{{wrapper.name}}</td> | ||||||
|  |             </tr> | ||||||
|  |         </tbody> | ||||||
|  |     </table> | ||||||
|  |  | ||||||
|  |     <!-- Text displayed if no sessions exist --> | ||||||
|  |     <p class="placeholder" ng-hide="wrapperPage.length"> | ||||||
|  |         {{'SETTINGS_SESSIONS.INFO_NO_SESSIONS' | translate}} | ||||||
|  |     </p> | ||||||
|  |  | ||||||
|  |     <!-- Pager for session list --> | ||||||
|  |     <guac-pager page="wrapperPage" page-size="25" | ||||||
|  |                 items="filteredWrappers | orderBy : wrapperOrder.predicate"></guac-pager> | ||||||
|  | </div> | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | <div class="settings section users" ng-class="{loading: !isLoaded()}"> | ||||||
|  |     <!-- | ||||||
|  |     Copyright 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. | ||||||
|  |     --> | ||||||
|  |  | ||||||
|  |     <!-- User management --> | ||||||
|  |     <p>{{'SETTINGS_USERS.HELP_USERS' | translate}}</p> | ||||||
|  |  | ||||||
|  |     <!-- Form action buttons --> | ||||||
|  |     <div class="action-buttons" ng-show="canCreateUsers"> | ||||||
|  |         <input type="text" ng-model="newUsername" class="name username" autocorrect="off" autocapitalize="off"/> | ||||||
|  |         <button class="add-user" ng-click="newUser()">{{'SETTINGS_USERS.ACTION_NEW_USER' | translate}}</button> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- List of users this user has access to --> | ||||||
|  |     <div class="user-list"> | ||||||
|  |         <div ng-repeat="user in userPage" class="user list-item"> | ||||||
|  |             <a ng-href="#/manage/users/{{user.username}}"> | ||||||
|  |                 <div class="caption"> | ||||||
|  |                     <div class="icon user"></div> | ||||||
|  |                     <span class="name">{{user.username}}</span> | ||||||
|  |                 </div> | ||||||
|  |             </a> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <!-- Pager controls for user list --> | ||||||
|  |     <guac-pager page="userPage" page-size="25" items="users | orderBy : 'username'"></guac-pager> | ||||||
|  |  | ||||||
|  | </div> | ||||||
| @@ -23,7 +23,7 @@ | |||||||
| /** | /** | ||||||
|  * A service for defining the ActiveConnectionWrapper class. |  * A service for defining the ActiveConnectionWrapper class. | ||||||
|  */ |  */ | ||||||
| angular.module('manage').factory('ActiveConnectionWrapper', [ | angular.module('settings').factory('ActiveConnectionWrapper', [ | ||||||
|     function defineActiveConnectionWrapper() { |     function defineActiveConnectionWrapper() { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @@ -10,7 +10,8 @@ | |||||||
|         "ACTION_DELETE_SESSIONS"    : "Kill Sessions", |         "ACTION_DELETE_SESSIONS"    : "Kill Sessions", | ||||||
|         "ACTION_LOGIN"              : "Login", |         "ACTION_LOGIN"              : "Login", | ||||||
|         "ACTION_LOGOUT"             : "Logout", |         "ACTION_LOGOUT"             : "Logout", | ||||||
|         "ACTION_MANAGE_CONNECTIONS" : "Manage Connections", |         "ACTION_MANAGE_CONNECTIONS" : "Connections", | ||||||
|  |         "ACTION_MANAGE_SETTINGS"    : "Settings", | ||||||
|         "ACTION_MANAGE_SESSIONS"    : "Active Sessions", |         "ACTION_MANAGE_SESSIONS"    : "Active Sessions", | ||||||
|         "ACTION_MANAGE_USERS"       : "Users", |         "ACTION_MANAGE_USERS"       : "Users", | ||||||
|         "ACTION_NAVIGATE_BACK"      : "Back", |         "ACTION_NAVIGATE_BACK"      : "Back", | ||||||
| @@ -154,8 +155,6 @@ | |||||||
|         "ACTION_CANCEL"               : "@:APP.ACTION_CANCEL", |         "ACTION_CANCEL"               : "@:APP.ACTION_CANCEL", | ||||||
|         "ACTION_CLONE"                : "@:APP.ACTION_CLONE", |         "ACTION_CLONE"                : "@:APP.ACTION_CLONE", | ||||||
|         "ACTION_DELETE"               : "@:APP.ACTION_DELETE", |         "ACTION_DELETE"               : "@:APP.ACTION_DELETE", | ||||||
|         "ACTION_NEW_CONNECTION"       : "New Connection", |  | ||||||
|         "ACTION_NEW_CONNECTION_GROUP" : "New Group", |  | ||||||
|         "ACTION_SAVE"                 : "@:APP.ACTION_SAVE", |         "ACTION_SAVE"                 : "@:APP.ACTION_SAVE", | ||||||
|  |  | ||||||
|         "DIALOG_HEADER_CONFIRM_DELETE" : "Delete Connection", |         "DIALOG_HEADER_CONFIRM_DELETE" : "Delete Connection", | ||||||
| @@ -167,14 +166,10 @@ | |||||||
|  |  | ||||||
|         "FORMAT_HISTORY_START" : "@:APP.FORMAT_DATE_TIME_PRECISE", |         "FORMAT_HISTORY_START" : "@:APP.FORMAT_DATE_TIME_PRECISE", | ||||||
|  |  | ||||||
|         "HELP_CONNECTIONS"   : "Click or tap on a connection below to manage that connection. Depending on your access level, connections can be added and deleted, and their properties (protocol, hostname, port, etc.) can be changed.", |  | ||||||
|          |  | ||||||
|         "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", |  | ||||||
|         "INFO_CONNECTION_DURATION_UNKNOWN" : "--", |         "INFO_CONNECTION_DURATION_UNKNOWN" : "--", | ||||||
|         "INFO_CONNECTION_ACTIVE_NOW"       : "Active Now", |         "INFO_CONNECTION_ACTIVE_NOW"       : "Active Now", | ||||||
|         "INFO_CONNECTION_NOT_USED"         : "This connection has not yet been used.", |         "INFO_CONNECTION_NOT_USED"         : "This connection has not yet been used.", | ||||||
|  |  | ||||||
|         "SECTION_HEADER_CONNECTIONS"     : "Manage Connections", |  | ||||||
|         "SECTION_HEADER_EDIT_CONNECTION" : "Edit Connection", |         "SECTION_HEADER_EDIT_CONNECTION" : "Edit Connection", | ||||||
|         "SECTION_HEADER_HISTORY"         : "Usage History", |         "SECTION_HEADER_HISTORY"         : "Usage History", | ||||||
|         "SECTION_HEADER_PARAMETERS"      : "Parameters", |         "SECTION_HEADER_PARAMETERS"      : "Parameters", | ||||||
| @@ -216,7 +211,6 @@ | |||||||
|         "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE", |         "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE", | ||||||
|         "ACTION_CANCEL"        : "@:APP.ACTION_CANCEL", |         "ACTION_CANCEL"        : "@:APP.ACTION_CANCEL", | ||||||
|         "ACTION_DELETE"        : "@:APP.ACTION_DELETE", |         "ACTION_DELETE"        : "@:APP.ACTION_DELETE", | ||||||
|         "ACTION_NEW_USER"      : "New User", |  | ||||||
|         "ACTION_SAVE"          : "@:APP.ACTION_SAVE", |         "ACTION_SAVE"          : "@:APP.ACTION_SAVE", | ||||||
|  |  | ||||||
|         "DIALOG_HEADER_CONFIRM_DELETE"  : "Delete User", |         "DIALOG_HEADER_CONFIRM_DELETE"  : "Delete User", | ||||||
| @@ -233,45 +227,14 @@ | |||||||
|         "FIELD_HEADER_PASSWORD_AGAIN"                : "@:APP.FIELD_HEADER_PASSWORD_AGAIN", |         "FIELD_HEADER_PASSWORD_AGAIN"                : "@:APP.FIELD_HEADER_PASSWORD_AGAIN", | ||||||
|         "FIELD_HEADER_USERNAME"                      : "Username:", |         "FIELD_HEADER_USERNAME"                      : "Username:", | ||||||
|          |          | ||||||
|         "HELP_USERS" : "Click or tap on a user below to manage that user. Depending on your access level, users can be added and deleted, and their passwords can be changed.", |  | ||||||
|  |  | ||||||
|         "SECTION_HEADER_CONNECTIONS" : "Connections", |         "SECTION_HEADER_CONNECTIONS" : "Connections", | ||||||
|         "SECTION_HEADER_EDIT_USER"   : "Edit User", |         "SECTION_HEADER_EDIT_USER"   : "Edit User", | ||||||
|         "SECTION_HEADER_PERMISSIONS" : "Permissions", |         "SECTION_HEADER_PERMISSIONS" : "Permissions", | ||||||
|         "SECTION_HEADER_USERS"       : "Users", |  | ||||||
|  |  | ||||||
|         "TEXT_CONFIRM_DELETE" : "Users cannot be restored after they have been deleted. Are you sure you want to delete this user?" |         "TEXT_CONFIRM_DELETE" : "Users cannot be restored after they have been deleted. Are you sure you want to delete this user?" | ||||||
|  |  | ||||||
|     }, |     }, | ||||||
|      |      | ||||||
|     "MANAGE_SESSION" : { |  | ||||||
|          |  | ||||||
|         "ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE", |  | ||||||
|         "ACTION_CANCEL"      : "@:APP.ACTION_CANCEL", |  | ||||||
|         "ACTION_DELETE"      : "Kill Sessions", |  | ||||||
|          |  | ||||||
|         "DIALOG_HEADER_CONFIRM_DELETE" : "Kill Sessions", |  | ||||||
|         "DIALOG_HEADER_ERROR"          : "Error", |  | ||||||
|          |  | ||||||
|         "FIELD_PLACEHOLDER_FILTER" : "Filter", |  | ||||||
|          |  | ||||||
|         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE", |  | ||||||
|  |  | ||||||
|         "HELP_SESSIONS" : "All currently-active Guacamole sessions are listed here. If you wish to kill one or more sessions, check the box next to those sessions and click \"Kill Sessions\". Killing a session will immediately disconnect the user from the associated connection.", |  | ||||||
|          |  | ||||||
|         "INFO_NO_SESSIONS" : "No active sessions", |  | ||||||
|  |  | ||||||
|         "SECTION_HEADER_SESSIONS" : "Active Sessions", |  | ||||||
|          |  | ||||||
|         "TABLE_HEADER_SESSION_USERNAME"        : "Username", |  | ||||||
|         "TABLE_HEADER_SESSION_STARTDATE"       : "Active since", |  | ||||||
|         "TABLE_HEADER_SESSION_REMOTEHOST"      : "Remote host", |  | ||||||
|         "TABLE_HEADER_SESSION_CONNECTION_NAME" : "Connection name", |  | ||||||
|          |  | ||||||
|         "TEXT_CONFIRM_DELETE" : "Are you sure you want to kill all selected sessions? The users using these sessions will be immediately disconnected." |  | ||||||
|  |  | ||||||
|     }, |  | ||||||
|  |  | ||||||
|     "PROTOCOL_RDP" : { |     "PROTOCOL_RDP" : { | ||||||
|  |  | ||||||
|         "FIELD_HEADER_COLOR_DEPTH"     : "Color depth:", |         "FIELD_HEADER_COLOR_DEPTH"     : "Color depth:", | ||||||
| @@ -414,6 +377,69 @@ | |||||||
|  |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     "SETTINGS" : { | ||||||
|  |  | ||||||
|  |         "SECTION_HEADER_SETTINGS" : "Settings" | ||||||
|  |  | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     "SETTINGS_CONNECTIONS" : { | ||||||
|  |  | ||||||
|  |         "ACTION_ACKNOWLEDGE"          : "@:APP.ACTION_ACKNOWLEDGE", | ||||||
|  |         "ACTION_NEW_CONNECTION"       : "New Connection", | ||||||
|  |         "ACTION_NEW_CONNECTION_GROUP" : "New Group", | ||||||
|  |  | ||||||
|  |         "DIALOG_HEADER_ERROR"          : "Error", | ||||||
|  |  | ||||||
|  |         "HELP_CONNECTIONS"   : "Click or tap on a connection below to manage that connection. Depending on your access level, connections can be added and deleted, and their properties (protocol, hostname, port, etc.) can be changed.", | ||||||
|  |          | ||||||
|  |         "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", | ||||||
|  |  | ||||||
|  |         "SECTION_HEADER_CONNECTIONS"     : "Connections" | ||||||
|  |  | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     "SETTINGS_USERS" : { | ||||||
|  |  | ||||||
|  |         "ACTION_ACKNOWLEDGE"   : "@:APP.ACTION_ACKNOWLEDGE", | ||||||
|  |         "ACTION_NEW_USER"      : "New User", | ||||||
|  |  | ||||||
|  |         "DIALOG_HEADER_ERROR"           : "Error", | ||||||
|  |  | ||||||
|  |         "HELP_USERS" : "Click or tap on a user below to manage that user. Depending on your access level, users can be added and deleted, and their passwords can be changed.", | ||||||
|  |  | ||||||
|  |         "SECTION_HEADER_USERS"       : "Users" | ||||||
|  |  | ||||||
|  |     }, | ||||||
|  |      | ||||||
|  |     "SETTINGS_SESSIONS" : { | ||||||
|  |          | ||||||
|  |         "ACTION_ACKNOWLEDGE" : "@:APP.ACTION_ACKNOWLEDGE", | ||||||
|  |         "ACTION_CANCEL"      : "@:APP.ACTION_CANCEL", | ||||||
|  |         "ACTION_DELETE"      : "Kill Sessions", | ||||||
|  |          | ||||||
|  |         "DIALOG_HEADER_CONFIRM_DELETE" : "Kill Sessions", | ||||||
|  |         "DIALOG_HEADER_ERROR"          : "Error", | ||||||
|  |          | ||||||
|  |         "FIELD_PLACEHOLDER_FILTER" : "Filter", | ||||||
|  |          | ||||||
|  |         "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE", | ||||||
|  |  | ||||||
|  |         "HELP_SESSIONS" : "All currently-active Guacamole sessions are listed here. If you wish to kill one or more sessions, check the box next to those sessions and click \"Kill Sessions\". Killing a session will immediately disconnect the user from the associated connection.", | ||||||
|  |          | ||||||
|  |         "INFO_NO_SESSIONS" : "No active sessions", | ||||||
|  |  | ||||||
|  |         "SECTION_HEADER_SESSIONS" : "Active Sessions", | ||||||
|  |          | ||||||
|  |         "TABLE_HEADER_SESSION_USERNAME"        : "Username", | ||||||
|  |         "TABLE_HEADER_SESSION_STARTDATE"       : "Active since", | ||||||
|  |         "TABLE_HEADER_SESSION_REMOTEHOST"      : "Remote host", | ||||||
|  |         "TABLE_HEADER_SESSION_CONNECTION_NAME" : "Connection name", | ||||||
|  |          | ||||||
|  |         "TEXT_CONFIRM_DELETE" : "Are you sure you want to kill all selected sessions? The users using these sessions will be immediately disconnected." | ||||||
|  |  | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     "USER_MENU" : { |     "USER_MENU" : { | ||||||
|  |  | ||||||
|         "ACTION_ACKNOWLEDGE"        : "@:APP.ACTION_ACKNOWLEDGE", |         "ACTION_ACKNOWLEDGE"        : "@:APP.ACTION_ACKNOWLEDGE", | ||||||
| @@ -422,6 +448,7 @@ | |||||||
|         "ACTION_LOGOUT"             : "@:APP.ACTION_LOGOUT", |         "ACTION_LOGOUT"             : "@:APP.ACTION_LOGOUT", | ||||||
|         "ACTION_MANAGE_CONNECTIONS" : "@:APP.ACTION_MANAGE_CONNECTIONS", |         "ACTION_MANAGE_CONNECTIONS" : "@:APP.ACTION_MANAGE_CONNECTIONS", | ||||||
|         "ACTION_MANAGE_SESSIONS"    : "@:APP.ACTION_MANAGE_SESSIONS", |         "ACTION_MANAGE_SESSIONS"    : "@:APP.ACTION_MANAGE_SESSIONS", | ||||||
|  |         "ACTION_MANAGE_SETTINGS"    : "@:APP.ACTION_MANAGE_SETTINGS", | ||||||
|         "ACTION_MANAGE_USERS"       : "@:APP.ACTION_MANAGE_USERS", |         "ACTION_MANAGE_USERS"       : "@:APP.ACTION_MANAGE_USERS", | ||||||
|         "ACTION_NAVIGATE_HOME"      : "@:APP.ACTION_NAVIGATE_HOME", |         "ACTION_NAVIGATE_HOME"      : "@:APP.ACTION_NAVIGATE_HOME", | ||||||
|         "ACTION_SAVE"               : "@:APP.ACTION_SAVE", |         "ACTION_SAVE"               : "@:APP.ACTION_SAVE", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user