Migrate Twilio numbers from static to dynamic configuration

This commit is contained in:
Chris Eager
2021-03-16 11:27:52 -05:00
committed by Chris Eager
parent 7118340f12
commit 5dc8086968
8 changed files with 125 additions and 65 deletions

View File

@@ -353,7 +353,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
ExternalServiceCredentialGenerator paymentsCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getPaymentsServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushSchedulerCluster, apnSender, accountsManager);
TwilioSmsSender twilioSmsSender = new TwilioSmsSender(config.getTwilioConfiguration());
TwilioSmsSender twilioSmsSender = new TwilioSmsSender(config.getTwilioConfiguration(), dynamicConfigurationManager);
SmsSender smsSender = new SmsSender(twilioSmsSender);
MessageSender messageSender = new MessageSender(apnFallbackManager, clientPresenceManager, messagesManager, gcmSender, apnSender, pushLatencyManager);
ReceiptSender receiptSender = new ReceiptSender(accountsManager, messageSender);

View File

@@ -5,11 +5,9 @@
package org.whispersystems.textsecuregcm.configuration;
import com.google.common.annotations.VisibleForTesting;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
public class TwilioConfiguration {
@@ -19,9 +17,6 @@ public class TwilioConfiguration {
@NotEmpty
private String accountToken;
@NotNull
private List<String> numbers;
@NotEmpty
private String localDomain;
@@ -68,16 +63,6 @@ public class TwilioConfiguration {
public void setAccountToken(String accountToken) {
this.accountToken = accountToken;
}
public List<String> getNumbers() {
return numbers;
}
@VisibleForTesting
public void setNumbers(List<String> numbers) {
this.numbers = numbers;
}
public String getLocalDomain() {
return localDomain;
}

View File

@@ -1,12 +1,12 @@
package org.whispersystems.textsecuregcm.configuration.dynamic;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.Valid;
import com.google.common.annotations.VisibleForTesting;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.validation.Valid;
public class DynamicConfiguration {
@@ -29,6 +29,10 @@ public class DynamicConfiguration {
@JsonProperty
private Set<String> featureFlags = Collections.emptySet();
@JsonProperty
@Valid
private DynamicTwilioConfiguration twilio = new DynamicTwilioConfiguration();
public Optional<DynamicExperimentEnrollmentConfiguration> getExperimentEnrollmentConfiguration(final String experimentName) {
return Optional.ofNullable(experiments.get(experimentName));
}
@@ -48,4 +52,14 @@ public class DynamicConfiguration {
public Set<String> getActiveFeatureFlags() {
return featureFlags;
}
public DynamicTwilioConfiguration getTwilioConfiguration() {
return twilio;
}
@VisibleForTesting
public void setTwilioConfiguration(DynamicTwilioConfiguration twilioConfiguration) {
this.twilio = twilioConfiguration;
}
}

View File

@@ -0,0 +1,23 @@
package org.whispersystems.textsecuregcm.configuration.dynamic;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.List;
public class DynamicTwilioConfiguration {
@JsonProperty
@NotNull
private List<String> numbers = Collections.emptyList();
public List<String> getNumbers() {
return numbers;
}
@VisibleForTesting
public void setNumbers(List<String> numbers) {
this.numbers = numbers;
}
}

View File

@@ -4,26 +4,14 @@
*/
package org.whispersystems.textsecuregcm.sms;
import static com.codahale.metrics.MetricRegistry.name;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SharedMetricRegistries;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration;
import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient;
import org.whispersystems.textsecuregcm.http.FormDataBodyPublisher;
import org.whispersystems.textsecuregcm.util.Base64;
import org.whispersystems.textsecuregcm.util.Constants;
import org.whispersystems.textsecuregcm.util.ExecutorUtils;
import org.whispersystems.textsecuregcm.util.SystemMapper;
import org.whispersystems.textsecuregcm.util.Util;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
@@ -31,16 +19,27 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import static com.codahale.metrics.MetricRegistry.name;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration;
import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient;
import org.whispersystems.textsecuregcm.http.FormDataBodyPublisher;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.util.Base64;
import org.whispersystems.textsecuregcm.util.Constants;
import org.whispersystems.textsecuregcm.util.ExecutorUtils;
import org.whispersystems.textsecuregcm.util.SystemMapper;
import org.whispersystems.textsecuregcm.util.Util;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class TwilioSmsSender {
@@ -53,7 +52,6 @@ public class TwilioSmsSender {
private final String accountId;
private final String accountToken;
private final ArrayList<String> numbers;
private final String messagingServiceSid;
private final String nanpaMessagingServiceSid;
private final String localDomain;
@@ -67,13 +65,14 @@ public class TwilioSmsSender {
private final URI smsUri;
private final URI voxUri;
private final DynamicConfigurationManager dynamicConfigurationManager;
@VisibleForTesting
public TwilioSmsSender(String baseUri, TwilioConfiguration twilioConfiguration) {
public TwilioSmsSender(String baseUri, TwilioConfiguration twilioConfiguration, DynamicConfigurationManager dynamicConfigurationManager) {
Executor executor = ExecutorUtils.newFixedThreadBoundedQueueExecutor(10, 100);
this.accountId = twilioConfiguration.getAccountId();
this.accountToken = twilioConfiguration.getAccountToken();
this.numbers = new ArrayList<>(twilioConfiguration.getNumbers());
this.localDomain = twilioConfiguration.getLocalDomain();
this.messagingServiceSid = twilioConfiguration.getMessagingServiceSid();
this.nanpaMessagingServiceSid = twilioConfiguration.getNanpaMessagingServiceSid();
@@ -93,10 +92,11 @@ public class TwilioSmsSender {
.withExecutor(executor)
.withName("twilio")
.build();
this.dynamicConfigurationManager = dynamicConfigurationManager;
}
public TwilioSmsSender(TwilioConfiguration twilioConfiguration) {
this("https://api.twilio.com", twilioConfiguration);
public TwilioSmsSender(TwilioConfiguration twilioConfiguration, DynamicConfigurationManager dynamicConfigurationManager) {
this("https://api.twilio.com", twilioConfiguration, dynamicConfigurationManager);
}
public CompletableFuture<Boolean> deliverSmsVerification(String destination, Optional<String> clientType, String verificationCode) {
@@ -148,7 +148,7 @@ public class TwilioSmsSender {
Map<String, String> requestParameters = new HashMap<>();
requestParameters.put("Url", url);
requestParameters.put("To", destination);
requestParameters.put("From", getRandom(random, numbers));
requestParameters.put("From", getRandom(random, dynamicConfigurationManager.getConfiguration().getTwilioConfiguration().getNumbers()));
HttpRequest request = HttpRequest.newBuilder()
.uri(voxUri)
@@ -164,7 +164,7 @@ public class TwilioSmsSender {
.handle(this::processResponse);
}
private String getRandom(Random random, ArrayList<String> elements) {
private String getRandom(Random random, List<String> elements) {
return elements.get(random.nextInt(elements.size()));
}