diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index 9bf73cdae..89f5b62d0 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -19,7 +19,6 @@ package org.whispersystems.textsecuregcm; import com.fasterxml.jackson.annotation.JsonProperty; import org.whispersystems.textsecuregcm.configuration.FederationConfiguration; import org.whispersystems.textsecuregcm.configuration.GraphiteConfiguration; -import org.whispersystems.textsecuregcm.configuration.NexmoConfiguration; import org.whispersystems.textsecuregcm.configuration.PushConfiguration; import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration; import org.whispersystems.textsecuregcm.configuration.RedPhoneConfiguration; @@ -31,7 +30,6 @@ import org.whispersystems.textsecuregcm.configuration.WebsocketConfiguration; import javax.validation.Valid; import javax.validation.constraints.NotNull; - import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -48,9 +46,6 @@ public class WhisperServerConfiguration extends Configuration { @JsonProperty private TwilioConfiguration twilio; - @JsonProperty - private NexmoConfiguration nexmo; - @NotNull @Valid @JsonProperty @@ -120,10 +115,6 @@ public class WhisperServerConfiguration extends Configuration { return twilio; } - public NexmoConfiguration getNexmoConfiguration() { - return nexmo; - } - public PushConfiguration getPushConfiguration() { return push; } diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 74ce4e0a2..107b98bd3 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -33,7 +33,6 @@ import org.whispersystems.dropwizard.simpleauth.AuthValueFactoryProvider; import org.whispersystems.dropwizard.simpleauth.BasicCredentialAuthFilter; import org.whispersystems.textsecuregcm.auth.AccountAuthenticator; import org.whispersystems.textsecuregcm.auth.FederatedPeerAuthenticator; -import org.whispersystems.textsecuregcm.configuration.NexmoConfiguration; import org.whispersystems.textsecuregcm.controllers.AccountController; import org.whispersystems.textsecuregcm.controllers.AttachmentController; import org.whispersystems.textsecuregcm.controllers.DeviceController; @@ -68,7 +67,6 @@ import org.whispersystems.textsecuregcm.push.PushSender; import org.whispersystems.textsecuregcm.push.PushServiceClient; import org.whispersystems.textsecuregcm.push.ReceiptSender; import org.whispersystems.textsecuregcm.push.WebsocketSender; -import org.whispersystems.textsecuregcm.sms.NexmoSmsSender; import org.whispersystems.textsecuregcm.sms.SmsSender; import org.whispersystems.textsecuregcm.sms.TwilioSmsSender; import org.whispersystems.textsecuregcm.storage.Account; @@ -185,8 +183,7 @@ public class WhisperServerService extends Application nexmoSmsSender = initializeNexmoSmsSender(config.getNexmoConfiguration()); - SmsSender smsSender = new SmsSender(twilioSmsSender, nexmoSmsSender, config.getTwilioConfiguration().isInternational()); + SmsSender smsSender = new SmsSender(twilioSmsSender); UrlSigner urlSigner = new UrlSigner(config.getS3Configuration()); PushSender pushSender = new PushSender(apnFallbackManager, pushServiceClient, websocketSender); ReceiptSender receiptSender = new ReceiptSender(accountsManager, pushSender, federatedClientManager); @@ -282,14 +279,6 @@ public class WhisperServerService extends Application initializeNexmoSmsSender(NexmoConfiguration configuration) { - if (configuration == null) { - return Optional.absent(); - } else { - return Optional.of(new NexmoSmsSender(configuration)); - } - } - private Client initializeHttpClient(Environment environment, WhisperServerConfiguration config) { Client httpClient = new JerseyClientBuilder(environment).using(config.getJerseyClientConfiguration()) .build(getName()); diff --git a/src/main/java/org/whispersystems/textsecuregcm/configuration/NexmoConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/configuration/NexmoConfiguration.java deleted file mode 100644 index b97311d22..000000000 --- a/src/main/java/org/whispersystems/textsecuregcm/configuration/NexmoConfiguration.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (C) 2013 Open WhisperSystems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.whispersystems.textsecuregcm.configuration; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class NexmoConfiguration { - - @JsonProperty - private String apiKey; - - @JsonProperty - private String apiSecret; - - @JsonProperty - private String number; - - public String getApiKey() { - return apiKey; - } - - public String getApiSecret() { - return apiSecret; - } - - public String getNumber() { - return number; - } -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/configuration/TwilioConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/configuration/TwilioConfiguration.java index c65e4fd3d..ab4140457 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/configuration/TwilioConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/configuration/TwilioConfiguration.java @@ -40,9 +40,6 @@ public class TwilioConfiguration { @JsonProperty private String localDomain; - @JsonProperty - private boolean international; - public String getAccountId() { return accountId; } @@ -58,8 +55,4 @@ public class TwilioConfiguration { public String getLocalDomain() { return localDomain; } - - public boolean isInternational() { - return international; - } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java b/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java index 9d711298a..c48afac9f 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java +++ b/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java @@ -105,7 +105,7 @@ public class AccountController { @Path("/{transport}/code/{number}") public Response createAccount(@PathParam("transport") String transport, @PathParam("number") String number, - @QueryParam("client") String client) + @QueryParam("client") Optional client) throws IOException, RateLimitExceededException { if (!Util.isValidNumber(number)) { diff --git a/src/main/java/org/whispersystems/textsecuregcm/sms/NexmoSmsSender.java b/src/main/java/org/whispersystems/textsecuregcm/sms/NexmoSmsSender.java deleted file mode 100644 index cafa7029e..000000000 --- a/src/main/java/org/whispersystems/textsecuregcm/sms/NexmoSmsSender.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (C) 2013 Open WhisperSystems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.whispersystems.textsecuregcm.sms; - -import com.codahale.metrics.Meter; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.SharedMetricRegistries; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.whispersystems.textsecuregcm.configuration.NexmoConfiguration; -import org.whispersystems.textsecuregcm.util.Constants; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; - -import static com.codahale.metrics.MetricRegistry.name; - -public class NexmoSmsSender { - - private final MetricRegistry metricRegistry = SharedMetricRegistries.getOrCreate(Constants.METRICS_NAME); - private final Meter smsMeter = metricRegistry.meter(name(getClass(), "sms", "delivered")); - private final Meter voxMeter = metricRegistry.meter(name(getClass(), "vox", "delivered")); - private final Logger logger = LoggerFactory.getLogger(NexmoSmsSender.class); - - private static final String NEXMO_SMS_URL = - "https://rest.nexmo.com/sms/json?api_key=%s&api_secret=%s&from=%s&to=%s&text=%s"; - - private static final String NEXMO_VOX_URL = - "https://rest.nexmo.com/tts/json?api_key=%s&api_secret=%s&to=%s&text=%s"; - - private final String apiKey; - private final String apiSecret; - private final String number; - - public NexmoSmsSender(NexmoConfiguration config) { - this.apiKey = config.getApiKey(); - this.apiSecret = config.getApiSecret(); - this.number = config.getNumber(); - } - - public void deliverSmsVerification(String destination, String clientType, String verificationCode) throws IOException { - String verificationMsg; - - if ("ios".equals(clientType)) { - verificationMsg = String.format(SmsSender.SMS_IOS_VERIFICATION_TEXT, verificationCode, verificationCode); - } else { - verificationMsg = String.format(SmsSender.SMS_VERIFICATION_TEXT, verificationCode); - } - - URL url = new URL(String.format(NEXMO_SMS_URL, apiKey, apiSecret, number, destination, - URLEncoder.encode(verificationMsg, "UTF-8"))); - - URLConnection connection = url.openConnection(); - connection.setDoInput(true); - connection.connect(); - - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - while (reader.readLine() != null) {} - reader.close(); - smsMeter.mark(); - } - - public void deliverVoxVerification(String destination, String message) throws IOException { - URL url = new URL(String.format(NEXMO_VOX_URL, apiKey, apiSecret, destination, - URLEncoder.encode(SmsSender.VOX_VERIFICATION_TEXT + message, "UTF-8"))); - - URLConnection connection = url.openConnection(); - connection.setDoInput(true); - connection.connect(); - - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - logger.debug(line); - } - reader.close(); - voxMeter.mark(); - } - - -} diff --git a/src/main/java/org/whispersystems/textsecuregcm/sms/SmsSender.java b/src/main/java/org/whispersystems/textsecuregcm/sms/SmsSender.java index ed537a28f..adf955df5 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/sms/SmsSender.java +++ b/src/main/java/org/whispersystems/textsecuregcm/sms/SmsSender.java @@ -25,26 +25,21 @@ import org.slf4j.LoggerFactory; import java.io.IOException; public class SmsSender { + static final String SMS_IOS_VERIFICATION_TEXT = "Your Signal verification code: %s\n\nOr tap: sgnl://verify/%s"; - static final String SMS_VERIFICATION_TEXT = "Your TextSecure verification code: "; - static final String VOX_VERIFICATION_TEXT = "Your Signal verification code is: "; + static final String SMS_VERIFICATION_TEXT = "Your TextSecure verification code: %s"; + static final String VOX_VERIFICATION_TEXT = "Your Signal verification code is: "; private final Logger logger = LoggerFactory.getLogger(SmsSender.class); - private final TwilioSmsSender twilioSender; - private final Optional nexmoSender; - private final boolean isTwilioInternational; + private final TwilioSmsSender twilioSender; - public SmsSender(TwilioSmsSender twilioSender, - Optional nexmoSender, - boolean isTwilioInternational) + public SmsSender(TwilioSmsSender twilioSender) { - this.isTwilioInternational = isTwilioInternational; - this.twilioSender = twilioSender; - this.nexmoSender = nexmoSender; + this.twilioSender = twilioSender; } - public void deliverSmsVerification(String destination, String clientType, String verificationCode) + public void deliverSmsVerification(String destination, Optional clientType, String verificationCode) throws IOException { // Fix up mexico numbers to 'mobile' format just for SMS delivery. @@ -52,38 +47,20 @@ public class SmsSender { destination = "+421" + destination.substring(3); } - if (!isTwilioDestination(destination) && nexmoSender.isPresent()) { - nexmoSender.get().deliverSmsVerification(destination, clientType, verificationCode); - } else { - try { - twilioSender.deliverSmsVerification(destination, clientType, verificationCode); - } catch (TwilioRestException e) { - logger.info("Twilio SMS Failed: " + e.getErrorMessage()); - if (nexmoSender.isPresent()) { - nexmoSender.get().deliverSmsVerification(destination, clientType, verificationCode); - } - } + try { + twilioSender.deliverSmsVerification(destination, clientType, verificationCode); + } catch (TwilioRestException e) { + logger.info("Twilio SMS Failed: " + e.getErrorMessage()); } } public void deliverVoxVerification(String destination, String verificationCode) throws IOException { - if (!isTwilioDestination(destination) && nexmoSender.isPresent()) { - nexmoSender.get().deliverVoxVerification(destination, verificationCode); - } else { - try { - twilioSender.deliverVoxVerification(destination, verificationCode); - } catch (TwilioRestException e) { - logger.info("Twilio Vox Failed: " + e.getErrorMessage()); - if (nexmoSender.isPresent()) { - nexmoSender.get().deliverVoxVerification(destination, verificationCode); - } - } + try { + twilioSender.deliverVoxVerification(destination, verificationCode); + } catch (TwilioRestException e) { + logger.info("Twilio Vox Failed: " + e.getErrorMessage()); } } - - private boolean isTwilioDestination(String number) { - return isTwilioInternational || number.length() == 12 && number.startsWith("+1"); - } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/sms/TwilioSmsSender.java b/src/main/java/org/whispersystems/textsecuregcm/sms/TwilioSmsSender.java index a578085de..a98bc3e6f 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/sms/TwilioSmsSender.java +++ b/src/main/java/org/whispersystems/textsecuregcm/sms/TwilioSmsSender.java @@ -19,6 +19,7 @@ package org.whispersystems.textsecuregcm.sms; import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.SharedMetricRegistries; +import com.google.common.base.Optional; import com.twilio.sdk.TwilioRestClient; import com.twilio.sdk.TwilioRestException; import com.twilio.sdk.resource.factory.CallFactory; @@ -63,7 +64,7 @@ public class TwilioSmsSender { this.random = new Random(System.currentTimeMillis()); } - public void deliverSmsVerification(String destination, String clientType, String verificationCode) + public void deliverSmsVerification(String destination, Optional clientType, String verificationCode) throws IOException, TwilioRestException { TwilioRestClient client = new TwilioRestClient(accountId, accountToken); @@ -72,7 +73,7 @@ public class TwilioSmsSender { messageParams.add(new BasicNameValuePair("To", destination)); messageParams.add(new BasicNameValuePair("From", getRandom(random, numbers))); - if ("ios".equals(clientType)) { + if ("ios".equals(clientType.orNull())) { messageParams.add(new BasicNameValuePair("Body", String.format(SmsSender.SMS_IOS_VERIFICATION_TEXT, verificationCode, verificationCode))); } else { messageParams.add(new BasicNameValuePair("Body", String.format(SmsSender.SMS_VERIFICATION_TEXT, verificationCode))); diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java index 6450c83f1..11aa87cc1 100644 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java +++ b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/AccountControllerTest.java @@ -82,7 +82,7 @@ public class AccountControllerTest { assertThat(response.getStatus()).isEqualTo(200); - verify(smsSender).deliverSmsVerification(eq(SENDER), isNull(String.class), anyString()); + verify(smsSender).deliverSmsVerification(eq(SENDER), eq(Optional.absent()), anyString()); } @Test @@ -96,7 +96,7 @@ public class AccountControllerTest { assertThat(response.getStatus()).isEqualTo(200); - verify(smsSender).deliverSmsVerification(eq(SENDER), eq("ios"), anyString()); + verify(smsSender).deliverSmsVerification(eq(SENDER), eq(Optional.of("ios")), anyString()); } @Test diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/sms/DeliveryPreferenceTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/sms/DeliveryPreferenceTest.java deleted file mode 100644 index 565408997..000000000 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/sms/DeliveryPreferenceTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.whispersystems.textsecuregcm.tests.sms; - -import com.google.common.base.Optional; -import com.twilio.sdk.TwilioRestException; -import junit.framework.TestCase; -import org.whispersystems.textsecuregcm.sms.NexmoSmsSender; -import org.whispersystems.textsecuregcm.sms.SmsSender; -import org.whispersystems.textsecuregcm.sms.TwilioSmsSender; - -import java.io.IOException; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -public class DeliveryPreferenceTest extends TestCase { - - private TwilioSmsSender twilioSender = mock(TwilioSmsSender.class); - private NexmoSmsSender nexmoSender = mock(NexmoSmsSender.class); - - public void testInternationalPreferenceOff() throws IOException, TwilioRestException { - SmsSender smsSender = new SmsSender(twilioSender, Optional.of(nexmoSender), false); - - smsSender.deliverSmsVerification("+441112223333", null, "123-456"); - verify(nexmoSender).deliverSmsVerification("+441112223333", null, "123-456"); - verifyNoMoreInteractions(twilioSender); - } - - public void testInternationalPreferenceOn() throws IOException, TwilioRestException { - SmsSender smsSender = new SmsSender(twilioSender, Optional.of(nexmoSender), true); - - smsSender.deliverSmsVerification("+441112223333", null, "123-456"); - verify(twilioSender).deliverSmsVerification("+441112223333", null, "123-456"); - verifyNoMoreInteractions(nexmoSender); - } -} diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/sms/TwilioFallbackTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/sms/TwilioFallbackTest.java deleted file mode 100644 index d81726409..000000000 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/sms/TwilioFallbackTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.whispersystems.textsecuregcm.tests.sms; - -import com.google.common.base.Optional; -import com.twilio.sdk.TwilioRestException; -import junit.framework.TestCase; -import org.whispersystems.textsecuregcm.sms.NexmoSmsSender; -import org.whispersystems.textsecuregcm.sms.SmsSender; -import org.whispersystems.textsecuregcm.sms.TwilioSmsSender; - -import java.io.IOException; - -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; - -public class TwilioFallbackTest extends TestCase { - - private NexmoSmsSender nexmoSender = mock(NexmoSmsSender.class ); - private TwilioSmsSender twilioSender = mock(TwilioSmsSender.class); - - @Override - protected void setUp() throws IOException, TwilioRestException { - doThrow(new TwilioRestException("foo", 404)).when(twilioSender).deliverSmsVerification(anyString(), anyString(), anyString()); - doThrow(new TwilioRestException("bar", 405)).when(twilioSender).deliverVoxVerification(anyString(), anyString()); - } - - public void testNexmoSmsFallback() throws IOException, TwilioRestException { - SmsSender smsSender = new SmsSender(twilioSender, Optional.of(nexmoSender), true); - smsSender.deliverSmsVerification("+442223334444", null, "123-456"); - - verify(nexmoSender).deliverSmsVerification("+442223334444", null, "123-456"); - verify(twilioSender).deliverSmsVerification("+442223334444", null, "123-456"); - } - - public void testNexmoVoxFallback() throws IOException, TwilioRestException { - SmsSender smsSender = new SmsSender(twilioSender, Optional.of(nexmoSender), true); - smsSender.deliverVoxVerification("+442223334444", "123-456"); - - verify(nexmoSender).deliverVoxVerification("+442223334444", "123-456"); - verify(twilioSender).deliverVoxVerification("+442223334444", "123-456"); - } - - -}