Remove expiration check from `Device#isEnabled()`

This commit is contained in:
Jon Chambers 2024-06-07 13:39:11 -04:00 committed by GitHub
parent b376458963
commit 2f55747601
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 99 additions and 128 deletions

View File

@ -23,9 +23,9 @@ import org.whispersystems.textsecuregcm.util.Pair;
/**
* This {@link WebsocketRefreshRequirementProvider} observes intra-request changes in {@link Account#isEnabled()} and
* {@link Device#isEnabled()}.
* {@link Device#hasMessageDeliveryChannel()}.
* <p>
* If a change in {@link Account#isEnabled()} or any associated {@link Device#isEnabled()} is observed, then any active
* If a change in {@link Account#isEnabled()} or any associated {@link Device#hasMessageDeliveryChannel()} is observed, then any active
* WebSocket connections for the account must be closed in order for clients to get a refreshed
* {@link io.dropwizard.auth.Auth} object with a current device list.
*

View File

@ -17,7 +17,7 @@ import java.util.stream.Collectors;
class ContainerRequestUtil {
private static Map<Byte, Boolean> buildDevicesEnabledMap(final Account account) {
return account.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::isEnabled));
return account.getDevices().stream().collect(Collectors.toMap(Device::getId, Device::hasMessageDeliveryChannel));
}
/**

View File

@ -31,7 +31,7 @@ public class OptionalAccess {
Optional<Device> targetDevice = targetAccount.get().getDevice(deviceId);
if (targetDevice.isPresent() && targetDevice.get().isEnabled()) {
if (targetDevice.isPresent() && targetDevice.get().hasMessageDeliveryChannel()) {
return;
}

View File

@ -440,11 +440,11 @@ public class KeysController {
private List<Device> parseDeviceId(String deviceId, Account account) {
if (deviceId.equals("*")) {
return account.getDevices().stream().filter(Device::isEnabled).toList();
return account.getDevices().stream().filter(Device::hasMessageDeliveryChannel).toList();
}
try {
byte id = Byte.parseByte(deviceId);
return account.getDevice(id).filter(Device::isEnabled).map(List::of).orElse(List.of());
return account.getDevice(id).filter(Device::hasMessageDeliveryChannel).map(List::of).orElse(List.of());
} catch (NumberFormatException e) {
throw new WebApplicationException(Response.status(422).build());
}

View File

@ -39,7 +39,7 @@ class KeysGrpcHelper {
: Flux.from(Mono.justOrEmpty(targetAccount.getDevice(targetDeviceId)));
return devices
.filter(Device::isEnabled)
.filter(Device::hasMessageDeliveryChannel)
.switchIfEmpty(Mono.error(Status.NOT_FOUND.asException()))
.flatMap(device -> Flux.merge(
Mono.fromFuture(() -> keysManager.takeEC(targetAccount.getIdentifier(identityType), device.getId())),

View File

@ -296,14 +296,14 @@ public class Account {
requireNotStale();
return devices.stream()
.filter(Device::isEnabled)
.filter(Device::hasMessageDeliveryChannel)
.allMatch(device -> device.getCapabilities() != null && predicate.test(device.getCapabilities()));
}
public boolean isEnabled() {
requireNotStale();
return getPrimaryDevice().isEnabled();
return getPrimaryDevice().hasMessageDeliveryChannel();
}
public byte getNextDeviceId() {
@ -327,7 +327,7 @@ public class Account {
return devices.stream()
.filter(d -> Device.PRIMARY_ID != d.getId())
.anyMatch(Device::isEnabled);
.anyMatch(Device::hasMessageDeliveryChannel);
}
public void setIdentityKey(final IdentityKey identityKey) {

View File

@ -490,7 +490,7 @@ public class AccountsManager {
account.getDevices()
.stream()
.filter(Device::isEnabled)
.filter(Device::hasMessageDeliveryChannel)
.forEach(device -> device.setPhoneNumberIdentityRegistrationId(pniRegistrationIds.get(device.getId())));
account.setPhoneNumberIdentityKey(pniIdentityKey);

View File

@ -11,7 +11,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.Duration;
import java.util.List;
import java.util.OptionalInt;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
@ -199,10 +198,8 @@ public class Device {
this.capabilities = capabilities;
}
public boolean isEnabled() {
boolean hasChannel = fetchesMessages || StringUtils.isNotEmpty(getApnId()) || StringUtils.isNotEmpty(getGcmId());
return (id == PRIMARY_ID && hasChannel) || (id != PRIMARY_ID && hasChannel && !isExpired());
public boolean hasMessageDeliveryChannel() {
return fetchesMessages || StringUtils.isNotEmpty(getApnId()) || StringUtils.isNotEmpty(getGcmId());
}
public boolean isExpired() {

View File

@ -245,7 +245,7 @@ public class MessagePersister implements Managed {
// its messages) is unlinked
final Device deviceToDelete = account.getDevices()
.stream()
.filter(d -> !d.isPrimary() && !d.isEnabled())
.filter(d -> !d.isPrimary() && !d.hasMessageDeliveryChannel())
.min(Comparator.comparing(Device::getLastSeen))
.or(() ->
Flux.fromIterable(account.getDevices())

View File

@ -89,7 +89,7 @@ public class DestinationDeviceValidator {
final Set<Byte> excludedDeviceIds) throws MismatchedDevicesException {
final Set<Byte> accountDeviceIds = account.getDevices().stream()
.filter(Device::isEnabled)
.filter(Device::hasMessageDeliveryChannel)
.map(Device::getId)
.filter(deviceId -> !excludedDeviceIds.contains(deviceId))
.collect(Collectors.toSet());

View File

@ -130,7 +130,7 @@ public class ProcessPushNotificationFeedbackCommand extends AbstractSinglePassCr
@VisibleForTesting
boolean deviceNeedsUpdate(final Device device) {
return pushFeedbackIntervalElapsed(device) && (device.isEnabled() || device.getLastSeen() > device.getUninstalledFeedbackTimestamp());
return pushFeedbackIntervalElapsed(device) && (device.hasMessageDeliveryChannel() || device.getLastSeen() > device.getUninstalledFeedbackTimestamp());
}
@VisibleForTesting

View File

@ -163,7 +163,7 @@ class AccountAuthenticatorTest {
when(account.getDevice(deviceId)).thenReturn(Optional.of(device));
when(account.isEnabled()).thenReturn(true);
when(device.getId()).thenReturn(deviceId);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getAuthTokenHash()).thenReturn(credentials);
when(credentials.verify(password)).thenReturn(true);
when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION);
@ -193,7 +193,7 @@ class AccountAuthenticatorTest {
when(account.getDevice(deviceId)).thenReturn(Optional.of(device));
when(account.isEnabled()).thenReturn(true);
when(device.getId()).thenReturn(deviceId);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getAuthTokenHash()).thenReturn(credentials);
when(credentials.verify(password)).thenReturn(true);
when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION);
@ -226,7 +226,7 @@ class AccountAuthenticatorTest {
when(account.getDevice(deviceId)).thenReturn(Optional.of(authenticatedDevice));
when(account.isEnabled()).thenReturn(accountEnabled);
when(authenticatedDevice.getId()).thenReturn(deviceId);
when(authenticatedDevice.isEnabled()).thenReturn(deviceEnabled);
when(authenticatedDevice.hasMessageDeliveryChannel()).thenReturn(deviceEnabled);
when(authenticatedDevice.getAuthTokenHash()).thenReturn(credentials);
when(credentials.verify(password)).thenReturn(true);
when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION);
@ -262,7 +262,7 @@ class AccountAuthenticatorTest {
when(account.getDevice(deviceId)).thenReturn(Optional.of(device));
when(account.isEnabled()).thenReturn(true);
when(device.getId()).thenReturn(deviceId);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getAuthTokenHash()).thenReturn(credentials);
when(credentials.verify(password)).thenReturn(true);
when(credentials.getVersion()).thenReturn(SaltedTokenHash.Version.V1);
@ -299,7 +299,7 @@ class AccountAuthenticatorTest {
when(account.getDevice(deviceId)).thenReturn(Optional.of(device));
when(account.isEnabled()).thenReturn(true);
when(device.getId()).thenReturn(deviceId);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getAuthTokenHash()).thenReturn(credentials);
when(credentials.verify(password)).thenReturn(true);
when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION);
@ -327,7 +327,7 @@ class AccountAuthenticatorTest {
when(account.getDevice(deviceId)).thenReturn(Optional.of(device));
when(account.isEnabled()).thenReturn(true);
when(device.getId()).thenReturn(deviceId);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getAuthTokenHash()).thenReturn(credentials);
when(credentials.verify(password)).thenReturn(true);
when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION);

View File

@ -136,7 +136,7 @@ class AuthEnablementRefreshRequirementProviderTest {
void testDeviceEnabledChanged(final Map<Byte, Boolean> initialEnabled, final Map<Byte, Boolean> finalEnabled) {
assert initialEnabled.size() == finalEnabled.size();
assert account.getPrimaryDevice().isEnabled();
assert account.getPrimaryDevice().hasMessageDeliveryChannel();
initialEnabled.forEach((deviceId, enabled) ->
DevicesHelper.setEnabled(account.getDevice(deviceId).orElseThrow(), enabled));
@ -177,7 +177,7 @@ class AuthEnablementRefreshRequirementProviderTest {
@Test
void testDeviceAdded() {
assert account.getPrimaryDevice().isEnabled();
assert account.getPrimaryDevice().hasMessageDeliveryChannel();
final int initialDeviceCount = account.getDevices().size();
@ -204,7 +204,7 @@ class AuthEnablementRefreshRequirementProviderTest {
@ParameterizedTest
@ValueSource(ints = {1, 2})
void testDeviceRemoved(final int removedDeviceCount) {
assert account.getPrimaryDevice().isEnabled();
assert account.getPrimaryDevice().hasMessageDeliveryChannel();
final List<Byte> initialDeviceIds = account.getDevices().stream().map(Device::getId).toList();
@ -367,7 +367,7 @@ class AuthEnablementRefreshRequirementProviderTest {
DevicesHelper.setEnabled(device, enabled);
assert device.isEnabled() == enabled;
assert device.hasMessageDeliveryChannel() == enabled;
return String.format("Set account to %s", enabled);
}

View File

@ -35,7 +35,7 @@ public class ContainerRequestUtilTest {
.forEach(id -> {
final Device device = mock(Device.class);
when(device.getId()).thenReturn((byte) id);
when(device.isEnabled()).thenReturn(id != disabledDeviceId);
when(device.hasMessageDeliveryChannel()).thenReturn(id != disabledDeviceId);
devices.add(device);
});

View File

@ -221,10 +221,10 @@ class KeysControllerTest {
when(sampleDevice3.getRegistrationId()).thenReturn(SAMPLE_REGISTRATION_ID2);
when(sampleDevice4.getRegistrationId()).thenReturn(SAMPLE_REGISTRATION_ID4);
when(sampleDevice.getPhoneNumberIdentityRegistrationId()).thenReturn(OptionalInt.of(SAMPLE_PNI_REGISTRATION_ID));
when(sampleDevice.isEnabled()).thenReturn(true);
when(sampleDevice2.isEnabled()).thenReturn(true);
when(sampleDevice3.isEnabled()).thenReturn(false);
when(sampleDevice4.isEnabled()).thenReturn(true);
when(sampleDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(sampleDevice2.hasMessageDeliveryChannel()).thenReturn(true);
when(sampleDevice3.hasMessageDeliveryChannel()).thenReturn(false);
when(sampleDevice4.hasMessageDeliveryChannel()).thenReturn(true);
when(sampleDevice.getId()).thenReturn(sampleDeviceId);
when(sampleDevice2.getId()).thenReturn(sampleDevice2Id);
when(sampleDevice3.getId()).thenReturn(sampleDevice3Id);

View File

@ -58,7 +58,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@ -211,13 +210,13 @@ class MessageControllerTest {
@BeforeEach
void setup() {
final List<Device> singleDeviceList = List.of(
generateTestDevice(SINGLE_DEVICE_ID1, SINGLE_DEVICE_REG_ID1, SINGLE_DEVICE_PNI_REG_ID1, System.currentTimeMillis(), System.currentTimeMillis())
generateTestDevice(SINGLE_DEVICE_ID1, SINGLE_DEVICE_REG_ID1, SINGLE_DEVICE_PNI_REG_ID1, true)
);
final List<Device> multiDeviceList = List.of(
generateTestDevice(MULTI_DEVICE_ID1, MULTI_DEVICE_REG_ID1, MULTI_DEVICE_PNI_REG_ID1, System.currentTimeMillis(), System.currentTimeMillis()),
generateTestDevice(MULTI_DEVICE_ID2, MULTI_DEVICE_REG_ID2, MULTI_DEVICE_PNI_REG_ID2, System.currentTimeMillis(), System.currentTimeMillis()),
generateTestDevice(MULTI_DEVICE_ID3, MULTI_DEVICE_REG_ID3, MULTI_DEVICE_PNI_REG_ID3, System.currentTimeMillis(), System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31))
generateTestDevice(MULTI_DEVICE_ID1, MULTI_DEVICE_REG_ID1, MULTI_DEVICE_PNI_REG_ID1, true),
generateTestDevice(MULTI_DEVICE_ID2, MULTI_DEVICE_REG_ID2, MULTI_DEVICE_PNI_REG_ID2, true),
generateTestDevice(MULTI_DEVICE_ID3, MULTI_DEVICE_REG_ID3, MULTI_DEVICE_PNI_REG_ID3, false)
);
Account singleDeviceAccount = AccountsHelper.generateTestAccount(SINGLE_DEVICE_RECIPIENT, SINGLE_DEVICE_UUID, SINGLE_DEVICE_PNI, singleDeviceList, UNIDENTIFIED_ACCESS_BYTES);
@ -260,14 +259,12 @@ class MessageControllerTest {
}
private static Device generateTestDevice(final byte id, final int registrationId, final int pniRegistrationId,
final long createdAt, final long lastSeen) {
final boolean enabled) {
final Device device = new Device();
device.setId(id);
device.setRegistrationId(registrationId);
device.setPhoneNumberIdentityRegistrationId(pniRegistrationId);
device.setCreated(createdAt);
device.setLastSeen(lastSeen);
device.setGcmId("isgcm");
device.setFetchesMessages(enabled);
return device;
}
@ -1125,8 +1122,7 @@ class MessageControllerTest {
IntStream.range(1, devicesPerRecipient + 1)
.mapToObj(
d -> generateTestDevice(
(byte) d, 100 + d, 10 * d, System.currentTimeMillis(),
System.currentTimeMillis()))
(byte) d, 100 + d, 10 * d, true))
.collect(Collectors.toList());
final UUID aci = new UUID(0L, (long) i);
final UUID pni = new UUID(1L, (long) i);

View File

@ -489,7 +489,7 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
final Device device = mock(Device.class);
when(device.getId()).thenReturn(deviceId);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
devices.put(deviceId, device);
when(targetAccount.getDevice(deviceId)).thenReturn(Optional.of(device));

View File

@ -53,35 +53,35 @@ class AccountTest {
@BeforeEach
void setup() {
when(oldPrimaryDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(366));
when(oldPrimaryDevice.isEnabled()).thenReturn(true);
when(oldPrimaryDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(oldPrimaryDevice.getId()).thenReturn(Device.PRIMARY_ID);
when(recentPrimaryDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1));
when(recentPrimaryDevice.isEnabled()).thenReturn(true);
when(recentPrimaryDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(recentPrimaryDevice.getId()).thenReturn(Device.PRIMARY_ID);
when(agingSecondaryDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31));
when(agingSecondaryDevice.isEnabled()).thenReturn(false);
when(agingSecondaryDevice.hasMessageDeliveryChannel()).thenReturn(false);
final byte deviceId2 = 2;
when(agingSecondaryDevice.getId()).thenReturn(deviceId2);
when(recentSecondaryDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1));
when(recentSecondaryDevice.isEnabled()).thenReturn(true);
when(recentSecondaryDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(recentSecondaryDevice.getId()).thenReturn(deviceId2);
when(oldSecondaryDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(366));
when(oldSecondaryDevice.isEnabled()).thenReturn(false);
when(oldSecondaryDevice.hasMessageDeliveryChannel()).thenReturn(false);
when(oldSecondaryDevice.getId()).thenReturn(deviceId2);
when(paymentActivationCapableDevice.getCapabilities()).thenReturn(
new DeviceCapabilities(true, true, true));
when(paymentActivationCapableDevice.isEnabled()).thenReturn(true);
when(paymentActivationCapableDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(paymentActivationIncapableDevice.getCapabilities()).thenReturn(
new DeviceCapabilities(true, true, false));
when(paymentActivationIncapableDevice.isEnabled()).thenReturn(true);
when(paymentActivationIncapableDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(paymentActivationIncapableExpiredDevice.getCapabilities()).thenReturn(
new DeviceCapabilities(true, true, false));
when(paymentActivationIncapableExpiredDevice.isEnabled()).thenReturn(false);
when(paymentActivationIncapableExpiredDevice.hasMessageDeliveryChannel()).thenReturn(false);
}
@ -92,10 +92,10 @@ class AccountTest {
final Device disabledPrimaryDevice = mock(Device.class);
final Device disabledLinkedDevice = mock(Device.class);
when(enabledPrimaryDevice.isEnabled()).thenReturn(true);
when(enabledLinkedDevice.isEnabled()).thenReturn(true);
when(disabledPrimaryDevice.isEnabled()).thenReturn(false);
when(disabledLinkedDevice.isEnabled()).thenReturn(false);
when(enabledPrimaryDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(enabledLinkedDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(disabledPrimaryDevice.hasMessageDeliveryChannel()).thenReturn(false);
when(disabledLinkedDevice.hasMessageDeliveryChannel()).thenReturn(false);
when(enabledPrimaryDevice.getId()).thenReturn(Device.PRIMARY_ID);
final byte deviceId2 = 2;
@ -296,7 +296,7 @@ class AccountTest {
static Stream<Arguments> testHasEnabledLinkedDevice() {
final Device enabledPrimary = mock(Device.class);
when(enabledPrimary.isEnabled()).thenReturn(true);
when(enabledPrimary.hasMessageDeliveryChannel()).thenReturn(true);
when(enabledPrimary.getId()).thenReturn(Device.PRIMARY_ID);
final Device disabledPrimary = mock(Device.class);
@ -304,7 +304,7 @@ class AccountTest {
final byte linked1DeviceId = Device.PRIMARY_ID + 1;
final Device enabledLinked1 = mock(Device.class);
when(enabledLinked1.isEnabled()).thenReturn(true);
when(enabledLinked1.hasMessageDeliveryChannel()).thenReturn(true);
when(enabledLinked1.getId()).thenReturn(linked1DeviceId);
final Device disabledLinked1 = mock(Device.class);
@ -312,7 +312,7 @@ class AccountTest {
final byte linked2DeviceId = Device.PRIMARY_ID + 2;
final Device enabledLinked2 = mock(Device.class);
when(enabledLinked2.isEnabled()).thenReturn(true);
when(enabledLinked2.hasMessageDeliveryChannel()).thenReturn(true);
when(enabledLinked2.getId()).thenReturn(linked2DeviceId);
final Device disabledLinked2 = mock(Device.class);

View File

@ -134,7 +134,7 @@ public class ChangeNumberManagerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(pni);
final Device d2 = mock(Device.class);
when(d2.isEnabled()).thenReturn(true);
when(d2.hasMessageDeliveryChannel()).thenReturn(true);
final byte deviceId2 = 2;
when(d2.getId()).thenReturn(deviceId2);
@ -181,7 +181,7 @@ public class ChangeNumberManagerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(pni);
final Device d2 = mock(Device.class);
when(d2.isEnabled()).thenReturn(true);
when(d2.hasMessageDeliveryChannel()).thenReturn(true);
final byte deviceId2 = 2;
when(d2.getId()).thenReturn(deviceId2);
@ -228,7 +228,7 @@ public class ChangeNumberManagerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(pni);
final Device d2 = mock(Device.class);
when(d2.isEnabled()).thenReturn(true);
when(d2.hasMessageDeliveryChannel()).thenReturn(true);
final byte deviceId2 = 2;
when(d2.getId()).thenReturn(deviceId2);
@ -273,7 +273,7 @@ public class ChangeNumberManagerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(pni);
final Device d2 = mock(Device.class);
when(d2.isEnabled()).thenReturn(true);
when(d2.hasMessageDeliveryChannel()).thenReturn(true);
final byte deviceId2 = 2;
when(d2.getId()).thenReturn(deviceId2);
@ -316,7 +316,7 @@ public class ChangeNumberManagerTest {
when(account.getPhoneNumberIdentifier()).thenReturn(pni);
final Device d2 = mock(Device.class);
when(d2.isEnabled()).thenReturn(true);
when(d2.hasMessageDeliveryChannel()).thenReturn(true);
final byte deviceId2 = 2;
when(d2.getId()).thenReturn(deviceId2);
@ -361,7 +361,7 @@ public class ChangeNumberManagerTest {
for (byte i = 1; i <= 3; i++) {
final Device device = mock(Device.class);
when(device.getId()).thenReturn(i);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getRegistrationId()).thenReturn((int) i);
devices.add(device);
@ -400,7 +400,7 @@ public class ChangeNumberManagerTest {
for (byte i = 1; i <= 3; i++) {
final Device device = mock(Device.class);
when(device.getId()).thenReturn(i);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getRegistrationId()).thenReturn((int) i);
devices.add(device);
@ -439,7 +439,7 @@ public class ChangeNumberManagerTest {
for (byte i = 1; i <= 3; i++) {
final Device device = mock(Device.class);
when(device.getId()).thenReturn(i);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getRegistrationId()).thenReturn((int) i);
devices.add(device);

View File

@ -19,41 +19,22 @@ class DeviceTest {
@ParameterizedTest
@MethodSource
void testIsEnabled(final boolean primary, final boolean fetchesMessages, final String apnId, final String gcmId,
final Duration timeSinceLastSeen, final boolean expectEnabled) {
final long lastSeen = System.currentTimeMillis() - timeSinceLastSeen.toMillis();
void testHasMessageDeliveryChannel(final boolean fetchesMessages, final String apnId, final String gcmId, final boolean expectEnabled) {
final Device device = new Device();
device.setId(primary ? Device.PRIMARY_ID : Device.PRIMARY_ID + 1);
device.setFetchesMessages(fetchesMessages);
device.setApnId(apnId);
device.setGcmId(gcmId);
device.setCreated(lastSeen);
device.setLastSeen(lastSeen);
assertEquals(expectEnabled, device.isEnabled());
assertEquals(expectEnabled, device.hasMessageDeliveryChannel());
}
private static Stream<Arguments> testIsEnabled() {
private static Stream<Arguments> testHasMessageDeliveryChannel() {
return Stream.of(
// primary fetchesMessages apnId gcmId lastSeen expectEnabled
Arguments.of(true, false, null, null, Duration.ofDays(60), false),
Arguments.of(true, false, null, null, Duration.ofDays(1), false),
Arguments.of(true, false, null, "gcm-id", Duration.ofDays(60), true),
Arguments.of(true, false, null, "gcm-id", Duration.ofDays(1), true),
Arguments.of(true, false, "apn-id", null, Duration.ofDays(60), true),
Arguments.of(true, false, "apn-id", null, Duration.ofDays(1), true),
Arguments.of(true, true, null, null, Duration.ofDays(60), true),
Arguments.of(true, true, null, null, Duration.ofDays(1), true),
Arguments.of(false, false, null, null, Duration.ofDays(60), false),
Arguments.of(false, false, null, null, Duration.ofDays(1), false),
Arguments.of(false, false, null, "gcm-id", Duration.ofDays(60), false),
Arguments.of(false, false, null, "gcm-id", Duration.ofDays(1), true),
Arguments.of(false, false, "apn-id", null, Duration.ofDays(60), false),
Arguments.of(false, false, "apn-id", null, Duration.ofDays(1), true),
Arguments.of(false, true, null, null, Duration.ofDays(60), false),
Arguments.of(false, true, null, null, Duration.ofDays(1), true)
Arguments.of(false, null, null, false),
Arguments.of(false, null, "gcm-id", true),
Arguments.of(false, "apn-id", null, true),
Arguments.of(true, null, null, true)
);
}

View File

@ -258,23 +258,23 @@ class MessagePersisterTest {
final Device primary = mock(Device.class);
when(primary.getId()).thenReturn((byte) 1);
when(primary.isPrimary()).thenReturn(true);
when(primary.isEnabled()).thenReturn(true);
when(primary.hasMessageDeliveryChannel()).thenReturn(true);
final Device activeA = mock(Device.class);
when(activeA.getId()).thenReturn((byte) 2);
when(activeA.isEnabled()).thenReturn(true);
when(activeA.hasMessageDeliveryChannel()).thenReturn(true);
final Device inactiveB = mock(Device.class);
final byte inactiveId = 3;
when(inactiveB.getId()).thenReturn(inactiveId);
when(inactiveB.isEnabled()).thenReturn(false);
when(inactiveB.hasMessageDeliveryChannel()).thenReturn(false);
final Device inactiveC = mock(Device.class);
when(inactiveC.getId()).thenReturn((byte) 4);
when(inactiveC.isEnabled()).thenReturn(false);
when(inactiveC.hasMessageDeliveryChannel()).thenReturn(false);
final Device activeD = mock(Device.class);
when(activeD.getId()).thenReturn((byte) 5);
when(activeD.isEnabled()).thenReturn(true);
when(activeD.hasMessageDeliveryChannel()).thenReturn(true);
final Device destination = mock(Device.class);
when(destination.getId()).thenReturn(DESTINATION_DEVICE_ID);
when(destination.isEnabled()).thenReturn(true);
when(destination.hasMessageDeliveryChannel()).thenReturn(true);
when(destinationAccount.getDevices()).thenReturn(List.of(primary, activeA, inactiveB, inactiveC, activeD, destination));
@ -302,27 +302,27 @@ class MessagePersisterTest {
final byte primaryId = 1;
when(primary.getId()).thenReturn(primaryId);
when(primary.isPrimary()).thenReturn(true);
when(primary.isEnabled()).thenReturn(true);
when(primary.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(primary)))
.thenReturn(Mono.just(4L));
final Device deviceA = mock(Device.class);
final byte deviceIdA = 2;
when(deviceA.getId()).thenReturn(deviceIdA);
when(deviceA.isEnabled()).thenReturn(true);
when(deviceA.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(deviceA)))
.thenReturn(Mono.empty());
final Device deviceB = mock(Device.class);
final byte deviceIdB = 3;
when(deviceB.getId()).thenReturn(deviceIdB);
when(deviceB.isEnabled()).thenReturn(true);
when(deviceB.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(deviceB)))
.thenReturn(Mono.just(2L));
final Device destination = mock(Device.class);
when(destination.getId()).thenReturn(DESTINATION_DEVICE_ID);
when(destination.isEnabled()).thenReturn(true);
when(destination.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(destination)))
.thenReturn(Mono.just(5L));
@ -352,27 +352,27 @@ class MessagePersisterTest {
final byte primaryId = 1;
when(primary.getId()).thenReturn(primaryId);
when(primary.isPrimary()).thenReturn(true);
when(primary.isEnabled()).thenReturn(true);
when(primary.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(primary)))
.thenReturn(Mono.just(1L));
final Device deviceA = mock(Device.class);
final byte deviceIdA = 2;
when(deviceA.getId()).thenReturn(deviceIdA);
when(deviceA.isEnabled()).thenReturn(true);
when(deviceA.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(deviceA)))
.thenReturn(Mono.just(3L));
final Device deviceB = mock(Device.class);
final byte deviceIdB = 2;
when(deviceB.getId()).thenReturn(deviceIdB);
when(deviceB.isEnabled()).thenReturn(true);
when(deviceB.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(deviceB)))
.thenReturn(Mono.empty());
final Device destination = mock(Device.class);
when(destination.getId()).thenReturn(DESTINATION_DEVICE_ID);
when(destination.isEnabled()).thenReturn(true);
when(destination.hasMessageDeliveryChannel()).thenReturn(true);
when(messagesManager.getEarliestUndeliveredTimestampForDevice(any(), eq(destination)))
.thenReturn(Mono.just(2L));

View File

@ -138,11 +138,11 @@ public class AuthHelper {
when(VALID_DEVICE_3_PRIMARY.getId()).thenReturn(Device.PRIMARY_ID);
when(VALID_DEVICE_3_LINKED.getId()).thenReturn((byte) 2);
when(VALID_DEVICE.isEnabled()).thenReturn(true);
when(VALID_DEVICE_TWO.isEnabled()).thenReturn(true);
when(VALID_DEVICE.hasMessageDeliveryChannel()).thenReturn(true);
when(VALID_DEVICE_TWO.hasMessageDeliveryChannel()).thenReturn(true);
when(UNDISCOVERABLE_DEVICE.isPrimary()).thenReturn(true);
when(VALID_DEVICE_3_PRIMARY.isEnabled()).thenReturn(true);
when(VALID_DEVICE_3_LINKED.isEnabled()).thenReturn(true);
when(VALID_DEVICE_3_PRIMARY.hasMessageDeliveryChannel()).thenReturn(true);
when(VALID_DEVICE_3_LINKED.hasMessageDeliveryChannel()).thenReturn(true);
when(VALID_ACCOUNT.getDevice(Device.PRIMARY_ID)).thenReturn(Optional.of(VALID_DEVICE));
when(VALID_ACCOUNT.getPrimaryDevice()).thenReturn(VALID_DEVICE);
@ -279,7 +279,7 @@ public class AuthHelper {
when(device.getAuthTokenHash()).thenReturn(saltedTokenHash);
when(device.isPrimary()).thenReturn(true);
when(device.getId()).thenReturn(Device.PRIMARY_ID);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(account.getDevice(Device.PRIMARY_ID)).thenReturn(Optional.of(device));
when(account.getPrimaryDevice()).thenReturn(device);
when(account.getNumber()).thenReturn(number);

View File

@ -6,9 +6,7 @@
package org.whispersystems.textsecuregcm.tests.util;
import java.util.Random;
import org.signal.libsignal.protocol.ecc.Curve;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.util.Util;
public class DevicesHelper {
@ -48,13 +46,12 @@ public class DevicesHelper {
public static void setEnabled(Device device, boolean enabled) {
if (enabled) {
device.setGcmId("testGcmId" + RANDOM.nextLong());
device.setLastSeen(Util.todayInMillis());
} else {
device.setLastSeen(0);
device.setGcmId(null);
}
// fail fast, to guard against a change to the isEnabled() implementation causing unexpected test behavior
assert enabled == device.isEnabled();
assert enabled == device.hasMessageDeliveryChannel();
}
}

View File

@ -107,7 +107,7 @@ class DestinationDeviceValidatorTest {
enabledStateByDeviceId.forEach((deviceId, enabled) -> {
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(enabled);
when(device.hasMessageDeliveryChannel()).thenReturn(enabled);
when(device.getId()).thenReturn(deviceId);
when(account.getDevice(deviceId)).thenReturn(Optional.of(device));

View File

@ -98,7 +98,7 @@ class ProcessPushNotificationFeedbackCommandTest {
final Account accountWithActiveDevice = mock(Account.class);
{
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(accountWithActiveDevice.getDevices()).thenReturn(List.of(device));
}
@ -106,7 +106,7 @@ class ProcessPushNotificationFeedbackCommandTest {
final Account accountWithUninstalledDevice = mock(Account.class);
{
final Device uninstalledDevice = mock(Device.class);
when(uninstalledDevice.isEnabled()).thenReturn(true);
when(uninstalledDevice.hasMessageDeliveryChannel()).thenReturn(true);
when(uninstalledDevice.getUninstalledFeedbackTimestamp())
.thenReturn(clock.instant().minus(ProcessPushNotificationFeedbackCommand.MAX_TOKEN_REFRESH_DELAY.multipliedBy(2)).toEpochMilli());
@ -116,7 +116,7 @@ class ProcessPushNotificationFeedbackCommandTest {
final Account accountWithAlreadyDisabledUninstalledDevice = mock(Account.class);
{
final Device previouslyDisabledUninstalledDevice = mock(Device.class);
when(previouslyDisabledUninstalledDevice.isEnabled()).thenReturn(false);
when(previouslyDisabledUninstalledDevice.hasMessageDeliveryChannel()).thenReturn(false);
when(previouslyDisabledUninstalledDevice.getUninstalledFeedbackTimestamp())
.thenReturn(clock.instant().minus(ProcessPushNotificationFeedbackCommand.MAX_TOKEN_REFRESH_DELAY.multipliedBy(2)).toEpochMilli());
@ -196,7 +196,7 @@ class ProcessPushNotificationFeedbackCommandTest {
{
// Device is active, enabled, and has no push feedback
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getUninstalledFeedbackTimestamp()).thenReturn(0L);
when(device.getLastSeen()).thenReturn(CURRENT_TIME.toEpochMilli());
@ -206,7 +206,7 @@ class ProcessPushNotificationFeedbackCommandTest {
{
// Device is active, but not enabled, and has no push feedback
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(false);
when(device.hasMessageDeliveryChannel()).thenReturn(false);
when(device.getUninstalledFeedbackTimestamp()).thenReturn(0L);
when(device.getLastSeen()).thenReturn(CURRENT_TIME.toEpochMilli());
@ -216,7 +216,7 @@ class ProcessPushNotificationFeedbackCommandTest {
{
// Device is active, enabled, and has "mature" push feedback
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(true);
when(device.hasMessageDeliveryChannel()).thenReturn(true);
when(device.getUninstalledFeedbackTimestamp()).thenReturn(maturePushFeedbackTimestamp);
when(device.getLastSeen()).thenReturn(CURRENT_TIME.toEpochMilli());
@ -226,7 +226,7 @@ class ProcessPushNotificationFeedbackCommandTest {
{
// Device is active, but not enabled, and has "mature" push feedback
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(false);
when(device.hasMessageDeliveryChannel()).thenReturn(false);
when(device.getUninstalledFeedbackTimestamp()).thenReturn(maturePushFeedbackTimestamp);
when(device.getLastSeen()).thenReturn(CURRENT_TIME.toEpochMilli());
@ -236,7 +236,7 @@ class ProcessPushNotificationFeedbackCommandTest {
{
// Device is inactive, not enabled, and has "mature" push feedback
final Device device = mock(Device.class);
when(device.isEnabled()).thenReturn(false);
when(device.hasMessageDeliveryChannel()).thenReturn(false);
when(device.getUninstalledFeedbackTimestamp()).thenReturn(maturePushFeedbackTimestamp);
when(device.getLastSeen()).thenReturn(maturePushFeedbackTimestamp);