diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index cb25a6860..7ae185a02 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -185,6 +185,7 @@ import org.whispersystems.textsecuregcm.storage.MessagesCache; import org.whispersystems.textsecuregcm.storage.MessagesDynamoDb; import org.whispersystems.textsecuregcm.storage.MessagesManager; import org.whispersystems.textsecuregcm.storage.NonNormalizedAccountCrawlerListener; +import org.whispersystems.textsecuregcm.storage.UsernameCleaner; import org.whispersystems.textsecuregcm.storage.PhoneNumberIdentifiers; import org.whispersystems.textsecuregcm.storage.Profiles; import org.whispersystems.textsecuregcm.storage.ProfilesManager; @@ -531,6 +532,17 @@ public class WhisperServerService extends Application accountDatabaseCrawlerListeners = List.of( new NonNormalizedAccountCrawlerListener(accountsManager, metricsCluster), @@ -560,6 +572,7 @@ public class WhisperServerService extends Application fromUuid, final List chunkAccounts) { + for (Account account : chunkAccounts) { + if (account.getUsername().isPresent()) { + logger.info("Deleting username present for account {}", account.getUuid()); + try { + this.accountsManager.clearUsername(account); + Metrics.counter(DELETED_USERNAME_COUNTER, Tags.of("outcome", "success")).increment(); + } catch (Exception e) { + logger.warn("Failed to clear username on account {}", account.getUuid(), e); + Metrics.counter(DELETED_USERNAME_COUNTER, Tags.of("outcome", "error")).increment(); + } + } + } + } + + @Override + public void onCrawlEnd(final Optional fromUuid) { + logger.info("Username cleaner crawl completed"); + } +} diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/UsernameCleanerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/UsernameCleanerTest.java new file mode 100644 index 000000000..47ce38811 --- /dev/null +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/UsernameCleanerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ +package org.whispersystems.textsecuregcm.storage; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.*; +import static org.mockito.Mockito.*; + +class UsernameCleanerTest { + + private final AccountsManager accountsManager = mock(AccountsManager.class); + private final Account hasUsername = mock(Account.class); + private final Account noUsername = mock(Account.class); + + + @BeforeEach + void setup() { + when(hasUsername.getUsername()).thenReturn(Optional.of("n00bkiller")); + when(noUsername.getUsername()).thenReturn(Optional.empty()); + } + + @Test + void testAccounts() throws AccountDatabaseCrawlerRestartException { + UsernameCleaner accountCleaner = new UsernameCleaner(accountsManager); + accountCleaner.onCrawlStart(); + accountCleaner.timeAndProcessCrawlChunk(Optional.empty(), Arrays.asList(hasUsername, noUsername)); + accountCleaner.onCrawlEnd(Optional.empty()); + verify(accountsManager).clearUsername(hasUsername); + verify(accountsManager, never()).clearUsername(noUsername); + } +}