Design patterns for enabling user interface elemen

2019-03-09 13:30发布

问题:

We have a web application and its front end is implemented with GWT/GXT. Users can belong to various groups and these groups can then have various permissions. The permissions are quite fine grained, for example comment_create, comment_edit, comment_delete and comment_read.

What would be the best way to enable and disable user interface controls based on user permissions? We have an utility method that returns boolean value with given user and permission name. But at the moment each control is wrapped inside if clause and that makes the code bit messy.

回答1:

I had the same problem, here my solution.

Each UI component has an on/off state (visible/hidden, enabled/disabled, editable/readonly) and the state can be bound to one or more permission. For example the edit button can be enabled if the user has an EDIT permission, or disabled otherwise.

I've created a binder class that binds the UI component to a permission. The binder knows the current user permissions (all the permissions) through a event bus where a set of permissions is sent using an event. Each time the event is received the binder check if the permission is present or not (an alternative is use a boolean for each permission) and apply the changes to the component (for example enabling or disabling it).

The event bus is the only connection between all the UI components.

Using Gin and some helper class I've ended up with something like this for the binding code:

FeatureBinder.bind(editButton, EDIT_PERMISSION);


回答2:

I'm not sure how you'd implement this in GWT/GXT, but the old MFC way of enabling menus might be a place to start.

This had a separate ON_UPDATE_COMMAND_UI message which you gave a menu id and method name. The method would be called and you could enable or disable that menu option depending on your logic. In your case it would be based on the user id. This is on a per menu id basis and is therefore as fine grained as you need it to be.



回答3:

See the decorator pattern.



回答4:

Acris security

Look at Securing GWT Clients With AcrIS: using annotations to define permissions on controls in a declarative fashion. From the article,

public class CustomerPanel extends SecuredComposite {
...
    @Secured(Grants.SECURITY_MANAGEMENT)
    protected TextBox securityID;
...
}

While the approach looks very promising, the project doesn't appear that active. The downloads page has the latest release in May 2012 with only a few hundred downloads of each version (although this doesn't account for use as a Maven dependency). The latest on acris' forum is a post from June 2013 on a move to Git.

Also, the latest published version is compatible with GWT 2.3, with current development focused on GWT 2.5.

Additionally, the framework looks very extensive, and I have concerns about its modularity. Just trying to pull in the security module requires a number of dependencies and other modules.

Even if you don't use acris, the approach is work looking into. (This is the same approach as mentioned in Attribute-Based Authorization linked in a comment on the OP.) Looking at the source, it looks like metaprogramming using a generator and SourceWriter.



回答5:

You can use setEnabled(boolean) on the restricted widgets and save 2 lines of code compared to the if version:

Button editButton = new Button();
editButton.setText("Edit");
editButton.setEnabled(SecurityManager.userHasPermission(currentUser, Permissions.DOCUMENT_EDIT));
toolbar.add(editButton);

Button deleteButton = new Button();
deleteButton.setText("Delete");
deleteButton.setEnabled(SecurityManager.userHasPermission(currentUser, Permissions.DOCUMENT_DELETE));
toolbar.add(deleteButton);