diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java index 21f6f5ea2..162e6db8c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java @@ -6,6 +6,7 @@ package org.whispersystems.textsecuregcm.tests.controllers; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.refEq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.eq; @@ -24,6 +25,7 @@ import io.dropwizard.testing.junit5.ResourceExtension; import java.net.MalformedURLException; import java.net.URL; import java.time.Clock; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -60,6 +62,7 @@ import org.whispersystems.textsecuregcm.limits.RateLimiters; import org.whispersystems.textsecuregcm.s3.PolicySigner; import org.whispersystems.textsecuregcm.s3.PostPolicyGenerator; import org.whispersystems.textsecuregcm.storage.Account; +import org.whispersystems.textsecuregcm.storage.AccountBadge; import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.ProfilesManager; @@ -134,6 +137,8 @@ class ProfileControllerTest { void setup() { reset(s3client); + when(clock.instant()).thenReturn(Instant.ofEpochSecond(42)); + AccountsHelper.setupMockUpdate(accountsManager); dynamicPaymentsConfiguration = mock(DynamicPaymentsConfiguration.class); @@ -652,4 +657,99 @@ class ProfileControllerTest { .get(Profile.class); assertThat(profile.getPaymentAddress()).isNull(); } + + @Test + void testSetProfileBadges() throws InvalidInputException { + ProfileKeyCommitment commitment = new ProfileKey(new byte[32]).getCommitment(AuthHelper.VALID_UUID); + + clearInvocations(AuthHelper.VALID_ACCOUNT_TWO); + + final String name = RandomStringUtils.randomAlphabetic(380); + final String emoji = RandomStringUtils.randomAlphanumeric(80); + final String text = RandomStringUtils.randomAlphanumeric(720); + + Response response = resources.getJerseyTest() + .target("/v1/profile/") + .request() + .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_TWO, AuthHelper.VALID_PASSWORD_TWO)) + .put(Entity.entity(new CreateProfileRequest(commitment, "anotherversion", name, emoji, text, null, false, List.of("TEST2")), MediaType.APPLICATION_JSON_TYPE)); + assertThat(response.getStatus()).isEqualTo(200); + assertThat(response.hasEntity()).isFalse(); + + @SuppressWarnings("unchecked") + ArgumentCaptor> badgeCaptor = ArgumentCaptor.forClass(List.class); + verify(AuthHelper.VALID_ACCOUNT_TWO).setBadges(refEq(clock), badgeCaptor.capture()); + + List badges = badgeCaptor.getValue(); + assertThat(badges).isNotNull().hasSize(1).containsOnly(new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), true)); + + clearInvocations(AuthHelper.VALID_ACCOUNT_TWO); + when(AuthHelper.VALID_ACCOUNT_TWO.getBadges()).thenReturn(List.of( + new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), true) + )); + + response = resources.getJerseyTest() + .target("/v1/profile/") + .request() + .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_TWO, AuthHelper.VALID_PASSWORD_TWO)) + .put(Entity.entity(new CreateProfileRequest(commitment, "anotherversion", name, emoji, text, null, false, List.of("TEST3", "TEST2")), MediaType.APPLICATION_JSON_TYPE)); + assertThat(response.getStatus()).isEqualTo(200); + assertThat(response.hasEntity()).isFalse(); + + //noinspection unchecked + badgeCaptor = ArgumentCaptor.forClass(List.class); + verify(AuthHelper.VALID_ACCOUNT_TWO).setBadges(refEq(clock), badgeCaptor.capture()); + + badges = badgeCaptor.getValue(); + assertThat(badges).isNotNull().hasSize(2).containsOnly( + new AccountBadge("TEST3", Instant.ofEpochSecond(42 + 86400), true), + new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), true)); + + clearInvocations(AuthHelper.VALID_ACCOUNT_TWO); + when(AuthHelper.VALID_ACCOUNT_TWO.getBadges()).thenReturn(List.of( + new AccountBadge("TEST3", Instant.ofEpochSecond(42 + 86400), true), + new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), true) + )); + + response = resources.getJerseyTest() + .target("/v1/profile/") + .request() + .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_TWO, AuthHelper.VALID_PASSWORD_TWO)) + .put(Entity.entity(new CreateProfileRequest(commitment, "anotherversion", name, emoji, text, null, false, List.of("TEST2", "TEST3")), MediaType.APPLICATION_JSON_TYPE)); + assertThat(response.getStatus()).isEqualTo(200); + assertThat(response.hasEntity()).isFalse(); + + //noinspection unchecked + badgeCaptor = ArgumentCaptor.forClass(List.class); + verify(AuthHelper.VALID_ACCOUNT_TWO).setBadges(refEq(clock), badgeCaptor.capture()); + + badges = badgeCaptor.getValue(); + assertThat(badges).isNotNull().hasSize(2).containsOnly( + new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), true), + new AccountBadge("TEST3", Instant.ofEpochSecond(42 + 86400), true)); + + clearInvocations(AuthHelper.VALID_ACCOUNT_TWO); + when(AuthHelper.VALID_ACCOUNT_TWO.getBadges()).thenReturn(List.of( + new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), true), + new AccountBadge("TEST3", Instant.ofEpochSecond(42 + 86400), true) + )); + + response = resources.getJerseyTest() + .target("/v1/profile/") + .request() + .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_TWO, AuthHelper.VALID_PASSWORD_TWO)) + .put(Entity.entity(new CreateProfileRequest(commitment, "anotherversion", name, emoji, text, null, false, List.of("TEST1")), MediaType.APPLICATION_JSON_TYPE)); + assertThat(response.getStatus()).isEqualTo(200); + assertThat(response.hasEntity()).isFalse(); + + //noinspection unchecked + badgeCaptor = ArgumentCaptor.forClass(List.class); + verify(AuthHelper.VALID_ACCOUNT_TWO).setBadges(refEq(clock), badgeCaptor.capture()); + + badges = badgeCaptor.getValue(); + assertThat(badges).isNotNull().hasSize(3).containsOnly( + new AccountBadge("TEST1", Instant.ofEpochSecond(42 + 86400), true), + new AccountBadge("TEST2", Instant.ofEpochSecond(42 + 86400), false), + new AccountBadge("TEST3", Instant.ofEpochSecond(42 + 86400), false)); + } } 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 aac16352a..7b09b3ffe 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 @@ -162,6 +162,10 @@ public class AccountsHelper { when(updatedAccount.getIdentityKey()).thenAnswer(stubbing); break; } + case "getBadges": { + when(updatedAccount.getBadges()).thenAnswer(stubbing); + break; + } default: { throw new IllegalArgumentException( "unsupported method: Account#" + stubbing.getInvocation().getMethod().getName()); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java index 690d11775..7643ab460 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java @@ -23,8 +23,8 @@ import java.util.UUID; import org.whispersystems.textsecuregcm.auth.AccountAuthenticator; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAccountAuthenticator; +import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.Device;