Consolidate account creation/directory updates into AccountsManager

This commit is contained in:
Jon Chambers
2021-07-27 10:27:47 -04:00
committed by GitHub
parent 917f667229
commit 8579190cdf
16 changed files with 368 additions and 589 deletions

View File

@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import javax.validation.Valid;
@@ -68,15 +67,12 @@ import org.whispersystems.textsecuregcm.push.GcmMessage;
import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
import org.whispersystems.textsecuregcm.sms.SmsSender;
import org.whispersystems.textsecuregcm.sms.TwilioVerifyExperimentEnrollmentManager;
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
import org.whispersystems.textsecuregcm.storage.AbusiveHostRule;
import org.whispersystems.textsecuregcm.storage.AbusiveHostRules;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.KeysDynamoDb;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.StoredVerificationCodeManager;
import org.whispersystems.textsecuregcm.storage.UsernamesManager;
import org.whispersystems.textsecuregcm.util.Constants;
@@ -91,7 +87,6 @@ public class AccountController {
private final Logger logger = LoggerFactory.getLogger(AccountController.class);
private final MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME);
private final Meter newUserMeter = metricRegistry.meter(name(AccountController.class, "brand_new_user" ));
private final Meter blockedHostMeter = metricRegistry.meter(name(AccountController.class, "blocked_host" ));
private final Meter filteredHostMeter = metricRegistry.meter(name(AccountController.class, "filtered_host" ));
private final Meter rateLimitedHostMeter = metricRegistry.meter(name(AccountController.class, "rate_limited_host" ));
@@ -119,9 +114,6 @@ public class AccountController {
private final AbusiveHostRules abusiveHostRules;
private final RateLimiters rateLimiters;
private final SmsSender smsSender;
private final DirectoryQueue directoryQueue;
private final MessagesManager messagesManager;
private final KeysDynamoDb keys;
private final DynamicConfigurationManager dynamicConfigurationManager;
private final TurnTokenGenerator turnTokenGenerator;
private final Map<String, Integer> testDevices;
@@ -138,9 +130,6 @@ public class AccountController {
AbusiveHostRules abusiveHostRules,
RateLimiters rateLimiters,
SmsSender smsSenderFactory,
DirectoryQueue directoryQueue,
MessagesManager messagesManager,
KeysDynamoDb keys,
DynamicConfigurationManager dynamicConfigurationManager,
TurnTokenGenerator turnTokenGenerator,
Map<String, Integer> testDevices,
@@ -156,9 +145,6 @@ public class AccountController {
this.abusiveHostRules = abusiveHostRules;
this.rateLimiters = rateLimiters;
this.smsSender = smsSenderFactory;
this.directoryQueue = directoryQueue;
this.messagesManager = messagesManager;
this.keys = keys;
this.dynamicConfigurationManager = dynamicConfigurationManager;
this.testDevices = testDevices;
this.turnTokenGenerator = turnTokenGenerator;
@@ -318,6 +304,7 @@ public class AccountController {
});
});
// TODO Remove this meter when external dependencies have been resolved
metricRegistry.meter(name(AccountController.class, "create", Util.getCountryCode(number))).mark();
{
@@ -392,7 +379,7 @@ public class AccountController {
throw new WebApplicationException(Response.status(409).build());
}
Account account = createAccount(number, password, signalAgent, accountAttributes);
Account account = accounts.create(number, password, signalAgent, accountAttributes);
{
metricRegistry.meter(name(AccountController.class, "verify", Util.getCountryCode(number))).mark();
@@ -431,7 +418,6 @@ public class AccountController {
public void setGcmRegistrationId(@Auth DisabledPermittedAccount disabledPermittedAccount, @Valid GcmRegistrationId registrationId) {
Account account = disabledPermittedAccount.getAccount();
Device device = account.getAuthenticatedDevice().get();
boolean wasAccountEnabled = account.isEnabled();
if (device.getGcmId() != null &&
device.getGcmId().equals(registrationId.getGcmRegistrationId()))
@@ -439,16 +425,12 @@ public class AccountController {
return;
}
account = accounts.updateDevice(account, device.getId(), d -> {
accounts.updateDevice(account, device.getId(), d -> {
d.setApnId(null);
d.setVoipApnId(null);
d.setGcmId(registrationId.getGcmRegistrationId());
d.setFetchesMessages(false);
});
if (!wasAccountEnabled && account.isEnabled()) {
directoryQueue.refreshRegisteredUser(account);
}
}
@Timed
@@ -458,12 +440,11 @@ public class AccountController {
Account account = disabledPermittedAccount.getAccount();
Device device = account.getAuthenticatedDevice().get();
account = accounts.updateDevice(account, device.getId(), d -> {
accounts.updateDevice(account, device.getId(), d -> {
d.setGcmId(null);
d.setFetchesMessages(false);
d.setUserAgent("OWA");
});
directoryQueue.refreshRegisteredUser(account);
}
@Timed
@@ -473,18 +454,13 @@ public class AccountController {
public void setApnRegistrationId(@Auth DisabledPermittedAccount disabledPermittedAccount, @Valid ApnRegistrationId registrationId) {
Account account = disabledPermittedAccount.getAccount();
Device device = account.getAuthenticatedDevice().get();
boolean wasAccountEnabled = account.isEnabled();
account = accounts.updateDevice(account, device.getId(), d -> {
accounts.updateDevice(account, device.getId(), d -> {
d.setApnId(registrationId.getApnRegistrationId());
d.setVoipApnId(registrationId.getVoipRegistrationId());
d.setGcmId(null);
d.setFetchesMessages(false);
});
if (!wasAccountEnabled && account.isEnabled()) {
directoryQueue.refreshRegisteredUser(account);
}
}
@Timed
@@ -503,7 +479,6 @@ public class AccountController {
d.setUserAgent("OWP");
}
});
directoryQueue.refreshRegisteredUser(account);
}
@Timed
@@ -577,7 +552,7 @@ public class AccountController {
Account account = disabledPermittedAccount.getAccount();
long deviceId = account.getAuthenticatedDevice().get().getId();
account = accounts.update(account, a-> {
accounts.update(account, a-> {
a.getDevice(deviceId).ifPresent(d -> {
d.setFetchesMessages(attributes.getFetchesMessages());
@@ -588,19 +563,12 @@ public class AccountController {
d.setUserAgent(userAgent);
});
setAccountRegistrationLockFromAttributes(a, attributes);
a.setRegistrationLockFromAttributes(attributes);
a.setUnidentifiedAccessKey(attributes.getUnidentifiedAccessKey());
a.setUnrestrictedUnidentifiedAccess(attributes.isUnrestrictedUnidentifiedAccess());
a.setDiscoverableByPhoneNumber(attributes.isDiscoverableByPhoneNumber());
});
final boolean hasDiscoverabilityChange = (account.isDiscoverableByPhoneNumber() != attributes.isDiscoverableByPhoneNumber());
if (hasDiscoverabilityChange) {
directoryQueue.refreshRegisteredUser(account);
}
}
@GET
@@ -752,57 +720,6 @@ public class AccountController {
return false;
}
private Account createAccount(String number, String password, String signalAgent, AccountAttributes accountAttributes) {
Optional<Account> maybeExistingAccount = accounts.get(number);
Device device = new Device();
device.setId(Device.MASTER_ID);
device.setAuthenticationCredentials(new AuthenticationCredentials(password));
device.setFetchesMessages(accountAttributes.getFetchesMessages());
device.setRegistrationId(accountAttributes.getRegistrationId());
device.setName(accountAttributes.getName());
device.setCapabilities(accountAttributes.getCapabilities());
device.setCreated(System.currentTimeMillis());
device.setLastSeen(Util.todayInMillis());
device.setUserAgent(signalAgent);
Account account = new Account();
account.setNumber(number);
account.setUuid(UUID.randomUUID());
account.addDevice(device);
setAccountRegistrationLockFromAttributes(account, accountAttributes);
account.setUnidentifiedAccessKey(accountAttributes.getUnidentifiedAccessKey());
account.setUnrestrictedUnidentifiedAccess(accountAttributes.isUnrestrictedUnidentifiedAccess());
account.setDiscoverableByPhoneNumber(accountAttributes.isDiscoverableByPhoneNumber());
if (accounts.create(account)) {
newUserMeter.mark();
}
directoryQueue.refreshRegisteredUser(account);
maybeExistingAccount.ifPresent(definitelyExistingAccount -> {
messagesManager.clear(definitelyExistingAccount.getUuid());
keys.delete(definitelyExistingAccount);
});
pendingAccounts.remove(number);
return account;
}
private void setAccountRegistrationLockFromAttributes(Account account, @Valid AccountAttributes attributes) {
if (!Util.isEmpty(attributes.getPin())) {
account.setPin(attributes.getPin());
} else if (!Util.isEmpty(attributes.getRegistrationLock())) {
AuthenticationCredentials credentials = new AuthenticationCredentials(attributes.getRegistrationLock());
account.setRegistrationLock(credentials.getHashedAuthenticationToken(), credentials.getSalt());
} else {
account.setPin(null);
account.setRegistrationLock(null, null);
}
}
@VisibleForTesting protected
VerificationCode generateVerificationCode(String number) {
if (testDevices.containsKey(number)) {

View File

@@ -62,13 +62,11 @@ public class DeviceController {
private final KeysDynamoDb keys;
private final RateLimiters rateLimiters;
private final Map<String, Integer> maxDeviceConfiguration;
private final DirectoryQueue directoryQueue;
public DeviceController(StoredVerificationCodeManager pendingDevices,
AccountsManager accounts,
MessagesManager messages,
KeysDynamoDb keys,
DirectoryQueue directoryQueue,
RateLimiters rateLimiters,
Map<String, Integer> maxDeviceConfiguration)
{
@@ -76,7 +74,6 @@ public class DeviceController {
this.accounts = accounts;
this.messages = messages;
this.keys = keys;
this.directoryQueue = directoryQueue;
this.rateLimiters = rateLimiters;
this.maxDeviceConfiguration = maxDeviceConfiguration;
}
@@ -105,7 +102,6 @@ public class DeviceController {
messages.clear(account.getUuid(), deviceId);
account = accounts.update(account, a -> a.removeDevice(deviceId));
directoryQueue.refreshRegisteredUser(account);
keys.delete(account, deviceId);
// ensure any messages that came in after the first clear() are also removed
messages.clear(account.getUuid(), deviceId);

View File

@@ -55,7 +55,6 @@ public class KeysController {
private final RateLimiters rateLimiters;
private final KeysDynamoDb keysDynamoDb;
private final AccountsManager accounts;
private final DirectoryQueue directoryQueue;
private final PreKeyRateLimiter preKeyRateLimiter;
private final DynamicConfigurationManager dynamicConfigurationManager;
@@ -69,13 +68,12 @@ public class KeysController {
private static final String PREKEY_TARGET_IDENTIFIER_TAG_NAME = "identifierType";
public KeysController(RateLimiters rateLimiters, KeysDynamoDb keysDynamoDb, AccountsManager accounts,
DirectoryQueue directoryQueue, PreKeyRateLimiter preKeyRateLimiter,
PreKeyRateLimiter preKeyRateLimiter,
DynamicConfigurationManager dynamicConfigurationManager,
RateLimitChallengeManager rateLimitChallengeManager) {
this.rateLimiters = rateLimiters;
this.keysDynamoDb = keysDynamoDb;
this.accounts = accounts;
this.directoryQueue = directoryQueue;
this.preKeyRateLimiter = preKeyRateLimiter;
this.dynamicConfigurationManager = dynamicConfigurationManager;
@@ -100,7 +98,6 @@ public class KeysController {
public void setKeys(@Auth DisabledPermittedAccount disabledPermittedAccount, @Valid PreKeyState preKeys) {
Account account = disabledPermittedAccount.getAccount();
Device device = account.getAuthenticatedDevice().get();
boolean wasAccountEnabled = account.isEnabled();
boolean updateAccount = false;
if (!preKeys.getSignedPreKey().equals(device.getSignedPreKey())) {
@@ -116,10 +113,6 @@ public class KeysController {
a.getDevice(device.getId()).ifPresent(d -> d.setSignedPreKey(preKeys.getSignedPreKey()));
a.setIdentityKey(preKeys.getIdentityKey());
});
if (!wasAccountEnabled && account.isEnabled()) {
directoryQueue.refreshRegisteredUser(account);
}
}
keysDynamoDb.store(account, device.getId(), preKeys.getPreKeys());
@@ -198,14 +191,9 @@ public class KeysController {
@Path("/signed")
@Consumes(MediaType.APPLICATION_JSON)
public void setSignedKey(@Auth Account account, @Valid SignedPreKey signedPreKey) {
Device device = account.getAuthenticatedDevice().get();
boolean wasAccountEnabled = account.isEnabled();
Device device = account.getAuthenticatedDevice().get();
account = accounts.updateDevice(account, device.getId(), d -> d.setSignedPreKey(signedPreKey));
if (!wasAccountEnabled && account.isEnabled()) {
directoryQueue.refreshRegisteredUser(account);
}
accounts.updateDevice(account, device.getId(), d -> d.setSignedPreKey(signedPreKey));
}
@Timed