mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-23 21:28:06 +01:00
Introduce and evaluate a client presence manager based on sharded pub/sub
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.auth;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -61,6 +60,7 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.whispersystems.textsecuregcm.filters.RemoteAddressFilter;
|
||||
import org.whispersystems.textsecuregcm.push.ClientPresenceManager;
|
||||
import org.whispersystems.textsecuregcm.push.PubSubClientEventManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
@@ -97,6 +97,7 @@ class LinkedDeviceRefreshRequirementProviderTest {
|
||||
|
||||
private AccountsManager accountsManager;
|
||||
private ClientPresenceManager clientPresenceManager;
|
||||
private PubSubClientEventManager pubSubClientEventManager;
|
||||
|
||||
private LinkedDeviceRefreshRequirementProvider provider;
|
||||
|
||||
@@ -104,11 +105,12 @@ class LinkedDeviceRefreshRequirementProviderTest {
|
||||
void setup() {
|
||||
accountsManager = mock(AccountsManager.class);
|
||||
clientPresenceManager = mock(ClientPresenceManager.class);
|
||||
pubSubClientEventManager = mock(PubSubClientEventManager.class);
|
||||
|
||||
provider = new LinkedDeviceRefreshRequirementProvider(accountsManager);
|
||||
|
||||
final WebsocketRefreshRequestEventListener listener =
|
||||
new WebsocketRefreshRequestEventListener(clientPresenceManager, provider);
|
||||
new WebsocketRefreshRequestEventListener(clientPresenceManager, pubSubClientEventManager, provider);
|
||||
|
||||
when(applicationEventListener.onRequest(any())).thenReturn(listener);
|
||||
|
||||
@@ -146,6 +148,10 @@ class LinkedDeviceRefreshRequirementProviderTest {
|
||||
verify(clientPresenceManager).disconnectPresence(account.getUuid(), (byte) 1);
|
||||
verify(clientPresenceManager).disconnectPresence(account.getUuid(), (byte) 2);
|
||||
verify(clientPresenceManager).disconnectPresence(account.getUuid(), (byte) 3);
|
||||
|
||||
verify(pubSubClientEventManager).requestDisconnection(account.getUuid(), List.of((byte) 1));
|
||||
verify(pubSubClientEventManager).requestDisconnection(account.getUuid(), List.of((byte) 2));
|
||||
verify(pubSubClientEventManager).requestDisconnection(account.getUuid(), List.of((byte) 3));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -173,8 +179,10 @@ class LinkedDeviceRefreshRequirementProviderTest {
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
initialDeviceIds.forEach(deviceId ->
|
||||
verify(clientPresenceManager).disconnectPresence(account.getUuid(), deviceId));
|
||||
initialDeviceIds.forEach(deviceId -> {
|
||||
verify(clientPresenceManager).disconnectPresence(account.getUuid(), deviceId);
|
||||
verify(pubSubClientEventManager).requestDisconnection(account.getUuid(), List.of(deviceId));
|
||||
});
|
||||
|
||||
verifyNoMoreInteractions(clientPresenceManager);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.DispatcherType;
|
||||
@@ -47,6 +48,7 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.whispersystems.textsecuregcm.filters.RemoteAddressFilter;
|
||||
import org.whispersystems.textsecuregcm.push.ClientPresenceManager;
|
||||
import org.whispersystems.textsecuregcm.push.PubSubClientEventManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
@@ -74,6 +76,7 @@ class PhoneNumberChangeRefreshRequirementProviderTest {
|
||||
private static final AccountAuthenticator AUTHENTICATOR = mock(AccountAuthenticator.class);
|
||||
private static final AccountsManager ACCOUNTS_MANAGER = mock(AccountsManager.class);
|
||||
private static final ClientPresenceManager CLIENT_PRESENCE = mock(ClientPresenceManager.class);
|
||||
private static final PubSubClientEventManager PUBSUB_CLIENT_PRESENCE = mock(PubSubClientEventManager.class);
|
||||
|
||||
private WebSocketClient client;
|
||||
private final Account account1 = new Account();
|
||||
@@ -122,9 +125,9 @@ class PhoneNumberChangeRefreshRequirementProviderTest {
|
||||
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");
|
||||
webSocketEnvironment.jersey().register(new RemoteAddressFilter());
|
||||
webSocketEnvironment.jersey()
|
||||
.register(new WebsocketRefreshApplicationEventListener(ACCOUNTS_MANAGER, CLIENT_PRESENCE));
|
||||
.register(new WebsocketRefreshApplicationEventListener(ACCOUNTS_MANAGER, CLIENT_PRESENCE, PUBSUB_CLIENT_PRESENCE));
|
||||
environment.jersey()
|
||||
.register(new WebsocketRefreshApplicationEventListener(ACCOUNTS_MANAGER, CLIENT_PRESENCE));
|
||||
.register(new WebsocketRefreshApplicationEventListener(ACCOUNTS_MANAGER, CLIENT_PRESENCE, PUBSUB_CLIENT_PRESENCE));
|
||||
webSocketEnvironment.setConnectListener(webSocketSessionContext -> {
|
||||
});
|
||||
|
||||
@@ -215,6 +218,10 @@ class PhoneNumberChangeRefreshRequirementProviderTest {
|
||||
verify(CLIENT_PRESENCE, timeout(5000))
|
||||
.disconnectPresence(eq(account1.getUuid()), eq(authenticatedDevice.getId()));
|
||||
verifyNoMoreInteractions(CLIENT_PRESENCE);
|
||||
|
||||
verify(PUBSUB_CLIENT_PRESENCE, timeout(5000))
|
||||
.requestDisconnection(account1.getUuid(), List.of(authenticatedDevice.getId()));
|
||||
verifyNoMoreInteractions(PUBSUB_CLIENT_PRESENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -231,6 +238,10 @@ class PhoneNumberChangeRefreshRequirementProviderTest {
|
||||
verify(CLIENT_PRESENCE, timeout(5000))
|
||||
.disconnectPresence(eq(account1.getUuid()), eq(authenticatedDevice.getId()));
|
||||
verifyNoMoreInteractions(CLIENT_PRESENCE);
|
||||
|
||||
verify(PUBSUB_CLIENT_PRESENCE, timeout(5000))
|
||||
.requestDisconnection(account1.getUuid(), List.of(authenticatedDevice.getId()));
|
||||
verifyNoMoreInteractions(PUBSUB_CLIENT_PRESENCE);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.push.ClientPresenceManager;
|
||||
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
||||
import org.whispersystems.textsecuregcm.push.PubSubClientEventManager;
|
||||
import org.whispersystems.textsecuregcm.push.PushNotificationManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
@@ -47,6 +48,7 @@ class RegistrationLockVerificationManagerTest {
|
||||
|
||||
private final AccountsManager accountsManager = mock(AccountsManager.class);
|
||||
private final ClientPresenceManager clientPresenceManager = mock(ClientPresenceManager.class);
|
||||
private final PubSubClientEventManager pubSubClientEventManager = mock(PubSubClientEventManager.class);
|
||||
private final ExternalServiceCredentialsGenerator svr2CredentialsGenerator = mock(
|
||||
ExternalServiceCredentialsGenerator.class);
|
||||
private final ExternalServiceCredentialsGenerator svr3CredentialsGenerator = mock(
|
||||
@@ -56,7 +58,7 @@ class RegistrationLockVerificationManagerTest {
|
||||
private static PushNotificationManager pushNotificationManager = mock(PushNotificationManager.class);
|
||||
private final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
private final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager(
|
||||
accountsManager, clientPresenceManager, svr2CredentialsGenerator, svr3CredentialsGenerator,
|
||||
accountsManager, clientPresenceManager, pubSubClientEventManager, svr2CredentialsGenerator, svr3CredentialsGenerator,
|
||||
registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters);
|
||||
|
||||
private final RateLimiter pinLimiter = mock(RateLimiter.class);
|
||||
@@ -108,6 +110,7 @@ class RegistrationLockVerificationManagerTest {
|
||||
verify(registrationRecoveryPasswordsManager, never()).removeForNumber(account.getNumber());
|
||||
}
|
||||
verify(clientPresenceManager).disconnectAllPresences(account.getUuid(), List.of(Device.PRIMARY_ID));
|
||||
verify(pubSubClientEventManager).requestDisconnection(account.getUuid(), List.of(Device.PRIMARY_ID));
|
||||
try {
|
||||
verify(pushNotificationManager).sendAttemptLoginNotification(any(), eq("failedRegistrationLock"));
|
||||
} catch (NotPushRegisteredException npre) {}
|
||||
@@ -131,6 +134,7 @@ class RegistrationLockVerificationManagerTest {
|
||||
} catch (NotPushRegisteredException npre) {}
|
||||
verify(registrationRecoveryPasswordsManager, never()).removeForNumber(account.getNumber());
|
||||
verify(clientPresenceManager, never()).disconnectAllPresences(account.getUuid(), List.of(Device.PRIMARY_ID));
|
||||
verify(pubSubClientEventManager, never()).requestDisconnection(any(), any());
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -169,6 +173,7 @@ class RegistrationLockVerificationManagerTest {
|
||||
verify(account, never()).lockAuthTokenHash();
|
||||
verify(registrationRecoveryPasswordsManager, never()).removeForNumber(account.getNumber());
|
||||
verify(clientPresenceManager, never()).disconnectAllPresences(account.getUuid(), List.of(Device.PRIMARY_ID));
|
||||
verify(pubSubClientEventManager, never()).requestDisconnection(any(), any());
|
||||
}
|
||||
|
||||
static Stream<Arguments> testSuccess() {
|
||||
|
||||
Reference in New Issue
Block a user