-
-
Notifications
You must be signed in to change notification settings - Fork 270
Description
Hello Rob,
we use the BeanPersistController on various places to intercept save/update events on bean.
Now, we noticed, when a M2M (and only a M2M) will be modified, the bean itself does not get dirty and no PersistController will be invoked.
Some context
To give you some context, we need to implement "row level security" for some entities in our DB.
For example, if you imagine an issue tracking system, not everyone should be able to see every issue.
This all depends on several factors:
- which group the ticket belongs to (
issueGroup- M2O - the issueGroup defines the access members) - was the ticket assigned to a specific person (
assignee- M2O - the issue itself defines assignee as access member) - other
partipiciants- an additional M2M relation may define more access members
To keep things fast, we build a cache using a PersistController. It collects all access members (that are normally a handfull) and stores them in a compressed form, so that we can then use an efficient SQL query like
select * from issue i where exists (select 1 from issue_permission_cache c where c.issue_id = i and c.user_id = :current_user)
This all works as we want it to, as long as no M2M relations are involved (and the procedure how we build the cache should not be the topic of discussion here)
We have code in our permission controller like this:
public void addUpdate(final BeanPersistRequest<?> request) {
Set<String> changedProps = request.database().beanState(request.bean()).changedProps()
if (changedProps .contains("issueGroup")) {
// the issue was moved to an other issue group, so
// we need to recalculate the cache accordingly
}
if (changedProps .changedProps().contains("assignee")) {
// new assignee added -> make sure, the assignee can access the issue
}
if (changedProps.changedProps().contains("partipiciants")) {
// partipiciants - a M2M was changed -> update the cache
}
}Problem
As mentioned above, the permissionController will not be invoked, when only a M2M like partipiciants will be updated.
The reason for this, that the issue bean does not get technically dirty, as no modification occurs.
Sample code:
issue.getPartipiciants().add(user)
DB.markDirty(issue); // workaround
DB.save(issue); // will call persistAdapter.addUpdate, only when bean gets dirtyWorkaround
Ensure, that the bean will get dirty, when only a M2M will be modified. (This will also solve an other problem, as we want that LastModified will be updated on the issue)
Question
Is there a reliable callback mechanism in ebean, that tracks M2M changes or is this "markDirty" the only workaround I currently have?
Thanks.