/** * ACL is sensible information and as such we should expose as few information as possible * to users. This method allows to filter a {@link MailboxACL} in order to present it to * the connected user. */ @VisibleForTesting static MailboxACL filteredForSession(Mailbox mailbox, MailboxACL acl, MailboxSession mailboxSession) throws UnsupportedRightException { if (mailbox.generateAssociatedPath().belongsTo(mailboxSession)) { return acl; } MailboxACL.EntryKey userAsKey = MailboxACL.EntryKey.createUserEntryKey(mailboxSession.getUser().getUserName()); Rfc4314Rights rights = acl.getEntries().getOrDefault(userAsKey, new Rfc4314Rights()); if (rights.contains(MailboxACL.Right.Administer)) { return acl; } return new MailboxACL(ImmutableMap.of(userAsKey, rights)); } }
public ACLWithVersion apply(MailboxACL.ACLCommand command) { try { return new ACLWithVersion(version, mailboxACL.apply(command)); } catch (UnsupportedRightException exception) { throw new RuntimeException(exception); } } }
/** * 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 except(EntryKey key, Rfc4314Rights mailboxACLRights) throws UnsupportedRightException { return except(new MailboxACL(new Entry(key, mailboxACLRights))); }
public MailboxACL union(EntryKey key, Rfc4314Rights mailboxACLRights) throws UnsupportedRightException { return union(new MailboxACL(new Entry(key, mailboxACLRights))); }
/** * Performs the set theoretic operation of relative complement of toRemove * {@link MailboxACL} in this {@link MailboxACL}. * * A schematic example: "user1:lr;user2:lrwt".except("user1:w;user2:t") * returns "user1:lr;user2:lrw". * * Implementations must return a new unmodifiable instance of * {@link MailboxACL}. However, implementations may decide to return this or * toRemove parameter value in case the result would be equal to the * respective one of those. * * Implementations must ensure that the result does not contain entries with * empty rigths. E.g. "user1:lr;user2:lrwt".except("user1:lr") should return * "user2:lrwt" rather than "user1:;user2:lrwt" */ public MailboxACL except(MailboxACL other) throws UnsupportedRightException { return new MailboxACL(entries.entrySet() .stream() .map(entry -> Pair.of( entry.getKey(), except(entry.getValue(), other.getEntries().get(entry.getKey())))) .filter(pair -> !pair.getValue().isEmpty()) .collect(Guavate.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))); }
@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 eventShouldDoNothingWhenNewACLIsTheSameAsTheOldOne() throws Exception { Mailbox grandChildMailbox = mailboxMapper.getMailboxMapper(mailboxSession).findMailboxById(grandChildMailboxId); mailboxMapper.getMailboxMapper(mailboxSession).setACL(grandChildMailbox, new MailboxACL( new Entry(SHARED_USER_KEY, new Rfc4314Rights(Right.Lookup)))); storeRightManager.applyRightsCommand( GRAND_CHILD_MAILBOX, MailboxACL.command() .key(SHARED_USER_KEY) .rights(Right.Lookup) .asAddition(), mailboxSession); MailboxACL actualACL = storeMailboxManager.getMailbox(parentMailboxId, mailboxSession) .getMetaData(RESET_RECENT, mailboxSession, MessageManager.MetaData.FetchGroup.NO_COUNT) .getACL(); assertThat(actualACL.getEntries()) .doesNotContainKeys(SHARED_USER_KEY); }
@Test public void eventShouldDoNothingWhenMailboxACLUpdatedButNoLookupRight() throws Exception { storeRightManager.applyRightsCommand( GRAND_CHILD_MAILBOX, MailboxACL.command() .key(SHARED_USER_KEY) .rights(Right.Administer) .asReplacement(), mailboxSession); MailboxACL actualACL = storeMailboxManager.getMailbox(parentMailboxId, mailboxSession) .getMetaData(RESET_RECENT, mailboxSession, MessageManager.MetaData.FetchGroup.NO_COUNT) .getACL(); assertThat(actualACL.getEntries()) .doesNotContainKeys(SHARED_USER_KEY); }
public MailboxACL toMailboxAcl() { BinaryOperator<MailboxACL> union = Throwing.binaryOperator(MailboxACL::union); return rights.asMap() .entrySet() .stream() .map(entry -> new MailboxACL( ImmutableMap.of( EntryKey.createUserEntryKey(entry.getKey().value), toMailboxAclRights(entry.getValue())))) .reduce(MailboxACL.EMPTY, union); }
public boolean equals(Object o) { if (o instanceof MailboxACL) { MailboxACL acl = (MailboxACL) o; return Objects.equals(this.getEntries(), acl.getEntries()); } return false; }
@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 public void testExceptEntryNew() throws UnsupportedRightException { /* actually no change expected */ Map<EntryKey, Rfc4314Rights> expectedEntries = new HashMap<>(u1u2g1g2ACL.getEntries()); MailboxACL result = u1u2g1g2ACL.except(MailboxACL.OWNER_KEY, MailboxACL.FULL_RIGHTS); Map<EntryKey, Rfc4314Rights> foundEntries = result.getEntries(); assertThat(expectedEntries).isEqualTo(foundEntries); }
@Override public void replaceRights(MailboxPath mailboxPath, String targetUser, Rfc4314Rights rights) throws MailboxException { MailboxSession mailboxSession = mailboxManager.createSystemSession(mailboxPath.getUser()); ACLCommand command = MailboxACL.command().forUser(targetUser).rights(rights).asReplacement(); mailboxManager.applyRightsCommand(mailboxPath, command, mailboxSession); }
@Test public void ofPositiveNameTypeShouldFilterOutNegativeEntries() throws Exception { MailboxACL mailboxACL = new MailboxACL( ImmutableMap.of(EntryKey.createUserEntryKey("user1", NEGATIVE), MailboxACL.FULL_RIGHTS)); assertThat(mailboxACL.ofPositiveNameType(NameType.user)) .isEmpty(); } }
/** * 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"); }
@Override public boolean equals(Object o) { if (o instanceof ACLResponse) { ACLResponse other = (ACLResponse) o; return (this.acl == other.acl || (this.acl != null && this.acl.equals(other.acl))) && (this.mailboxName == other.mailboxName || (this.mailboxName != null && this.mailboxName.equals(other.mailboxName))) ; } return false; }
@Test public void removedEntriesShouldReturnEmptyWhenAddedEntry() throws Exception { PositiveUserACLDiff positiveUserAclDiff = PositiveUserACLDiff.computeDiff( MailboxACL.EMPTY, MailboxACL.EMPTY.apply( MailboxACL.command() .key(USER_ENTRY_KEY) .rights(RIGHTS) .asAddition())); assertThat(positiveUserAclDiff.removedEntries()) .isEmpty(); }