replicate directory updates on GCM/APN token & signed prekey changes
This commit is contained in:
parent
266f1c3a49
commit
dbfe4fd5ac
|
@ -211,7 +211,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
environment.lifecycle().manage(directoryReconciler);
|
environment.lifecycle().manage(directoryReconciler);
|
||||||
|
|
||||||
AttachmentController attachmentController = new AttachmentController(rateLimiters, urlSigner);
|
AttachmentController attachmentController = new AttachmentController(rateLimiters, urlSigner);
|
||||||
KeysController keysController = new KeysController(rateLimiters, keys, accountsManager);
|
KeysController keysController = new KeysController(rateLimiters, keys, accountsManager, directoryQueue);
|
||||||
MessageController messageController = new MessageController(rateLimiters, pushSender, receiptSender, accountsManager, messagesManager, apnFallbackManager);
|
MessageController messageController = new MessageController(rateLimiters, pushSender, receiptSender, accountsManager, messagesManager, apnFallbackManager);
|
||||||
ProfileController profileController = new ProfileController(rateLimiters , accountsManager, config.getProfilesConfiguration());
|
ProfileController profileController = new ProfileController(rateLimiters , accountsManager, config.getProfilesConfiguration());
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,8 @@ public class AccountController {
|
||||||
@Path("/gcm/")
|
@Path("/gcm/")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public void setGcmRegistrationId(@Auth Account account, @Valid GcmRegistrationId registrationId) {
|
public void setGcmRegistrationId(@Auth Account account, @Valid GcmRegistrationId registrationId) {
|
||||||
Device device = account.getAuthenticatedDevice().get();
|
Device device = account.getAuthenticatedDevice().get();
|
||||||
|
boolean wasAccountActive = account.isActive();
|
||||||
|
|
||||||
if (device.getGcmId() != null &&
|
if (device.getGcmId() != null &&
|
||||||
device.getGcmId().equals(registrationId.getGcmRegistrationId()))
|
device.getGcmId().equals(registrationId.getGcmRegistrationId()))
|
||||||
|
@ -286,6 +287,10 @@ public class AccountController {
|
||||||
else device.setFetchesMessages(false);
|
else device.setFetchesMessages(false);
|
||||||
|
|
||||||
accounts.update(account);
|
accounts.update(account);
|
||||||
|
|
||||||
|
if (!wasAccountActive && account.isActive()) {
|
||||||
|
directoryQueue.addRegisteredUser(account.getNumber());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Timed
|
@Timed
|
||||||
|
@ -308,12 +313,18 @@ public class AccountController {
|
||||||
@Path("/apn/")
|
@Path("/apn/")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public void setApnRegistrationId(@Auth Account account, @Valid ApnRegistrationId registrationId) {
|
public void setApnRegistrationId(@Auth Account account, @Valid ApnRegistrationId registrationId) {
|
||||||
Device device = account.getAuthenticatedDevice().get();
|
Device device = account.getAuthenticatedDevice().get();
|
||||||
|
boolean wasAccountActive = account.isActive();
|
||||||
|
|
||||||
device.setApnId(registrationId.getApnRegistrationId());
|
device.setApnId(registrationId.getApnRegistrationId());
|
||||||
device.setVoipApnId(registrationId.getVoipRegistrationId());
|
device.setVoipApnId(registrationId.getVoipRegistrationId());
|
||||||
device.setGcmId(null);
|
device.setGcmId(null);
|
||||||
device.setFetchesMessages(true);
|
device.setFetchesMessages(true);
|
||||||
accounts.update(account);
|
accounts.update(account);
|
||||||
|
|
||||||
|
if (!wasAccountActive && account.isActive()) {
|
||||||
|
directoryQueue.addRegisteredUser(account.getNumber());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Timed
|
@Timed
|
||||||
|
@ -413,7 +424,11 @@ public class AccountController {
|
||||||
newUserMeter.mark();
|
newUserMeter.mark();
|
||||||
}
|
}
|
||||||
|
|
||||||
directoryQueue.addRegisteredUser(number);
|
if (account.isActive()) {
|
||||||
|
directoryQueue.addRegisteredUser(number);
|
||||||
|
} else {
|
||||||
|
directoryQueue.deleteRegisteredUser(number);
|
||||||
|
}
|
||||||
|
|
||||||
messagesManager.clear(number);
|
messagesManager.clear(number);
|
||||||
pendingAccounts.remove(number);
|
pendingAccounts.remove(number);
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.whispersystems.textsecuregcm.entities.PreKeyResponseItem;
|
||||||
import org.whispersystems.textsecuregcm.entities.PreKeyState;
|
import org.whispersystems.textsecuregcm.entities.PreKeyState;
|
||||||
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||||
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
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.Device;
|
import org.whispersystems.textsecuregcm.storage.Device;
|
||||||
|
@ -61,11 +62,13 @@ public class KeysController {
|
||||||
private final RateLimiters rateLimiters;
|
private final RateLimiters rateLimiters;
|
||||||
private final Keys keys;
|
private final Keys keys;
|
||||||
private final AccountsManager accounts;
|
private final AccountsManager accounts;
|
||||||
|
private final DirectoryQueue directoryQueue;
|
||||||
|
|
||||||
public KeysController(RateLimiters rateLimiters, Keys keys, AccountsManager accounts) {
|
public KeysController(RateLimiters rateLimiters, Keys keys, AccountsManager accounts, DirectoryQueue directoryQueue) {
|
||||||
this.rateLimiters = rateLimiters;
|
this.rateLimiters = rateLimiters;
|
||||||
this.keys = keys;
|
this.keys = keys;
|
||||||
this.accounts = accounts;
|
this.accounts = accounts;
|
||||||
|
this.directoryQueue = directoryQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -84,8 +87,9 @@ public class KeysController {
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public void setKeys(@Auth Account account, @Valid PreKeyState preKeys) {
|
public void setKeys(@Auth Account account, @Valid PreKeyState preKeys) {
|
||||||
Device device = account.getAuthenticatedDevice().get();
|
Device device = account.getAuthenticatedDevice().get();
|
||||||
boolean updateAccount = false;
|
boolean wasAccountActive = account.isActive();
|
||||||
|
boolean updateAccount = false;
|
||||||
|
|
||||||
if (!preKeys.getSignedPreKey().equals(device.getSignedPreKey())) {
|
if (!preKeys.getSignedPreKey().equals(device.getSignedPreKey())) {
|
||||||
device.setSignedPreKey(preKeys.getSignedPreKey());
|
device.setSignedPreKey(preKeys.getSignedPreKey());
|
||||||
|
@ -99,6 +103,10 @@ public class KeysController {
|
||||||
|
|
||||||
if (updateAccount) {
|
if (updateAccount) {
|
||||||
accounts.update(account);
|
accounts.update(account);
|
||||||
|
|
||||||
|
if (!wasAccountActive && account.isActive()) {
|
||||||
|
directoryQueue.addRegisteredUser(account.getNumber());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keys.store(account.getNumber(), device.getId(), preKeys.getPreKeys());
|
keys.store(account.getNumber(), device.getId(), preKeys.getPreKeys());
|
||||||
|
@ -158,9 +166,15 @@ public class KeysController {
|
||||||
@Path("/signed")
|
@Path("/signed")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public void setSignedKey(@Auth Account account, @Valid SignedPreKey signedPreKey) {
|
public void setSignedKey(@Auth Account account, @Valid SignedPreKey signedPreKey) {
|
||||||
Device device = account.getAuthenticatedDevice().get();
|
Device device = account.getAuthenticatedDevice().get();
|
||||||
|
boolean wasAccountActive = account.isActive();
|
||||||
|
|
||||||
device.setSignedPreKey(signedPreKey);
|
device.setSignedPreKey(signedPreKey);
|
||||||
accounts.update(account);
|
accounts.update(account);
|
||||||
|
|
||||||
|
if (!wasAccountActive && account.isActive()) {
|
||||||
|
directoryQueue.addRegisteredUser(account.getNumber());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Timed
|
@Timed
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.whispersystems.textsecuregcm.WhisperServerConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials;
|
import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials;
|
||||||
import org.whispersystems.textsecuregcm.providers.RedisClientFactory;
|
import org.whispersystems.textsecuregcm.providers.RedisClientFactory;
|
||||||
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
||||||
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
import org.whispersystems.textsecuregcm.storage.Accounts;
|
import org.whispersystems.textsecuregcm.storage.Accounts;
|
||||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||||
|
@ -76,6 +77,7 @@ public class DeleteUserCommand extends EnvironmentCommand<WhisperServerConfigura
|
||||||
Accounts accounts = dbi.onDemand(Accounts.class);
|
Accounts accounts = dbi.onDemand(Accounts.class);
|
||||||
ReplicatedJedisPool cacheClient = new RedisClientFactory(configuration.getCacheConfiguration().getUrl(), configuration.getCacheConfiguration().getReplicaUrls()).getRedisClientPool();
|
ReplicatedJedisPool cacheClient = new RedisClientFactory(configuration.getCacheConfiguration().getUrl(), configuration.getCacheConfiguration().getReplicaUrls()).getRedisClientPool();
|
||||||
ReplicatedJedisPool redisClient = new RedisClientFactory(configuration.getDirectoryConfiguration().getRedisConfiguration().getUrl(), configuration.getDirectoryConfiguration().getRedisConfiguration().getReplicaUrls()).getRedisClientPool();
|
ReplicatedJedisPool redisClient = new RedisClientFactory(configuration.getDirectoryConfiguration().getRedisConfiguration().getUrl(), configuration.getDirectoryConfiguration().getRedisConfiguration().getReplicaUrls()).getRedisClientPool();
|
||||||
|
DirectoryQueue directoryQueue = new DirectoryQueue(configuration.getDirectoryConfiguration().getSqsConfiguration());
|
||||||
DirectoryManager directory = new DirectoryManager(redisClient);
|
DirectoryManager directory = new DirectoryManager(redisClient);
|
||||||
AccountsManager accountsManager = new AccountsManager(accounts, directory, cacheClient);
|
AccountsManager accountsManager = new AccountsManager(accounts, directory, cacheClient);
|
||||||
|
|
||||||
|
@ -94,6 +96,7 @@ public class DeleteUserCommand extends EnvironmentCommand<WhisperServerConfigura
|
||||||
device.get().setAuthenticationCredentials(new AuthenticationCredentials(Base64.encodeBytes(random)));
|
device.get().setAuthenticationCredentials(new AuthenticationCredentials(Base64.encodeBytes(random)));
|
||||||
|
|
||||||
accountsManager.update(account.get());
|
accountsManager.update(account.get());
|
||||||
|
directoryQueue.deleteRegisteredUser(account.get().getNumber());
|
||||||
|
|
||||||
logger.warn("Removed " + account.get().getNumber());
|
logger.warn("Removed " + account.get().getNumber());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -236,7 +236,7 @@ public class AccountControllerTest {
|
||||||
assertThat(response.getStatus()).isEqualTo(204);
|
assertThat(response.getStatus()).isEqualTo(204);
|
||||||
|
|
||||||
verify(accountsManager, times(1)).create(isA(Account.class));
|
verify(accountsManager, times(1)).create(isA(Account.class));
|
||||||
verify(directoryQueue, times(1)).addRegisteredUser(eq(SENDER));
|
verify(directoryQueue, times(1)).deleteRegisteredUser(eq(SENDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.whispersystems.textsecuregcm.entities.PreKeyState;
|
||||||
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||||
|
import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
|
||||||
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.Device;
|
import org.whispersystems.textsecuregcm.storage.Device;
|
||||||
|
@ -54,9 +55,10 @@ public class KeyControllerTest {
|
||||||
private final SignedPreKey SAMPLE_SIGNED_KEY2 = new SignedPreKey(2222, "foobar", "sig22");
|
private final SignedPreKey SAMPLE_SIGNED_KEY2 = new SignedPreKey(2222, "foobar", "sig22");
|
||||||
private final SignedPreKey SAMPLE_SIGNED_KEY3 = new SignedPreKey(3333, "barfoo", "sig33");
|
private final SignedPreKey SAMPLE_SIGNED_KEY3 = new SignedPreKey(3333, "barfoo", "sig33");
|
||||||
|
|
||||||
private final Keys keys = mock(Keys.class );
|
private final Keys keys = mock(Keys.class );
|
||||||
private final AccountsManager accounts = mock(AccountsManager.class);
|
private final AccountsManager accounts = mock(AccountsManager.class);
|
||||||
private final Account existsAccount = mock(Account.class );
|
private final DirectoryQueue directoryQueue = mock(DirectoryQueue.class);
|
||||||
|
private final Account existsAccount = mock(Account.class );
|
||||||
|
|
||||||
private RateLimiters rateLimiters = mock(RateLimiters.class);
|
private RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||||
private RateLimiter rateLimiter = mock(RateLimiter.class );
|
private RateLimiter rateLimiter = mock(RateLimiter.class );
|
||||||
|
@ -66,7 +68,7 @@ public class KeyControllerTest {
|
||||||
.addProvider(AuthHelper.getAuthFilter())
|
.addProvider(AuthHelper.getAuthFilter())
|
||||||
.addProvider(new AuthValueFactoryProvider.Binder<>(Account.class))
|
.addProvider(new AuthValueFactoryProvider.Binder<>(Account.class))
|
||||||
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
|
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
|
||||||
.addResource(new KeysController(rateLimiters, keys, accounts))
|
.addResource(new KeysController(rateLimiters, keys, accounts, directoryQueue))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
|
Loading…
Reference in New Issue