diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js
index 1614524b9..b613838e4 100644
--- a/guacamole/src/main/webapp/app/client/controllers/clientController.js
+++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js
@@ -517,9 +517,6 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
}
- // Hide any status dialog
- $scope.showStatus(false);
-
});
}]);
diff --git a/guacamole/src/main/webapp/app/home/controllers/homeController.js b/guacamole/src/main/webapp/app/home/controllers/homeController.js
index a8d3caccb..c96f3a053 100644
--- a/guacamole/src/main/webapp/app/home/controllers/homeController.js
+++ b/guacamole/src/main/webapp/app/home/controllers/homeController.js
@@ -28,20 +28,61 @@ angular.module('home').controller('homeController', ['$scope', '$injector',
// Get required types
var ConnectionGroup = $injector.get("ConnectionGroup");
+ var PermissionSet = $injector.get("PermissionSet");
// Get required services
- var connectionGroupService = $injector.get("connectionGroupService");
+ var authenticationService = $injector.get("authenticationService");
+ var connectionGroupService = $injector.get("connectionGroupService");
+ var permissionService = $injector.get("permissionService");
- // Set status to loading until we have all the connections and groups loaded
- $scope.loading = true;
+ /**
+ * The root connection group, or null if the connection group hierarchy has
+ * not yet been loaded.
+ *
+ * @type ConnectionGroup
+ */
+ $scope.rootConnectionGroup = null;
+
+ /**
+ * Whether the current user has sufficient permissions to use the
+ * management interface. If permissions have not yet been loaded, this will
+ * be null.
+ *
+ * @type Boolean
+ */
+ $scope.canManageGuacamole = 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.rootConnectionGroup !== null
+ && $scope.canManageGuacamole !== null;
+
+ };
// Retrieve root group and all descendants
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER)
.success(function rootGroupRetrieved(rootConnectionGroup) {
-
$scope.rootConnectionGroup = rootConnectionGroup;
- $scope.loading = false;
+ });
+ // Retrieve current permissions
+ permissionService.getPermissions(authenticationService.getCurrentUserID())
+ .success(function permissionsRetrieved(permissions) {
+
+ // Determine whether the current user can access the management UI
+ $scope.canManageGuacamole =
+ PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
+ || PermissionSet.hasConnectionPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE)
+ || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE)
+ || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE);
+
});
}]);
diff --git a/guacamole/src/main/webapp/app/home/templates/home.html b/guacamole/src/main/webapp/app/home/templates/home.html
index 9e8bf7eb8..887b93cad 100644
--- a/guacamole/src/main/webapp/app/home/templates/home.html
+++ b/guacamole/src/main/webapp/app/home/templates/home.html
@@ -20,26 +20,30 @@
THE SOFTWARE.
-->
-
\ No newline at end of file
diff --git a/guacamole/src/main/webapp/app/index/controllers/indexController.js b/guacamole/src/main/webapp/app/index/controllers/indexController.js
index 6ef71eac5..3e7f1e733 100644
--- a/guacamole/src/main/webapp/app/index/controllers/indexController.js
+++ b/guacamole/src/main/webapp/app/index/controllers/indexController.js
@@ -26,16 +26,11 @@
angular.module('index').controller('indexController', ['$scope', '$injector',
function indexController($scope, $injector) {
- // Required types
- var PermissionSet = $injector.get("PermissionSet");
-
// Required services
- var $document = $injector.get("$document");
- var $location = $injector.get("$location");
- var $q = $injector.get("$q");
- var $window = $injector.get("$window");
- var authenticationService = $injector.get("authenticationService");
- var permissionService = $injector.get("permissionService");
+ var $document = $injector.get("$document");
+ var $location = $injector.get("$location");
+ var $window = $injector.get("$window");
+ var authenticationService = $injector.get("authenticationService");
/**
* The current status notification, or false if no status is currently
@@ -52,27 +47,35 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
*/
$scope.notifications = [];
- // Put some useful variables in the top level scope
+ /**
+ * Basic page-level information.
+ */
$scope.page = {
+
+ /**
+ * The title of the page.
+ *
+ * @type String
+ */
title: '',
+
+ /**
+ * The name of the CSS class to apply to the page body, if any.
+ *
+ * @type String
+ */
bodyClassName: ''
+
};
- $scope.currentUserID = null;
- $scope.currentUserIsAdmin = false;
- $scope.currentUserHasUpdate = false;
- $scope.currentUserPermissions = null;
+
+ /**
+ * The ID of the most recently shown notification, or 0 if no notifications
+ * have yet been shown.
+ *
+ * @type Number
+ */
var notificationUniqueID = 0;
- // A promise to be fulfilled when all basic user permissions are loaded.
- var permissionsLoaded= $q.defer();
- $scope.basicPermissionsLoaded = permissionsLoaded.promise;
-
- $scope.currentUserID = authenticationService.getCurrentUserID();
-
- // If the user is unknown, force a login
- if(!$scope.currentUserID)
- $location.path('/login');
-
/**
* Shows or hides the given notification as a modal status. If a status
* notification is currently shown, no further statuses will be shown
@@ -150,25 +153,6 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
}
};
- // Allow the permissions to be reloaded elsewhere if needed
- $scope.loadBasicPermissions = function loadBasicPermissions() {
-
- permissionService.getPermissions($scope.currentUserID).success(function fetchCurrentUserPermissions(permissions) {
- $scope.currentUserPermissions = permissions;
-
- // Whether the user has system-wide admin permission
- $scope.currentUserIsAdmin = PermissionSet.hasSystemPermission($scope.currentUserPermissions, PermissionSet.SystemPermissionType.ADMINISTER);
-
- // Whether the user can update at least one object
- $scope.currentUserHasUpdate = $scope.currentUserIsAdmin
- || PermissionSet.hasConnectionPermission($scope.currentUserPermissions, "UPDATE")
- || PermissionSet.hasConnectionGroupPermission($scope.currentUserPermissions, "UPDATE")
- || PermissionSet.hasUserPermission($scope.currentUserPermissions, "UPDATE");
-
- permissionsLoaded.resolve();
- });
- };
-
// Provide simple mechanism for logging out the current user
$scope.logout = function logout() {
authenticationService.logout()['finally'](function logoutComplete() {
@@ -176,9 +160,6 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
});
};
- // Try to load them now
- $scope.loadBasicPermissions();
-
// Create event listeners at the global level
var keyboard = new Guacamole.Keyboard($document[0]);
@@ -217,12 +198,17 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
// Update title and CSS class upon navigation
$scope.$on('$routeChangeSuccess', function(event, current, previous) {
+ // Set title
var title = current.$$route.title;
if (title)
$scope.page.title = title;
+ // Set body CSS class
$scope.page.bodyClassName = current.$$route.bodyClassName || '';
+ // Hide any status dialog
+ $scope.showStatus(false);
+
});
}]);
diff --git a/guacamole/src/main/webapp/app/index/styles/loading.css b/guacamole/src/main/webapp/app/index/styles/loading.css
index 159cace25..da1d8df9f 100644
--- a/guacamole/src/main/webapp/app/index/styles/loading.css
+++ b/guacamole/src/main/webapp/app/index/styles/loading.css
@@ -25,6 +25,14 @@
min-height: 200px;
}
+.view.loading {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
.loading * {
visibility: hidden;
}
diff --git a/guacamole/src/main/webapp/app/login/controllers/loginController.js b/guacamole/src/main/webapp/app/login/controllers/loginController.js
index 7283f4c28..9f8078733 100644
--- a/guacamole/src/main/webapp/app/login/controllers/loginController.js
+++ b/guacamole/src/main/webapp/app/login/controllers/loginController.js
@@ -52,8 +52,6 @@ angular.module('login').controller('loginController', ['$scope', '$injector',
// Redirect to main view upon success
.success(function success(data, status, headers, config) {
- // Set up the basic permissions for the user
- $scope.loadBasicPermissions();
$location.path('/');
})
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
index 16058192b..0f57ff032 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
@@ -60,6 +60,59 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i
*/
var identifier = $routeParams.id;
+ /**
+ * All known protocols.
+ *
+ * @type Object.
+ */
+ $scope.protocols = null;
+
+ /**
+ * The root connection group of the connection group hierarchy.
+ *
+ * @type ConnectionGroup
+ */
+ $scope.rootGroup = null;
+
+ /**
+ * The connection being modified.
+ *
+ * @type Connection
+ */
+ $scope.connection = null;
+
+ /**
+ * The parameter name/value pairs associated with the connection being
+ * modified.
+ *
+ * @type Object.
+ */
+ $scope.parameters = null;
+
+ /**
+ * The usage history of the connection being modified.
+ *
+ * @type HistoryEntryWrapper[]
+ */
+ $scope.historyEntryWrappers = 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.protocols !== null
+ && $scope.rootGroup !== null
+ && $scope.connection !== null
+ && $scope.parameters !== null
+ && $scope.historyEntryWrappers !== null;
+
+ };
+
// Pull connection group hierarchy
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
.success(function connectionGroupReceived(rootGroup) {
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
index 38010b37a..31f751ea0 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js
@@ -55,6 +55,35 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope'
*/
var identifier = $routeParams.id;
+ /**
+ * The root connection group of the connection group hierarchy.
+ *
+ * @type ConnectionGroup
+ */
+ $scope.rootGroup = null;
+
+ /**
+ * The connection group being modified.
+ *
+ * @type ConnectionGroup
+ */
+ $scope.connectionGroup = 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.connectionGroup !== null;
+
+ };
+
+
// Pull connection group hierarchy
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
.success(function connectionGroupReceived(rootGroup) {
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageController.js b/guacamole/src/main/webapp/app/manage/controllers/manageController.js
index b4ae57306..84733fe55 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageController.js
@@ -32,7 +32,9 @@ angular.module('manage').controller('manageController', ['$scope', '$injector',
var User = $injector.get('User');
// Required services
+ var authenticationService = $injector.get('authenticationService');
var connectionGroupService = $injector.get('connectionGroupService');
+ var permissionService = $injector.get('permissionService');
var userService = $injector.get('userService');
/**
@@ -47,6 +49,46 @@ angular.module('manage').controller('manageController', ['$scope', '$injector',
}
};
+ /**
+ * 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 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 users. If the current
+ * permissions have not yet been loaded, this will be null.
+ *
+ * @type Boolean
+ */
+ $scope.canCreateUsers = 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;
+
/**
* The name of the new user to create, if any, when user creation is
* requested via newUser().
@@ -54,6 +96,58 @@ angular.module('manage').controller('manageController', ['$scope', '$injector',
* @type String
*/
$scope.newUsername = "";
+
+ /**
+ * 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.rootGroup !== null
+ && $scope.canManageUsers !== null
+ && $scope.canManageConnections !== null
+ && $scope.canCreateUsers !== null
+ && $scope.canCreateConnections !== null
+ && $scope.canCreateConnectionGroups !== null;
+
+ };
+
+ // Retrieve current permissions
+ permissionService.getPermissions(authenticationService.getCurrentUserID())
+ .success(function permissionsRetrieved(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 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 users
+ $scope.canManageUsers =
+ $scope.canCreateUsers
+ || PermissionSet.hasUserPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE);
+
+ // Determine whether the current user can manage other connections
+ $scope.canManageConnections =
+ $scope.canCreateConnections
+ || $scope.canCreateConnectionGroups
+ || PermissionSet.hasConnectionPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE)
+ || PermissionSet.hasConnectionGroupPermission(permissions, PermissionSet.ObjectPermissionType.UPDATE);
+
+ });
// Retrieve all connections for which we have UPDATE permission
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
index bf860a78e..e7642149f 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js
@@ -57,6 +57,42 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
*/
var username = $routeParams.id;
+ /**
+ * The user being modified.
+ *
+ * @type User
+ */
+ $scope.user = null;
+
+ /**
+ * All permissions associated with the user being modified.
+ *
+ * @type PermissionFlagSet
+ */
+ $scope.permissionFlags = null;
+
+ /**
+ * The root connection group of the connection group hierarchy.
+ *
+ * @type ConnectionGroup
+ */
+ $scope.rootGroup = 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.user !== null
+ && $scope.permissionFlags !== null
+ && $scope.rootGroup !== null;
+
+ };
+
// Pull user data
userService.getUser(username).success(function userReceived(user) {
$scope.user = user;
diff --git a/guacamole/src/main/webapp/app/manage/templates/manage.html b/guacamole/src/main/webapp/app/manage/templates/manage.html
index 433516a9e..d079c3fe4 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manage.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manage.html
@@ -20,53 +20,67 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
-
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html
index 241dc1e97..4ffe4fe08 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html
@@ -20,83 +20,87 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
-
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
index f853162db..169717dfb 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html
@@ -20,46 +20,50 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
-
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageUser.html b/guacamole/src/main/webapp/app/manage/templates/manageUser.html
index a460077b8..b3dd7f5b7 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageUser.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageUser.html
@@ -20,58 +20,62 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
-