Absorb `DeletedAccounts` into `Accounts`

This commit is contained in:
Jon Chambers 2023-09-12 22:27:36 -04:00 committed by Jon Chambers
parent 9945367fa1
commit 1b9bf01ab1
16 changed files with 181 additions and 261 deletions

View File

@ -176,7 +176,6 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.ChangeNumberManager; import org.whispersystems.textsecuregcm.storage.ChangeNumberManager;
import org.whispersystems.textsecuregcm.storage.ClientReleaseManager; import org.whispersystems.textsecuregcm.storage.ClientReleaseManager;
import org.whispersystems.textsecuregcm.storage.ClientReleases; import org.whispersystems.textsecuregcm.storage.ClientReleases;
import org.whispersystems.textsecuregcm.storage.DeletedAccounts;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager; import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager;
import org.whispersystems.textsecuregcm.storage.KeysManager; import org.whispersystems.textsecuregcm.storage.KeysManager;
@ -299,9 +298,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
DynamoDbClient dynamoDbClient = DynamoDbFromConfig.client(config.getDynamoDbClientConfiguration(), DynamoDbClient dynamoDbClient = DynamoDbFromConfig.client(config.getDynamoDbClientConfiguration(),
AWSSDK_CREDENTIALS_PROVIDER); AWSSDK_CREDENTIALS_PROVIDER);
DeletedAccounts deletedAccounts = new DeletedAccounts(dynamoDbClient,
config.getDynamoDbTables().getDeletedAccounts().getTableName());
DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager = DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager =
new DynamicConfigurationManager<>(config.getAppConfig().getApplication(), new DynamicConfigurationManager<>(config.getAppConfig().getApplication(),
config.getAppConfig().getEnvironment(), config.getAppConfig().getEnvironment(),
@ -325,6 +321,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
config.getDynamoDbTables().getAccounts().getPhoneNumberTableName(), config.getDynamoDbTables().getAccounts().getPhoneNumberTableName(),
config.getDynamoDbTables().getAccounts().getPhoneNumberIdentifierTableName(), config.getDynamoDbTables().getAccounts().getPhoneNumberIdentifierTableName(),
config.getDynamoDbTables().getAccounts().getUsernamesTableName(), config.getDynamoDbTables().getAccounts().getUsernamesTableName(),
config.getDynamoDbTables().getDeletedAccounts().getTableName(),
config.getDynamoDbTables().getAccounts().getScanPageSize()); config.getDynamoDbTables().getAccounts().getScanPageSize());
ClientReleases clientReleases = new ClientReleases(dynamoDbAsyncClient, ClientReleases clientReleases = new ClientReleases(dynamoDbAsyncClient,
config.getDynamoDbTables().getClientReleases().getTableName()); config.getDynamoDbTables().getClientReleases().getTableName());
@ -514,7 +511,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
AccountLockManager accountLockManager = new AccountLockManager(dynamoDbClient, AccountLockManager accountLockManager = new AccountLockManager(dynamoDbClient,
config.getDynamoDbTables().getDeletedAccountsLock().getTableName()); config.getDynamoDbTables().getDeletedAccountsLock().getTableName());
AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster, AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster,
accountLockManager, deletedAccounts, keys, messagesManager, profilesManager, accountLockManager, keys, messagesManager, profilesManager,
secureStorageClient, secureBackupClient, secureValueRecovery2Client, secureStorageClient, secureBackupClient, secureValueRecovery2Client,
clientPresenceManager, clientPresenceManager,
experimentEnrollmentManager, registrationRecoveryPasswordsManager, clock); experimentEnrollmentManager, registrationRecoveryPasswordsManager, clock);
@ -764,7 +761,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
new DonationController(clock, zkReceiptOperations, redeemedReceiptsManager, accountsManager, config.getBadges(), new DonationController(clock, zkReceiptOperations, redeemedReceiptsManager, accountsManager, config.getBadges(),
ReceiptCredentialPresentation::new), ReceiptCredentialPresentation::new),
new MessageController(rateLimiters, messageByteLimitCardinalityEstimator, messageSender, receiptSender, new MessageController(rateLimiters, messageByteLimitCardinalityEstimator, messageSender, receiptSender,
accountsManager, deletedAccounts, messagesManager, pushNotificationManager, reportMessageManager, accountsManager, messagesManager, pushNotificationManager, reportMessageManager,
multiRecipientMessageExecutor, messageDeliveryScheduler, reportSpamTokenProvider, clientReleaseManager, multiRecipientMessageExecutor, messageDeliveryScheduler, reportSpamTokenProvider, clientReleaseManager,
dynamicConfigurationManager), dynamicConfigurationManager),
new PaymentsController(currencyManager, paymentsCredentialsGenerator), new PaymentsController(currencyManager, paymentsCredentialsGenerator),

View File

@ -99,7 +99,6 @@ import org.whispersystems.textsecuregcm.spam.ReportSpamTokenProvider;
import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.ClientReleaseManager; import org.whispersystems.textsecuregcm.storage.ClientReleaseManager;
import org.whispersystems.textsecuregcm.storage.DeletedAccounts;
import org.whispersystems.textsecuregcm.storage.Device; import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.MessagesManager; import org.whispersystems.textsecuregcm.storage.MessagesManager;
@ -123,7 +122,6 @@ public class MessageController {
private final MessageSender messageSender; private final MessageSender messageSender;
private final ReceiptSender receiptSender; private final ReceiptSender receiptSender;
private final AccountsManager accountsManager; private final AccountsManager accountsManager;
private final DeletedAccounts deletedAccounts;
private final MessagesManager messagesManager; private final MessagesManager messagesManager;
private final PushNotificationManager pushNotificationManager; private final PushNotificationManager pushNotificationManager;
private final ReportMessageManager reportMessageManager; private final ReportMessageManager reportMessageManager;
@ -159,7 +157,6 @@ public class MessageController {
MessageSender messageSender, MessageSender messageSender,
ReceiptSender receiptSender, ReceiptSender receiptSender,
AccountsManager accountsManager, AccountsManager accountsManager,
DeletedAccounts deletedAccounts,
MessagesManager messagesManager, MessagesManager messagesManager,
PushNotificationManager pushNotificationManager, PushNotificationManager pushNotificationManager,
ReportMessageManager reportMessageManager, ReportMessageManager reportMessageManager,
@ -173,7 +170,6 @@ public class MessageController {
this.messageSender = messageSender; this.messageSender = messageSender;
this.receiptSender = receiptSender; this.receiptSender = receiptSender;
this.accountsManager = accountsManager; this.accountsManager = accountsManager;
this.deletedAccounts = deletedAccounts;
this.messagesManager = messagesManager; this.messagesManager = messagesManager;
this.pushNotificationManager = pushNotificationManager; this.pushNotificationManager = pushNotificationManager;
this.reportMessageManager = reportMessageManager; this.reportMessageManager = reportMessageManager;
@ -628,7 +624,7 @@ public class MessageController {
sourceAci = maybeAccount.map(Account::getUuid); sourceAci = maybeAccount.map(Account::getUuid);
sourcePni = maybeAccount.map(Account::getPhoneNumberIdentifier); sourcePni = maybeAccount.map(Account::getPhoneNumberIdentifier);
} else { } else {
sourceAci = deletedAccounts.findUuid(source); sourceAci = accountsManager.findRecentlyDeletedAccountIdentifier(source);
sourcePni = Optional.ofNullable(accountsManager.getPhoneNumberIdentifier(source)); sourcePni = Optional.ofNullable(accountsManager.getPhoneNumberIdentifier(source));
} }
} else { } else {
@ -638,7 +634,7 @@ public class MessageController {
if (sourceAccount.isEmpty()) { if (sourceAccount.isEmpty()) {
logger.warn("Could not find source: {}", sourceAci.get()); logger.warn("Could not find source: {}", sourceAci.get());
sourceNumber = deletedAccounts.findE164(sourceAci.get()); sourceNumber = accountsManager.findRecentlyDeletedE164(sourceAci.get());
sourcePni = sourceNumber.map(accountsManager::getPhoneNumberIdentifier); sourcePni = sourceNumber.map(accountsManager::getPhoneNumberIdentifier);
} else { } else {
sourceNumber = sourceAccount.map(Account::getNumber); sourceNumber = sourceAccount.map(Account::getNumber);

View File

@ -15,10 +15,12 @@ public class AccountLockManager {
private final AmazonDynamoDBLockClient lockClient; private final AmazonDynamoDBLockClient lockClient;
static final String KEY_ACCOUNT_E164 = "P";
public AccountLockManager(final DynamoDbClient lockDynamoDb, final String lockTableName) { public AccountLockManager(final DynamoDbClient lockDynamoDb, final String lockTableName) {
this(new AmazonDynamoDBLockClient( this(new AmazonDynamoDBLockClient(
AmazonDynamoDBLockClientOptions.builder(lockDynamoDb, lockTableName) AmazonDynamoDBLockClientOptions.builder(lockDynamoDb, lockTableName)
.withPartitionKeyName(DeletedAccounts.KEY_ACCOUNT_E164) .withPartitionKeyName(KEY_ACCOUNT_E164)
.withLeaseDuration(15L) .withLeaseDuration(15L)
.withHeartbeatPeriod(2L) .withHeartbeatPeriod(2L)
.withTimeUnit(TimeUnit.SECONDS) .withTimeUnit(TimeUnit.SECONDS)

View File

@ -17,6 +17,7 @@ import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.time.Clock; import java.time.Clock;
import java.time.Duration; import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -48,9 +49,11 @@ import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.CancellationReason; import software.amazon.awssdk.services.dynamodb.model.CancellationReason;
import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.awssdk.services.dynamodb.model.Delete; import software.amazon.awssdk.services.dynamodb.model.Delete;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
import software.amazon.awssdk.services.dynamodb.model.Put; import software.amazon.awssdk.services.dynamodb.model.Put;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest; import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse; import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure;
@ -124,18 +127,23 @@ public class Accounts extends AbstractDynamoDbStore {
// time to live; number // time to live; number
static final String ATTR_TTL = "TTL"; static final String ATTR_TTL = "TTL";
static final String DELETED_ACCOUNTS_KEY_ACCOUNT_E164 = "P";
static final String DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID = "U";
static final String DELETED_ACCOUNTS_ATTR_EXPIRES = "E";
static final String DELETED_ACCOUNTS_UUID_TO_E164_INDEX_NAME = "u_to_p";
static final String USERNAME_LINK_TO_UUID_INDEX = "ul_to_u"; static final String USERNAME_LINK_TO_UUID_INDEX = "ul_to_u";
static final Duration DELETED_ACCOUNTS_TIME_TO_LIVE = Duration.ofDays(30);
private final Clock clock; private final Clock clock;
private final DynamoDbAsyncClient asyncClient; private final DynamoDbAsyncClient asyncClient;
private final String phoneNumberConstraintTableName; private final String phoneNumberConstraintTableName;
private final String phoneNumberIdentifierConstraintTableName; private final String phoneNumberIdentifierConstraintTableName;
private final String usernamesConstraintTableName; private final String usernamesConstraintTableName;
private final String deletedAccountsTableName;
private final String accountsTableName; private final String accountsTableName;
private final int scanPageSize; private final int scanPageSize;
@ -150,6 +158,7 @@ public class Accounts extends AbstractDynamoDbStore {
final String phoneNumberConstraintTableName, final String phoneNumberConstraintTableName,
final String phoneNumberIdentifierConstraintTableName, final String phoneNumberIdentifierConstraintTableName,
final String usernamesConstraintTableName, final String usernamesConstraintTableName,
final String deletedAccountsTableName,
final int scanPageSize) { final int scanPageSize) {
super(client); super(client);
this.clock = clock; this.clock = clock;
@ -158,6 +167,7 @@ public class Accounts extends AbstractDynamoDbStore {
this.phoneNumberIdentifierConstraintTableName = phoneNumberIdentifierConstraintTableName; this.phoneNumberIdentifierConstraintTableName = phoneNumberIdentifierConstraintTableName;
this.accountsTableName = accountsTableName; this.accountsTableName = accountsTableName;
this.usernamesConstraintTableName = usernamesConstraintTableName; this.usernamesConstraintTableName = usernamesConstraintTableName;
this.deletedAccountsTableName = deletedAccountsTableName;
this.scanPageSize = scanPageSize; this.scanPageSize = scanPageSize;
} }
@ -168,10 +178,11 @@ public class Accounts extends AbstractDynamoDbStore {
final String phoneNumberConstraintTableName, final String phoneNumberConstraintTableName,
final String phoneNumberIdentifierConstraintTableName, final String phoneNumberIdentifierConstraintTableName,
final String usernamesConstraintTableName, final String usernamesConstraintTableName,
final String deletedAccountsTableName,
final int scanPageSize) { final int scanPageSize) {
this(Clock.systemUTC(), client, asyncClient, accountsTableName, this(Clock.systemUTC(), client, asyncClient, accountsTableName,
phoneNumberConstraintTableName, phoneNumberIdentifierConstraintTableName, usernamesConstraintTableName, phoneNumberConstraintTableName, phoneNumberIdentifierConstraintTableName, usernamesConstraintTableName,
scanPageSize); deletedAccountsTableName, scanPageSize);
} }
public boolean create(final Account account) { public boolean create(final Account account) {
@ -706,6 +717,23 @@ public class Accounts extends AbstractDynamoDbStore {
.map(Accounts::fromItem))); .map(Accounts::fromItem)));
} }
public void putRecentlyDeletedAccount(final UUID uuid, final String e164) {
db().putItem(PutItemRequest.builder()
.tableName(deletedAccountsTableName)
.item(Map.of(
DELETED_ACCOUNTS_KEY_ACCOUNT_E164, AttributeValues.fromString(e164),
DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID, AttributeValues.fromUUID(uuid),
DELETED_ACCOUNTS_ATTR_EXPIRES, AttributeValues.fromLong(Instant.now().plus(DELETED_ACCOUNTS_TIME_TO_LIVE).getEpochSecond())))
.build());
}
public void removeRecentlyDeletedAccount(final String e164) {
db().deleteItem(DeleteItemRequest.builder()
.tableName(deletedAccountsTableName)
.key(Map.of(DELETED_ACCOUNTS_KEY_ACCOUNT_E164, AttributeValues.fromString(e164)))
.build());
}
@Nonnull @Nonnull
public CompletableFuture<Optional<Account>> getByAccountIdentifierAsync(final UUID uuid) { public CompletableFuture<Optional<Account>> getByAccountIdentifierAsync(final UUID uuid) {
return AsyncTimerUtil.record(GET_BY_UUID_TIMER, () -> itemByKeyAsync(accountsTableName, KEY_ACCOUNT_UUID, AttributeValues.fromUUID(uuid)) return AsyncTimerUtil.record(GET_BY_UUID_TIMER, () -> itemByKeyAsync(accountsTableName, KEY_ACCOUNT_UUID, AttributeValues.fromUUID(uuid))
@ -713,6 +741,37 @@ public class Accounts extends AbstractDynamoDbStore {
.toCompletableFuture(); .toCompletableFuture();
} }
public Optional<UUID> findRecentlyDeletedAccountIdentifier(final String e164) {
final GetItemResponse response = db().getItem(GetItemRequest.builder()
.tableName(deletedAccountsTableName)
.consistentRead(true)
.key(Map.of(DELETED_ACCOUNTS_KEY_ACCOUNT_E164, AttributeValues.fromString(e164)))
.build());
return Optional.ofNullable(AttributeValues.getUUID(response.item(), DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID, null));
}
public Optional<String> findRecentlyDeletedE164(final UUID uuid) {
final QueryResponse response = db().query(QueryRequest.builder()
.tableName(deletedAccountsTableName)
.indexName(DELETED_ACCOUNTS_UUID_TO_E164_INDEX_NAME)
.keyConditionExpression("#uuid = :uuid")
.projectionExpression("#e164")
.expressionAttributeNames(Map.of("#uuid", DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID,
"#e164", DELETED_ACCOUNTS_KEY_ACCOUNT_E164))
.expressionAttributeValues(Map.of(":uuid", AttributeValues.fromUUID(uuid))).build());
if (response.count() == 0) {
return Optional.empty();
}
if (response.count() > 1) {
throw new RuntimeException("Impossible result: more than one phone number returned for UUID: " + uuid);
}
return Optional.ofNullable(response.items().get(0).get(DELETED_ACCOUNTS_KEY_ACCOUNT_E164).s());
}
public void delete(final UUID uuid) { public void delete(final UUID uuid) {
DELETE_TIMER.record(() -> getByAccountIdentifier(uuid).ifPresent(account -> { DELETE_TIMER.record(() -> getByAccountIdentifier(uuid).ifPresent(account -> {

View File

@ -101,7 +101,6 @@ public class AccountsManager {
private final PhoneNumberIdentifiers phoneNumberIdentifiers; private final PhoneNumberIdentifiers phoneNumberIdentifiers;
private final FaultTolerantRedisCluster cacheCluster; private final FaultTolerantRedisCluster cacheCluster;
private final AccountLockManager accountLockManager; private final AccountLockManager accountLockManager;
private final DeletedAccounts deletedAccounts;
private final KeysManager keysManager; private final KeysManager keysManager;
private final MessagesManager messagesManager; private final MessagesManager messagesManager;
private final ProfilesManager profilesManager; private final ProfilesManager profilesManager;
@ -147,7 +146,6 @@ public class AccountsManager {
final PhoneNumberIdentifiers phoneNumberIdentifiers, final PhoneNumberIdentifiers phoneNumberIdentifiers,
final FaultTolerantRedisCluster cacheCluster, final FaultTolerantRedisCluster cacheCluster,
final AccountLockManager accountLockManager, final AccountLockManager accountLockManager,
final DeletedAccounts deletedAccounts,
final KeysManager keysManager, final KeysManager keysManager,
final MessagesManager messagesManager, final MessagesManager messagesManager,
final ProfilesManager profilesManager, final ProfilesManager profilesManager,
@ -162,7 +160,6 @@ public class AccountsManager {
this.phoneNumberIdentifiers = phoneNumberIdentifiers; this.phoneNumberIdentifiers = phoneNumberIdentifiers;
this.cacheCluster = cacheCluster; this.cacheCluster = cacheCluster;
this.accountLockManager = accountLockManager; this.accountLockManager = accountLockManager;
this.deletedAccounts = deletedAccounts;
this.keysManager = keysManager; this.keysManager = keysManager;
this.messagesManager = messagesManager; this.messagesManager = messagesManager;
this.profilesManager = profilesManager; this.profilesManager = profilesManager;
@ -201,7 +198,7 @@ public class AccountsManager {
// Reuse the ACI from any recently-deleted account with this number to cover cases where somebody is // Reuse the ACI from any recently-deleted account with this number to cover cases where somebody is
// re-registering. // re-registering.
account.setUuid(deletedAccounts.findUuid(number).orElseGet(UUID::randomUUID)); account.setUuid(accounts.findRecentlyDeletedAccountIdentifier(number).orElseGet(UUID::randomUUID));
account.addDevice(device); account.addDevice(device);
account.setRegistrationLockFromAttributes(accountAttributes); account.setRegistrationLockFromAttributes(accountAttributes);
account.setUnidentifiedAccessKey(accountAttributes.getUnidentifiedAccessKey()); account.setUnidentifiedAccessKey(accountAttributes.getUnidentifiedAccessKey());
@ -261,7 +258,7 @@ public class AccountsManager {
// Clear any "recently deleted account" record for this number since, if it existed, we've used its old ACI for // Clear any "recently deleted account" record for this number since, if it existed, we've used its old ACI for
// the newly-created account. // the newly-created account.
deletedAccounts.remove(number); accounts.removeRecentlyDeletedAccount(number);
}); });
return account; return account;
@ -303,7 +300,7 @@ public class AccountsManager {
// of the account changing its number (which facilitates ACI consistency in cases that a party is switching // of the account changing its number (which facilitates ACI consistency in cases that a party is switching
// back and forth between numbers). // back and forth between numbers).
// 3. No account with the target number exists at all, in which case no additional action is needed. // 3. No account with the target number exists at all, in which case no additional action is needed.
final Optional<UUID> recentlyDeletedAci = deletedAccounts.findUuid(targetNumber); final Optional<UUID> recentlyDeletedAci = accounts.findRecentlyDeletedAccountIdentifier(targetNumber);
final Optional<Account> maybeExistingAccount = getByE164(targetNumber); final Optional<Account> maybeExistingAccount = getByE164(targetNumber);
final Optional<UUID> maybeDisplacedUuid; final Optional<UUID> maybeDisplacedUuid;
@ -314,7 +311,7 @@ public class AccountsManager {
maybeDisplacedUuid = recentlyDeletedAci; maybeDisplacedUuid = recentlyDeletedAci;
} }
maybeDisplacedUuid.ifPresent(displacedUuid -> deletedAccounts.put(displacedUuid, originalNumber)); maybeDisplacedUuid.ifPresent(displacedUuid -> accounts.putRecentlyDeletedAccount(displacedUuid, originalNumber));
final UUID uuid = account.getUuid(); final UUID uuid = account.getUuid();
final UUID phoneNumberIdentifier = phoneNumberIdentifiers.getPhoneNumberIdentifier(targetNumber); final UUID phoneNumberIdentifier = phoneNumberIdentifiers.getPhoneNumberIdentifier(targetNumber);
@ -836,6 +833,14 @@ public class AccountsManager {
return phoneNumberIdentifiers.getPhoneNumberIdentifier(e164); return phoneNumberIdentifiers.getPhoneNumberIdentifier(e164);
} }
public Optional<UUID> findRecentlyDeletedAccountIdentifier(final String e164) {
return accounts.findRecentlyDeletedAccountIdentifier(e164);
}
public Optional<String> findRecentlyDeletedE164(final UUID uuid) {
return accounts.findRecentlyDeletedE164(uuid);
}
public AccountCrawlChunk getAllFromDynamo(int length) { public AccountCrawlChunk getAllFromDynamo(int length) {
return accounts.getAllFromStart(length); return accounts.getAllFromStart(length);
} }
@ -856,7 +861,7 @@ public class AccountsManager {
delete(account); delete(account);
deletedAccounts.put(accountIdentifier, e164); accounts.putRecentlyDeletedAccount(accountIdentifier, e164);
}); });
} catch (final RuntimeException | InterruptedException e) { } catch (final RuntimeException | InterruptedException e) {
logger.warn("Failed to delete account", e); logger.warn("Failed to delete account", e);

View File

@ -1,87 +0,0 @@
/*
* Copyright 2013-2021 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.storage;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.whispersystems.textsecuregcm.util.AttributeValues;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
public class DeletedAccounts {
// e164, primary key
static final String KEY_ACCOUNT_E164 = "P";
static final String ATTR_ACCOUNT_UUID = "U";
static final String ATTR_EXPIRES = "E";
static final String UUID_TO_E164_INDEX_NAME = "u_to_p";
static final Duration TIME_TO_LIVE = Duration.ofDays(30);
private final DynamoDbClient dynamoDbClient;
private final String tableName;
public DeletedAccounts(final DynamoDbClient dynamoDbClient, final String tableName) {
this.dynamoDbClient = dynamoDbClient;
this.tableName = tableName;
}
public void put(UUID uuid, String e164) {
dynamoDbClient.putItem(PutItemRequest.builder()
.tableName(tableName)
.item(Map.of(
KEY_ACCOUNT_E164, AttributeValues.fromString(e164),
ATTR_ACCOUNT_UUID, AttributeValues.fromUUID(uuid),
ATTR_EXPIRES, AttributeValues.fromLong(Instant.now().plus(TIME_TO_LIVE).getEpochSecond())))
.build());
}
public Optional<UUID> findUuid(final String e164) {
final GetItemResponse response = dynamoDbClient.getItem(GetItemRequest.builder()
.tableName(tableName)
.consistentRead(true)
.key(Map.of(KEY_ACCOUNT_E164, AttributeValues.fromString(e164)))
.build());
return Optional.ofNullable(AttributeValues.getUUID(response.item(), ATTR_ACCOUNT_UUID, null));
}
public Optional<String> findE164(final UUID uuid) {
final QueryResponse response = dynamoDbClient.query(QueryRequest.builder()
.tableName(tableName)
.indexName(UUID_TO_E164_INDEX_NAME)
.keyConditionExpression("#uuid = :uuid")
.projectionExpression("#e164")
.expressionAttributeNames(Map.of("#uuid", ATTR_ACCOUNT_UUID,
"#e164", KEY_ACCOUNT_E164))
.expressionAttributeValues(Map.of(":uuid", AttributeValues.fromUUID(uuid))).build());
if (response.count() == 0) {
return Optional.empty();
}
if (response.count() > 1) {
throw new RuntimeException("Impossible result: more than one phone number returned for UUID: " + uuid);
}
return Optional.ofNullable(response.items().get(0).get(KEY_ACCOUNT_E164).s());
}
public void remove(final String e164) {
dynamoDbClient.deleteItem(DeleteItemRequest.builder()
.tableName(tableName)
.key(Map.of(KEY_ACCOUNT_E164, AttributeValues.fromString(e164)))
.build());
}
}

View File

@ -38,7 +38,6 @@ import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountLockManager; import org.whispersystems.textsecuregcm.storage.AccountLockManager;
import org.whispersystems.textsecuregcm.storage.Accounts; import org.whispersystems.textsecuregcm.storage.Accounts;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.DeletedAccounts;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.KeysManager; import org.whispersystems.textsecuregcm.storage.KeysManager;
import org.whispersystems.textsecuregcm.storage.MessagesCache; import org.whispersystems.textsecuregcm.storage.MessagesCache;
@ -141,8 +140,6 @@ public class AssignUsernameCommand extends EnvironmentCommand<WhisperServerConfi
DynamoDbClient dynamoDbClient = DynamoDbFromConfig.client(configuration.getDynamoDbClientConfiguration(), DynamoDbClient dynamoDbClient = DynamoDbFromConfig.client(configuration.getDynamoDbClientConfiguration(),
WhisperServerService.AWSSDK_CREDENTIALS_PROVIDER); WhisperServerService.AWSSDK_CREDENTIALS_PROVIDER);
DeletedAccounts deletedAccounts = new DeletedAccounts(dynamoDbClient,
configuration.getDynamoDbTables().getDeletedAccounts().getTableName());
RegistrationRecoveryPasswords registrationRecoveryPasswords = new RegistrationRecoveryPasswords( RegistrationRecoveryPasswords registrationRecoveryPasswords = new RegistrationRecoveryPasswords(
configuration.getDynamoDbTables().getRegistrationRecovery().getTableName(), configuration.getDynamoDbTables().getRegistrationRecovery().getTableName(),
configuration.getDynamoDbTables().getRegistrationRecovery().getExpiration(), configuration.getDynamoDbTables().getRegistrationRecovery().getExpiration(),
@ -159,6 +156,7 @@ public class AssignUsernameCommand extends EnvironmentCommand<WhisperServerConfi
configuration.getDynamoDbTables().getAccounts().getPhoneNumberTableName(), configuration.getDynamoDbTables().getAccounts().getPhoneNumberTableName(),
configuration.getDynamoDbTables().getAccounts().getPhoneNumberIdentifierTableName(), configuration.getDynamoDbTables().getAccounts().getPhoneNumberIdentifierTableName(),
configuration.getDynamoDbTables().getAccounts().getUsernamesTableName(), configuration.getDynamoDbTables().getAccounts().getUsernamesTableName(),
configuration.getDynamoDbTables().getDeletedAccounts().getTableName(),
configuration.getDynamoDbTables().getAccounts().getScanPageSize()); configuration.getDynamoDbTables().getAccounts().getScanPageSize());
PhoneNumberIdentifiers phoneNumberIdentifiers = new PhoneNumberIdentifiers(dynamoDbClient, PhoneNumberIdentifiers phoneNumberIdentifiers = new PhoneNumberIdentifiers(dynamoDbClient,
configuration.getDynamoDbTables().getPhoneNumberIdentifiers().getTableName()); configuration.getDynamoDbTables().getPhoneNumberIdentifiers().getTableName());
@ -206,7 +204,7 @@ public class AssignUsernameCommand extends EnvironmentCommand<WhisperServerConfi
AccountLockManager accountLockManager = new AccountLockManager(dynamoDbClient, AccountLockManager accountLockManager = new AccountLockManager(dynamoDbClient,
configuration.getDynamoDbTables().getDeletedAccountsLock().getTableName()); configuration.getDynamoDbTables().getDeletedAccountsLock().getTableName());
AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster, AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster,
accountLockManager, deletedAccounts, keys, messagesManager, profilesManager, accountLockManager, keys, messagesManager, profilesManager,
secureStorageClient, secureBackupClient, secureValueRecovery2Client, clientPresenceManager, secureStorageClient, secureBackupClient, secureValueRecovery2Client, clientPresenceManager,
experimentEnrollmentManager, registrationRecoveryPasswordsManager, Clock.systemUTC()); experimentEnrollmentManager, registrationRecoveryPasswordsManager, Clock.systemUTC());

View File

@ -31,7 +31,6 @@ import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2
import org.whispersystems.textsecuregcm.storage.AccountLockManager; import org.whispersystems.textsecuregcm.storage.AccountLockManager;
import org.whispersystems.textsecuregcm.storage.Accounts; import org.whispersystems.textsecuregcm.storage.Accounts;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.DeletedAccounts;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.KeysManager; import org.whispersystems.textsecuregcm.storage.KeysManager;
import org.whispersystems.textsecuregcm.storage.MessagesCache; import org.whispersystems.textsecuregcm.storage.MessagesCache;
@ -117,8 +116,6 @@ record CommandDependencies(
DynamoDbClient dynamoDbClient = DynamoDbFromConfig.client( DynamoDbClient dynamoDbClient = DynamoDbFromConfig.client(
configuration.getDynamoDbClientConfiguration(), WhisperServerService.AWSSDK_CREDENTIALS_PROVIDER); configuration.getDynamoDbClientConfiguration(), WhisperServerService.AWSSDK_CREDENTIALS_PROVIDER);
DeletedAccounts deletedAccounts = new DeletedAccounts(dynamoDbClient,
configuration.getDynamoDbTables().getDeletedAccounts().getTableName());
RegistrationRecoveryPasswords registrationRecoveryPasswords = new RegistrationRecoveryPasswords( RegistrationRecoveryPasswords registrationRecoveryPasswords = new RegistrationRecoveryPasswords(
configuration.getDynamoDbTables().getRegistrationRecovery().getTableName(), configuration.getDynamoDbTables().getRegistrationRecovery().getTableName(),
configuration.getDynamoDbTables().getRegistrationRecovery().getExpiration(), configuration.getDynamoDbTables().getRegistrationRecovery().getExpiration(),
@ -136,6 +133,7 @@ record CommandDependencies(
configuration.getDynamoDbTables().getAccounts().getPhoneNumberTableName(), configuration.getDynamoDbTables().getAccounts().getPhoneNumberTableName(),
configuration.getDynamoDbTables().getAccounts().getPhoneNumberIdentifierTableName(), configuration.getDynamoDbTables().getAccounts().getPhoneNumberIdentifierTableName(),
configuration.getDynamoDbTables().getAccounts().getUsernamesTableName(), configuration.getDynamoDbTables().getAccounts().getUsernamesTableName(),
configuration.getDynamoDbTables().getDeletedAccounts().getTableName(),
configuration.getDynamoDbTables().getAccounts().getScanPageSize()); configuration.getDynamoDbTables().getAccounts().getScanPageSize());
PhoneNumberIdentifiers phoneNumberIdentifiers = new PhoneNumberIdentifiers(dynamoDbClient, PhoneNumberIdentifiers phoneNumberIdentifiers = new PhoneNumberIdentifiers(dynamoDbClient,
configuration.getDynamoDbTables().getPhoneNumberIdentifiers().getTableName()); configuration.getDynamoDbTables().getPhoneNumberIdentifiers().getTableName());
@ -184,7 +182,7 @@ record CommandDependencies(
AccountLockManager accountLockManager = new AccountLockManager(dynamoDbClient, AccountLockManager accountLockManager = new AccountLockManager(dynamoDbClient,
configuration.getDynamoDbTables().getDeletedAccountsLock().getTableName()); configuration.getDynamoDbTables().getDeletedAccountsLock().getTableName());
AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster, AccountsManager accountsManager = new AccountsManager(accounts, phoneNumberIdentifiers, cacheCluster,
accountLockManager, deletedAccounts, keys, messagesManager, profilesManager, accountLockManager, keys, messagesManager, profilesManager,
secureStorageClient, secureBackupClient, secureValueRecovery2Client, secureStorageClient, secureBackupClient, secureValueRecovery2Client,
clientPresenceManager, clientPresenceManager,
experimentEnrollmentManager, registrationRecoveryPasswordsManager, clock); experimentEnrollmentManager, registrationRecoveryPasswordsManager, clock);

View File

@ -113,7 +113,6 @@ import org.whispersystems.textsecuregcm.spam.ReportSpamTokenProvider;
import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.ClientReleaseManager; import org.whispersystems.textsecuregcm.storage.ClientReleaseManager;
import org.whispersystems.textsecuregcm.storage.DeletedAccounts;
import org.whispersystems.textsecuregcm.storage.Device; import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.MessagesManager; import org.whispersystems.textsecuregcm.storage.MessagesManager;
@ -159,7 +158,6 @@ class MessageControllerTest {
private static final MessageSender messageSender = mock(MessageSender.class); private static final MessageSender messageSender = mock(MessageSender.class);
private static final ReceiptSender receiptSender = mock(ReceiptSender.class); private static final ReceiptSender receiptSender = mock(ReceiptSender.class);
private static final AccountsManager accountsManager = mock(AccountsManager.class); private static final AccountsManager accountsManager = mock(AccountsManager.class);
private static final DeletedAccounts deletedAccounts = mock(DeletedAccounts.class);
private static final MessagesManager messagesManager = mock(MessagesManager.class); private static final MessagesManager messagesManager = mock(MessagesManager.class);
private static final RateLimiters rateLimiters = mock(RateLimiters.class); private static final RateLimiters rateLimiters = mock(RateLimiters.class);
private static final CardinalityEstimator cardinalityEstimator = mock(CardinalityEstimator.class); private static final CardinalityEstimator cardinalityEstimator = mock(CardinalityEstimator.class);
@ -179,7 +177,7 @@ class MessageControllerTest {
.addProvider(MultiRecipientMessageProvider.class) .addProvider(MultiRecipientMessageProvider.class)
.setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addResource( .addResource(
new MessageController(rateLimiters, cardinalityEstimator, messageSender, receiptSender, accountsManager, deletedAccounts, new MessageController(rateLimiters, cardinalityEstimator, messageSender, receiptSender, accountsManager,
messagesManager, pushNotificationManager, reportMessageManager, multiRecipientMessageExecutor, messagesManager, pushNotificationManager, reportMessageManager, multiRecipientMessageExecutor,
messageDeliveryScheduler, ReportSpamTokenProvider.noop(), mock(ClientReleaseManager.class), dynamicConfigurationManager)) messageDeliveryScheduler, ReportSpamTokenProvider.noop(), mock(ClientReleaseManager.class), dynamicConfigurationManager))
.build(); .build();
@ -245,7 +243,6 @@ class MessageControllerTest {
messageSender, messageSender,
receiptSender, receiptSender,
accountsManager, accountsManager,
deletedAccounts,
messagesManager, messagesManager,
rateLimiters, rateLimiters,
rateLimiter, rateLimiter,
@ -681,7 +678,7 @@ class MessageControllerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(senderPni); when(account.getPhoneNumberIdentifier()).thenReturn(senderPni);
when(accountsManager.getByE164(senderNumber)).thenReturn(Optional.of(account)); when(accountsManager.getByE164(senderNumber)).thenReturn(Optional.of(account));
when(deletedAccounts.findUuid(senderNumber)).thenReturn(Optional.of(senderAci)); when(accountsManager.findRecentlyDeletedAccountIdentifier(senderNumber)).thenReturn(Optional.of(senderAci));
when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni); when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni);
Response response = Response response =
@ -696,7 +693,7 @@ class MessageControllerTest {
verify(reportMessageManager).report(Optional.of(senderNumber), Optional.of(senderAci), Optional.of(senderPni), verify(reportMessageManager).report(Optional.of(senderNumber), Optional.of(senderAci), Optional.of(senderPni),
messageGuid, AuthHelper.VALID_UUID, Optional.empty(), userAgent); messageGuid, AuthHelper.VALID_UUID, Optional.empty(), userAgent);
verify(deletedAccounts, never()).findE164(any(UUID.class)); verify(accountsManager, never()).findRecentlyDeletedE164(any(UUID.class));
verify(accountsManager, never()).getPhoneNumberIdentifier(anyString()); verify(accountsManager, never()).getPhoneNumberIdentifier(anyString());
when(accountsManager.getByE164(senderNumber)).thenReturn(Optional.empty()); when(accountsManager.getByE164(senderNumber)).thenReturn(Optional.empty());
@ -731,7 +728,7 @@ class MessageControllerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(senderPni); when(account.getPhoneNumberIdentifier()).thenReturn(senderPni);
when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.of(account)); when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.of(account));
when(deletedAccounts.findE164(senderAci)).thenReturn(Optional.of(senderNumber)); when(accountsManager.findRecentlyDeletedE164(senderAci)).thenReturn(Optional.of(senderNumber));
when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni); when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni);
Response response = Response response =
@ -746,7 +743,7 @@ class MessageControllerTest {
verify(reportMessageManager).report(Optional.of(senderNumber), Optional.of(senderAci), Optional.of(senderPni), verify(reportMessageManager).report(Optional.of(senderNumber), Optional.of(senderAci), Optional.of(senderPni),
messageGuid, AuthHelper.VALID_UUID, Optional.empty(), userAgent); messageGuid, AuthHelper.VALID_UUID, Optional.empty(), userAgent);
verify(deletedAccounts, never()).findE164(any(UUID.class)); verify(accountsManager, never()).findRecentlyDeletedE164(any(UUID.class));
verify(accountsManager, never()).getPhoneNumberIdentifier(anyString()); verify(accountsManager, never()).getPhoneNumberIdentifier(anyString());
when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.empty()); when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.empty());
@ -781,7 +778,7 @@ class MessageControllerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(senderPni); when(account.getPhoneNumberIdentifier()).thenReturn(senderPni);
when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.of(account)); when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.of(account));
when(deletedAccounts.findE164(senderAci)).thenReturn(Optional.of(senderNumber)); when(accountsManager.findRecentlyDeletedE164(senderAci)).thenReturn(Optional.of(senderNumber));
when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni); when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni);
Entity<SpamReport> entity = Entity.entity(new SpamReport(new byte[3]), "application/json"); Entity<SpamReport> entity = Entity.entity(new SpamReport(new byte[3]), "application/json");
@ -800,7 +797,7 @@ class MessageControllerTest {
eq(AuthHelper.VALID_UUID), eq(AuthHelper.VALID_UUID),
argThat(maybeBytes -> maybeBytes.map(bytes -> Arrays.equals(bytes, new byte[3])).orElse(false)), argThat(maybeBytes -> maybeBytes.map(bytes -> Arrays.equals(bytes, new byte[3])).orElse(false)),
any()); any());
verify(deletedAccounts, never()).findE164(any(UUID.class)); verify(accountsManager, never()).findRecentlyDeletedE164(any(UUID.class));
verify(accountsManager, never()).getPhoneNumberIdentifier(anyString()); verify(accountsManager, never()).getPhoneNumberIdentifier(anyString());
when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.empty()); when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.empty());
@ -839,7 +836,7 @@ class MessageControllerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(senderPni); when(account.getPhoneNumberIdentifier()).thenReturn(senderPni);
when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.of(account)); when(accountsManager.getByAccountIdentifier(senderAci)).thenReturn(Optional.of(account));
when(deletedAccounts.findE164(senderAci)).thenReturn(Optional.of(senderNumber)); when(accountsManager.findRecentlyDeletedE164(senderAci)).thenReturn(Optional.of(senderNumber));
when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni); when(accountsManager.getPhoneNumberIdentifier(senderNumber)).thenReturn(senderPni);
Response response = Response response =

View File

@ -58,7 +58,6 @@ class AccountsManagerChangeNumberIntegrationTest {
static final RedisClusterExtension CACHE_CLUSTER_EXTENSION = RedisClusterExtension.builder().build(); static final RedisClusterExtension CACHE_CLUSTER_EXTENSION = RedisClusterExtension.builder().build();
private ClientPresenceManager clientPresenceManager; private ClientPresenceManager clientPresenceManager;
private DeletedAccounts deletedAccounts;
private AccountsManager accountsManager; private AccountsManager accountsManager;
@ -79,11 +78,9 @@ class AccountsManagerChangeNumberIntegrationTest {
Tables.NUMBERS.tableName(), Tables.NUMBERS.tableName(),
Tables.PNI_ASSIGNMENTS.tableName(), Tables.PNI_ASSIGNMENTS.tableName(),
Tables.USERNAMES.tableName(), Tables.USERNAMES.tableName(),
Tables.DELETED_ACCOUNTS.tableName(),
SCAN_PAGE_SIZE); SCAN_PAGE_SIZE);
deletedAccounts = new DeletedAccounts(DYNAMO_DB_EXTENSION.getDynamoDbClient(),
Tables.DELETED_ACCOUNTS.tableName());
final AccountLockManager accountLockManager = new AccountLockManager(DYNAMO_DB_EXTENSION.getDynamoDbClient(), final AccountLockManager accountLockManager = new AccountLockManager(DYNAMO_DB_EXTENSION.getDynamoDbClient(),
Tables.DELETED_ACCOUNTS_LOCK.tableName()); Tables.DELETED_ACCOUNTS_LOCK.tableName());
@ -112,7 +109,6 @@ class AccountsManagerChangeNumberIntegrationTest {
phoneNumberIdentifiers, phoneNumberIdentifiers,
CACHE_CLUSTER_EXTENSION.getRedisCluster(), CACHE_CLUSTER_EXTENSION.getRedisCluster(),
accountLockManager, accountLockManager,
deletedAccounts,
keysManager, keysManager,
messagesManager, messagesManager,
mock(ProfilesManager.class), mock(ProfilesManager.class),
@ -145,8 +141,8 @@ class AccountsManagerChangeNumberIntegrationTest {
assertEquals(secondNumber, accountsManager.getByAccountIdentifier(originalUuid).map(Account::getNumber).orElseThrow()); assertEquals(secondNumber, accountsManager.getByAccountIdentifier(originalUuid).map(Account::getNumber).orElseThrow());
assertEquals(Optional.empty(), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(originalNumber));
assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(secondNumber));
} }
@Test @Test
@ -178,8 +174,8 @@ class AccountsManagerChangeNumberIntegrationTest {
assertEquals(secondNumber, accountsManager.getByAccountIdentifier(originalUuid).map(Account::getNumber).orElseThrow()); assertEquals(secondNumber, accountsManager.getByAccountIdentifier(originalUuid).map(Account::getNumber).orElseThrow());
assertEquals(Optional.empty(), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(originalNumber));
assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(secondNumber));
assertEquals(pniIdentityKey, updatedAccount.getIdentityKey(IdentityType.PNI)); assertEquals(pniIdentityKey, updatedAccount.getIdentityKey(IdentityType.PNI));
@ -209,8 +205,8 @@ class AccountsManagerChangeNumberIntegrationTest {
assertEquals(originalNumber, accountsManager.getByAccountIdentifier(originalUuid).map(Account::getNumber).orElseThrow()); assertEquals(originalNumber, accountsManager.getByAccountIdentifier(originalUuid).map(Account::getNumber).orElseThrow());
assertEquals(Optional.empty(), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(originalNumber));
assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(secondNumber));
} }
@Test @Test
@ -235,8 +231,8 @@ class AccountsManagerChangeNumberIntegrationTest {
verify(clientPresenceManager).disconnectPresence(existingAccountUuid, Device.MASTER_ID); verify(clientPresenceManager).disconnectPresence(existingAccountUuid, Device.MASTER_ID);
assertEquals(Optional.of(existingAccountUuid), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.of(existingAccountUuid), accountsManager.findRecentlyDeletedAccountIdentifier(originalNumber));
assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(secondNumber));
accountsManager.changeNumber(accountsManager.getByAccountIdentifier(originalUuid).orElseThrow(), originalNumber, null, null, null, null); accountsManager.changeNumber(accountsManager.getByAccountIdentifier(originalUuid).orElseThrow(), originalNumber, null, null, null, null);
@ -266,13 +262,13 @@ class AccountsManagerChangeNumberIntegrationTest {
assertEquals(existingAccountUuid, reRegisteredAccount.getUuid()); assertEquals(existingAccountUuid, reRegisteredAccount.getUuid());
assertEquals(originalPni, reRegisteredAccount.getPhoneNumberIdentifier()); assertEquals(originalPni, reRegisteredAccount.getPhoneNumberIdentifier());
assertEquals(Optional.empty(), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(originalNumber));
assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(secondNumber));
final Account changedNumberReRegisteredAccount = accountsManager.changeNumber(reRegisteredAccount, secondNumber, null, null, null, null); final Account changedNumberReRegisteredAccount = accountsManager.changeNumber(reRegisteredAccount, secondNumber, null, null, null, null);
assertEquals(Optional.of(originalUuid), deletedAccounts.findUuid(originalNumber)); assertEquals(Optional.of(originalUuid), accountsManager.findRecentlyDeletedAccountIdentifier(originalNumber));
assertEquals(Optional.empty(), deletedAccounts.findUuid(secondNumber)); assertEquals(Optional.empty(), accountsManager.findRecentlyDeletedAccountIdentifier(secondNumber));
assertEquals(secondPni, changedNumberReRegisteredAccount.getPhoneNumberIdentifier()); assertEquals(secondPni, changedNumberReRegisteredAccount.getPhoneNumberIdentifier());
} }
} }

View File

@ -23,7 +23,6 @@ import java.io.IOException;
import java.time.Clock; import java.time.Clock;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -63,7 +62,8 @@ class AccountsManagerConcurrentModificationIntegrationTest {
static final DynamoDbExtension DYNAMO_DB_EXTENSION = new DynamoDbExtension( static final DynamoDbExtension DYNAMO_DB_EXTENSION = new DynamoDbExtension(
Tables.ACCOUNTS, Tables.ACCOUNTS,
Tables.NUMBERS, Tables.NUMBERS,
Tables.PNI_ASSIGNMENTS Tables.PNI_ASSIGNMENTS,
Tables.DELETED_ACCOUNTS
); );
private Accounts accounts; private Accounts accounts;
@ -88,6 +88,7 @@ class AccountsManagerConcurrentModificationIntegrationTest {
Tables.NUMBERS.tableName(), Tables.NUMBERS.tableName(),
Tables.PNI_ASSIGNMENTS.tableName(), Tables.PNI_ASSIGNMENTS.tableName(),
Tables.USERNAMES.tableName(), Tables.USERNAMES.tableName(),
Tables.DELETED_ACCOUNTS.tableName(),
SCAN_PAGE_SIZE); SCAN_PAGE_SIZE);
{ {
@ -103,9 +104,6 @@ class AccountsManagerConcurrentModificationIntegrationTest {
return null; return null;
}).when(accountLockManager).withLock(any(), any()); }).when(accountLockManager).withLock(any(), any());
final DeletedAccounts deletedAccounts = mock(DeletedAccounts.class);
when(deletedAccounts.findUuid(any())).thenReturn(Optional.empty());
final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class); final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class);
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(anyString())) when(phoneNumberIdentifiers.getPhoneNumberIdentifier(anyString()))
.thenAnswer((Answer<UUID>) invocation -> UUID.randomUUID()); .thenAnswer((Answer<UUID>) invocation -> UUID.randomUUID());
@ -115,7 +113,6 @@ class AccountsManagerConcurrentModificationIntegrationTest {
phoneNumberIdentifiers, phoneNumberIdentifiers,
RedisClusterHelper.builder().stringCommands(commands).build(), RedisClusterHelper.builder().stringCommands(commands).build(),
accountLockManager, accountLockManager,
deletedAccounts,
mock(KeysManager.class), mock(KeysManager.class),
mock(MessagesManager.class), mock(MessagesManager.class),
mock(ProfilesManager.class), mock(ProfilesManager.class),

View File

@ -92,7 +92,6 @@ class AccountsManagerTest {
private static final byte[] ENCRYPTED_USERNAME_2 = Base64.getUrlDecoder().decode(BASE_64_URL_ENCRYPTED_USERNAME_2); private static final byte[] ENCRYPTED_USERNAME_2 = Base64.getUrlDecoder().decode(BASE_64_URL_ENCRYPTED_USERNAME_2);
private Accounts accounts; private Accounts accounts;
private DeletedAccounts deletedAccounts;
private KeysManager keysManager; private KeysManager keysManager;
private MessagesManager messagesManager; private MessagesManager messagesManager;
private ProfilesManager profilesManager; private ProfilesManager profilesManager;
@ -125,7 +124,6 @@ class AccountsManagerTest {
@BeforeEach @BeforeEach
void setup() throws InterruptedException { void setup() throws InterruptedException {
accounts = mock(Accounts.class); accounts = mock(Accounts.class);
deletedAccounts = mock(DeletedAccounts.class);
keysManager = mock(KeysManager.class); keysManager = mock(KeysManager.class);
messagesManager = mock(MessagesManager.class); messagesManager = mock(MessagesManager.class);
profilesManager = mock(ProfilesManager.class); profilesManager = mock(ProfilesManager.class);
@ -152,8 +150,6 @@ class AccountsManagerTest {
return null; return null;
}).when(accounts).changeNumber(any(), anyString(), any()); }).when(accounts).changeNumber(any(), anyString(), any());
when(deletedAccounts.findUuid(anyString())).thenReturn(Optional.empty());
final SecureStorageClient storageClient = mock(SecureStorageClient.class); final SecureStorageClient storageClient = mock(SecureStorageClient.class);
when(storageClient.deleteStoredData(any())).thenReturn(CompletableFuture.completedFuture(null)); when(storageClient.deleteStoredData(any())).thenReturn(CompletableFuture.completedFuture(null));
@ -202,7 +198,6 @@ class AccountsManagerTest {
.stringAsyncCommands(asyncCommands) .stringAsyncCommands(asyncCommands)
.build(), .build(),
accountLockManager, accountLockManager,
deletedAccounts,
keysManager, keysManager,
messagesManager, messagesManager,
profilesManager, profilesManager,
@ -954,7 +949,7 @@ class AccountsManagerTest {
void testCreateAccountRecentlyDeleted() throws InterruptedException { void testCreateAccountRecentlyDeleted() throws InterruptedException {
final UUID recentlyDeletedUuid = UUID.randomUUID(); final UUID recentlyDeletedUuid = UUID.randomUUID();
when(deletedAccounts.findUuid(anyString())).thenReturn(Optional.of(recentlyDeletedUuid)); when(accounts.findRecentlyDeletedAccountIdentifier(anyString())).thenReturn(Optional.of(recentlyDeletedUuid));
when(accounts.create(any())).thenReturn(true); when(accounts.create(any())).thenReturn(true);
final String e164 = "+18005550123"; final String e164 = "+18005550123";
@ -1036,7 +1031,7 @@ class AccountsManagerTest {
account = accountsManager.changeNumber(account, number, null, null, null, null); account = accountsManager.changeNumber(account, number, null, null, null, null);
assertEquals(number, account.getNumber()); assertEquals(number, account.getNumber());
verify(deletedAccounts, never()).put(any(), any()); verify(accounts, never()).putRecentlyDeletedAccount(any(), any());
verify(keysManager, never()).delete(any()); verify(keysManager, never()).delete(any());
} }
@ -1052,7 +1047,6 @@ class AccountsManagerTest {
"AccountsManager should not allow use of changeNumber with new PNI keys but without changing number"); "AccountsManager should not allow use of changeNumber with new PNI keys but without changing number");
verify(accounts, never()).update(any()); verify(accounts, never()).update(any());
verifyNoInteractions(deletedAccounts);
verifyNoInteractions(keysManager); verifyNoInteractions(keysManager);
} }
@ -1210,7 +1204,6 @@ class AccountsManagerTest {
updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, d -> d.getPhoneNumberIdentityRegistrationId().getAsInt()))); updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, d -> d.getPhoneNumberIdentityRegistrationId().getAsInt())));
verify(accounts).update(any()); verify(accounts).update(any());
verifyNoInteractions(deletedAccounts);
verify(keysManager).delete(oldPni); verify(keysManager).delete(oldPni);
} }
@ -1264,7 +1257,6 @@ class AccountsManagerTest {
updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, d -> d.getPhoneNumberIdentityRegistrationId().getAsInt()))); updatedAccount.getDevices().stream().collect(Collectors.toMap(Device::getId, d -> d.getPhoneNumberIdentityRegistrationId().getAsInt())));
verify(accounts).update(any()); verify(accounts).update(any());
verifyNoInteractions(deletedAccounts);
verify(keysManager).delete(oldPni); verify(keysManager).delete(oldPni);
verify(keysManager).storeEcSignedPreKeys(oldPni, newSignedKeys); verify(keysManager).storeEcSignedPreKeys(oldPni, newSignedKeys);
@ -1297,7 +1289,6 @@ class AccountsManagerTest {
() -> accountsManager.updatePniKeys(account, pniIdentityKey, newSignedKeys, null, newRegistrationIds)); () -> accountsManager.updatePniKeys(account, pniIdentityKey, newSignedKeys, null, newRegistrationIds));
verifyNoInteractions(accounts); verifyNoInteractions(accounts);
verifyNoInteractions(deletedAccounts);
verifyNoInteractions(keysManager); verifyNoInteractions(keysManager);
} }
@ -1327,7 +1318,6 @@ class AccountsManagerTest {
() -> accountsManager.updatePniKeys(account, pniIdentityKey, newSignedKeys, newSignedPqKeys, newRegistrationIds)); () -> accountsManager.updatePniKeys(account, pniIdentityKey, newSignedKeys, newSignedPqKeys, newRegistrationIds));
verifyNoInteractions(accounts); verifyNoInteractions(accounts);
verifyNoInteractions(deletedAccounts);
verifyNoInteractions(keysManager); verifyNoInteractions(keysManager);
} }

View File

@ -28,7 +28,6 @@ import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -65,6 +64,7 @@ class AccountsManagerUsernameIntegrationTest {
Tables.ACCOUNTS, Tables.ACCOUNTS,
Tables.NUMBERS, Tables.NUMBERS,
Tables.USERNAMES, Tables.USERNAMES,
Tables.DELETED_ACCOUNTS,
Tables.PNI, Tables.PNI,
Tables.PNI_ASSIGNMENTS); Tables.PNI_ASSIGNMENTS);
@ -94,6 +94,7 @@ class AccountsManagerUsernameIntegrationTest {
Tables.NUMBERS.tableName(), Tables.NUMBERS.tableName(),
Tables.PNI_ASSIGNMENTS.tableName(), Tables.PNI_ASSIGNMENTS.tableName(),
Tables.USERNAMES.tableName(), Tables.USERNAMES.tableName(),
Tables.DELETED_ACCOUNTS.tableName(),
SCAN_PAGE_SIZE)); SCAN_PAGE_SIZE));
final AccountLockManager accountLockManager = mock(AccountLockManager.class); final AccountLockManager accountLockManager = mock(AccountLockManager.class);
@ -105,9 +106,6 @@ class AccountsManagerUsernameIntegrationTest {
return null; return null;
}).when(accountLockManager).withLock(any(), any()); }).when(accountLockManager).withLock(any(), any());
final DeletedAccounts deletedAccounts = mock(DeletedAccounts.class);
when(deletedAccounts.findUuid(any())).thenReturn(Optional.empty());
final PhoneNumberIdentifiers phoneNumberIdentifiers = final PhoneNumberIdentifiers phoneNumberIdentifiers =
new PhoneNumberIdentifiers(DYNAMO_DB_EXTENSION.getDynamoDbClient(), Tables.PNI.tableName()); new PhoneNumberIdentifiers(DYNAMO_DB_EXTENSION.getDynamoDbClient(), Tables.PNI.tableName());
@ -119,7 +117,6 @@ class AccountsManagerUsernameIntegrationTest {
phoneNumberIdentifiers, phoneNumberIdentifiers,
CACHE_CLUSTER_EXTENSION.getRedisCluster(), CACHE_CLUSTER_EXTENSION.getRedisCluster(),
accountLockManager, accountLockManager,
deletedAccounts,
mock(KeysManager.class), mock(KeysManager.class),
mock(MessagesManager.class), mock(MessagesManager.class),
mock(ProfilesManager.class), mock(ProfilesManager.class),

View File

@ -98,7 +98,8 @@ class AccountsTest {
Tables.ACCOUNTS, Tables.ACCOUNTS,
Tables.NUMBERS, Tables.NUMBERS,
Tables.PNI_ASSIGNMENTS, Tables.PNI_ASSIGNMENTS,
Tables.USERNAMES); Tables.USERNAMES,
Tables.DELETED_ACCOUNTS);
private final TestClock clock = TestClock.pinned(Instant.EPOCH); private final TestClock clock = TestClock.pinned(Instant.EPOCH);
private DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager; private DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager;
@ -121,6 +122,7 @@ class AccountsTest {
Tables.NUMBERS.tableName(), Tables.NUMBERS.tableName(),
Tables.PNI_ASSIGNMENTS.tableName(), Tables.PNI_ASSIGNMENTS.tableName(),
Tables.USERNAMES.tableName(), Tables.USERNAMES.tableName(),
Tables.DELETED_ACCOUNTS.tableName(),
SCAN_PAGE_SIZE); SCAN_PAGE_SIZE);
} }
@ -166,7 +168,6 @@ class AccountsTest {
mock(PhoneNumberIdentifiers.class), mock(PhoneNumberIdentifiers.class),
mock(FaultTolerantRedisCluster.class), mock(FaultTolerantRedisCluster.class),
mock(AccountLockManager.class), mock(AccountLockManager.class),
mock(DeletedAccounts.class),
mock(KeysManager.class), mock(KeysManager.class),
mock(MessagesManager.class), mock(MessagesManager.class),
mock(ProfilesManager.class), mock(ProfilesManager.class),
@ -442,7 +443,8 @@ class AccountsTest {
final DynamoDbAsyncClient dynamoDbAsyncClient = mock(DynamoDbAsyncClient.class); final DynamoDbAsyncClient dynamoDbAsyncClient = mock(DynamoDbAsyncClient.class);
accounts = new Accounts(mock(DynamoDbClient.class), accounts = new Accounts(mock(DynamoDbClient.class),
dynamoDbAsyncClient, Tables.ACCOUNTS.tableName(), dynamoDbAsyncClient, Tables.ACCOUNTS.tableName(),
Tables.NUMBERS.tableName(), Tables.PNI_ASSIGNMENTS.tableName(), Tables.USERNAMES.tableName(), SCAN_PAGE_SIZE); Tables.NUMBERS.tableName(), Tables.PNI_ASSIGNMENTS.tableName(), Tables.USERNAMES.tableName(),
Tables.DELETED_ACCOUNTS.tableName(), SCAN_PAGE_SIZE);
Exception e = TransactionConflictException.builder().build(); Exception e = TransactionConflictException.builder().build();
e = wrapException ? new CompletionException(e) : e; e = wrapException ? new CompletionException(e) : e;
@ -990,6 +992,59 @@ class AccountsTest {
assertThat(account.getUsernameHash()).isEmpty(); assertThat(account.getUsernameHash()).isEmpty();
} }
@Test
void testPutFindRecentlyDeletedAccount() {
final UUID uuid = UUID.randomUUID();
final String e164 = "+18005551234";
assertEquals(Optional.empty(), accounts.findRecentlyDeletedAccountIdentifier(e164));
accounts.putRecentlyDeletedAccount(uuid, e164);
assertEquals(Optional.of(uuid), accounts.findRecentlyDeletedAccountIdentifier(e164));
}
@Test
void testRemoveRecentlyDeletedAccount() {
final UUID uuid = UUID.randomUUID();
final String e164 = "+18005551234";
assertEquals(Optional.empty(), accounts.findRecentlyDeletedAccountIdentifier(e164));
accounts.putRecentlyDeletedAccount(uuid, e164);
assertEquals(Optional.of(uuid), accounts.findRecentlyDeletedAccountIdentifier(e164));
accounts.removeRecentlyDeletedAccount(e164);
assertEquals(Optional.empty(), accounts.findRecentlyDeletedAccountIdentifier(e164));
}
@Test
void testFindRecentlyDeletedE164() {
assertEquals(Optional.empty(), accounts.findRecentlyDeletedE164(UUID.randomUUID()));
final UUID uuid = UUID.randomUUID();
final String e164 = "+18005551234";
accounts.putRecentlyDeletedAccount(uuid, e164);
assertEquals(Optional.of(e164), accounts.findRecentlyDeletedE164(uuid));
}
@Test
void testFindRecentlyDeletedUUID() {
final String e164 = "+18005551234";
assertEquals(Optional.empty(), accounts.findRecentlyDeletedAccountIdentifier(e164));
final UUID uuid = UUID.randomUUID();
accounts.putRecentlyDeletedAccount(uuid, e164);
assertEquals(Optional.of(uuid), accounts.findRecentlyDeletedAccountIdentifier(e164));
}
@Test @Test
public void testIgnoredFieldsNotAddedToDataAttribute() throws Exception { public void testIgnoredFieldsNotAddedToDataAttribute() throws Exception {
final Account account = generateAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID()); final Account account = generateAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID());

View File

@ -1,80 +0,0 @@
/*
* Copyright 2013-2021 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.storage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Optional;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.whispersystems.textsecuregcm.storage.DynamoDbExtensionSchema.Tables;
class DeletedAccountsTest {
@RegisterExtension
static final DynamoDbExtension DYNAMO_DB_EXTENSION = new DynamoDbExtension(Tables.DELETED_ACCOUNTS);
private DeletedAccounts deletedAccounts;
@BeforeEach
void setUp() {
deletedAccounts = new DeletedAccounts(DYNAMO_DB_EXTENSION.getDynamoDbClient(), Tables.DELETED_ACCOUNTS.tableName());
}
@Test
void testPutFind() {
final UUID uuid = UUID.randomUUID();
final String e164 = "+18005551234";
assertEquals(Optional.empty(), deletedAccounts.findUuid(e164));
deletedAccounts.put(uuid, e164);
assertEquals(Optional.of(uuid), deletedAccounts.findUuid(e164));
}
@Test
void testRemove() {
final UUID uuid = UUID.randomUUID();
final String e164 = "+18005551234";
assertEquals(Optional.empty(), deletedAccounts.findUuid(e164));
deletedAccounts.put(uuid, e164);
assertEquals(Optional.of(uuid), deletedAccounts.findUuid(e164));
deletedAccounts.remove(e164);
assertEquals(Optional.empty(), deletedAccounts.findUuid(e164));
}
@Test
void testFindE164() {
assertEquals(Optional.empty(), deletedAccounts.findE164(UUID.randomUUID()));
final UUID uuid = UUID.randomUUID();
final String e164 = "+18005551234";
deletedAccounts.put(uuid, e164);
assertEquals(Optional.of(e164), deletedAccounts.findE164(uuid));
}
@Test
void testFindUUID() {
final String e164 = "+18005551234";
assertEquals(Optional.empty(), deletedAccounts.findUuid(e164));
final UUID uuid = UUID.randomUUID();
deletedAccounts.put(uuid, e164);
assertEquals(Optional.of(uuid), deletedAccounts.findUuid(e164));
}
}

View File

@ -63,21 +63,21 @@ public final class DynamoDbExtensionSchema {
List.of()), List.of()),
DELETED_ACCOUNTS("deleted_accounts_test", DELETED_ACCOUNTS("deleted_accounts_test",
DeletedAccounts.KEY_ACCOUNT_E164, Accounts.DELETED_ACCOUNTS_KEY_ACCOUNT_E164,
null, null,
List.of( List.of(
AttributeDefinition.builder() AttributeDefinition.builder()
.attributeName(DeletedAccounts.KEY_ACCOUNT_E164) .attributeName(Accounts.DELETED_ACCOUNTS_KEY_ACCOUNT_E164)
.attributeType(ScalarAttributeType.S).build(), .attributeType(ScalarAttributeType.S).build(),
AttributeDefinition.builder() AttributeDefinition.builder()
.attributeName(DeletedAccounts.ATTR_ACCOUNT_UUID) .attributeName(Accounts.DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID)
.attributeType(ScalarAttributeType.B) .attributeType(ScalarAttributeType.B)
.build()), .build()),
List.of( List.of(
GlobalSecondaryIndex.builder() GlobalSecondaryIndex.builder()
.indexName(DeletedAccounts.UUID_TO_E164_INDEX_NAME) .indexName(Accounts.DELETED_ACCOUNTS_UUID_TO_E164_INDEX_NAME)
.keySchema( .keySchema(
KeySchemaElement.builder().attributeName(DeletedAccounts.ATTR_ACCOUNT_UUID).keyType(KeyType.HASH).build() KeySchemaElement.builder().attributeName(Accounts.DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID).keyType(KeyType.HASH).build()
) )
.projection(Projection.builder().projectionType(ProjectionType.KEYS_ONLY).build()) .projection(Projection.builder().projectionType(ProjectionType.KEYS_ONLY).build())
.provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L).writeCapacityUnits(10L).build()) .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L).writeCapacityUnits(10L).build())
@ -86,10 +86,10 @@ public final class DynamoDbExtensionSchema {
), ),
DELETED_ACCOUNTS_LOCK("deleted_accounts_lock_test", DELETED_ACCOUNTS_LOCK("deleted_accounts_lock_test",
DeletedAccounts.KEY_ACCOUNT_E164, AccountLockManager.KEY_ACCOUNT_E164,
null, null,
List.of(AttributeDefinition.builder() List.of(AttributeDefinition.builder()
.attributeName(DeletedAccounts.KEY_ACCOUNT_E164) .attributeName(AccountLockManager.KEY_ACCOUNT_E164)
.attributeType(ScalarAttributeType.S).build()), .attributeType(ScalarAttributeType.S).build()),
List.of(), List.of()), List.of(), List.of()),