Bring badge configuration into levels information
This commit is contained in:
		
							parent
							
								
									fe21d014f7
								
							
						
					
					
						commit
						c0837104cd
					
				|  | @ -72,7 +72,6 @@ import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialGenerator; | ||||||
| import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator; | import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator; | ||||||
| import org.whispersystems.textsecuregcm.auth.WebsocketRefreshApplicationEventListener; | import org.whispersystems.textsecuregcm.auth.WebsocketRefreshApplicationEventListener; | ||||||
| import org.whispersystems.textsecuregcm.badges.ConfiguredProfileBadgeConverter; | import org.whispersystems.textsecuregcm.badges.ConfiguredProfileBadgeConverter; | ||||||
| import org.whispersystems.textsecuregcm.badges.ProfileBadgeConverter; |  | ||||||
| import org.whispersystems.textsecuregcm.configuration.DirectoryServerConfiguration; | import org.whispersystems.textsecuregcm.configuration.DirectoryServerConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.controllers.AccountController; | import org.whispersystems.textsecuregcm.controllers.AccountController; | ||||||
| import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV1; | import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV1; | ||||||
|  | @ -296,7 +295,8 @@ public class WhisperServerService extends Application<WhisperServerConfiguration | ||||||
|     environment.getObjectMapper().setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); |     environment.getObjectMapper().setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); | ||||||
|     environment.getObjectMapper().setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); |     environment.getObjectMapper().setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); | ||||||
| 
 | 
 | ||||||
|     ProfileBadgeConverter profileBadgeConverter = new ConfiguredProfileBadgeConverter(clock, config.getBadges()); |     ConfiguredProfileBadgeConverter profileBadgeConverter = | ||||||
|  |         new ConfiguredProfileBadgeConverter(clock, config.getBadges()); | ||||||
| 
 | 
 | ||||||
|     JdbiFactory jdbiFactory = new JdbiFactory(DefaultNameStrategy.CHECK_EMPTY); |     JdbiFactory jdbiFactory = new JdbiFactory(DefaultNameStrategy.CHECK_EMPTY); | ||||||
|     Jdbi        accountJdbi = jdbiFactory.build(environment, config.getAccountsDatabaseConfiguration(), "accountdb"); |     Jdbi        accountJdbi = jdbiFactory.build(environment, config.getAccountsDatabaseConfiguration(), "accountdb"); | ||||||
|  | @ -636,7 +636,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration | ||||||
|     ); |     ); | ||||||
|     if (config.getSubscription() != null) { |     if (config.getSubscription() != null) { | ||||||
|       commonControllers.add(new SubscriptionController(clock, config.getSubscription(), subscriptionManager, |       commonControllers.add(new SubscriptionController(clock, config.getSubscription(), subscriptionManager, | ||||||
|           stripeManager, zkReceiptOperations, issuedReceiptsManager)); |           stripeManager, zkReceiptOperations, issuedReceiptsManager, profileBadgeConverter)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (Object controller : commonControllers) { |     for (Object controller : commonControllers) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright 2021 Signal Messenger, LLC | ||||||
|  |  * SPDX-License-Identifier: AGPL-3.0-only | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.whispersystems.textsecuregcm.badges; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Locale; | ||||||
|  | import org.whispersystems.textsecuregcm.entities.Badge; | ||||||
|  | 
 | ||||||
|  | public interface BadgeTranslator { | ||||||
|  |   Badge translate(List<Locale> acceptableLanguages, String badgeId); | ||||||
|  | } | ||||||
|  | @ -18,13 +18,14 @@ import java.util.ResourceBundle; | ||||||
| import java.util.ResourceBundle.Control; | import java.util.ResourceBundle.Control; | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  | import javax.annotation.Nonnull; | ||||||
| import org.whispersystems.textsecuregcm.configuration.BadgeConfiguration; | import org.whispersystems.textsecuregcm.configuration.BadgeConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.configuration.BadgesConfiguration; | import org.whispersystems.textsecuregcm.configuration.BadgesConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.entities.Badge; | import org.whispersystems.textsecuregcm.entities.Badge; | ||||||
| import org.whispersystems.textsecuregcm.entities.SelfBadge; | import org.whispersystems.textsecuregcm.entities.SelfBadge; | ||||||
| import org.whispersystems.textsecuregcm.storage.AccountBadge; | import org.whispersystems.textsecuregcm.storage.AccountBadge; | ||||||
| 
 | 
 | ||||||
| public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter { | public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter, BadgeTranslator { | ||||||
| 
 | 
 | ||||||
|   private static final int MAX_LOCALES = 15; |   private static final int MAX_LOCALES = 15; | ||||||
|   @VisibleForTesting |   @VisibleForTesting | ||||||
|  | @ -53,6 +54,23 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter { | ||||||
|     this.resourceBundleFactory = resourceBundleFactory; |     this.resourceBundleFactory = resourceBundleFactory; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @Override | ||||||
|  |   public Badge translate(final List<Locale> acceptableLanguages, final String badgeId) { | ||||||
|  |     final List<Locale> acceptableLocales = getAcceptableLocales(acceptableLanguages); | ||||||
|  |     final ResourceBundle resourceBundle = getResourceBundle(acceptableLocales); | ||||||
|  |     final BadgeConfiguration configuration = knownBadges.get(badgeId); | ||||||
|  |     return newBadge( | ||||||
|  |         false, | ||||||
|  |         configuration.getId(), | ||||||
|  |         configuration.getCategory(), | ||||||
|  |         resourceBundle.getString(configuration.getId() + "_name"), | ||||||
|  |         resourceBundle.getString(configuration.getId() + "_description"), | ||||||
|  |         configuration.getSprites(), | ||||||
|  |         configuration.getSvgs(), | ||||||
|  |         null, | ||||||
|  |         false); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   @Override |   @Override | ||||||
|   public List<Badge> convert( |   public List<Badge> convert( | ||||||
|       final List<Locale> acceptableLanguages, |       final List<Locale> acceptableLanguages, | ||||||
|  | @ -63,35 +81,8 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     final Instant now = clock.instant(); |     final Instant now = clock.instant(); | ||||||
| 
 |     final List<Locale> acceptableLocales = getAcceptableLocales(acceptableLanguages); | ||||||
|     final List<Locale> acceptableLocales = acceptableLanguages.stream().limit(MAX_LOCALES).distinct() |     final ResourceBundle resourceBundle = getResourceBundle(acceptableLocales); | ||||||
|         .collect(Collectors.toList()); |  | ||||||
|     final Locale desiredLocale = acceptableLocales.isEmpty() ? Locale.getDefault() : acceptableLocales.get(0); |  | ||||||
| 
 |  | ||||||
|     // define a control with a fallback order as specified in the header |  | ||||||
|     ResourceBundle.Control control = new Control() { |  | ||||||
|       @Override |  | ||||||
|       public List<String> getFormats(final String baseName) { |  | ||||||
|         Objects.requireNonNull(baseName); |  | ||||||
|         return Control.FORMAT_PROPERTIES; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       @Override |  | ||||||
|       public Locale getFallbackLocale(final String baseName, final Locale locale) { |  | ||||||
|         Objects.requireNonNull(baseName); |  | ||||||
|         if (locale.equals(Locale.getDefault())) { |  | ||||||
|           return null; |  | ||||||
|         } |  | ||||||
|         final int localeIndex = acceptableLocales.indexOf(locale); |  | ||||||
|         if (localeIndex < 0 || localeIndex >= acceptableLocales.size() - 1) { |  | ||||||
|           return Locale.getDefault(); |  | ||||||
|         } |  | ||||||
|         // [0, acceptableLocales.size() - 2] is now the possible range for localeIndex |  | ||||||
|         return acceptableLocales.get(localeIndex + 1); |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     final ResourceBundle resourceBundle = resourceBundleFactory.createBundle(BASE_NAME, desiredLocale, control); |  | ||||||
|     List<Badge> badges = accountBadges.stream() |     List<Badge> badges = accountBadges.stream() | ||||||
|         .filter(accountBadge -> (isSelf || accountBadge.isVisible()) |         .filter(accountBadge -> (isSelf || accountBadge.isVisible()) | ||||||
|             && now.isBefore(accountBadge.getExpiration()) |             && now.isBefore(accountBadge.getExpiration()) | ||||||
|  | @ -126,6 +117,40 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter { | ||||||
|     return badges; |     return badges; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @Nonnull | ||||||
|  |   private ResourceBundle getResourceBundle(final List<Locale> acceptableLocales) { | ||||||
|  |     final Locale desiredLocale = acceptableLocales.isEmpty() ? Locale.getDefault() : acceptableLocales.get(0); | ||||||
|  |     // define a control with a fallback order as specified in the header | ||||||
|  |     Control control = new Control() { | ||||||
|  |       @Override | ||||||
|  |       public List<String> getFormats(final String baseName) { | ||||||
|  |         Objects.requireNonNull(baseName); | ||||||
|  |         return Control.FORMAT_PROPERTIES; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       @Override | ||||||
|  |       public Locale getFallbackLocale(final String baseName, final Locale locale) { | ||||||
|  |         Objects.requireNonNull(baseName); | ||||||
|  |         if (locale.equals(Locale.getDefault())) { | ||||||
|  |           return null; | ||||||
|  |         } | ||||||
|  |         final int localeIndex = acceptableLocales.indexOf(locale); | ||||||
|  |         if (localeIndex < 0 || localeIndex >= acceptableLocales.size() - 1) { | ||||||
|  |           return Locale.getDefault(); | ||||||
|  |         } | ||||||
|  |         // [0, acceptableLocales.size() - 2] is now the possible range for localeIndex | ||||||
|  |         return acceptableLocales.get(localeIndex + 1); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     return resourceBundleFactory.createBundle(BASE_NAME, desiredLocale, control); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @Nonnull | ||||||
|  |   private List<Locale> getAcceptableLocales(final List<Locale> acceptableLanguages) { | ||||||
|  |     return acceptableLanguages.stream().limit(MAX_LOCALES).distinct().collect(Collectors.toList()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   private Badge newBadge( |   private Badge newBadge( | ||||||
|       final boolean isSelf, |       final boolean isSelf, | ||||||
|       final String id, |       final String id, | ||||||
|  |  | ||||||
|  | @ -44,7 +44,10 @@ import javax.ws.rs.POST; | ||||||
| import javax.ws.rs.PUT; | import javax.ws.rs.PUT; | ||||||
| import javax.ws.rs.Path; | import javax.ws.rs.Path; | ||||||
| import javax.ws.rs.PathParam; | import javax.ws.rs.PathParam; | ||||||
|  | import javax.ws.rs.ProcessingException; | ||||||
| import javax.ws.rs.Produces; | import javax.ws.rs.Produces; | ||||||
|  | import javax.ws.rs.container.ContainerRequestContext; | ||||||
|  | import javax.ws.rs.core.Context; | ||||||
| import javax.ws.rs.core.MediaType; | import javax.ws.rs.core.MediaType; | ||||||
| import javax.ws.rs.core.Response; | import javax.ws.rs.core.Response; | ||||||
| import javax.ws.rs.core.Response.Status; | import javax.ws.rs.core.Response.Status; | ||||||
|  | @ -56,9 +59,11 @@ import org.signal.zkgroup.receipts.ServerZkReceiptOperations; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; | import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; | ||||||
|  | import org.whispersystems.textsecuregcm.badges.BadgeTranslator; | ||||||
| import org.whispersystems.textsecuregcm.configuration.SubscriptionConfiguration; | import org.whispersystems.textsecuregcm.configuration.SubscriptionConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.configuration.SubscriptionLevelConfiguration; | import org.whispersystems.textsecuregcm.configuration.SubscriptionLevelConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.configuration.SubscriptionPriceConfiguration; | import org.whispersystems.textsecuregcm.configuration.SubscriptionPriceConfiguration; | ||||||
|  | import org.whispersystems.textsecuregcm.entities.Badge; | ||||||
| import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager; | import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager; | ||||||
| import org.whispersystems.textsecuregcm.storage.SubscriptionManager; | import org.whispersystems.textsecuregcm.storage.SubscriptionManager; | ||||||
| import org.whispersystems.textsecuregcm.storage.SubscriptionManager.GetResult; | import org.whispersystems.textsecuregcm.storage.SubscriptionManager.GetResult; | ||||||
|  | @ -76,6 +81,7 @@ public class SubscriptionController { | ||||||
|   private final StripeManager stripeManager; |   private final StripeManager stripeManager; | ||||||
|   private final ServerZkReceiptOperations zkReceiptOperations; |   private final ServerZkReceiptOperations zkReceiptOperations; | ||||||
|   private final IssuedReceiptsManager issuedReceiptsManager; |   private final IssuedReceiptsManager issuedReceiptsManager; | ||||||
|  |   private final BadgeTranslator badgeTranslator; | ||||||
| 
 | 
 | ||||||
|   public SubscriptionController( |   public SubscriptionController( | ||||||
|       @Nonnull Clock clock, |       @Nonnull Clock clock, | ||||||
|  | @ -83,13 +89,15 @@ public class SubscriptionController { | ||||||
|       @Nonnull SubscriptionManager subscriptionManager, |       @Nonnull SubscriptionManager subscriptionManager, | ||||||
|       @Nonnull StripeManager stripeManager, |       @Nonnull StripeManager stripeManager, | ||||||
|       @Nonnull ServerZkReceiptOperations zkReceiptOperations, |       @Nonnull ServerZkReceiptOperations zkReceiptOperations, | ||||||
|       @Nonnull IssuedReceiptsManager issuedReceiptsManager) { |       @Nonnull IssuedReceiptsManager issuedReceiptsManager, | ||||||
|  |       @Nonnull BadgeTranslator badgeTranslator) { | ||||||
|     this.clock = Objects.requireNonNull(clock); |     this.clock = Objects.requireNonNull(clock); | ||||||
|     this.config = Objects.requireNonNull(config); |     this.config = Objects.requireNonNull(config); | ||||||
|     this.subscriptionManager = Objects.requireNonNull(subscriptionManager); |     this.subscriptionManager = Objects.requireNonNull(subscriptionManager); | ||||||
|     this.stripeManager = Objects.requireNonNull(stripeManager); |     this.stripeManager = Objects.requireNonNull(stripeManager); | ||||||
|     this.zkReceiptOperations = Objects.requireNonNull(zkReceiptOperations); |     this.zkReceiptOperations = Objects.requireNonNull(zkReceiptOperations); | ||||||
|     this.issuedReceiptsManager = Objects.requireNonNull(issuedReceiptsManager); |     this.issuedReceiptsManager = Objects.requireNonNull(issuedReceiptsManager); | ||||||
|  |     this.badgeTranslator = Objects.requireNonNull(badgeTranslator); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Timed |   @Timed | ||||||
|  | @ -328,19 +336,19 @@ public class SubscriptionController { | ||||||
| 
 | 
 | ||||||
|     public static class Level { |     public static class Level { | ||||||
| 
 | 
 | ||||||
|       private final String badgeId; |       private final Badge badge; | ||||||
|       private final Map<String, BigDecimal> currencies; |       private final Map<String, BigDecimal> currencies; | ||||||
| 
 | 
 | ||||||
|       @JsonCreator |       @JsonCreator | ||||||
|       public Level( |       public Level( | ||||||
|           @JsonProperty("badgeId") String badgeId, |           @JsonProperty("badge") Badge badge, | ||||||
|           @JsonProperty("currencies") Map<String, BigDecimal> currencies) { |           @JsonProperty("currencies") Map<String, BigDecimal> currencies) { | ||||||
|         this.badgeId = badgeId; |         this.badge = badge; | ||||||
|         this.currencies = currencies; |         this.currencies = currencies; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       public String getBadgeId() { |       public Badge getBadge() { | ||||||
|         return badgeId; |         return badge; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       public Map<String, BigDecimal> getCurrencies() { |       public Map<String, BigDecimal> getCurrencies() { | ||||||
|  | @ -366,11 +374,13 @@ public class SubscriptionController { | ||||||
|   @Path("/levels") |   @Path("/levels") | ||||||
|   @Consumes(MediaType.APPLICATION_JSON) |   @Consumes(MediaType.APPLICATION_JSON) | ||||||
|   @Produces(MediaType.APPLICATION_JSON) |   @Produces(MediaType.APPLICATION_JSON) | ||||||
|   public CompletableFuture<Response> getLevels() { |   public CompletableFuture<Response> getLevels(@Context ContainerRequestContext containerRequestContext) { | ||||||
|     return CompletableFuture.supplyAsync(() -> { |     return CompletableFuture.supplyAsync(() -> { | ||||||
|  |       List<Locale> acceptableLanguages = getAcceptableLanguagesForRequest(containerRequestContext); | ||||||
|       GetLevelsResponse getLevelsResponse = new GetLevelsResponse( |       GetLevelsResponse getLevelsResponse = new GetLevelsResponse( | ||||||
|           config.getLevels().entrySet().stream().collect(Collectors.toMap(Entry::getKey, |           config.getLevels().entrySet().stream().collect(Collectors.toMap(Entry::getKey, | ||||||
|               entry -> new GetLevelsResponse.Level(entry.getValue().getBadge(), |               entry -> new GetLevelsResponse.Level( | ||||||
|  |                   badgeTranslator.translate(acceptableLanguages, entry.getValue().getBadge()), | ||||||
|                   entry.getValue().getPrices().entrySet().stream().collect( |                   entry.getValue().getPrices().entrySet().stream().collect( | ||||||
|                       Collectors.toMap(levelEntry -> levelEntry.getKey().toUpperCase(Locale.ROOT), |                       Collectors.toMap(levelEntry -> levelEntry.getKey().toUpperCase(Locale.ROOT), | ||||||
|                           levelEntry -> levelEntry.getValue().getAmount())))))); |                           levelEntry -> levelEntry.getValue().getAmount())))))); | ||||||
|  | @ -620,6 +630,15 @@ public class SubscriptionController { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   private List<Locale> getAcceptableLanguagesForRequest(ContainerRequestContext containerRequestContext) { | ||||||
|  |     try { | ||||||
|  |       return containerRequestContext.getAcceptableLanguages(); | ||||||
|  |     } catch (final ProcessingException e) { | ||||||
|  |       logger.warn("Could not get acceptable languages", e); | ||||||
|  |       return List.of(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   private static class RequestData { |   private static class RequestData { | ||||||
| 
 | 
 | ||||||
|     public final byte[] subscriberBytes; |     public final byte[] subscriberBytes; | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ | ||||||
| package org.whispersystems.textsecuregcm.controllers; | package org.whispersystems.textsecuregcm.controllers; | ||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.mockito.ArgumentMatchers.any; | ||||||
|  | import static org.mockito.ArgumentMatchers.eq; | ||||||
| import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||||
| import static org.mockito.Mockito.reset; | import static org.mockito.Mockito.reset; | ||||||
| import static org.mockito.Mockito.when; | import static org.mockito.Mockito.when; | ||||||
|  | @ -15,6 +17,7 @@ import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; | ||||||
| import io.dropwizard.testing.junit5.ResourceExtension; | import io.dropwizard.testing.junit5.ResourceExtension; | ||||||
| import java.math.BigDecimal; | import java.math.BigDecimal; | ||||||
| import java.time.Clock; | import java.time.Clock; | ||||||
|  | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import org.glassfish.jersey.server.ServerProperties; | import org.glassfish.jersey.server.ServerProperties; | ||||||
|  | @ -25,10 +28,12 @@ import org.junit.jupiter.api.extension.ExtendWith; | ||||||
| import org.signal.zkgroup.receipts.ServerZkReceiptOperations; | import org.signal.zkgroup.receipts.ServerZkReceiptOperations; | ||||||
| import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; | import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; | ||||||
| import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; | import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; | ||||||
|  | import org.whispersystems.textsecuregcm.badges.BadgeTranslator; | ||||||
| import org.whispersystems.textsecuregcm.configuration.SubscriptionConfiguration; | import org.whispersystems.textsecuregcm.configuration.SubscriptionConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.configuration.SubscriptionLevelConfiguration; | import org.whispersystems.textsecuregcm.configuration.SubscriptionLevelConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.configuration.SubscriptionPriceConfiguration; | import org.whispersystems.textsecuregcm.configuration.SubscriptionPriceConfiguration; | ||||||
| import org.whispersystems.textsecuregcm.controllers.SubscriptionController.GetLevelsResponse; | import org.whispersystems.textsecuregcm.controllers.SubscriptionController.GetLevelsResponse; | ||||||
|  | import org.whispersystems.textsecuregcm.entities.Badge; | ||||||
| import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager; | import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager; | ||||||
| import org.whispersystems.textsecuregcm.storage.SubscriptionManager; | import org.whispersystems.textsecuregcm.storage.SubscriptionManager; | ||||||
| import org.whispersystems.textsecuregcm.stripe.StripeManager; | import org.whispersystems.textsecuregcm.stripe.StripeManager; | ||||||
|  | @ -44,8 +49,10 @@ class SubscriptionControllerTest { | ||||||
|   private static final StripeManager STRIPE_MANAGER = mock(StripeManager.class); |   private static final StripeManager STRIPE_MANAGER = mock(StripeManager.class); | ||||||
|   private static final ServerZkReceiptOperations ZK_OPS = mock(ServerZkReceiptOperations.class); |   private static final ServerZkReceiptOperations ZK_OPS = mock(ServerZkReceiptOperations.class); | ||||||
|   private static final IssuedReceiptsManager ISSUED_RECEIPTS_MANAGER = mock(IssuedReceiptsManager.class); |   private static final IssuedReceiptsManager ISSUED_RECEIPTS_MANAGER = mock(IssuedReceiptsManager.class); | ||||||
|  |   private static final BadgeTranslator BADGE_TRANSLATOR = mock(BadgeTranslator.class); | ||||||
|   private static final SubscriptionController SUBSCRIPTION_CONTROLLER = new SubscriptionController( |   private static final SubscriptionController SUBSCRIPTION_CONTROLLER = new SubscriptionController( | ||||||
|       CLOCK, SUBSCRIPTION_CONFIG, SUBSCRIPTION_MANAGER, STRIPE_MANAGER, ZK_OPS, ISSUED_RECEIPTS_MANAGER); |       CLOCK, SUBSCRIPTION_CONFIG, SUBSCRIPTION_MANAGER, STRIPE_MANAGER, ZK_OPS, ISSUED_RECEIPTS_MANAGER, | ||||||
|  |       BADGE_TRANSLATOR); | ||||||
|   private static final ResourceExtension RESOURCE_EXTENSION = ResourceExtension.builder() |   private static final ResourceExtension RESOURCE_EXTENSION = ResourceExtension.builder() | ||||||
|       .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) |       .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) | ||||||
|       .addProvider(AuthHelper.getAuthFilter()) |       .addProvider(AuthHelper.getAuthFilter()) | ||||||
|  | @ -58,7 +65,8 @@ class SubscriptionControllerTest { | ||||||
| 
 | 
 | ||||||
|   @AfterEach |   @AfterEach | ||||||
|   void tearDown() { |   void tearDown() { | ||||||
|     reset(CLOCK, SUBSCRIPTION_CONFIG, SUBSCRIPTION_MANAGER, STRIPE_MANAGER, ZK_OPS, ISSUED_RECEIPTS_MANAGER); |     reset(CLOCK, SUBSCRIPTION_CONFIG, SUBSCRIPTION_MANAGER, STRIPE_MANAGER, ZK_OPS, ISSUED_RECEIPTS_MANAGER, | ||||||
|  |         BADGE_TRANSLATOR); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Test |   @Test | ||||||
|  | @ -68,6 +76,12 @@ class SubscriptionControllerTest { | ||||||
|         2L, new SubscriptionLevelConfiguration("B2", "P2", Map.of("USD", new SubscriptionPriceConfiguration("R2", BigDecimal.valueOf(200)))), |         2L, new SubscriptionLevelConfiguration("B2", "P2", Map.of("USD", new SubscriptionPriceConfiguration("R2", BigDecimal.valueOf(200)))), | ||||||
|         3L, new SubscriptionLevelConfiguration("B3", "P3", Map.of("USD", new SubscriptionPriceConfiguration("R3", BigDecimal.valueOf(300)))) |         3L, new SubscriptionLevelConfiguration("B3", "P3", Map.of("USD", new SubscriptionPriceConfiguration("R3", BigDecimal.valueOf(300)))) | ||||||
|     )); |     )); | ||||||
|  |     when(BADGE_TRANSLATOR.translate(any(), eq("B1"))).thenReturn(new Badge("B1", "cat1", "name1", "desc1", | ||||||
|  |         List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))); | ||||||
|  |     when(BADGE_TRANSLATOR.translate(any(), eq("B2"))).thenReturn(new Badge("B2", "cat2", "name2", "desc2", | ||||||
|  |         List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))); | ||||||
|  |     when(BADGE_TRANSLATOR.translate(any(), eq("B3"))).thenReturn(new Badge("B3", "cat3", "name3", "desc3", | ||||||
|  |         List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))); | ||||||
| 
 | 
 | ||||||
|     GetLevelsResponse response = RESOURCE_EXTENSION.target("/v1/subscription/levels") |     GetLevelsResponse response = RESOURCE_EXTENSION.target("/v1/subscription/levels") | ||||||
|         .request() |         .request() | ||||||
|  | @ -75,19 +89,19 @@ class SubscriptionControllerTest { | ||||||
| 
 | 
 | ||||||
|     assertThat(response.getLevels()).containsKeys(1L, 2L, 3L).satisfies(longLevelMap -> { |     assertThat(response.getLevels()).containsKeys(1L, 2L, 3L).satisfies(longLevelMap -> { | ||||||
|       assertThat(longLevelMap).extractingByKey(1L).satisfies(level -> { |       assertThat(longLevelMap).extractingByKey(1L).satisfies(level -> { | ||||||
|         assertThat(level.getBadgeId()).isEqualTo("B1"); |         assertThat(level.getBadge().getId()).isEqualTo("B1"); | ||||||
|         assertThat(level.getCurrencies()).containsKeys("USD").extractingByKey("USD").satisfies(price -> { |         assertThat(level.getCurrencies()).containsKeys("USD").extractingByKey("USD").satisfies(price -> { | ||||||
|           assertThat(price).isEqualTo("100"); |           assertThat(price).isEqualTo("100"); | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
|       assertThat(longLevelMap).extractingByKey(2L).satisfies(level -> { |       assertThat(longLevelMap).extractingByKey(2L).satisfies(level -> { | ||||||
|         assertThat(level.getBadgeId()).isEqualTo("B2"); |         assertThat(level.getBadge().getId()).isEqualTo("B2"); | ||||||
|         assertThat(level.getCurrencies()).containsKeys("USD").extractingByKey("USD").satisfies(price -> { |         assertThat(level.getCurrencies()).containsKeys("USD").extractingByKey("USD").satisfies(price -> { | ||||||
|           assertThat(price).isEqualTo("200"); |           assertThat(price).isEqualTo("200"); | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
|       assertThat(longLevelMap).extractingByKey(3L).satisfies(level -> { |       assertThat(longLevelMap).extractingByKey(3L).satisfies(level -> { | ||||||
|         assertThat(level.getBadgeId()).isEqualTo("B3"); |         assertThat(level.getBadge().getId()).isEqualTo("B3"); | ||||||
|         assertThat(level.getCurrencies()).containsKeys("USD").extractingByKey("USD").satisfies(price -> { |         assertThat(level.getCurrencies()).containsKeys("USD").extractingByKey("USD").satisfies(price -> { | ||||||
|           assertThat(price).isEqualTo("300"); |           assertThat(price).isEqualTo("300"); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Ehren Kret
						Ehren Kret