Create a strategy class to decide which sender id to use

The rules around selecting sender ids can get complicated with some
countries not supporting it and others requiring pre-registration that
may result in having a different sender id for that country than
others. This strategy class handles the logic of dealing with this
expanded configuration and applying the appropriate sender id or none
when it's not appropriate to do so at all.
This commit is contained in:
Ehren Kret
2020-07-13 23:25:06 -05:00
parent e3aecb2aa9
commit b7e0e5a356
7 changed files with 240 additions and 81 deletions

View File

@@ -0,0 +1,47 @@
package org.whispersystems.textsecuregcm.sms;
import com.google.common.base.Strings;
import org.whispersystems.textsecuregcm.configuration.TwilioCountrySenderIdConfiguration;
import org.whispersystems.textsecuregcm.configuration.TwilioSenderIdConfiguration;
import org.whispersystems.textsecuregcm.util.Util;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
public class SenderIdStrategy {
private final String defaultSenderId;
private final Map<String, String> countrySpecificSenderIds;
private final Set<String> countryCodesWithoutSenderId;
public SenderIdStrategy(String defaultSenderId, List<TwilioCountrySenderIdConfiguration> countrySpecificSenderIds, Set<String> countryCodesWithoutSenderId) {
this.defaultSenderId = defaultSenderId;
this.countrySpecificSenderIds = countrySpecificSenderIds.stream().collect(Collectors.toMap(
TwilioCountrySenderIdConfiguration::getCountryCode,
TwilioCountrySenderIdConfiguration::getSenderId));
this.countryCodesWithoutSenderId = countryCodesWithoutSenderId;
}
public SenderIdStrategy(TwilioSenderIdConfiguration configuration) {
this(configuration.getDefaultSenderId(),
configuration.getCountrySpecificSenderIds(),
configuration.getCountryCodesWithoutSenderId());
}
public Optional<String> get(@NotNull String destination) {
final String countryCode = Util.getCountryCode(destination);
if (countryCodesWithoutSenderId.contains(countryCode)) {
return Optional.empty();
}
final String countrySpecificSenderId = countrySpecificSenderIds.get(countryCode);
if (!Strings.isNullOrEmpty(countrySpecificSenderId)) {
return Optional.of(countrySpecificSenderId);
}
return Optional.ofNullable(defaultSenderId);
}
}

View File

@@ -24,7 +24,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.configuration.TwilioAlphaIdConfiguration;
import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration;
import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient;
import org.whispersystems.textsecuregcm.http.FormDataBodyPublisher;
@@ -42,7 +41,6 @@ import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
@@ -62,13 +60,13 @@ public class TwilioSmsSender {
private final Meter voxMeter = metricRegistry.meter(name(getClass(), "vox", "delivered"));
private final Meter priceMeter = metricRegistry.meter(name(getClass(), "price"));
private final String accountId;
private final String accountToken;
private final ArrayList<String> numbers;
private final String messagingServicesId;
private final String localDomain;
private final List<TwilioAlphaIdConfiguration> alphaId;
private final Random random;
private final String accountId;
private final String accountToken;
private final ArrayList<String> numbers;
private final String messagingServicesId;
private final String localDomain;
private final Random random;
private final SenderIdStrategy senderIdStrategy;
private final FaultTolerantHttpClient httpClient;
private final URI smsUri;
@@ -83,7 +81,7 @@ public class TwilioSmsSender {
this.numbers = new ArrayList<>(twilioConfiguration.getNumbers());
this.localDomain = twilioConfiguration.getLocalDomain();
this.messagingServicesId = twilioConfiguration.getMessagingServicesId();
this.alphaId = twilioConfiguration.getAlphaId();
this.senderIdStrategy = new SenderIdStrategy(twilioConfiguration.getSenderId());
this.random = new Random(System.currentTimeMillis());
this.smsUri = URI.create(baseUri + "/2010-04-01/Accounts/" + accountId + "/Messages.json");
this.voxUri = URI.create(baseUri + "/2010-04-01/Accounts/" + accountId + "/Calls.json" );
@@ -176,9 +174,9 @@ public class TwilioSmsSender {
}
private void setOriginationRequestParameter(String destination, Map<String, String> requestParameters) {
final Optional<TwilioAlphaIdConfiguration> alphaIdConfiguration = getAlphaIdConfigurationForNumber(destination);
if (alphaIdConfiguration.isPresent()) {
requestParameters.put("From", alphaIdConfiguration.get().getValue());
final Optional<String> senderId = senderIdStrategy.get(destination);
if (senderId.isPresent()) {
requestParameters.put("From", senderId.get());
} else if (Util.isEmpty(messagingServicesId)) {
requestParameters.put("From", getRandom(random, numbers));
} else {
@@ -224,21 +222,6 @@ public class TwilioSmsSender {
}
}
private Optional<TwilioAlphaIdConfiguration> getAlphaIdConfigurationForNumber(String number) {
if (alphaId == null) {
return Optional.empty();
}
final String countryCode = Util.getCountryCode(number);
for (TwilioAlphaIdConfiguration twilioAlphaIdConfiguration : alphaId) {
if (twilioAlphaIdConfiguration.getPrefix().equalsIgnoreCase(countryCode)) {
return Optional.of(twilioAlphaIdConfiguration);
}
}
return Optional.empty();
}
public static class TwilioResponse {
private TwilioSuccessResponse successResponse;