Move "remove device" logic into AccountsManager

This commit is contained in:
Jon Chambers
2023-11-29 12:07:57 -05:00
committed by Jon Chambers
parent 4f42c10d60
commit 37e3bcfc3e
9 changed files with 88 additions and 58 deletions

View File

@@ -15,7 +15,6 @@ import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -801,13 +800,16 @@ class DeviceControllerTest {
}
@Test
void deviceRemovalClearsMessagesAndKeys() {
void removeDevice() {
// this is a static mock, so it might have previous invocations
clearInvocations(AuthHelper.VALID_ACCOUNT);
final byte deviceId = 2;
when(accountsManager.removeDevice(AuthHelper.VALID_ACCOUNT, deviceId))
.thenReturn(CompletableFuture.completedFuture(AuthHelper.VALID_ACCOUNT));
final Response response = resources
.getJerseyTest()
.target("/v1/devices/" + deviceId)
@@ -819,10 +821,7 @@ class DeviceControllerTest {
assertThat(response.getStatus()).isEqualTo(204);
assertThat(response.hasEntity()).isFalse();
verify(messagesManager, times(2)).clear(AuthHelper.VALID_UUID, deviceId);
verify(accountsManager, times(1)).update(eq(AuthHelper.VALID_ACCOUNT), any());
verify(AuthHelper.VALID_ACCOUNT).removeDevice(deviceId);
verify(keysManager).delete(AuthHelper.VALID_UUID, deviceId);
verify(accountsManager).removeDevice(AuthHelper.VALID_ACCOUNT, deviceId);
}
@Test
@@ -840,10 +839,7 @@ class DeviceControllerTest {
assertThat(response.getStatus()).isEqualTo(403);
verify(messagesManager, never()).clear(any(), anyByte());
verify(accountsManager, never()).update(eq(AuthHelper.VALID_ACCOUNT), any());
verify(AuthHelper.VALID_ACCOUNT, never()).removeDevice(anyByte());
verify(keysManager, never()).delete(any(), anyByte());
verify(accountsManager, never()).removeDevice(any(), anyByte());
}
}

View File

@@ -149,13 +149,14 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
void removeDevice() {
final byte deviceId = 17;
when(accountsManager.removeDevice(any(), anyByte()))
.thenReturn(CompletableFuture.completedFuture(authenticatedAccount));
final RemoveDeviceResponse ignored = authenticatedServiceStub().removeDevice(RemoveDeviceRequest.newBuilder()
.setId(deviceId)
.build());
verify(messagesManager, times(2)).clear(AUTHENTICATED_ACI, deviceId);
verify(keysManager).delete(AUTHENTICATED_ACI, deviceId);
verify(authenticatedAccount).removeDevice(deviceId);
verify(accountsManager).removeDevice(authenticatedAccount, deviceId);
}
@Test
@@ -163,6 +164,8 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
assertStatusException(Status.INVALID_ARGUMENT, () -> authenticatedServiceStub().removeDevice(RemoveDeviceRequest.newBuilder()
.setId(1)
.build()));
verify(accountsManager, never()).removeDevice(any(), anyByte());
}
@Test
@@ -171,6 +174,8 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
assertStatusException(Status.PERMISSION_DENIED, () -> authenticatedServiceStub().removeDevice(RemoveDeviceRequest.newBuilder()
.setId(17)
.build()));
verify(accountsManager, never()).removeDevice(any(), anyByte());
}
@ParameterizedTest

View File

@@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyByte;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -930,6 +931,47 @@ class AccountsManagerTest {
verify(unknownDeviceUpdater, never()).accept(any(Device.class));
}
@Test
void testRemoveDevice() {
final Device primaryDevice = new Device();
primaryDevice.setId(Device.PRIMARY_ID);
final Device linkedDevice = new Device();
linkedDevice.setId((byte) (Device.PRIMARY_ID + 1));
Account account = AccountsHelper.generateTestAccount("+14152222222", List.of(primaryDevice, linkedDevice));
when(keysManager.delete(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
when(messagesManager.clear(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
assertTrue(account.getDevice(linkedDevice.getId()).isPresent());
account = accountsManager.removeDevice(account, linkedDevice.getId()).join();
assertFalse(account.getDevice(linkedDevice.getId()).isPresent());
verify(messagesManager, times(2)).clear(account.getUuid(), linkedDevice.getId());
verify(keysManager).delete(account.getUuid(), linkedDevice.getId());
verify(clientPresenceManager).disconnectPresence(account.getUuid(), linkedDevice.getId());
}
@Test
void testRemovePrimaryDevice() {
final Device primaryDevice = new Device();
primaryDevice.setId(Device.PRIMARY_ID);
final Account account = AccountsHelper.generateTestAccount("+14152222222", List.of(primaryDevice));
when(keysManager.delete(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
when(messagesManager.clear(any(), anyByte())).thenReturn(CompletableFuture.completedFuture(null));
assertThrows(IllegalArgumentException.class, () -> accountsManager.removeDevice(account, Device.PRIMARY_ID));
assertTrue(account.getPrimaryDevice().isPresent());
verify(messagesManager, never()).clear(any(), anyByte());
verify(keysManager, never()).delete(any(), anyByte());
verify(clientPresenceManager, never()).disconnectPresence(any(), anyByte());
}
@Test
void testCreateFreshAccount() throws InterruptedException {
when(accounts.create(any(), any())).thenReturn(true);

View File

@@ -6,7 +6,6 @@
package org.whispersystems.textsecuregcm.storage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.mockito.ArgumentMatchers.any;
@@ -17,8 +16,6 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.whispersystems.textsecuregcm.util.MockUtils.exactly;
@@ -49,8 +46,6 @@ import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfigurati
import org.whispersystems.textsecuregcm.entities.MessageProtos;
import org.whispersystems.textsecuregcm.push.ClientPresenceManager;
import org.whispersystems.textsecuregcm.redis.RedisClusterExtension;
import org.whispersystems.textsecuregcm.storage.KeysManager;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
@@ -93,6 +88,9 @@ class MessagePersisterTest {
destinationAccount = mock(Account.class);;
when(accountsManager.getByAccountIdentifier(DESTINATION_ACCOUNT_UUID)).thenReturn(Optional.of(destinationAccount));
when(accountsManager.removeDevice(any(), anyByte()))
.thenAnswer(invocation -> CompletableFuture.completedFuture(invocation.getArgument(0)));
when(destinationAccount.getUuid()).thenReturn(DESTINATION_ACCOUNT_UUID);
when(destinationAccount.getNumber()).thenReturn(DESTINATION_ACCOUNT_NUMBER);
when(dynamicConfigurationManager.getConfiguration()).thenReturn(new DynamicConfiguration());