mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-292: Merge attribute editing permissioning.
This commit is contained in:
@@ -97,9 +97,12 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
|
||||
*
|
||||
* @return
|
||||
* An object which is backed by the given model object.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the object instance cannot be created.
|
||||
*/
|
||||
protected abstract InternalType getObjectInstance(ModeledAuthenticatedUser currentUser,
|
||||
ModelType model);
|
||||
ModelType model) throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Returns an instance of a model object which is based on the given
|
||||
@@ -113,9 +116,12 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
|
||||
*
|
||||
* @return
|
||||
* A model object which is based on the given object.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the model object instance cannot be created.
|
||||
*/
|
||||
protected abstract ModelType getModelInstance(ModeledAuthenticatedUser currentUser,
|
||||
ExternalType object);
|
||||
ExternalType object) throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Returns whether the given user has permission to create the type of
|
||||
@@ -199,9 +205,12 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
|
||||
* @return
|
||||
* A collection of objects which are backed by the models in the given
|
||||
* collection.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If any of the object instances cannot be created.
|
||||
*/
|
||||
protected Collection<InternalType> getObjectInstances(ModeledAuthenticatedUser currentUser,
|
||||
Collection<ModelType> models) {
|
||||
Collection<ModelType> models) throws GuacamoleException {
|
||||
|
||||
// Create new collection of objects by manually converting each model
|
||||
Collection<InternalType> objects = new ArrayList<InternalType>(models.size());
|
||||
|
@@ -176,6 +176,34 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> 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<UserModel> implements Us
|
||||
return userPermissionService.getPermissionSet(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getAttributes() {
|
||||
|
||||
Map<String, String> attributes = new HashMap<String, String>();
|
||||
/**
|
||||
* 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<String, String> attributes) {
|
||||
|
||||
// Set disabled attribute
|
||||
attributes.put(DISABLED_ATTRIBUTE_NAME, getModel().isDisabled() ? "true" : null);
|
||||
@@ -335,7 +369,6 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
|
||||
// Set timezone attribute
|
||||
attributes.put(TIMEZONE_ATTRIBUTE_NAME, getModel().getTimeZone());
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,8 +429,14 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttributes(Map<String, String> 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<String, String> attributes) {
|
||||
|
||||
// Translate disabled attribute
|
||||
getModel().setDisabled("true".equals(attributes.get(DISABLED_ATTRIBUTE_NAME)));
|
||||
@@ -438,6 +477,27 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getAttributes() {
|
||||
|
||||
Map<String, String> attributes = new HashMap<String, String>();
|
||||
|
||||
// Include restricted attributes only if they should be exposed
|
||||
if (exposeRestrictedAttributes)
|
||||
putRestrictedAttributes(attributes);
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttributes(Map<String, String> 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.
|
||||
|
@@ -147,15 +147,35 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
|
||||
@Override
|
||||
protected ModeledUser getObjectInstance(ModeledAuthenticatedUser currentUser,
|
||||
UserModel model) {
|
||||
UserModel model) throws GuacamoleException {
|
||||
|
||||
boolean exposeRestrictedAttributes;
|
||||
|
||||
// Expose restricted attributes if the user does not yet exist
|
||||
if (model.getObjectID() == null)
|
||||
exposeRestrictedAttributes = true;
|
||||
|
||||
// Otherwise, if the user permissions are available, expose restricted
|
||||
// attributes only if the user has ADMINISTER permission
|
||||
else if (currentUser != null)
|
||||
exposeRestrictedAttributes = hasObjectPermission(currentUser,
|
||||
model.getIdentifier(), ObjectPermission.Type.ADMINISTER);
|
||||
|
||||
// If user permissions are not available, do not expose anything
|
||||
else
|
||||
exposeRestrictedAttributes = false;
|
||||
|
||||
// Produce ModeledUser exposing only those attributes for which the
|
||||
// current user has permission
|
||||
ModeledUser user = userProvider.get();
|
||||
user.init(currentUser, model);
|
||||
user.init(currentUser, model, exposeRestrictedAttributes);
|
||||
return user;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserModel getModelInstance(ModeledAuthenticatedUser currentUser,
|
||||
final User object) {
|
||||
final User object) throws GuacamoleException {
|
||||
|
||||
// Create new ModeledUser backed by blank model
|
||||
UserModel model = new UserModel();
|
||||
@@ -362,9 +382,13 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
* @return
|
||||
* The ModeledUser which corresponds to the given AuthenticatedUser, or
|
||||
* null if no such user exists.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If a ModeledUser object for the user corresponding to the given
|
||||
* AuthenticatedUser cannot be created.
|
||||
*/
|
||||
public ModeledUser retrieveUser(AuthenticationProvider authenticationProvider,
|
||||
AuthenticatedUser authenticatedUser) {
|
||||
AuthenticatedUser authenticatedUser) throws GuacamoleException {
|
||||
|
||||
// If we already queried this user, return that rather than querying again
|
||||
if (authenticatedUser instanceof ModeledAuthenticatedUser)
|
||||
|
@@ -55,7 +55,16 @@ angular.module('form').directive('guacForm', [function form() {
|
||||
*
|
||||
* @type Object.<String, String>
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<div class="form-group">
|
||||
<div ng-repeat="form in forms" class="form">
|
||||
<div ng-repeat="form in forms" class="form"
|
||||
ng-show="containsVisible(form.fields)">
|
||||
|
||||
<!-- Form name -->
|
||||
<h3 ng-show="form.name">{{getSectionHeader(form) | translate}}</h3>
|
||||
@@ -7,6 +8,7 @@
|
||||
<!-- All fields in form -->
|
||||
<div class="fields">
|
||||
<guac-form-field ng-repeat="field in form.fields" namespace="namespace"
|
||||
ng-if="isVisible(field)"
|
||||
field="field" model="values[field.name]"></guac-form-field>
|
||||
</div>
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -40,7 +40,8 @@
|
||||
|
||||
<!-- Connection attributes section -->
|
||||
<div class="attributes">
|
||||
<guac-form namespace="'CONNECTION_ATTRIBUTES'" content="attributes" model="connection.attributes"></guac-form>
|
||||
<guac-form namespace="'CONNECTION_ATTRIBUTES'" content="attributes"
|
||||
model="connection.attributes" model-only="!canChangeAllAttributes()"></guac-form>
|
||||
</div>
|
||||
|
||||
<!-- Connection parameters -->
|
||||
|
@@ -40,7 +40,8 @@
|
||||
|
||||
<!-- Connection group attributes section -->
|
||||
<div class="attributes">
|
||||
<guac-form namespace="'CONNECTION_GROUP_ATTRIBUTES'" content="attributes" model="connectionGroup.attributes"></guac-form>
|
||||
<guac-form namespace="'CONNECTION_GROUP_ATTRIBUTES'" content="attributes"
|
||||
model="connectionGroup.attributes" model-only="!canChangeAllAttributes()"></guac-form>
|
||||
</div>
|
||||
|
||||
<!-- Form action buttons -->
|
||||
|
@@ -22,7 +22,7 @@
|
||||
<!-- Sharing profile attributes section -->
|
||||
<div class="attributes">
|
||||
<guac-form namespace="'SHARING_PROFILE_ATTRIBUTES'" content="attributes"
|
||||
model="sharingProfile.attributes"></guac-form>
|
||||
model="sharingProfile.attributes" model-only="!canChangeAllAttributes()"></guac-form>
|
||||
</div>
|
||||
|
||||
<!-- Sharing profile parameters -->
|
||||
|
@@ -41,7 +41,8 @@
|
||||
|
||||
<!-- User attributes section -->
|
||||
<div class="attributes" ng-show="canChangeAttributes()">
|
||||
<guac-form namespace="'USER_ATTRIBUTES'" content="attributes" model="user.attributes"></guac-form>
|
||||
<guac-form namespace="'USER_ATTRIBUTES'" content="attributes"
|
||||
model="user.attributes" model-only="!canChangeAllAttributes()"></guac-form>
|
||||
</div>
|
||||
|
||||
<!-- System permissions section -->
|
||||
|
Reference in New Issue
Block a user