Delete data in the storage service when deleting accounts.
This commit is contained in:
parent
c870a1bbd5
commit
ff1a721d5b
|
@ -101,6 +101,7 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||||
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
||||||
import org.whispersystems.textsecuregcm.s3.PolicySigner;
|
import org.whispersystems.textsecuregcm.s3.PolicySigner;
|
||||||
import org.whispersystems.textsecuregcm.s3.PostPolicyGenerator;
|
import org.whispersystems.textsecuregcm.s3.PostPolicyGenerator;
|
||||||
|
import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient;
|
||||||
import org.whispersystems.textsecuregcm.sms.SmsSender;
|
import org.whispersystems.textsecuregcm.sms.SmsSender;
|
||||||
import org.whispersystems.textsecuregcm.sms.TwilioSmsSender;
|
import org.whispersystems.textsecuregcm.sms.TwilioSmsSender;
|
||||||
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
|
@ -292,7 +293,17 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
ExecutorService keyspaceNotificationDispatchExecutor = environment.lifecycle().executorService(name(getClass(), "keyspaceNotification-%d")).maxThreads(16).workQueue(keyspaceNotificationDispatchQueue).build();
|
ExecutorService keyspaceNotificationDispatchExecutor = environment.lifecycle().executorService(name(getClass(), "keyspaceNotification-%d")).maxThreads(16).workQueue(keyspaceNotificationDispatchQueue).build();
|
||||||
ExecutorService apnSenderExecutor = environment.lifecycle().executorService(name(getClass(), "apnSender-%d")).maxThreads(1).minThreads(1).build();
|
ExecutorService apnSenderExecutor = environment.lifecycle().executorService(name(getClass(), "apnSender-%d")).maxThreads(1).minThreads(1).build();
|
||||||
ExecutorService gcmSenderExecutor = environment.lifecycle().executorService(name(getClass(), "gcmSender-%d")).maxThreads(1).minThreads(1).build();
|
ExecutorService gcmSenderExecutor = environment.lifecycle().executorService(name(getClass(), "gcmSender-%d")).maxThreads(1).minThreads(1).build();
|
||||||
|
ExecutorService storageServiceExecutor = environment.lifecycle().executorService(name(getClass(), "storageService-%d")).maxThreads(8).minThreads(1).build();
|
||||||
|
|
||||||
|
ExternalServiceCredentialGenerator directoryCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getDirectoryConfiguration().getDirectoryClientConfiguration().getUserAuthenticationTokenSharedSecret(),
|
||||||
|
config.getDirectoryConfiguration().getDirectoryClientConfiguration().getUserAuthenticationTokenUserIdSecret(),
|
||||||
|
true);
|
||||||
|
|
||||||
|
ExternalServiceCredentialGenerator storageCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getSecureStorageServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
||||||
|
ExternalServiceCredentialGenerator backupCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getSecureBackupServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
||||||
|
ExternalServiceCredentialGenerator paymentsCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getPaymentsServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
||||||
|
|
||||||
|
SecureStorageClient secureStorageClient = new SecureStorageClient(storageCredentialsGenerator, storageServiceExecutor, config.getSecureStorageServiceConfiguration());
|
||||||
ClientPresenceManager clientPresenceManager = new ClientPresenceManager(messagesCacheCluster, recurringJobExecutor, keyspaceNotificationDispatchExecutor);
|
ClientPresenceManager clientPresenceManager = new ClientPresenceManager(messagesCacheCluster, recurringJobExecutor, keyspaceNotificationDispatchExecutor);
|
||||||
DirectoryManager directory = new DirectoryManager(directoryClient);
|
DirectoryManager directory = new DirectoryManager(directoryClient);
|
||||||
DirectoryQueue directoryQueue = new DirectoryQueue(config.getDirectoryConfiguration().getSqsConfiguration());
|
DirectoryQueue directoryQueue = new DirectoryQueue(config.getDirectoryConfiguration().getSqsConfiguration());
|
||||||
|
@ -303,7 +314,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
MessagesCache messagesCache = new MessagesCache(messagesCacheCluster, keyspaceNotificationDispatchExecutor);
|
MessagesCache messagesCache = new MessagesCache(messagesCacheCluster, keyspaceNotificationDispatchExecutor);
|
||||||
PushLatencyManager pushLatencyManager = new PushLatencyManager(metricsCluster);
|
PushLatencyManager pushLatencyManager = new PushLatencyManager(metricsCluster);
|
||||||
MessagesManager messagesManager = new MessagesManager(messages, messagesCache, pushLatencyManager);
|
MessagesManager messagesManager = new MessagesManager(messages, messagesCache, pushLatencyManager);
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directory, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directory, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
RemoteConfigsManager remoteConfigsManager = new RemoteConfigsManager(remoteConfigs);
|
RemoteConfigsManager remoteConfigsManager = new RemoteConfigsManager(remoteConfigs);
|
||||||
FeatureFlagsManager featureFlagsManager = new FeatureFlagsManager(featureFlags, recurringJobExecutor);
|
FeatureFlagsManager featureFlagsManager = new FeatureFlagsManager(featureFlags, recurringJobExecutor);
|
||||||
DeadLetterHandler deadLetterHandler = new DeadLetterHandler(accountsManager, messagesManager);
|
DeadLetterHandler deadLetterHandler = new DeadLetterHandler(accountsManager, messagesManager);
|
||||||
|
@ -317,14 +328,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
AccountAuthenticator accountAuthenticator = new AccountAuthenticator(accountsManager);
|
AccountAuthenticator accountAuthenticator = new AccountAuthenticator(accountsManager);
|
||||||
DisabledPermittedAccountAuthenticator disabledPermittedAccountAuthenticator = new DisabledPermittedAccountAuthenticator(accountsManager);
|
DisabledPermittedAccountAuthenticator disabledPermittedAccountAuthenticator = new DisabledPermittedAccountAuthenticator(accountsManager);
|
||||||
|
|
||||||
ExternalServiceCredentialGenerator directoryCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getDirectoryConfiguration().getDirectoryClientConfiguration().getUserAuthenticationTokenSharedSecret(),
|
|
||||||
config.getDirectoryConfiguration().getDirectoryClientConfiguration().getUserAuthenticationTokenUserIdSecret(),
|
|
||||||
true);
|
|
||||||
|
|
||||||
ExternalServiceCredentialGenerator storageCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getSecureStorageServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
|
||||||
ExternalServiceCredentialGenerator backupCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getSecureBackupServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
|
||||||
ExternalServiceCredentialGenerator paymentsCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getPaymentsServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
|
||||||
|
|
||||||
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushSchedulerClient, apnSender, accountsManager);
|
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushSchedulerClient, apnSender, accountsManager);
|
||||||
TwilioSmsSender twilioSmsSender = new TwilioSmsSender(config.getTwilioConfiguration());
|
TwilioSmsSender twilioSmsSender = new TwilioSmsSender(config.getTwilioConfiguration());
|
||||||
SmsSender smsSender = new SmsSender(twilioSmsSender);
|
SmsSender smsSender = new SmsSender(twilioSmsSender);
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class SecureStorageClient {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException("Failed to delete storage service data: " + response.statusCode());
|
throw new SecureStorageException("Failed to delete storage service data: " + response.statusCode());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.textsecuregcm.securestorage;
|
||||||
|
|
||||||
|
public class SecureStorageException extends RuntimeException {
|
||||||
|
|
||||||
|
public SecureStorageException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,8 @@ import com.codahale.metrics.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.SharedMetricRegistries;
|
import com.codahale.metrics.SharedMetricRegistries;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.textsecuregcm.util.Constants;
|
import org.whispersystems.textsecuregcm.util.Constants;
|
||||||
import org.whispersystems.textsecuregcm.util.Util;
|
import org.whispersystems.textsecuregcm.util.Util;
|
||||||
|
|
||||||
|
@ -21,6 +23,8 @@ import static com.codahale.metrics.MetricRegistry.name;
|
||||||
|
|
||||||
public class AccountCleaner extends AccountDatabaseCrawlerListener {
|
public class AccountCleaner extends AccountDatabaseCrawlerListener {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AccountCleaner.class);
|
||||||
|
|
||||||
private static final MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME);
|
private static final MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME);
|
||||||
private static final Meter expiredAccountsMeter = metricRegistry.meter(name(AccountCleaner.class, "expiredAccounts"));
|
private static final Meter expiredAccountsMeter = metricRegistry.meter(name(AccountCleaner.class, "expiredAccounts"));
|
||||||
private static final Histogram deletableAccountHistogram = metricRegistry.histogram(name(AccountCleaner.class, "deletableAccountsPerChunk"));
|
private static final Histogram deletableAccountHistogram = metricRegistry.histogram(name(AccountCleaner.class, "deletableAccountsPerChunk"));
|
||||||
|
@ -56,8 +60,12 @@ public class AccountCleaner extends AccountDatabaseCrawlerListener {
|
||||||
expiredAccountsMeter.mark();
|
expiredAccountsMeter.mark();
|
||||||
|
|
||||||
if (accountUpdateCount < MAX_ACCOUNT_UPDATES_PER_CHUNK) {
|
if (accountUpdateCount < MAX_ACCOUNT_UPDATES_PER_CHUNK) {
|
||||||
accountsManager.delete(account, AccountsManager.DeletionReason.EXPIRED);
|
try {
|
||||||
accountUpdateCount++;
|
accountsManager.delete(account, AccountsManager.DeletionReason.EXPIRED);
|
||||||
|
accountUpdateCount++;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.warn("Failed to delete account {}", account.getUuid(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.textsecuregcm.auth.AmbiguousIdentifier;
|
import org.whispersystems.textsecuregcm.auth.AmbiguousIdentifier;
|
||||||
import org.whispersystems.textsecuregcm.entities.ClientContact;
|
import org.whispersystems.textsecuregcm.entities.ClientContact;
|
||||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||||
|
import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient;
|
||||||
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
import org.whispersystems.textsecuregcm.util.Constants;
|
import org.whispersystems.textsecuregcm.util.Constants;
|
||||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||||
|
@ -27,6 +28,7 @@ import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import static com.codahale.metrics.MetricRegistry.name;
|
import static com.codahale.metrics.MetricRegistry.name;
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@ public class AccountsManager {
|
||||||
private final MessagesManager messagesManager;
|
private final MessagesManager messagesManager;
|
||||||
private final UsernamesManager usernamesManager;
|
private final UsernamesManager usernamesManager;
|
||||||
private final ProfilesManager profilesManager;
|
private final ProfilesManager profilesManager;
|
||||||
|
private final SecureStorageClient secureStorageClient;
|
||||||
private final ObjectMapper mapper;
|
private final ObjectMapper mapper;
|
||||||
|
|
||||||
public enum DeletionReason {
|
public enum DeletionReason {
|
||||||
|
@ -73,16 +76,17 @@ public class AccountsManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountsManager(Accounts accounts, DirectoryManager directory, FaultTolerantRedisCluster cacheCluster, final DirectoryQueue directoryQueue, final Keys keys, final MessagesManager messagesManager, final UsernamesManager usernamesManager, final ProfilesManager profilesManager) {
|
public AccountsManager(Accounts accounts, DirectoryManager directory, FaultTolerantRedisCluster cacheCluster, final DirectoryQueue directoryQueue, final Keys keys, final MessagesManager messagesManager, final UsernamesManager usernamesManager, final ProfilesManager profilesManager, final SecureStorageClient secureStorageClient) {
|
||||||
this.accounts = accounts;
|
this.accounts = accounts;
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
this.cacheCluster = cacheCluster;
|
this.cacheCluster = cacheCluster;
|
||||||
this.directoryQueue = directoryQueue;
|
this.directoryQueue = directoryQueue;
|
||||||
this.keys = keys;
|
this.keys = keys;
|
||||||
this.messagesManager = messagesManager;
|
this.messagesManager = messagesManager;
|
||||||
this.usernamesManager = usernamesManager;
|
this.usernamesManager = usernamesManager;
|
||||||
this.profilesManager = profilesManager;
|
this.profilesManager = profilesManager;
|
||||||
this.mapper = SystemMapper.getMapper();
|
this.secureStorageClient = secureStorageClient;
|
||||||
|
this.mapper = SystemMapper.getMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean create(Account account) {
|
public boolean create(Account account) {
|
||||||
|
@ -146,12 +150,17 @@ public class AccountsManager {
|
||||||
|
|
||||||
public void delete(final Account account, final DeletionReason deletionReason) {
|
public void delete(final Account account, final DeletionReason deletionReason) {
|
||||||
try (final Timer.Context ignored = deleteTimer.time()) {
|
try (final Timer.Context ignored = deleteTimer.time()) {
|
||||||
|
final CompletableFuture<Void> deleteStorageServiceDataFuture = secureStorageClient.deleteStoredData(account.getUuid());
|
||||||
|
|
||||||
usernamesManager.delete(account.getUuid());
|
usernamesManager.delete(account.getUuid());
|
||||||
directoryQueue.deleteAccount(account);
|
directoryQueue.deleteAccount(account);
|
||||||
directory.remove(account.getNumber());
|
directory.remove(account.getNumber());
|
||||||
profilesManager.deleteAll(account.getUuid());
|
profilesManager.deleteAll(account.getUuid());
|
||||||
keys.delete(account.getNumber());
|
keys.delete(account.getNumber());
|
||||||
messagesManager.clear(account.getNumber(), account.getUuid());
|
messagesManager.clear(account.getNumber(), account.getUuid());
|
||||||
|
|
||||||
|
deleteStorageServiceDataFuture.join();
|
||||||
|
|
||||||
redisDelete(account);
|
redisDelete(account);
|
||||||
databaseDelete(account);
|
databaseDelete(account);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,12 @@ import org.jdbi.v3.core.Jdbi;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.textsecuregcm.WhisperServerConfiguration;
|
import org.whispersystems.textsecuregcm.WhisperServerConfiguration;
|
||||||
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialGenerator;
|
||||||
import org.whispersystems.textsecuregcm.metrics.PushLatencyManager;
|
import org.whispersystems.textsecuregcm.metrics.PushLatencyManager;
|
||||||
import org.whispersystems.textsecuregcm.providers.RedisClientFactory;
|
import org.whispersystems.textsecuregcm.providers.RedisClientFactory;
|
||||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||||
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
||||||
|
import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient;
|
||||||
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
import org.whispersystems.textsecuregcm.storage.Accounts;
|
import org.whispersystems.textsecuregcm.storage.Accounts;
|
||||||
|
@ -88,6 +90,9 @@ public class DeleteUserCommand extends EnvironmentCommand<WhisperServerConfigura
|
||||||
FaultTolerantRedisCluster cacheCluster = new FaultTolerantRedisCluster("main_cache_cluster", configuration.getCacheClusterConfiguration(), redisClusterClientResources);
|
FaultTolerantRedisCluster cacheCluster = new FaultTolerantRedisCluster("main_cache_cluster", configuration.getCacheClusterConfiguration(), redisClusterClientResources);
|
||||||
|
|
||||||
ExecutorService keyspaceNotificationDispatchExecutor = environment.lifecycle().executorService(name(getClass(), "keyspaceNotification-%d")).maxThreads(4).build();
|
ExecutorService keyspaceNotificationDispatchExecutor = environment.lifecycle().executorService(name(getClass(), "keyspaceNotification-%d")).maxThreads(4).build();
|
||||||
|
ExecutorService storageServiceExecutor = environment.lifecycle().executorService(name(getClass(), "storageService-%d")).maxThreads(8).minThreads(1).build();
|
||||||
|
|
||||||
|
ExternalServiceCredentialGenerator storageCredentialsGenerator = new ExternalServiceCredentialGenerator(configuration.getSecureStorageServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
|
||||||
|
|
||||||
Accounts accounts = new Accounts(accountDatabase);
|
Accounts accounts = new Accounts(accountDatabase);
|
||||||
Usernames usernames = new Usernames(accountDatabase);
|
Usernames usernames = new Usernames(accountDatabase);
|
||||||
|
@ -98,6 +103,7 @@ public class DeleteUserCommand extends EnvironmentCommand<WhisperServerConfigura
|
||||||
ReplicatedJedisPool redisClient = new RedisClientFactory("directory_cache_delete_command", configuration.getDirectoryConfiguration().getRedisConfiguration().getUrl(), configuration.getDirectoryConfiguration().getRedisConfiguration().getReplicaUrls(), configuration.getDirectoryConfiguration().getRedisConfiguration().getCircuitBreakerConfiguration()).getRedisClientPool();
|
ReplicatedJedisPool redisClient = new RedisClientFactory("directory_cache_delete_command", configuration.getDirectoryConfiguration().getRedisConfiguration().getUrl(), configuration.getDirectoryConfiguration().getRedisConfiguration().getReplicaUrls(), configuration.getDirectoryConfiguration().getRedisConfiguration().getCircuitBreakerConfiguration()).getRedisClientPool();
|
||||||
FaultTolerantRedisCluster messagesCacheCluster = new FaultTolerantRedisCluster("messages_cluster", configuration.getMessageCacheConfiguration().getRedisClusterConfiguration(), redisClusterClientResources);
|
FaultTolerantRedisCluster messagesCacheCluster = new FaultTolerantRedisCluster("messages_cluster", configuration.getMessageCacheConfiguration().getRedisClusterConfiguration(), redisClusterClientResources);
|
||||||
FaultTolerantRedisCluster metricsCluster = new FaultTolerantRedisCluster("metrics_cluster", configuration.getMetricsClusterConfiguration(), redisClusterClientResources);
|
FaultTolerantRedisCluster metricsCluster = new FaultTolerantRedisCluster("metrics_cluster", configuration.getMetricsClusterConfiguration(), redisClusterClientResources);
|
||||||
|
SecureStorageClient secureStorageClient = new SecureStorageClient(storageCredentialsGenerator, storageServiceExecutor, configuration.getSecureStorageServiceConfiguration());
|
||||||
MessagesCache messagesCache = new MessagesCache(messagesCacheCluster, keyspaceNotificationDispatchExecutor);
|
MessagesCache messagesCache = new MessagesCache(messagesCacheCluster, keyspaceNotificationDispatchExecutor);
|
||||||
PushLatencyManager pushLatencyManager = new PushLatencyManager(metricsCluster);
|
PushLatencyManager pushLatencyManager = new PushLatencyManager(metricsCluster);
|
||||||
DirectoryQueue directoryQueue = new DirectoryQueue (configuration.getDirectoryConfiguration().getSqsConfiguration());
|
DirectoryQueue directoryQueue = new DirectoryQueue (configuration.getDirectoryConfiguration().getSqsConfiguration());
|
||||||
|
@ -105,7 +111,7 @@ public class DeleteUserCommand extends EnvironmentCommand<WhisperServerConfigura
|
||||||
UsernamesManager usernamesManager = new UsernamesManager(usernames, reservedUsernames, cacheCluster);
|
UsernamesManager usernamesManager = new UsernamesManager(usernames, reservedUsernames, cacheCluster);
|
||||||
ProfilesManager profilesManager = new ProfilesManager(profiles, cacheCluster);
|
ProfilesManager profilesManager = new ProfilesManager(profiles, cacheCluster);
|
||||||
MessagesManager messagesManager = new MessagesManager(messages, messagesCache, pushLatencyManager);
|
MessagesManager messagesManager = new MessagesManager(messages, messagesCache, pushLatencyManager);
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directory, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directory, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
|
|
||||||
for (String user: users) {
|
for (String user: users) {
|
||||||
Optional<Account> account = accountsManager.get(user);
|
Optional<Account> account = accountsManager.get(user);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
||||||
import org.whispersystems.textsecuregcm.configuration.SecureStorageServiceConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.SecureStorageServiceConfiguration;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -25,6 +26,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.delete;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
|
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ -83,6 +85,7 @@ public class SecureStorageClientTest {
|
||||||
.withBasicAuth(username, password)
|
.withBasicAuth(username, password)
|
||||||
.willReturn(aResponse().withStatus(400)));
|
.willReturn(aResponse().withStatus(400)));
|
||||||
|
|
||||||
assertThrows(RuntimeException.class, () -> secureStorageClient.deleteStoredData(accountUuid).join());
|
final CompletionException completionException = assertThrows(CompletionException.class, () -> secureStorageClient.deleteStoredData(accountUuid).join());
|
||||||
|
assertTrue(completionException.getCause() instanceof SecureStorageException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ package org.whispersystems.textsecuregcm.tests.storage;
|
||||||
import io.lettuce.core.RedisException;
|
import io.lettuce.core.RedisException;
|
||||||
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
|
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.whispersystems.textsecuregcm.entities.Profile;
|
|
||||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||||
|
import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient;
|
||||||
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
import org.whispersystems.textsecuregcm.storage.Accounts;
|
import org.whispersystems.textsecuregcm.storage.Accounts;
|
||||||
|
@ -40,22 +40,23 @@ public class AccountsManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAccountByNumberInCache() {
|
public void testGetAccountByNumberInCache() {
|
||||||
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
||||||
Accounts accounts = mock(Accounts.class);
|
Accounts accounts = mock(Accounts.class);
|
||||||
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
||||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
Keys keys = mock(Keys.class);
|
Keys keys = mock(Keys.class);
|
||||||
MessagesManager messagesManager = mock(MessagesManager.class);
|
MessagesManager messagesManager = mock(MessagesManager.class);
|
||||||
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
||||||
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
||||||
|
SecureStorageClient secureStorageClient = mock(SecureStorageClient.class);
|
||||||
|
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
|
|
||||||
when(commands.get(eq("AccountMap::+14152222222"))).thenReturn(uuid.toString());
|
when(commands.get(eq("AccountMap::+14152222222"))).thenReturn(uuid.toString());
|
||||||
when(commands.get(eq("Account3::" + uuid.toString()))).thenReturn("{\"number\": \"+14152222222\", \"name\": \"test\"}");
|
when(commands.get(eq("Account3::" + uuid.toString()))).thenReturn("{\"number\": \"+14152222222\", \"name\": \"test\"}");
|
||||||
|
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
Optional<Account> account = accountsManager.get("+14152222222");
|
Optional<Account> account = accountsManager.get("+14152222222");
|
||||||
|
|
||||||
assertTrue(account.isPresent());
|
assertTrue(account.isPresent());
|
||||||
|
@ -70,21 +71,22 @@ public class AccountsManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAccountByUuidInCache() {
|
public void testGetAccountByUuidInCache() {
|
||||||
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
||||||
Accounts accounts = mock(Accounts.class);
|
Accounts accounts = mock(Accounts.class);
|
||||||
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
||||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
Keys keys = mock(Keys.class);
|
Keys keys = mock(Keys.class);
|
||||||
MessagesManager messagesManager = mock(MessagesManager.class);
|
MessagesManager messagesManager = mock(MessagesManager.class);
|
||||||
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
||||||
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
||||||
|
SecureStorageClient secureStorageClient = mock(SecureStorageClient.class);
|
||||||
|
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
|
|
||||||
when(commands.get(eq("Account3::" + uuid.toString()))).thenReturn("{\"number\": \"+14152222222\", \"name\": \"test\"}");
|
when(commands.get(eq("Account3::" + uuid.toString()))).thenReturn("{\"number\": \"+14152222222\", \"name\": \"test\"}");
|
||||||
|
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
Optional<Account> account = accountsManager.get(uuid);
|
Optional<Account> account = accountsManager.get(uuid);
|
||||||
|
|
||||||
assertTrue(account.isPresent());
|
assertTrue(account.isPresent());
|
||||||
|
@ -100,22 +102,23 @@ public class AccountsManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAccountByNumberNotInCache() {
|
public void testGetAccountByNumberNotInCache() {
|
||||||
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
||||||
Accounts accounts = mock(Accounts.class);
|
Accounts accounts = mock(Accounts.class);
|
||||||
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
||||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
Keys keys = mock(Keys.class);
|
Keys keys = mock(Keys.class);
|
||||||
MessagesManager messagesManager = mock(MessagesManager.class);
|
MessagesManager messagesManager = mock(MessagesManager.class);
|
||||||
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
||||||
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
||||||
|
SecureStorageClient secureStorageClient = mock(SecureStorageClient.class);
|
||||||
|
|
||||||
when(commands.get(eq("AccountMap::+14152222222"))).thenReturn(null);
|
when(commands.get(eq("AccountMap::+14152222222"))).thenReturn(null);
|
||||||
when(accounts.get(eq("+14152222222"))).thenReturn(Optional.of(account));
|
when(accounts.get(eq("+14152222222"))).thenReturn(Optional.of(account));
|
||||||
|
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
Optional<Account> retrieved = accountsManager.get("+14152222222");
|
Optional<Account> retrieved = accountsManager.get("+14152222222");
|
||||||
|
|
||||||
assertTrue(retrieved.isPresent());
|
assertTrue(retrieved.isPresent());
|
||||||
|
@ -132,22 +135,23 @@ public class AccountsManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAccountByUuidNotInCache() {
|
public void testGetAccountByUuidNotInCache() {
|
||||||
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
||||||
Accounts accounts = mock(Accounts.class);
|
Accounts accounts = mock(Accounts.class);
|
||||||
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
||||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
Keys keys = mock(Keys.class);
|
Keys keys = mock(Keys.class);
|
||||||
MessagesManager messagesManager = mock(MessagesManager.class);
|
MessagesManager messagesManager = mock(MessagesManager.class);
|
||||||
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
||||||
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
||||||
|
SecureStorageClient secureStorageClient = mock(SecureStorageClient.class);
|
||||||
|
|
||||||
when(commands.get(eq("Account3::" + uuid))).thenReturn(null);
|
when(commands.get(eq("Account3::" + uuid))).thenReturn(null);
|
||||||
when(accounts.get(eq(uuid))).thenReturn(Optional.of(account));
|
when(accounts.get(eq(uuid))).thenReturn(Optional.of(account));
|
||||||
|
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
Optional<Account> retrieved = accountsManager.get(uuid);
|
Optional<Account> retrieved = accountsManager.get(uuid);
|
||||||
|
|
||||||
assertTrue(retrieved.isPresent());
|
assertTrue(retrieved.isPresent());
|
||||||
|
@ -164,22 +168,23 @@ public class AccountsManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAccountByNumberBrokenCache() {
|
public void testGetAccountByNumberBrokenCache() {
|
||||||
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
||||||
Accounts accounts = mock(Accounts.class);
|
Accounts accounts = mock(Accounts.class);
|
||||||
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
||||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
Keys keys = mock(Keys.class);
|
Keys keys = mock(Keys.class);
|
||||||
MessagesManager messagesManager = mock(MessagesManager.class);
|
MessagesManager messagesManager = mock(MessagesManager.class);
|
||||||
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
||||||
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
||||||
|
SecureStorageClient secureStorageClient = mock(SecureStorageClient.class);
|
||||||
|
|
||||||
when(commands.get(eq("AccountMap::+14152222222"))).thenThrow(new RedisException("Connection lost!"));
|
when(commands.get(eq("AccountMap::+14152222222"))).thenThrow(new RedisException("Connection lost!"));
|
||||||
when(accounts.get(eq("+14152222222"))).thenReturn(Optional.of(account));
|
when(accounts.get(eq("+14152222222"))).thenReturn(Optional.of(account));
|
||||||
|
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
Optional<Account> retrieved = accountsManager.get("+14152222222");
|
Optional<Account> retrieved = accountsManager.get("+14152222222");
|
||||||
|
|
||||||
assertTrue(retrieved.isPresent());
|
assertTrue(retrieved.isPresent());
|
||||||
|
@ -196,22 +201,23 @@ public class AccountsManagerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAccountByUuidBrokenCache() {
|
public void testGetAccountByUuidBrokenCache() {
|
||||||
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
RedisAdvancedClusterCommands<String, String> commands = mock(RedisAdvancedClusterCommands.class);
|
||||||
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
FaultTolerantRedisCluster cacheCluster = RedisClusterHelper.buildMockRedisCluster(commands);
|
||||||
Accounts accounts = mock(Accounts.class);
|
Accounts accounts = mock(Accounts.class);
|
||||||
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
DirectoryManager directoryManager = mock(DirectoryManager.class);
|
||||||
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
Keys keys = mock(Keys.class);
|
Keys keys = mock(Keys.class);
|
||||||
MessagesManager messagesManager = mock(MessagesManager.class);
|
MessagesManager messagesManager = mock(MessagesManager.class);
|
||||||
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
UsernamesManager usernamesManager = mock(UsernamesManager.class);
|
||||||
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
ProfilesManager profilesManager = mock(ProfilesManager.class);
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
Account account = new Account("+14152222222", uuid, new HashSet<>(), new byte[16]);
|
||||||
|
SecureStorageClient secureStorageClient = mock(SecureStorageClient.class);
|
||||||
|
|
||||||
when(commands.get(eq("Account3::" + uuid))).thenThrow(new RedisException("Connection lost!"));
|
when(commands.get(eq("Account3::" + uuid))).thenThrow(new RedisException("Connection lost!"));
|
||||||
when(accounts.get(eq(uuid))).thenReturn(Optional.of(account));
|
when(accounts.get(eq(uuid))).thenReturn(Optional.of(account));
|
||||||
|
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager);
|
AccountsManager accountsManager = new AccountsManager(accounts, directoryManager, cacheCluster, directoryQueue, keys, messagesManager, usernamesManager, profilesManager, secureStorageClient);
|
||||||
Optional<Account> retrieved = accountsManager.get(uuid);
|
Optional<Account> retrieved = accountsManager.get(uuid);
|
||||||
|
|
||||||
assertTrue(retrieved.isPresent());
|
assertTrue(retrieved.isPresent());
|
||||||
|
|
Loading…
Reference in New Issue