Hello, I am looking for some advise on how to proceed on the following.
Within the application there’s a role that restricts users to allow editing and saving certain entities only if they are the assigned owner. The owner is a field on the entity.
This is done using a constraint like this:
{E}.owner.id == userSession.user.id
This works ok, although on objects that the user is not assigned to as an owner, the user is able to assign his or her selves as an owner and still be able to save the entity. Likewise, when the user would like to transfer the entity to someone different, it cannot be saved.
What would be the best way to solve this issue elegantly? This scenario is specific to a certain customer and I would like to have it applied as much as possible through configuration thus avoiding a lot of coding for this customer only.
Summarized, the best solution would need to work as follows:
allow for editing & saving when the user is initially assigned as an owner (but being able to reassign the entity)
prevent the user from re-assigning the entity if it is not the initial owner; best case: show the entity read-only
require a minimum of coding, mostly by configuration
Thanks for the elaborate follow-up. I have taken a look at your approach which is great but it doesn’t cover the idea I want to achieve yet.
Your approach allows a user to edit the entity only if it is assigned to it, which is great. When editing however and assigning it to someone else, it cannot be saved (as is the case in my setup as well). An error appears.
Also, the button ‘Assign to me’ is only available to the user if it is already assigned to it. So that doesn’t help much either, sorry.
Moreover, I would like the user to view the details of the entity if it is not assigned to it.
On a side note, seeing the edit button disabled if the entity is not assigned to the current user is something I can use in other situations - so have picked that one up - thanks!
Then you probably cannot use constraints and do all the work programmatically. For example, define a bean which encapsulates your access rules like this:
public class FooEdit extends AbstractEditor<Foo> {
@Inject
private Datasource<Foo> fooDs;
@Inject
private UserSessionSource userSessionSource;
@Inject
private OwnerAccessControl accessControl;
@Override
protected void postInit() {
if (!accessControl.isEditAvailable(getItem())) {
for (Component component : getComponents()) {
if (component instanceof Editable)
((Editable) component).setEditable(false);
else
component.setEnabled(false);
}
}
}
public void assignToMe() {
fooDs.getItem().setOwner(userSessionSource.getUserSession().getCurrentOrSubstitutedUser());
}
}
Of course, you can make this approach more generic by creating a MappedSuperclass for your entities containing owner attribute. Then the OwnerAccessControl bean will work with this superclass. Screen controllers logic can also be encapsulated in appropriate base classes or delegates.
Although I will need some adjustments as it only applies to a certain role - not all users will have this restriction. In fact, there are roles that allow for editing these entities regardless of the ownership and other roles that may not edit the entities at all.