mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 04:28:04 +01:00
Create deleted-accounts records keyed by both e164 and PNI
This commit is contained in:
committed by
GitHub
parent
49d6a5e32d
commit
ffed19d198
@@ -65,6 +65,7 @@ import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import org.whispersystems.textsecuregcm.util.TestClock;
|
||||
import org.whispersystems.textsecuregcm.util.TestRandomUtil;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
import reactor.util.function.Tuples;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
|
||||
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
|
||||
@@ -74,6 +75,7 @@ import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
|
||||
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
|
||||
import software.amazon.awssdk.services.dynamodb.model.Put;
|
||||
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
|
||||
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
|
||||
import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure;
|
||||
import software.amazon.awssdk.services.dynamodb.model.TransactWriteItem;
|
||||
import software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest;
|
||||
@@ -211,6 +213,7 @@ class AccountsTest {
|
||||
|
||||
accounts.delete(originalUuid, Collections.emptyList()).join();
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(account.getNumber())).hasValue(originalUuid);
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(account.getPhoneNumberIdentifier())).hasValue(originalUuid);
|
||||
|
||||
freshUser = createAccount(account);
|
||||
assertThat(freshUser).isTrue();
|
||||
@@ -220,6 +223,7 @@ class AccountsTest {
|
||||
assertPhoneNumberIdentifierConstraintExists(account.getPhoneNumberIdentifier(), account.getUuid());
|
||||
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(account.getNumber())).isEmpty();
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(account.getPhoneNumberIdentifier())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -742,6 +746,7 @@ class AccountsTest {
|
||||
createAccount(retainedAccount);
|
||||
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(deletedAccount.getNumber())).isEmpty();
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(deletedAccount.getPhoneNumberIdentifier())).isEmpty();
|
||||
|
||||
assertPhoneNumberConstraintExists("+14151112222", deletedAccount.getUuid());
|
||||
assertPhoneNumberIdentifierConstraintExists(deletedAccount.getPhoneNumberIdentifier(), deletedAccount.getUuid());
|
||||
@@ -755,6 +760,7 @@ class AccountsTest {
|
||||
|
||||
assertThat(accounts.getByAccountIdentifier(deletedAccount.getUuid())).isNotPresent();
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(deletedAccount.getNumber())).hasValue(deletedAccount.getUuid());
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(deletedAccount.getPhoneNumberIdentifier())).hasValue(deletedAccount.getUuid());
|
||||
|
||||
assertPhoneNumberConstraintDoesNotExist(deletedAccount.getNumber());
|
||||
assertPhoneNumberIdentifierConstraintDoesNotExist(deletedAccount.getPhoneNumberIdentifier());
|
||||
@@ -764,7 +770,7 @@ class AccountsTest {
|
||||
|
||||
{
|
||||
final Account recreatedAccount = generateAccount(deletedAccount.getNumber(), UUID.randomUUID(),
|
||||
UUID.randomUUID(), List.of(generateDevice(DEVICE_ID_1)));
|
||||
deletedAccount.getPhoneNumberIdentifier(), List.of(generateDevice(DEVICE_ID_1)));
|
||||
|
||||
final boolean freshUser = createAccount(recreatedAccount);
|
||||
|
||||
@@ -893,6 +899,7 @@ class AccountsTest {
|
||||
}
|
||||
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(originalNumber)).isEqualTo(maybeDisplacedAccountIdentifier);
|
||||
assertThat(accounts.findRecentlyDeletedAccountIdentifier(originalPni)).isEqualTo(maybeDisplacedAccountIdentifier);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> testChangeNumber() {
|
||||
@@ -1697,7 +1704,142 @@ class AccountsTest {
|
||||
assertInstanceOf(DeviceIdDeserializer.DeviceIdDeserializationException.class, cause);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getE164KeyedDeletedAccounts() {
|
||||
final Account deletedAccount = generateAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID());
|
||||
createAccount(deletedAccount);
|
||||
accounts.delete(deletedAccount.getUuid(), List.of()).join();
|
||||
assertEquals(
|
||||
List.of(Tuples.of("+18005551234", deletedAccount.getUuid(), clock.instant().plus(Accounts.DELETED_ACCOUNTS_TIME_TO_LIVE).toEpochMilli() / 1000)),
|
||||
accounts.getE164KeyedDeletedAccounts(1, Schedulers.immediate()).collectList().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertPniDeletedAccount() throws Exception {
|
||||
final String e164 = "+18005551234";
|
||||
final UUID aci = UUID.randomUUID();
|
||||
final UUID pni = UUID.randomUUID();
|
||||
final Long expires = 1234567890L;
|
||||
|
||||
final ScanRequest scanRequest = ScanRequest.builder()
|
||||
.tableName(Tables.DELETED_ACCOUNTS.tableName())
|
||||
.build();
|
||||
assertThat(
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items())
|
||||
.isEmpty();
|
||||
|
||||
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient().putItem(
|
||||
PutItemRequest.builder()
|
||||
.tableName(Tables.DELETED_ACCOUNTS.tableName())
|
||||
.item(Map.of(
|
||||
Accounts.DELETED_ACCOUNTS_KEY_ACCOUNT_E164, AttributeValues.fromString(e164),
|
||||
Accounts.DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID, AttributeValues.fromUUID(aci),
|
||||
Accounts.DELETED_ACCOUNTS_ATTR_EXPIRES, AttributeValues.fromLong(expires)))
|
||||
.build());
|
||||
|
||||
assertThat(accounts.insertPniDeletedAccount(e164, pni, aci, expires).get()).isTrue();
|
||||
|
||||
List<Map<String, AttributeValue>> items =
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items();
|
||||
assertThat(items).hasSize(2);
|
||||
final Map<String, AttributeValue> item = items.stream().filter(i -> !i.get(Accounts.DELETED_ACCOUNTS_KEY_ACCOUNT_E164).s().equals(e164)).findFirst().get();
|
||||
assertThat(item.get(Accounts.DELETED_ACCOUNTS_KEY_ACCOUNT_E164).s())
|
||||
.isEqualTo(pni.toString());
|
||||
assertThat(AttributeValues.getUUID(item, Accounts.DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID, null))
|
||||
.isEqualTo(aci);
|
||||
assertThat(AttributeValues.getLong(item, Accounts.DELETED_ACCOUNTS_ATTR_EXPIRES, 0))
|
||||
.isEqualTo(expires);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertPniDeletedAccount_concurrentChange() throws Exception {
|
||||
final String e164 = "+18005551234";
|
||||
final UUID aci = UUID.randomUUID();
|
||||
final UUID pni = UUID.randomUUID();
|
||||
final Long expires = 1234567890L;
|
||||
|
||||
final ScanRequest scanRequest = ScanRequest.builder()
|
||||
.tableName(Tables.DELETED_ACCOUNTS.tableName())
|
||||
.build();
|
||||
assertThat(
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items())
|
||||
.isEmpty();
|
||||
|
||||
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient().putItem(
|
||||
PutItemRequest.builder()
|
||||
.tableName(Tables.DELETED_ACCOUNTS.tableName())
|
||||
.item(Map.of(
|
||||
Accounts.DELETED_ACCOUNTS_KEY_ACCOUNT_E164, AttributeValues.fromString(e164),
|
||||
Accounts.DELETED_ACCOUNTS_ATTR_ACCOUNT_UUID, AttributeValues.fromUUID(aci),
|
||||
Accounts.DELETED_ACCOUNTS_ATTR_EXPIRES, AttributeValues.fromLong(expires + 1)))
|
||||
.build());
|
||||
|
||||
assertThat(accounts.insertPniDeletedAccount(e164, pni, aci, expires).get()).isFalse();
|
||||
|
||||
List<Map<String, AttributeValue>> items =
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items();
|
||||
assertThat(items).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertPniDeletedAccount_concurrentDeletion() throws Exception {
|
||||
final String e164 = "+18005551234";
|
||||
final UUID aci = UUID.randomUUID();
|
||||
final UUID pni = UUID.randomUUID();
|
||||
final Long expires = 1234567890L;
|
||||
|
||||
final ScanRequest scanRequest = ScanRequest.builder()
|
||||
.tableName(Tables.DELETED_ACCOUNTS.tableName())
|
||||
.build();
|
||||
assertThat(
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items())
|
||||
.isEmpty();
|
||||
|
||||
assertThat(accounts.insertPniDeletedAccount(e164, pni, aci, expires).get()).isFalse();
|
||||
|
||||
List<Map<String, AttributeValue>> items =
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items();
|
||||
assertThat(items).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertPniDeletedAccount_alreadyMigrated() throws Exception {
|
||||
final Account deletedAccount = generateAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID());
|
||||
|
||||
createAccount(deletedAccount);
|
||||
accounts.delete(deletedAccount.getUuid(), List.of()).join();
|
||||
|
||||
final ScanRequest scanRequest = ScanRequest.builder()
|
||||
.tableName(Tables.DELETED_ACCOUNTS.tableName())
|
||||
.build();
|
||||
assertThat(
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items())
|
||||
.hasSize(2);
|
||||
|
||||
assertThat(accounts.insertPniDeletedAccount(deletedAccount.getNumber(), deletedAccount.getPhoneNumberIdentifier(), deletedAccount.getUuid(), clock.instant().plus(Accounts.DELETED_ACCOUNTS_TIME_TO_LIVE).toEpochMilli() / 1000).get()).isFalse();
|
||||
|
||||
List<Map<String, AttributeValue>> items =
|
||||
DYNAMO_DB_EXTENSION.getDynamoDbClient()
|
||||
.scan(scanRequest)
|
||||
.items();
|
||||
assertThat(items).hasSize(2);
|
||||
}
|
||||
|
||||
private static Device generateDevice(byte id) {
|
||||
return DevicesHelper.createDevice(id);
|
||||
|
||||
Reference in New Issue
Block a user