From 9e66f8ac111f9d274acfbcca368d83ae372d94e5 Mon Sep 17 00:00:00 2001 From: Ehren Kret Date: Tue, 19 Apr 2022 10:09:54 -0500 Subject: [PATCH] Add gift badges device capability --- .../controllers/DeviceController.java | 1 + .../textsecuregcm/storage/Account.java | 8 +++ .../textsecuregcm/storage/Device.java | 10 ++- .../controllers/MessageControllerTest.java | 14 ++--- ...ConcurrentModificationIntegrationTest.java | 3 +- .../storage/AccountsManagerTest.java | 2 +- .../textsecuregcm/storage/AccountsTest.java | 2 +- .../textsecuregcm/storage/DeviceTest.java | 2 +- .../controllers/DeviceControllerTest.java | 53 ++++++++++++---- .../tests/storage/AccountTest.java | 63 +++++++++++++------ .../tests/util/AccountsHelper.java | 4 ++ 11 files changed, 116 insertions(+), 46 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java index 4dd141e8f..ef078dee0 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java @@ -246,6 +246,7 @@ public class DeviceController { isDowngrade |= account.isAnnouncementGroupSupported() && !capabilities.isAnnouncementGroup(); isDowngrade |= account.isSenderKeySupported() && !capabilities.isSenderKey(); isDowngrade |= account.isGv1MigrationSupported() && !capabilities.isGv1Migration(); + isDowngrade |= account.isGiftBadgesSupported() && !capabilities.isGiftBadges(); if (account.isGroupsV2Supported()) { try { diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java index 817bd5cc4..4fb8e29d5 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java @@ -252,6 +252,14 @@ public class Account { .anyMatch(device -> device.getCapabilities() != null && device.getCapabilities().isStories()); } + public boolean isGiftBadgesSupported() { + requireNotStale(); + + return devices.stream() + .filter(Device::isEnabled) + .allMatch(device -> device.getCapabilities() != null && device.getCapabilities().isGiftBadges()); + } + public boolean isEnabled() { requireNotStale(); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java index 36fe2bfe4..1b43fee6e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java @@ -295,12 +295,15 @@ public class Device { @JsonProperty private boolean stories; + @JsonProperty + private boolean giftBadges; + public DeviceCapabilities() { } public DeviceCapabilities(boolean gv2, final boolean gv2_2, final boolean gv2_3, boolean storage, boolean transfer, boolean gv1Migration, final boolean senderKey, final boolean announcementGroup, final boolean changeNumber, - final boolean pni, final boolean stories) { + final boolean pni, final boolean stories, final boolean giftBadges) { this.gv2 = gv2; this.gv2_2 = gv2_2; this.gv2_3 = gv2_3; @@ -312,6 +315,7 @@ public class Device { this.changeNumber = changeNumber; this.pni = pni; this.stories = stories; + this.giftBadges = giftBadges; } public boolean isGv2() { @@ -357,5 +361,9 @@ public class Device { public boolean isStories() { return stories; } + + public boolean isGiftBadges() { + return giftBadges; + } } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java index 33444d950..3fd297341 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java @@ -11,9 +11,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyBoolean; @@ -37,7 +35,6 @@ import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands; import java.io.ByteArrayOutputStream; import java.util.Arrays; import java.util.Base64; -import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -50,7 +47,6 @@ import java.util.stream.Stream; import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.assertj.core.api.Assertions; import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -85,8 +81,6 @@ import org.whispersystems.textsecuregcm.storage.Device; import org.whispersystems.textsecuregcm.storage.MessagesManager; import org.whispersystems.textsecuregcm.storage.ReportMessageManager; import org.whispersystems.textsecuregcm.tests.util.AuthHelper; -import org.whispersystems.textsecuregcm.util.MessageValidation; -import org.whispersystems.textsecuregcm.util.Pair; import org.whispersystems.textsecuregcm.util.SystemMapper; @ExtendWith(DropwizardExtensionsSupport.class) @@ -136,22 +130,22 @@ class MessageControllerTest { add(new Device(1, null, "foo", "bar", "isgcm", null, null, false, 111, new SignedPreKey(333, "baz", "boop"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(true, false, false, true, true, false, - false, false, false, false, false))); + false, false, false, false, false, false))); }}; Set multiDeviceList = new HashSet<>() {{ add(new Device(1, null, "foo", "bar", "isgcm", null, null, false, 222, new SignedPreKey(111, "foo", "bar"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(true, false, false, true, false, false, - false, false, false, false, false))); + false, false, false, false, false, false))); add(new Device(2, null, "foo", "bar", "isgcm", null, null, false, 333, new SignedPreKey(222, "oof", "rab"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(true, false, false, true, false, false, - false, false, false, false, false))); + false, false, false, false, false, false))); add(new Device(3, null, "foo", "bar", "isgcm", null, null, false, 444, null, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(false, false, false, false, false, false, - false, false, false, false, false))); + false, false, false, false, false, false))); }}; Account singleDeviceAccount = new Account(SINGLE_DEVICE_RECIPIENT, SINGLE_DEVICE_UUID, SINGLE_DEVICE_PNI, singleDeviceList, "1234".getBytes()); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java index 9fcf35ae6..1ac52288b 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerConcurrentModificationIntegrationTest.java @@ -190,7 +190,8 @@ class AccountsManagerConcurrentModificationIntegrationTest { "testUserAgent-" + random.nextInt(), 0, new Device.DeviceCapabilities(random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), - random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean()))); + random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), + random.nextBoolean()))); }); uuid = account.getUuid(); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java index f7af3d7cd..b11e86ffe 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsManagerTest.java @@ -585,7 +585,7 @@ class AccountsManagerTest { @ValueSource(booleans = {true, false}) void testCreateWithStorageCapability(final boolean hasStorage) throws InterruptedException { final AccountAttributes attributes = new AccountAttributes(false, 0, null, null, true, - new DeviceCapabilities(false, false, false, hasStorage, false, false, false, false, false, false, false)); + new DeviceCapabilities(false, false, false, hasStorage, false, false, false, false, false, false, false, false)); final Account account = accountsManager.create("+18005550123", "password", null, attributes, new ArrayList<>()); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java index b8090c023..5bbc77541 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsTest.java @@ -963,7 +963,7 @@ class AccountsTest { new Device.DeviceCapabilities(random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), - random.nextBoolean())); + random.nextBoolean(), random.nextBoolean())); } private Account generateAccount(String number, UUID uuid, final UUID pni) { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java index 031add05e..600cfdc58 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java @@ -72,7 +72,7 @@ class DeviceTest { final boolean gv2_2Capability, final boolean gv2_3Capability, final boolean expectGv2Supported) { final Device.DeviceCapabilities capabilities = new Device.DeviceCapabilities(gv2Capability, gv2_2Capability, gv2_3Capability, false, false, false, - false, false, false, false, false); + false, false, false, false, false, false); final Device device = new Device(master ? 1 : 2, "test", "auth-token", "salt", null, apnId, null, false, 1, null, 0, 0, "user-agent", 0, capabilities); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java index 78108ebb8..854d84e0c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java @@ -129,6 +129,7 @@ class DeviceControllerTest { when(account.isAnnouncementGroupSupported()).thenReturn(true); when(account.isChangeNumberSupported()).thenReturn(true); when(account.isPniSupported()).thenReturn(true); + when(account.isGiftBadgesSupported()).thenReturn(true); when(pendingDevicesManager.getCodeForNumber(AuthHelper.VALID_NUMBER)).thenReturn( Optional.of(new StoredVerificationCode("5678901", System.currentTimeMillis(), null, null))); @@ -305,7 +306,7 @@ class DeviceControllerTest { void deviceDowngradeCapabilitiesTest(final String userAgent, final boolean gv2, final boolean gv2_2, final boolean gv2_3, final int expectedStatus) { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(gv2, gv2_2, gv2_3, true, false, true, true, true, - true, true, true); + true, true, true, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources.getJerseyTest() .target("/v1/devices/5678901") @@ -346,7 +347,7 @@ class DeviceControllerTest { @Test void deviceDowngradeGv1MigrationTest() { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, false, true, true, - true, true, true); + true, true, true, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources.getJerseyTest() .target("/v1/devices/5678901") @@ -357,7 +358,7 @@ class DeviceControllerTest { assertThat(response.getStatus()).isEqualTo(409); - deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, true, true, true, true, true, true); + deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, true, true, true, true, true, true, true); accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); response = resources.getJerseyTest() .target("/v1/devices/5678901") @@ -372,7 +373,7 @@ class DeviceControllerTest { @Test void deviceDowngradeSenderKeyTest() { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, false, true, - true, true, true); + true, true, true, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources @@ -384,7 +385,7 @@ class DeviceControllerTest { .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE)); assertThat(response.getStatus()).isEqualTo(409); - deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true); + deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true); accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); response = resources .getJerseyTest() @@ -399,7 +400,7 @@ class DeviceControllerTest { @Test void deviceDowngradeAnnouncementGroupTest() { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, false, - true, true, true); + true, true, true, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources @@ -411,7 +412,7 @@ class DeviceControllerTest { .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE)); assertThat(response.getStatus()).isEqualTo(409); - deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true); + deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true); accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); response = resources .getJerseyTest() @@ -426,7 +427,7 @@ class DeviceControllerTest { @Test void deviceDowngradeChangeNumberTest() { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, - false, true, true); + false, true, true, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources @@ -439,7 +440,7 @@ class DeviceControllerTest { .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE)); assertThat(response.getStatus()).isEqualTo(409); - deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true); + deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true); accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); response = resources .getJerseyTest() @@ -455,7 +456,7 @@ class DeviceControllerTest { @Test void deviceDowngradePniTest() { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, - false, true); + false, true, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources @@ -467,7 +468,7 @@ class DeviceControllerTest { .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE)); assertThat(response.getStatus()).isEqualTo(409); - deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true); + deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true); accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); response = resources .getJerseyTest() @@ -483,7 +484,7 @@ class DeviceControllerTest { @Test void deviceDowngradeStoriesTest() { DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, - true, false); + true, false, true); AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); Response response = resources @@ -498,7 +499,33 @@ class DeviceControllerTest { // TODO stories capability // assertThat(response.getStatus()).isEqualTo(409); - deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true); + deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true); + accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); + response = resources + .getJerseyTest() + .target("/v1/devices/5678901") + .request() + .header("Authorization", + AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD)) + .header("User-Agent", "Signal-Android/5.42.8675309 Android/30") + .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE)); + assertThat(response.getStatus()).isEqualTo(200); + } + + @Test + void deviceDowngradeGiftBadgesTest() { + DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, false); + AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); + Response response = resources + .getJerseyTest() + .target("/v1/devices/5678901") + .request() + .header("Authorization", AuthHelper.getProvisioningAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD)) + .header("User-Agent", "Signal-Android/5.42.8675309 Android/30") + .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE)); + assertThat(response.getStatus()).isEqualTo(409); + + deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true); accountAttributes = new AccountAttributes(false, 1234, null, null, true, deviceCapabilities); response = resources .getJerseyTest() diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java index 6f8bb38ff..33a5d0711 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java @@ -66,6 +66,10 @@ class AccountTest { private final Device storiesIncapableDevice = mock(Device.class); private final Device storiesIncapableExpiredDevice = mock(Device.class); + private final Device giftBadgesCapableDevice = mock(Device.class); + private final Device giftBadgesIncapableDevice = mock(Device.class); + private final Device giftBadgesIncapableExpiredDevice = mock(Device.class); + @BeforeEach void setup() { when(oldMasterDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(366)); @@ -101,76 +105,86 @@ class AccountTest { when(gv2IncapableExpiredDevice.isEnabled()).thenReturn(false); when(gv1MigrationCapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, false, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, false, false, false, false, false, false)); when(gv1MigrationCapableDevice.isEnabled()).thenReturn(true); when(gv1MigrationIncapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, false, false, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, false, false, false, false, false, false, false)); when(gv1MigrationIncapableDevice.isEnabled()).thenReturn(true); when(gv1MigrationIncapableExpiredDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, false, false, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, false, false, false, false, false, false, false)); when(gv1MigrationIncapableExpiredDevice.isEnabled()).thenReturn(false); when(senderKeyCapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(senderKeyCapableDevice.isEnabled()).thenReturn(true); when(senderKeyIncapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, false, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, false, false, false, false, false, false)); when(senderKeyIncapableDevice.isEnabled()).thenReturn(true); when(senderKeyIncapableExpiredDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, false, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, false, false, false, false, false, false)); when(senderKeyIncapableExpiredDevice.isEnabled()).thenReturn(false); when(announcementGroupCapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, true, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, true, false, false, false, false)); when(announcementGroupCapableDevice.isEnabled()).thenReturn(true); when(announcementGroupIncapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(announcementGroupIncapableDevice.isEnabled()).thenReturn(true); when(announcementGroupIncapableExpiredDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(announcementGroupIncapableExpiredDevice.isEnabled()).thenReturn(false); when(changeNumberCapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, true, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, true, false, false, false)); when(changeNumberCapableDevice.isEnabled()).thenReturn(true); when(changeNumberIncapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(changeNumberIncapableDevice.isEnabled()).thenReturn(true); when(changeNumberIncapableExpiredDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(changeNumberIncapableExpiredDevice.isEnabled()).thenReturn(false); when(pniCapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, true, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, true, false, false)); when(pniCapableDevice.isEnabled()).thenReturn(true); when(pniIncapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(pniIncapableDevice.isEnabled()).thenReturn(true); when(pniIncapableExpiredDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(pniIncapableExpiredDevice.isEnabled()).thenReturn(false); when(storiesCapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, true)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, true, false)); when(storiesCapableDevice.isEnabled()).thenReturn(true); when(storiesIncapableDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(storiesIncapableDevice.isEnabled()).thenReturn(true); when(storiesIncapableExpiredDevice.getCapabilities()).thenReturn( - new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false)); + new DeviceCapabilities(true, true, true, true, true, true, true, false, false, false, false, false)); when(storiesIncapableExpiredDevice.isEnabled()).thenReturn(false); + + when(giftBadgesCapableDevice.getCapabilities()).thenReturn( + new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, true)); + when(giftBadgesCapableDevice.isEnabled()).thenReturn(true); + when(giftBadgesIncapableDevice.getCapabilities()).thenReturn( + new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, false)); + when(giftBadgesIncapableDevice.isEnabled()).thenReturn(true); + when(giftBadgesIncapableExpiredDevice.getCapabilities()).thenReturn( + new DeviceCapabilities(true, true, true, true, true, true, true, true, true, true, true, false)); + when(giftBadgesIncapableExpiredDevice.isEnabled()).thenReturn(false); } @Test @@ -377,6 +391,19 @@ class AccountTest { "1234".getBytes(StandardCharsets.UTF_8)).isStoriesSupported()).isTrue(); } + @Test + void isGiftBadgesSupported() { + assertThat(new Account("+18005551234", UUID.randomUUID(), UUID.randomUUID(), + Set.of(giftBadgesCapableDevice), + "1234".getBytes(StandardCharsets.UTF_8)).isGiftBadgesSupported()).isTrue(); + assertThat(new Account("+18005551234", UUID.randomUUID(), UUID.randomUUID(), + Set.of(giftBadgesCapableDevice, giftBadgesIncapableDevice), + "1234".getBytes(StandardCharsets.UTF_8)).isGiftBadgesSupported()).isFalse(); + assertThat(new Account("+18005551234", UUID.randomUUID(), UUID.randomUUID(), + Set.of(giftBadgesCapableDevice, giftBadgesIncapableExpiredDevice), + "1234".getBytes(StandardCharsets.UTF_8)).isGiftBadgesSupported()).isTrue(); + } + @Test void stale() { final Account account = new Account("+14151234567", UUID.randomUUID(), UUID.randomUUID(), Collections.emptySet(), diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java index 01a81d1c0..6b12e6589 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AccountsHelper.java @@ -161,6 +161,10 @@ public class AccountsHelper { when(updatedAccount.isStoriesSupported()).thenAnswer(stubbing); break; } + case "isGiftBadgesSupported": { + when(updatedAccount.isGiftBadgesSupported()).thenAnswer(stubbing); + break; + } case "getEnabledDeviceCount": { when(updatedAccount.getEnabledDeviceCount()).thenAnswer(stubbing); break;