private void mergeRights(CassandraId oldMailboxId, CassandraId newMailboxId) { try { MailboxACL oldAcl = cassandraACLMapper.getACL(oldMailboxId).join(); MailboxACL newAcl = cassandraACLMapper.getACL(newMailboxId).join(); MailboxACL finalAcl = newAcl.union(oldAcl); cassandraACLMapper.setACL(newMailboxId, finalAcl); rightsDAO.update(oldMailboxId, ACLDiff.computeDiff(oldAcl, MailboxACL.EMPTY)).join(); } catch (MailboxException e) { throw new RuntimeException(e); } } }
/** * Performs the set theoretic operation of union of this {@link MailboxACL} * and toAdd {@link MailboxACL}. * * A schematic example: * "user1:lr;user2:lrwt".union("user1:at;-$group1:lrwt") returns * "user1:alrt;user2:lrwt;-$group1:lrwt". * * Implementations must return a new unmodifiable instance of * {@link MailboxACL}. However, implementations may decide to return this or * toAdd parameter value in case the result would be equal to the respective * one of those. */ public MailboxACL union(MailboxACL other) throws UnsupportedRightException { return new MailboxACL( Stream.concat( this.entries.entrySet().stream(), other.getEntries().entrySet().stream()) .collect(Guavate.toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)) .asMap() .entrySet() .stream() .collect(Guavate.toImmutableMap(Map.Entry::getKey, e -> union(e.getValue())))); }
public MailboxACL union(EntryKey key, Rfc4314Rights mailboxACLRights) throws UnsupportedRightException { return union(new MailboxACL(new Entry(key, mailboxACLRights))); }
@Test public void testUnionACLNew() throws UnsupportedRightException { Map<EntryKey, Rfc4314Rights> expectedEntries = new HashMap<>(u1u2g1g2ACL.getEntries()); expectedEntries.put(MailboxACL.OWNER_KEY, MailboxACL.FULL_RIGHTS); MailboxACL toAdd = MailboxACL.OWNER_FULL_ACL; MailboxACL result = u1u2g1g2ACL.union(toAdd); Map<EntryKey, Rfc4314Rights> foundEntries = result.getEntries(); assertThat(expectedEntries).isEqualTo(foundEntries); }
@Test public void testUnionEntryNew() throws UnsupportedRightException { Map<EntryKey, Rfc4314Rights> expectedEntries = new HashMap<>(u1u2g1g2ACL.getEntries()); expectedEntries.put(MailboxACL.OWNER_KEY, MailboxACL.FULL_RIGHTS); MailboxACL result = u1u2g1g2ACL.union(MailboxACL.OWNER_KEY, MailboxACL.FULL_RIGHTS); Map<EntryKey, Rfc4314Rights> foundEntries = result.getEntries(); assertThat(foundEntries).isEqualTo(expectedEntries); }
@Test void twoConcurrentUpdatesWhenNoACEStoredShouldReturnACEWithTwoEntries(CassandraCluster cassandra) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(2); MailboxACL.EntryKey keyBob = new MailboxACL.EntryKey("bob", MailboxACL.NameType.user, false); MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); MailboxACL.EntryKey keyAlice = new MailboxACL.EntryKey("alice", MailboxACL.NameType.user, false); Future<Boolean> future1 = performACLUpdateInExecutor(cassandra, executor, keyBob, rights, countDownLatch::countDown); Future<Boolean> future2 = performACLUpdateInExecutor(cassandra, executor, keyAlice, rights, countDownLatch::countDown); awaitAll(future1, future2); assertThat(cassandraACLMapper.getACL(MAILBOX_ID).join()) .isEqualTo(new MailboxACL().union(keyBob, rights).union(keyAlice, rights)); }
/** * Apply the given ACL update on current ACL and return the result as a new ACL. * * @param aclUpdate Update to perform * @return Copy of current ACL updated * @throws UnsupportedRightException */ public MailboxACL apply(ACLCommand aclUpdate) throws UnsupportedRightException { switch (aclUpdate.getEditMode()) { case ADD: return union(aclUpdate.getEntryKey(), aclUpdate.getRights()); case REMOVE: return except(aclUpdate.getEntryKey(), aclUpdate.getRights()); case REPLACE: return replace(aclUpdate.getEntryKey(), aclUpdate.getRights()); } throw new RuntimeException("Unknown edit mode"); }
@Test public void testUnionEntryExisting() throws UnsupportedRightException { Map<EntryKey, Rfc4314Rights> expectedEntries = new HashMap<>(u1u2g1g2ACL.getEntries()); expectedEntries.put(EntryKey.deserialize(USER_1), Rfc4314Rights.fromSerializedRfc4314Rights(aeik + lprs)); MailboxACL result = u1u2g1g2ACL.union(EntryKey.deserialize(USER_1), Rfc4314Rights.fromSerializedRfc4314Rights(lprs)); Map<EntryKey, Rfc4314Rights> foundEntries = result.getEntries(); assertThat(foundEntries).isEqualTo(expectedEntries); }
@Test void twoConcurrentUpdatesWhenStoredShouldReturnACEWithTwoEntries(CassandraCluster cassandra) throws Exception { CountDownLatch countDownLatch = new CountDownLatch(2); MailboxACL.EntryKey keyBenwa = new MailboxACL.EntryKey("benwa", MailboxACL.NameType.user, false); MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(keyBenwa).rights(rights).asAddition()); MailboxACL.EntryKey keyBob = new MailboxACL.EntryKey("bob", MailboxACL.NameType.user, false); MailboxACL.EntryKey keyAlice = new MailboxACL.EntryKey("alice", MailboxACL.NameType.user, false); Future<Boolean> future1 = performACLUpdateInExecutor(cassandra, executor, keyBob, rights, countDownLatch::countDown); Future<Boolean> future2 = performACLUpdateInExecutor(cassandra, executor, keyAlice, rights, countDownLatch::countDown); awaitAll(future1, future2); assertThat(cassandraACLMapper.getACL(MAILBOX_ID).join()) .isEqualTo(new MailboxACL().union(keyBob, rights).union(keyAlice, rights).union(keyBenwa, rights)); }
@Test void replaceWhenNotStoredShouldUpdateACLEntry() throws MailboxException { MailboxACL.EntryKey key = new MailboxACL.EntryKey("bob", MailboxACL.NameType.user, false); MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(key).rights(rights).asReplacement()); assertThat(cassandraACLMapper.getACL(MAILBOX_ID).join()).isEqualTo(new MailboxACL().union(key, rights)); }
@Test public void testUnionACLExisting() throws UnsupportedRightException { Map<EntryKey, Rfc4314Rights> expectedEntries = new HashMap<>(u1u2g1g2ACL.getEntries()); expectedEntries.put(EntryKey.deserialize(USER_1), Rfc4314Rights.fromSerializedRfc4314Rights(aeik + lprs)); MailboxACL toAdd = new MailboxACL(new Entry(USER_1, lprs)); MailboxACL result = u1u2g1g2ACL.union(toAdd); Map<EntryKey, Rfc4314Rights> foundEntries = result.getEntries(); assertThat(expectedEntries).isEqualTo(foundEntries); }
@Test void addACLWhenNoneStoredShouldReturnUpdatedACL() throws Exception { MailboxACL.EntryKey key = new MailboxACL.EntryKey("bob", MailboxACL.NameType.user, false); MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(key).rights(rights).asAddition()); assertThat(cassandraACLMapper.getACL(MAILBOX_ID).join()) .isEqualTo(new MailboxACL().union(key, rights)); }
@Test void modifyACLWhenStoredShouldReturnUpdatedACL() throws MailboxException { MailboxACL.EntryKey keyBob = new MailboxACL.EntryKey("bob", MailboxACL.NameType.user, false); MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(keyBob).rights(rights).asAddition()); MailboxACL.EntryKey keyAlice = new MailboxACL.EntryKey("alice", MailboxACL.NameType.user, false); cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(keyAlice).rights(rights).asAddition()); assertThat(cassandraACLMapper.getACL(MAILBOX_ID).join()) .isEqualTo(new MailboxACL().union(keyBob, rights).union(keyAlice, rights)); }
@Test void updateInvalidACLShouldBeBasedOnEmptyACL(CassandraCluster cassandra) throws Exception { cassandra.getConf().execute( insertInto(CassandraACLTable.TABLE_NAME) .value(CassandraACLTable.ID, MAILBOX_ID.asUuid()) .value(CassandraACLTable.ACL, "{\"entries\":{\"bob\":invalid}}") .value(CassandraACLTable.VERSION, 1)); MailboxACL.EntryKey key = new MailboxACL.EntryKey("bob", MailboxACL.NameType.user, false); MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(key).rights(rights).asAddition()); assertThat(cassandraACLMapper.getACL(MAILBOX_ID).join()).isEqualTo(new MailboxACL().union(key, rights)); }