mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 08:58:13 +01:00
Canonical discoverability writing.
This commit is contained in:
committed by
gram-signal
parent
92f035bc2a
commit
b4aabd799b
@@ -156,6 +156,7 @@ import org.whispersystems.textsecuregcm.storage.Accounts;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsDynamoDb;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsDynamoDbMigrator;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.ContactDiscoveryWriter;
|
||||
import org.whispersystems.textsecuregcm.storage.DeletedAccounts;
|
||||
import org.whispersystems.textsecuregcm.storage.DeletedAccountsDirectoryReconciler;
|
||||
import org.whispersystems.textsecuregcm.storage.DeletedAccountsManager;
|
||||
@@ -482,6 +483,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
directoryServerConfiguration.getReplicationName(), directoryReconciliationClient);
|
||||
deletedAccountsDirectoryReconcilers.add(deletedAccountsDirectoryReconciler);
|
||||
}
|
||||
accountDatabaseCrawlerListeners.add(new ContactDiscoveryWriter(accounts));
|
||||
// PushFeedbackProcessor may update device properties
|
||||
accountDatabaseCrawlerListeners.add(new PushFeedbackProcessor(accountsManager));
|
||||
// delete accounts last
|
||||
|
||||
@@ -66,6 +66,9 @@ public class Account {
|
||||
@JsonIgnore
|
||||
private boolean stale;
|
||||
|
||||
@JsonIgnore
|
||||
private boolean canonicallyDiscoverable;
|
||||
|
||||
public Account() {}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -93,6 +96,12 @@ public class Account {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public void setCanonicallyDiscoverable(boolean canonicallyDiscoverable) {
|
||||
requireNotStale();
|
||||
|
||||
this.canonicallyDiscoverable = canonicallyDiscoverable;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
requireNotStale();
|
||||
|
||||
@@ -228,6 +237,12 @@ public class Account {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isCanonicallyDiscoverable() {
|
||||
requireNotStale();
|
||||
|
||||
return canonicallyDiscoverable;
|
||||
}
|
||||
|
||||
public Optional<String> getRelay() {
|
||||
requireNotStale();
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ public class AccountsDynamoDb extends AbstractDynamoDbStore implements AccountSt
|
||||
static final String ATTR_ACCOUNT_DATA = "D";
|
||||
// internal version for optimistic locking
|
||||
static final String ATTR_VERSION = "V";
|
||||
// canonically discoverable
|
||||
static final String ATTR_CANONICALLY_DISCOVERABLE = "C";
|
||||
|
||||
private final DynamoDbClient client;
|
||||
private final DynamoDbAsyncClient asyncClient;
|
||||
@@ -160,7 +162,8 @@ public class AccountsDynamoDb extends AbstractDynamoDbStore implements AccountSt
|
||||
KEY_ACCOUNT_UUID, AttributeValues.fromUUID(uuid),
|
||||
ATTR_ACCOUNT_E164, AttributeValues.fromString(account.getNumber()),
|
||||
ATTR_ACCOUNT_DATA, AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
ATTR_VERSION, AttributeValues.fromInt(account.getVersion())))
|
||||
ATTR_VERSION, AttributeValues.fromInt(account.getVersion()),
|
||||
ATTR_CANONICALLY_DISCOVERABLE, AttributeValues.fromBool(account.shouldBeVisibleInDirectory())))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
@@ -193,13 +196,15 @@ public class AccountsDynamoDb extends AbstractDynamoDbStore implements AccountSt
|
||||
updateItemRequest = UpdateItemRequest.builder()
|
||||
.tableName(accountsTableName)
|
||||
.key(Map.of(KEY_ACCOUNT_UUID, AttributeValues.fromUUID(account.getUuid())))
|
||||
.updateExpression("SET #data = :data ADD #version :version_increment")
|
||||
.updateExpression("SET #data = :data, #cds = :cds ADD #version :version_increment")
|
||||
.conditionExpression("attribute_exists(#number) AND #version = :version")
|
||||
.expressionAttributeNames(Map.of("#number", ATTR_ACCOUNT_E164,
|
||||
"#data", ATTR_ACCOUNT_DATA,
|
||||
"#cds", ATTR_CANONICALLY_DISCOVERABLE,
|
||||
"#version", ATTR_VERSION))
|
||||
.expressionAttributeValues(Map.of(
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
":cds", AttributeValues.fromBool(account.shouldBeVisibleInDirectory()),
|
||||
":version", AttributeValues.fromInt(account.getVersion()),
|
||||
":version_increment", AttributeValues.fromInt(1)))
|
||||
.returnValues(ReturnValue.UPDATED_NEW)
|
||||
@@ -428,6 +433,7 @@ public class AccountsDynamoDb extends AbstractDynamoDbStore implements AccountSt
|
||||
static Account fromItem(Map<String, AttributeValue> item) {
|
||||
if (!item.containsKey(ATTR_ACCOUNT_DATA) ||
|
||||
!item.containsKey(ATTR_ACCOUNT_E164) ||
|
||||
// TODO: eventually require ATTR_CANONICALLY_DISCOVERABLE
|
||||
!item.containsKey(KEY_ACCOUNT_UUID)) {
|
||||
throw new RuntimeException("item missing values");
|
||||
}
|
||||
@@ -436,6 +442,7 @@ public class AccountsDynamoDb extends AbstractDynamoDbStore implements AccountSt
|
||||
account.setNumber(item.get(ATTR_ACCOUNT_E164).s());
|
||||
account.setUuid(UUIDUtil.fromByteBuffer(item.get(KEY_ACCOUNT_UUID).b().asByteBuffer()));
|
||||
account.setVersion(Integer.parseInt(item.get(ATTR_VERSION).n()));
|
||||
account.setCanonicallyDiscoverable(Optional.ofNullable(item.get(ATTR_CANONICALLY_DISCOVERABLE)).map(av -> av.bool()).orElse(false));
|
||||
|
||||
return account;
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.whispersystems.textsecuregcm.storage;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ContactDiscoveryWriter extends AccountDatabaseCrawlerListener {
|
||||
|
||||
private final AccountStore accounts;
|
||||
|
||||
public ContactDiscoveryWriter(final AccountStore accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrawlStart() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrawlEnd(final Optional<UUID> fromUuid) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCrawlChunk(final Optional<UUID> fromUuid, final List<Account> chunkAccounts)
|
||||
throws AccountDatabaseCrawlerRestartException {
|
||||
for (Account account : chunkAccounts) {
|
||||
if (account.isCanonicallyDiscoverable() != account.shouldBeVisibleInDirectory()) {
|
||||
accounts.update(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ public class AttributeValues {
|
||||
return AttributeValue.builder().n(Long.toString(value)).build();
|
||||
}
|
||||
|
||||
public static AttributeValue fromBool(boolean value) { return AttributeValue.builder().bool(value).build(); }
|
||||
|
||||
public static AttributeValue fromInt(int value) {
|
||||
return AttributeValue.builder().n(Integer.toString(value)).build();
|
||||
}
|
||||
@@ -43,6 +45,10 @@ public class AttributeValues {
|
||||
return AttributeValue.builder().b(value).build();
|
||||
}
|
||||
|
||||
private static boolean toBool(AttributeValue av) {
|
||||
return av.bool();
|
||||
}
|
||||
|
||||
private static int toInt(AttributeValue av) {
|
||||
return Integer.parseInt(av.n());
|
||||
}
|
||||
@@ -67,6 +73,10 @@ public class AttributeValues {
|
||||
return Optional.ofNullable(item.get(key));
|
||||
}
|
||||
|
||||
public static boolean getBool(Map<String, AttributeValue> item, String key, boolean defaultValue) {
|
||||
return AttributeValues.get(item, key).map(AttributeValues::toBool).orElse(defaultValue);
|
||||
}
|
||||
|
||||
public static int getInt(Map<String, AttributeValue> item, String key, int defaultValue) {
|
||||
return AttributeValues.get(item, key).map(AttributeValues::toInt).orElse(defaultValue);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user