From 22cce485585c0dce3d615ae3accc7e3930b97f7d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 21 Feb 2017 23:32:38 -0800 Subject: [PATCH 1/5] GUACAMOLE-292: Restrict attributes on object management pages to those explicitly present on the object. --- .../main/webapp/app/form/directives/form.js | 60 ++++++++++++++++++- .../main/webapp/app/form/templates/form.html | 4 +- .../manage/templates/manageConnection.html | 3 +- .../templates/manageConnectionGroup.html | 3 +- .../templates/manageSharingProfile.html | 2 +- .../app/manage/templates/manageUser.html | 3 +- 6 files changed, 69 insertions(+), 6 deletions(-) diff --git a/guacamole/src/main/webapp/app/form/directives/form.js b/guacamole/src/main/webapp/app/form/directives/form.js index f65989934..518db7dba 100644 --- a/guacamole/src/main/webapp/app/form/directives/form.js +++ b/guacamole/src/main/webapp/app/form/directives/form.js @@ -55,7 +55,16 @@ angular.module('form').directive('guacForm', [function form() { * * @type Object. */ - model : '=' + model : '=', + + /** + * Whether the contents of the form should be restricted to those + * fields/forms which match properties defined within the given + * model object. By default, all fields will be shown. + * + * @type Boolean + */ + modelOnly : '=' }, templateUrl: 'app/form/templates/form.html', @@ -163,6 +172,55 @@ angular.module('form').directive('guacForm', [function form() { }); + /** + * Returns whether the given field should be displayed to the + * current user. + * + * @param {Field} field + * The field to check. + * + * @returns {Boolean} + * true if the given field should be visible, false otherwise. + */ + $scope.isVisible = function isVisible(field) { + + // All fields are visible if contents are not restricted to + // model properties only + if (!$scope.modelOnly) + return true; + + // Otherwise, fields are only visible if they are present + // within the model + return field && (field.name in $scope.values); + + }; + + /** + * Returns whether at least one of the given fields should be + * displayed to the current user. + * + * @param {Field[]} fields + * The array of fields to check. + * + * @returns {Boolean} + * true if at least one field within the given array should be + * visible, false otherwise. + */ + $scope.containsVisible = function containsVisible(fields) { + + // If fields are defined, check whether at least one is visible + if (fields) { + for (var i = 0; i < fields.length; i++) { + if ($scope.isVisible(fields[i])) + return true; + } + } + + // Otherwise, there are no visible fields + return false; + + }; + }] // end controller }; diff --git a/guacamole/src/main/webapp/app/form/templates/form.html b/guacamole/src/main/webapp/app/form/templates/form.html index 6013543d6..e4564e895 100644 --- a/guacamole/src/main/webapp/app/form/templates/form.html +++ b/guacamole/src/main/webapp/app/form/templates/form.html @@ -1,5 +1,6 @@
-
+

{{getSectionHeader(form) | translate}}

@@ -7,6 +8,7 @@
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html index 9df51a0d8..80796a4c9 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html @@ -40,7 +40,8 @@
- +
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html index 0b952518c..2d5ac5881 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html @@ -40,7 +40,8 @@
- +
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html b/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html index 4873b867d..a8e6438cf 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html @@ -22,7 +22,7 @@
+ model="sharingProfile.attributes" model-only="true">
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageUser.html b/guacamole/src/main/webapp/app/manage/templates/manageUser.html index e32d725ae..dc71d27ac 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageUser.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageUser.html @@ -41,7 +41,8 @@
- +
From 0a4b1f33da94b9b551f32ae4d4477738e256a88d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 21 Feb 2017 23:39:42 -0800 Subject: [PATCH 2/5] GUACAMOLE-292: Allow object/model creation to throw exceptions. --- .../jdbc/base/ModeledDirectoryObjectService.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java index 1ee9bee89..2c1402eb6 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java @@ -97,9 +97,12 @@ public abstract class ModeledDirectoryObjectService getObjectInstances(ModeledAuthenticatedUser currentUser, - Collection models) { + Collection models) throws GuacamoleException { // Create new collection of objects by manually converting each model Collection objects = new ArrayList(models.size()); From ae7c792d10f1252a4e3a483bdf10a9023ae04883 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 21 Feb 2017 23:54:32 -0800 Subject: [PATCH 3/5] GUACAMOLE-292: Require ADMINISTER permission to get/set attributes which control scheduled access. --- .../guacamole/auth/jdbc/user/ModeledUser.java | 74 +++++++++++++++++-- .../guacamole/auth/jdbc/user/UserService.java | 32 +++++++- 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java index c2b16eff4..052849520 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java @@ -176,6 +176,34 @@ public class ModeledUser extends ModeledDirectoryObject implements Us @Inject private UserPermissionService userPermissionService; + /** + * Whether attributes which control access restrictions should be exposed + * via getAttributes() or allowed to be set via setAttributes(). + */ + private boolean exposeRestrictedAttributes = false; + + /** + * Initializes this ModeledUser, associating it with the current + * authenticated user and populating it with data from the given user + * model. + * + * @param currentUser + * The user that created or retrieved this object. + * + * @param model + * The backing model object. + * + * @param exposeRestrictedAttributes + * Whether attributes which control access restrictions should be + * exposed via getAttributes() or allowed to be set via + * setAttributes(). + */ + public void init(ModeledAuthenticatedUser currentUser, UserModel model, + boolean exposeRestrictedAttributes) { + super.init(currentUser, model); + this.exposeRestrictedAttributes = exposeRestrictedAttributes; + } + /** * The plaintext password previously set by a call to setPassword(), if * any. The password of a user cannot be retrieved once saved into the @@ -309,10 +337,16 @@ public class ModeledUser extends ModeledDirectoryObject implements Us return userPermissionService.getPermissionSet(getCurrentUser(), this); } - @Override - public Map getAttributes() { - - Map attributes = new HashMap(); + /** + * Stores all restricted (privileged) attributes within the given Map, + * pulling the values of those attributes from the underlying user model. + * If no value is yet defined for an attribute, that attribute will be set + * to null. + * + * @param attributes + * The Map to store all restricted attributes within. + */ + private void putRestrictedAttributes(Map attributes) { // Set disabled attribute attributes.put(DISABLED_ATTRIBUTE_NAME, getModel().isDisabled() ? "true" : null); @@ -335,7 +369,6 @@ public class ModeledUser extends ModeledDirectoryObject implements Us // Set timezone attribute attributes.put(TIMEZONE_ATTRIBUTE_NAME, getModel().getTimeZone()); - return attributes; } /** @@ -396,8 +429,14 @@ public class ModeledUser extends ModeledDirectoryObject implements Us } - @Override - public void setAttributes(Map attributes) { + /** + * Stores all restricted (privileged) attributes within the underlying user + * model, pulling the values of those attributes from the given Map. + * + * @param attributes + * The Map to pull all restricted attributes from. + */ + private void setRestrictedAttributes(Map attributes) { // Translate disabled attribute getModel().setDisabled("true".equals(attributes.get(DISABLED_ATTRIBUTE_NAME))); @@ -438,6 +477,27 @@ public class ModeledUser extends ModeledDirectoryObject implements Us } + @Override + public Map getAttributes() { + + Map attributes = new HashMap(); + + // Include restricted attributes only if they should be exposed + if (exposeRestrictedAttributes) + putRestrictedAttributes(attributes); + + return attributes; + } + + @Override + public void setAttributes(Map attributes) { + + // Assign restricted attributes only if they are exposed + if (exposeRestrictedAttributes) + setRestrictedAttributes(attributes); + + } + /** * Returns the time zone associated with this user. This time zone must be * used when interpreting all date/time restrictions related to this user. diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java index 76a05f857..7935f864d 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java @@ -147,15 +147,35 @@ public class UserService extends ModeledDirectoryObjectService Date: Sat, 6 May 2017 22:37:37 -0700 Subject: [PATCH 4/5] GUACAMOLE-292: Use ngIf to determine visibility of guacFormField. Using ngShow collides with the ngShow used internally on the guacFormField directive's root element. --- guacamole/src/main/webapp/app/form/templates/form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guacamole/src/main/webapp/app/form/templates/form.html b/guacamole/src/main/webapp/app/form/templates/form.html index e4564e895..b58393f8b 100644 --- a/guacamole/src/main/webapp/app/form/templates/form.html +++ b/guacamole/src/main/webapp/app/form/templates/form.html @@ -8,7 +8,7 @@
From 74293c23dd819539bbce5cfa4d262ddf9dd7ad89 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 21 May 2017 20:14:11 -0700 Subject: [PATCH 5/5] GUACAMOLE-292: Display all object attributes if we are creating the object. --- .../controllers/manageConnectionController.js | 17 +++++++++++++++ .../manageConnectionGroupController.js | 21 ++++++++++++++++++- .../manageSharingProfileController.js | 19 +++++++++++++++++ .../controllers/manageUserController.js | 21 +++++++++++++++++-- .../manage/templates/manageConnection.html | 2 +- .../templates/manageConnectionGroup.html | 2 +- .../templates/manageSharingProfile.html | 2 +- .../app/manage/templates/manageUser.html | 2 +- 8 files changed, 79 insertions(+), 7 deletions(-) diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js index 868842eaf..856220767 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js @@ -299,6 +299,23 @@ angular.module('manage').controller('manageConnectionController', ['$scope', '$i $scope.parameters = {}; } + /** + * Returns whether the current user can change/set all connection + * attributes for the connection being edited, regardless of whether those + * attributes are already explicitly associated with that connection. + * + * @returns {Boolean} + * true if the current user can change all attributes for the + * connection being edited, regardless of whether those attributes are + * already explicitly associated with that connection, false otherwise. + */ + $scope.canChangeAllAttributes = function canChangeAllAttributes() { + + // All attributes can be set if we are creating the connection + return !identifier; + + }; + /** * Returns the translation string namespace for the protocol having the * given name. The namespace will be of the form: diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js index e4c61156f..bafe5912c 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionGroupController.js @@ -195,7 +195,26 @@ angular.module('manage').controller('manageConnectionGroupController', ['$scope' value : ConnectionGroup.Type.BALANCING } ]; - + + /** + * Returns whether the current user can change/set all connection group + * attributes for the connection group being edited, regardless of whether + * those attributes are already explicitly associated with that connection + * group. + * + * @returns {Boolean} + * true if the current user can change all attributes for the + * connection group being edited, regardless of whether those + * attributes are already explicitly associated with that connection + * group, false otherwise. + */ + $scope.canChangeAllAttributes = function canChangeAllAttributes() { + + // All attributes can be set if we are creating the connection group + return !identifier; + + }; + /** * Cancels all pending edits, returning to the management page. */ diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js b/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js index ca7d11e9a..c5329750e 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageSharingProfileController.js @@ -280,6 +280,25 @@ angular.module('manage').controller('manageSharingProfileController', ['$scope', }); + /** + * Returns whether the current user can change/set all sharing profile + * attributes for the sharing profile being edited, regardless of whether + * those attributes are already explicitly associated with that sharing + * profile. + * + * @returns {Boolean} + * true if the current user can change all attributes for the sharing + * profile being edited, regardless of whether those attributes are + * already explicitly associated with that sharing profile, false + * otherwise. + */ + $scope.canChangeAllAttributes = function canChangeAllAttributes() { + + // All attributes can be set if we are creating the sharing profile + return !identifier; + + }; + /** * Returns the translation string namespace for the protocol having the * given name. The namespace will be of the form: diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js index 5337caf01..7f50e434d 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageUserController.js @@ -225,8 +225,8 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto }; /** - * Returns whether the current user can change attributes associated with - * the user being edited within the given data source. + * Returns whether the current user can change attributes explicitly + * associated with the user being edited within the given data source. * * @param {String} [dataSource] * The identifier of the data source to check. If omitted, this will @@ -260,6 +260,23 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto }; + /** + * Returns whether the current user can change/set all user attributes for + * the user being edited, regardless of whether those attributes are + * already explicitly associated with that user. + * + * @returns {Boolean} + * true if the current user can change all attributes for the user + * being edited, regardless of whether those attributes are already + * explicitly associated with that user, false otherwise. + */ + $scope.canChangeAllAttributes = function canChangeAllAttributes() { + + // All attributes can be set if we are creating the user + return !$scope.userExists(selectedDataSource); + + }; + /** * Returns whether the current user can change permissions of any kind * which are associated with the user being edited within the given data diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html index 80796a4c9..85e4f917e 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html @@ -41,7 +41,7 @@
+ model="connection.attributes" model-only="!canChangeAllAttributes()">
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html index 2d5ac5881..d4c6613a7 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnectionGroup.html @@ -41,7 +41,7 @@
+ model="connectionGroup.attributes" model-only="!canChangeAllAttributes()">
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html b/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html index a8e6438cf..d6c704332 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageSharingProfile.html @@ -22,7 +22,7 @@
+ model="sharingProfile.attributes" model-only="!canChangeAllAttributes()">
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageUser.html b/guacamole/src/main/webapp/app/manage/templates/manageUser.html index dc71d27ac..55b6d3098 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageUser.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageUser.html @@ -42,7 +42,7 @@
+ model="user.attributes" model-only="!canChangeAllAttributes()">