This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 1ab035fb7d24c8091f0ab6a0b12838dc15760f56 Author: Benoit Tellier <[email protected]> AuthorDate: Tue May 2 09:34:09 2023 +0700 [PERF] Allow to disable ACLs --- .../init/configuration/CassandraConfiguration.java | 26 ++++-- .../mailbox/cassandra/mail/CassandraACLMapper.java | 35 +++++++- .../cassandra/CassandraMailboxManagerTest.java | 2 +- ...2Test.java => CassandraACLMapperNoACLTest.java} | 98 +++++++--------------- .../cassandra/mail/CassandraACLMapperV1Test.java | 2 +- .../cassandra/mail/CassandraACLMapperV2Test.java | 2 +- .../cassandra/mail/CassandraMailboxMapperTest.java | 2 +- .../modules/ROOT/pages/configure/cassandra.adoc | 8 +- src/site/xdoc/server/config-cassandra.xml | 4 + 9 files changed, 101 insertions(+), 78 deletions(-) diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java index a8f85d367d..b1a7fcc55e 100644 --- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java +++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/CassandraConfiguration.java @@ -82,6 +82,7 @@ public class CassandraConfiguration { private static final String CONSISTENCY_LEVEL_LIGHTWEIGHT_TRANSACTION = "cassandra.consistency_level.lightweight_transaction"; private static final String OPTIMISTIC_CONSISTENCY_LEVEL = "optimistic.consistency.level.enabled"; private static final String MAIL_REPOSITORY_STRONG_CONSISTENCY = "mailrepository.strong.consistency"; + private static final String ACL_ENABLED = "acl.enabled"; public static final CassandraConfiguration DEFAULT_CONFIGURATION = builder().build(); @@ -108,6 +109,7 @@ public class CassandraConfiguration { private Optional<Boolean> modseqReadStrongConsistency = Optional.empty(); private Optional<Boolean> optimisticConsistencyLevel = Optional.empty(); private Optional<Boolean> mailRepositoryStrongConsistency = Optional.empty(); + private Optional<Boolean> aclEnabled = Optional.empty(); public Builder mailboxReadStrongConsistency(boolean value) { this.mailboxReadStrongConsistency = Optional.of(value); @@ -119,6 +121,11 @@ public class CassandraConfiguration { return this; } + public Builder aclEnabled(Optional<Boolean> value) { + this.aclEnabled = value; + return this; + } + public Builder messageReadStrongConsistency(boolean value) { this.messageReadStrongConsistency = Optional.of(value); return this; @@ -364,7 +371,8 @@ public class CassandraConfiguration { optimisticConsistencyLevel.orElse(DEFAULT_OPTIMISTIC_CONSISTENCY_LEVEL), mailRepositoryStrongConsistency.orElse(DEFAULT_MAIL_REPOSITORY_STRONG_CONSISTENCY), uidReadStrongConsistency.orElse(DEFAULT_STRONG_CONSISTENCY), - modseqReadStrongConsistency.orElse(DEFAULT_STRONG_CONSISTENCY)); + modseqReadStrongConsistency.orElse(DEFAULT_STRONG_CONSISTENCY), + aclEnabled.orElse(true)); } } @@ -418,6 +426,7 @@ public class CassandraConfiguration { propertiesConfiguration.getBoolean(OPTIMISTIC_CONSISTENCY_LEVEL, null))) .mailRepositoryStrongConsistency(Optional.ofNullable( propertiesConfiguration.getBoolean(MAIL_REPOSITORY_STRONG_CONSISTENCY, null))) + .aclEnabled(Optional.ofNullable(propertiesConfiguration.getBoolean(ACL_ENABLED, null))) .build(); } @@ -443,6 +452,7 @@ public class CassandraConfiguration { private final boolean mailRepositoryStrongConsistency; private final boolean uidReadStrongConsistency; private final boolean modseqReadStrongConsistency; + private final boolean aclEnabled; @VisibleForTesting CassandraConfiguration(int aclMaxRetry, int expungeChunkSize, @@ -454,7 +464,7 @@ public class CassandraConfiguration { float mailboxCountersReadRepairChanceOneHundred, boolean mailboxReadStrongConsistency, boolean messageReadStrongConsistency, boolean messageWriteStrongConsistency, boolean optimisticConsistencyLevel, boolean mailRepositoryStrongConsistency, - boolean uidReadStrongConsistency, boolean modseqReadStrongConsistency) { + boolean uidReadStrongConsistency, boolean modseqReadStrongConsistency, boolean aclEnabled) { this.aclMaxRetry = aclMaxRetry; this.expungeChunkSize = expungeChunkSize; this.flagsUpdateMessageIdMaxRetry = flagsUpdateMessageIdMaxRetry; @@ -477,6 +487,7 @@ public class CassandraConfiguration { this.mailRepositoryStrongConsistency = mailRepositoryStrongConsistency; this.uidReadStrongConsistency = uidReadStrongConsistency; this.modseqReadStrongConsistency = modseqReadStrongConsistency; + this.aclEnabled = aclEnabled; } public boolean isUidReadStrongConsistency() { @@ -567,6 +578,10 @@ public class CassandraConfiguration { return mailRepositoryStrongConsistency; } + public boolean isAclEnabled() { + return aclEnabled; + } + @Override public final boolean equals(Object o) { if (o instanceof CassandraConfiguration) { @@ -593,8 +608,8 @@ public class CassandraConfiguration { && Objects.equals(this.optimisticConsistencyLevel, that.optimisticConsistencyLevel) && Objects.equals(this.uidReadStrongConsistency, that.uidReadStrongConsistency) && Objects.equals(this.modseqReadStrongConsistency, that.modseqReadStrongConsistency) - && Objects.equals(this.mailRepositoryStrongConsistency, that.mailRepositoryStrongConsistency); - + && Objects.equals(this.mailRepositoryStrongConsistency, that.mailRepositoryStrongConsistency) + && Objects.equals(this.aclEnabled, that.aclEnabled); } return false; } @@ -608,7 +623,7 @@ public class CassandraConfiguration { consistencyLevelRegular, consistencyLevelLightweightTransaction, mailboxReadRepair, messageReadStrongConsistency, mailboxReadStrongConsistency, messageWriteStrongConsistency, optimisticConsistencyLevel, mailRepositoryStrongConsistency, uidReadStrongConsistency, - modseqReadStrongConsistency); + modseqReadStrongConsistency, aclEnabled); } @Override @@ -636,6 +651,7 @@ public class CassandraConfiguration { .add("mailRepositoryStrongConsistency", mailRepositoryStrongConsistency) .add("modseqReadStrongConsistency", modseqReadStrongConsistency) .add("uidReadStrongConsistency", uidReadStrongConsistency) + .add("aclEnabled", aclEnabled) .toString(); } } diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java index da83a9adda..b050c2be23 100644 --- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java +++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java @@ -23,6 +23,8 @@ import java.util.Set; import javax.inject.Inject; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager; import org.apache.james.backends.cassandra.versions.SchemaVersion; import org.apache.james.eventsourcing.Command; @@ -47,6 +49,7 @@ import com.google.common.collect.ImmutableSet; import reactor.core.publisher.Mono; public class CassandraACLMapper implements ACLMapper { + public interface Store { Mono<MailboxACL> getACL(CassandraId cassandraId); @@ -145,20 +148,50 @@ public class CassandraACLMapper implements ACLMapper { } } + public static class NaiveStore implements Store { + @Override + public Mono<MailboxACL> getACL(CassandraId cassandraId) { + return Mono.just(MailboxACL.EMPTY); + } + + @Override + public Mono<ACLDiff> updateACL(CassandraId cassandraId, MailboxACL.ACLCommand command) { + return Mono.error(new NotImplementedException()); + } + + @Override + public Mono<ACLDiff> setACL(CassandraId cassandraId, MailboxACL mailboxACL) { + return Mono.error(new NotImplementedException()); + } + + @Override + public Mono<Void> delete(CassandraId cassandraId) { + // DOn't fail as the ACL never existed: this is a NOOP + return Mono.empty(); + } + } + public static final SchemaVersion ACL_V2_SCHEME_VERSION = new SchemaVersion(10); private final StoreV1 storeV1; private final StoreV2 storeV2; + private final NaiveStore naiveStore; private final CassandraSchemaVersionManager versionManager; + private final CassandraConfiguration cassandraConfiguration; @Inject - public CassandraACLMapper(StoreV1 storeV1, StoreV2 storeV2, CassandraSchemaVersionManager versionManager) { + public CassandraACLMapper(StoreV1 storeV1, StoreV2 storeV2, CassandraSchemaVersionManager versionManager, CassandraConfiguration cassandraConfiguration) { this.storeV1 = storeV1; this.storeV2 = storeV2; + naiveStore = new NaiveStore(); this.versionManager = versionManager; + this.cassandraConfiguration = cassandraConfiguration; } private Mono<Store> store() { + if (!cassandraConfiguration.isAclEnabled()) { + return Mono.just(naiveStore); + } return versionManager.isBefore(ACL_V2_SCHEME_VERSION) .map(isBefore -> { if (isBefore) { diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java index 7fff10ce0b..2e698aba26 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java @@ -830,7 +830,7 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai return new CassandraACLMapper( new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1), new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore), - versionManager); + versionManager, CassandraConfiguration.DEFAULT_CONFIGURATION); } private CassandraUserMailboxRightsDAO rightsDAO(CassandraCluster cassandraCluster) { diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperNoACLTest.java similarity index 55% copy from mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java copy to mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperNoACLTest.java index 16b6b2d33f..8cb14f70df 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperNoACLTest.java @@ -18,18 +18,17 @@ ****************************************************************/ package org.apache.james.mailbox.cassandra.mail; -import static org.apache.james.backends.cassandra.Scenario.Builder.awaitOn; +import static org.apache.james.mailbox.cassandra.mail.CassandraACLMapperContract.MAILBOX_ID; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.Optional; +import org.apache.commons.lang3.NotImplementedException; import org.apache.james.backends.cassandra.CassandraCluster; import org.apache.james.backends.cassandra.CassandraClusterExtension; -import org.apache.james.backends.cassandra.Scenario.Barrier; +import org.apache.james.backends.cassandra.StatementRecorder; import org.apache.james.backends.cassandra.components.CassandraModule; import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration; import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO; @@ -47,7 +46,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -class CassandraACLMapperV2Test extends CassandraACLMapperContract { +class CassandraACLMapperNoACLTest { @RegisterExtension static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension( CassandraModule.aggregateModules(CassandraAclModule.MODULE, CassandraSchemaVersionModule.MODULE, CassandraEventStoreModule.MODULE())); @@ -58,7 +57,7 @@ class CassandraACLMapperV2Test extends CassandraACLMapperContract { void setUp(CassandraCluster cassandra) { CassandraSchemaVersionDAO schemaVersionDAO = new CassandraSchemaVersionDAO(cassandra.getConf()); schemaVersionDAO.truncateVersion().block(); - schemaVersionDAO.updateVersion(new SchemaVersion(10)).block(); + schemaVersionDAO.updateVersion(new SchemaVersion(9)).block(); CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(schemaVersionDAO); CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION); CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandra.getConf()); @@ -70,77 +69,42 @@ class CassandraACLMapperV2Test extends CassandraACLMapperContract { cassandraACLMapper = new CassandraACLMapper( new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1), new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore), - versionManager); + versionManager, CassandraConfiguration.builder() + .aclEnabled(Optional.of(false)) + .build()); } - @Override - CassandraACLMapper cassandraACLMapper() { - return cassandraACLMapper; + @Test + void getACLShouldReturnEmpty() { + assertThat(cassandraACLMapper.getACL(MAILBOX_ID).block()).isEqualTo(MailboxACL.EMPTY); } @Test - void twoConcurrentUpdatesWhenNoACLStoredShouldReturnACLWithTwoEntries(CassandraCluster cassandra) throws Exception { - Barrier barrier = new Barrier(2); - cassandra.getConf() - .registerScenario(awaitOn(barrier) - .thenExecuteNormally() - .times(2) - .whenQueryStartsWith("SELECT event FROM eventstore WHERE aggregateid=:aggregateid")); - - 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(executor, keyBob, rights); - Future<Boolean> future2 = performACLUpdateInExecutor(executor, keyAlice, rights); - - barrier.awaitCaller(); - barrier.releaseCaller(); + void getACLShouldNotIssueCassandraQueries(CassandraCluster cassandra) { + StatementRecorder statementRecorder = cassandra.getConf().recordStatements(); - awaitAll(future1, future2); + cassandraACLMapper.getACL(MAILBOX_ID).block(); - assertThat(cassandraACLMapper.getACL(MAILBOX_ID).block()) - .isEqualTo(new MailboxACL().union(keyBob, rights).union(keyAlice, rights)); + assertThat(statementRecorder.listExecutedStatements()).isEmpty(); } @Test - void twoConcurrentUpdatesWhenStoredShouldReturnACLWithTwoEntries(CassandraCluster cassandra) throws Exception { - 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()).block(); - - Barrier barrier = new Barrier(2); - cassandra.getConf() - .registerScenario(awaitOn(barrier) - .thenExecuteNormally() - .times(2) - .whenQueryStartsWith("SELECT event FROM eventstore WHERE aggregateid=:aggregateid")); - - 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(executor, keyBob, rights); - Future<Boolean> future2 = performACLUpdateInExecutor(executor, keyAlice, rights); - - barrier.awaitCaller(); - barrier.releaseCaller(); - - awaitAll(future1, future2); - - assertThat(cassandraACLMapper.getACL(MAILBOX_ID).block()) - .isEqualTo(new MailboxACL().union(keyBob, rights).union(keyAlice, rights).union(keyBenwa, rights)); + void deleteShouldBeSupported() { + assertThatCode(() -> cassandraACLMapper.delete(MAILBOX_ID).block()) + .doesNotThrowAnyException(); } - private void awaitAll(Future<?>... futures) - throws InterruptedException, ExecutionException, TimeoutException { - for (Future<?> future : futures) { - future.get(10L, TimeUnit.SECONDS); - } + @Test + void setACLShouldNotBeSupported() { + assertThatThrownBy(() -> cassandraACLMapper.setACL(MAILBOX_ID, MailboxACL.EMPTY).block()) + .isInstanceOf(NotImplementedException.class); } - private Future<Boolean> performACLUpdateInExecutor(ExecutorService executor, MailboxACL.EntryKey key, MailboxACL.Rfc4314Rights rights) { - return executor.submit(() -> { - cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(key).rights(rights).asAddition()).block(); - return true; - }); + @Test + void updateACLShouldNotBeSupported() { + MailboxACL.EntryKey keyBenwa = new MailboxACL.EntryKey("benwa", MailboxACL.NameType.user, false); + MailboxACL.Rfc4314Rights rights = new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read); + assertThatThrownBy(() -> cassandraACLMapper.updateACL(MAILBOX_ID, MailboxACL.command().key(keyBenwa).rights(rights).asAddition()).block()) + .isInstanceOf(NotImplementedException.class); } - } diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java index 4861556560..45bb0bb52d 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java @@ -73,7 +73,7 @@ class CassandraACLMapperV1Test extends CassandraACLMapperContract { cassandraACLMapper = new CassandraACLMapper( new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1), new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore), - versionManager); + versionManager, CassandraConfiguration.DEFAULT_CONFIGURATION); } @Override diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java index 16b6b2d33f..9ce65ec9d8 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java @@ -70,7 +70,7 @@ class CassandraACLMapperV2Test extends CassandraACLMapperContract { cassandraACLMapper = new CassandraACLMapper( new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1), new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore), - versionManager); + versionManager, CassandraConfiguration.DEFAULT_CONFIGURATION); } @Override diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java index d8b3ee9810..f617f5d7d2 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java @@ -124,7 +124,7 @@ class CassandraMailboxMapperTest { CassandraACLMapper aclMapper = new CassandraACLMapper( new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1), new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore), - versionManager); + versionManager, CassandraConfiguration.DEFAULT_CONFIGURATION); testee = new CassandraMailboxMapper( mailboxDAO, mailboxPathV3DAO, diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc index 5cadd23c04..0f26f36efa 100644 --- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc +++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/cassandra.adoc @@ -145,5 +145,11 @@ by turning it off. Reads performed as part of write transaction are also perform | mailrepository.strong.consistency | Optional. Boolean, defaults to true. Allows not to use lightweight transactions in CassandraMailRepository. -| If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored). + If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored). + +| acl.enabled +| Optional. Boolean, defaults to true. Allows disabling ACLs: if set to false, delegation will fail and users will only +have access to the mailboxes they own. ACLs can represent a high volume of requests. If you do not propose mailbox sharing +features to your users, you can consider disabling them in order to improve performance. + |=== \ No newline at end of file diff --git a/src/site/xdoc/server/config-cassandra.xml b/src/site/xdoc/server/config-cassandra.xml index 8aa0dc4265..9909bd1d35 100644 --- a/src/site/xdoc/server/config-cassandra.xml +++ b/src/site/xdoc/server/config-cassandra.xml @@ -122,6 +122,10 @@ <dt><strong>mailrepository.strong.consistency</strong></dt> <dd>Optional. Defaults to true. Allows not to use lightweight transactions in CassandraMailRepository. If disabled we implement an idempotent behaviour (duplicates are overridden, missing entries upon deletes are ignored).</dd> + <dt><strong>acl.enabled</strong></dt> + <dd>Optional. Boolean, defaults to true. Allows disabling ACLs: if set to false, delegation will fail and users will only + have access to the mailboxes they own. ACLs can represent a high volume of requests. If you do not propose mailbox sharing + features to your users, you can consider disabling them in order to improve performance.</dd> </dl> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
