diff --git a/store/src/main/java/com/zimbra/cs/account/ProvisioningCache.java b/store/src/main/java/com/zimbra/cs/account/ProvisioningCache.java new file mode 100644 index 00000000000..77794c8d64b --- /dev/null +++ b/store/src/main/java/com/zimbra/cs/account/ProvisioningCache.java @@ -0,0 +1,6 @@ +package com.zimbra.cs.account; + +public interface ProvisioningCache { + + void removeFromCache(Entry entry); +} diff --git a/store/src/main/java/com/zimbra/cs/account/ldap/LdapProv.java b/store/src/main/java/com/zimbra/cs/account/ldap/LdapProv.java index 31b718cdc21..990ea57e5c7 100644 --- a/store/src/main/java/com/zimbra/cs/account/ldap/LdapProv.java +++ b/store/src/main/java/com/zimbra/cs/account/ldap/LdapProv.java @@ -8,7 +8,7 @@ import com.zimbra.common.service.ServiceException; import com.zimbra.cs.account.Account; import com.zimbra.cs.account.Domain; -import com.zimbra.cs.account.Entry; +import com.zimbra.cs.account.ProvisioningCache; import com.zimbra.cs.account.Provisioning; import com.zimbra.cs.account.auth.AuthMechanism.AuthMech; import com.zimbra.cs.ldap.LdapClient; @@ -24,7 +24,7 @@ /** * @author pshao */ -public abstract class LdapProv extends Provisioning { +public abstract class LdapProv extends Provisioning implements ProvisioningCache { protected LdapDIT mDIT; protected LdapHelper helper; @@ -122,8 +122,6 @@ public abstract void externalLdapAuth( public abstract void zimbraLdapAuthenticate( Account acct, String password, Map authCtxt) throws ServiceException; - public abstract void removeFromCache(Entry entry); - @TODO // deprecate public abstract void searchLdapOnMaster( String base, String filter, String[] returnAttrs, SearchLdapOptions.SearchLdapVisitor visitor) diff --git a/store/src/main/java/com/zimbra/cs/mailbox/Mailbox.java b/store/src/main/java/com/zimbra/cs/mailbox/Mailbox.java index 15dcd6d3c32..04f4b50ed6b 100644 --- a/store/src/main/java/com/zimbra/cs/mailbox/Mailbox.java +++ b/store/src/main/java/com/zimbra/cs/mailbox/Mailbox.java @@ -66,8 +66,11 @@ import com.zimbra.cs.account.DataSource; import com.zimbra.cs.account.Domain; import com.zimbra.cs.account.Provisioning; +import com.zimbra.cs.account.ProvisioningCache; import com.zimbra.cs.account.Server; import com.zimbra.cs.account.ShareLocator; +import com.zimbra.cs.account.ldap.LdapProv; +import com.zimbra.cs.account.ldap.LdapProvisioning; import com.zimbra.cs.datasource.DataSourceManager; import com.zimbra.cs.db.DbDataSource; import com.zimbra.cs.db.DbMailItem; @@ -2663,6 +2666,22 @@ public void deleteMailbox(DeleteBlobs deleteBlobs) throws ServiceException { } } + public void markMailboxDeleted() throws ServiceException { + MailboxManager.getInstance().markMailboxDeleted(this); + try { + Provisioning provisioning = Provisioning.getInstance(); + if (provisioning instanceof ProvisioningCache) { + ((ProvisioningCache) provisioning).removeFromCache(this.getAccount()); + } + } catch (AccountServiceException e) { + if (AccountServiceException.NO_SUCH_ACCOUNT.equals(e.getCode())) { + ZimbraLog.mailbox.warn(this.getAccountId() + " account deleted"); + return; + } + throw e; + } + } + public void renameMailbox(String oldName, String newName) throws ServiceException { renameMailbox(null, oldName, newName); } diff --git a/store/src/test/java/com/zimbra/cs/account/MockProvisioning.java b/store/src/test/java/com/zimbra/cs/account/MockProvisioning.java index 1400d70ba5c..d6b3881a40a 100644 --- a/store/src/test/java/com/zimbra/cs/account/MockProvisioning.java +++ b/store/src/test/java/com/zimbra/cs/account/MockProvisioning.java @@ -47,7 +47,7 @@ * * @author ysasaki */ -public final class MockProvisioning extends Provisioning { +public final class MockProvisioning extends Provisioning implements ProvisioningCache { public static final String DEFAULT_ACCOUNT_ID = new UUID(0L, 0L).toString(); private final Map id2account = Maps.newHashMap(); @@ -951,4 +951,13 @@ public void resetPassword(Account acct, String newPassword, boolean dryRun) throws ServiceException { throw ServiceException.UNSUPPORTED(); } + + @Override + public void removeFromCache(Entry entry) { + if (entry instanceof Account) { + id2account.remove(((Account) entry).getId()); + } else { + throw new UnsupportedOperationException(); + } + } } diff --git a/store/src/test/java/com/zimbra/cs/mailbox/MailboxTest.java b/store/src/test/java/com/zimbra/cs/mailbox/MailboxTest.java index 05eb5c5e6a3..3f82925a735 100644 --- a/store/src/test/java/com/zimbra/cs/mailbox/MailboxTest.java +++ b/store/src/test/java/com/zimbra/cs/mailbox/MailboxTest.java @@ -14,6 +14,7 @@ import com.zimbra.common.mailbox.ContactConstants; import com.zimbra.common.mime.InternetAddress; import com.zimbra.cs.account.Account; +import com.zimbra.cs.account.AccountServiceException; import com.zimbra.cs.account.MockProvisioning; import com.zimbra.cs.account.Provisioning; import com.zimbra.cs.index.BrowseTerm; @@ -31,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Set; + import org.junit.jupiter.api.*; /** @@ -272,6 +274,35 @@ void trimTombstones() throws Exception { mbox.getTombstones(changeId3).isEmpty(), "sync token matches last purged tombstone"); } + @Test + void test_markMailboxDeleted_deletes_account_when_account_exists() throws Exception { + Account acct = Provisioning.getInstance().getAccount("test@zimbra.com"); + MailboxManager mailboxManager = MailboxManager.getInstance(); + Mailbox mbox = mailboxManager.getMailboxByAccount(acct); + mbox.markMailboxDeleted(); + AccountServiceException thrown = assertThrows( + AccountServiceException.class, + () -> mailboxManager.getMailboxByAccountId(acct.getId()), + "Expected doThing() to throw, but it didn't" + ); + assertEquals(AccountServiceException.NO_SUCH_ACCOUNT, thrown.getCode()); + } + + @Test + void test_markMailboxDeleted_is_ok_when_account_does_not_exists() throws Exception { + Account acct = Provisioning.getInstance().getAccount("test@zimbra.com"); + MailboxManager mailboxManager = MailboxManager.getInstance(); + Mailbox mbox = mailboxManager.getMailboxByAccount(acct); + mbox.markMailboxDeleted(); + mbox.markMailboxDeleted(); + AccountServiceException thrown = assertThrows( + AccountServiceException.class, + () -> mailboxManager.getMailboxByAccountId(acct.getId()), + "Expected doThing() to throw, but it didn't" + ); + assertEquals(AccountServiceException.NO_SUCH_ACCOUNT, thrown.getCode()); + } + static class MockListener extends MailboxListener { /** * Information on creations/modifications and deletions seen since {@link clear} was last called