Unable to update series acl (sometimes) if original acl has access roles duplicated

Steps to reproduce

Lets use ROLE_USER_ADMIN and ROLE_USER for this example.

Steps to reproduce:
1. Use the new series wizard to create a new series.
2. Add ROLE_USER_ADMIN twice to the access policy setup for the new series (once for read/write, and another for say read)
3. Once series is created, add read access for ROLE_USER to the newly created series.

Actual Results:
ROLE_USER does not have read access to the series.

Expected Results:
ROLE_USER should have read access to the series.

Workaround (if any):
Add both read and write access for ROLE_USER, then remove write access after the initial update is complete. Any follow-on ACL changes will stick going forward (after the initial update).


duncan smith
September 5, 2018, 10:54 AM

The issue lies with EqualsUtil's eqListUnsorted method, which assumes unique entries when doing comparisons on lists:

/** Compare the elements of two lists for equality treating the lists as sets. */
public static boolean eqListUnsorted(List<?> as, List<?> bs) {
if (as != null && bs != null && as.size() == bs.size()) {
for (Object a : as) {
if (!bs.contains(a))
return false;
return true;
} else {
return eqObj(as, bs);

For our example in the description, we have the following entries:
current ACL: [read for ROLE_USER_ADMIN, write for ROLE_USER_ADMIN, read for ROLE_USER_ADMIN] (3 entries, where read for ROLE_USER_ADMIN is duplicated)
updated ACL: [read for ROLE_USER_ADMIN, write for ROLE_USER_ADMIN, read for ROLE_USER] (3 unique entries)

The comparator method EqualsUtil.equals checks:
1. that the lists are of equal size (3 apiece in this case),
2. that every entry in current ACL is contained within updated ACL.

Both of these checks equate to true, hence the ACL update does not proceed as "the ACLs are the same".

Either EqualsUtil.equal should be adapted to filter out duplicated entries (imo tough [streams to the rescue?]), or originating methods should filter out duplicated entries prior to calling EqualsUtil.equal.

Fixed and reviewed
Your pinned fields
Click on the next to a field label to start pinning.




duncan smith


Incorrectly Functioning With Workaround