Use RecaptchaClient interface

This commit is contained in:
Ehren Kret 2021-07-30 13:50:16 -07:00
parent 2c808e369c
commit 33fb7a72de
5 changed files with 40 additions and 32 deletions

View File

@ -132,7 +132,9 @@ import org.whispersystems.textsecuregcm.push.GCMSender;
import org.whispersystems.textsecuregcm.push.MessageSender; import org.whispersystems.textsecuregcm.push.MessageSender;
import org.whispersystems.textsecuregcm.push.ProvisioningManager; import org.whispersystems.textsecuregcm.push.ProvisioningManager;
import org.whispersystems.textsecuregcm.push.ReceiptSender; import org.whispersystems.textsecuregcm.push.ReceiptSender;
import org.whispersystems.textsecuregcm.recaptcha.EnterpriseRecaptchaClient;
import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient; import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient;
import org.whispersystems.textsecuregcm.recaptcha.TransitionalRecaptchaClient;
import org.whispersystems.textsecuregcm.redis.ConnectionEventLogger; import org.whispersystems.textsecuregcm.redis.ConnectionEventLogger;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool; import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
@ -467,9 +469,12 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
ReceiptSender receiptSender = new ReceiptSender(accountsManager, messageSender); ReceiptSender receiptSender = new ReceiptSender(accountsManager, messageSender);
TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(config.getTurnConfiguration()); TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(config.getTurnConfiguration());
LegacyRecaptchaClient legacyRecaptchaClient = new LegacyRecaptchaClient(config.getRecaptchaConfiguration().getSecret()); LegacyRecaptchaClient legacyRecaptchaClient = new LegacyRecaptchaClient(config.getRecaptchaConfiguration().getSecret());
EnterpriseRecaptchaClient enterpriseRecaptchaClient = new EnterpriseRecaptchaClient();
TransitionalRecaptchaClient transitionalRecaptchaClient = new TransitionalRecaptchaClient(legacyRecaptchaClient, enterpriseRecaptchaClient);
PushChallengeManager pushChallengeManager = new PushChallengeManager(apnSender, gcmSender, pushChallengeDynamoDb); PushChallengeManager pushChallengeManager = new PushChallengeManager(apnSender, gcmSender, pushChallengeDynamoDb);
RateLimitChallengeManager rateLimitChallengeManager = new RateLimitChallengeManager(pushChallengeManager, RateLimitChallengeManager rateLimitChallengeManager = new RateLimitChallengeManager(pushChallengeManager,
legacyRecaptchaClient, preKeyRateLimiter, unsealedSenderRateLimiter, rateLimiters, dynamicConfigurationManager); transitionalRecaptchaClient, preKeyRateLimiter, unsealedSenderRateLimiter, rateLimiters,
dynamicConfigurationManager);
MessagePersister messagePersister = new MessagePersister(messagesCache, messagesManager, accountsManager, dynamicConfigurationManager, Duration.ofMinutes(config.getMessageCacheConfiguration().getPersistDelayMinutes())); MessagePersister messagePersister = new MessagePersister(messagesCache, messagesManager, accountsManager, dynamicConfigurationManager, Duration.ofMinutes(config.getMessageCacheConfiguration().getPersistDelayMinutes()));
@ -553,8 +558,11 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
webSocketEnvironment.jersey().register(new KeepAliveController(clientPresenceManager)); webSocketEnvironment.jersey().register(new KeepAliveController(clientPresenceManager));
// these should be common, but use @Auth DisabledPermittedAccount, which isnt supported yet on websocket // these should be common, but use @Auth DisabledPermittedAccount, which isnt supported yet on websocket
environment.jersey().register(new AccountController(pendingAccountsManager, accountsManager, usernamesManager, abusiveHostRules, rateLimiters, smsSender, dynamicConfigurationManager, turnTokenGenerator, config.getTestDevices(), environment.jersey().register(
legacyRecaptchaClient, gcmSender, apnSender, backupCredentialsGenerator, verifyExperimentEnrollmentManager)); new AccountController(pendingAccountsManager, accountsManager, usernamesManager, abusiveHostRules, rateLimiters,
smsSender, dynamicConfigurationManager, turnTokenGenerator, config.getTestDevices(),
transitionalRecaptchaClient, gcmSender, apnSender, backupCredentialsGenerator,
verifyExperimentEnrollmentManager));
environment.jersey().register(new KeysController(rateLimiters, keysDynamoDb, accountsManager, preKeyRateLimiter, dynamicConfigurationManager, rateLimitChallengeManager)); environment.jersey().register(new KeysController(rateLimiters, keysDynamoDb, accountsManager, preKeyRateLimiter, dynamicConfigurationManager, rateLimitChallengeManager));
final List<Object> commonControllers = List.of( final List<Object> commonControllers = List.of(

View File

@ -63,7 +63,7 @@ import org.whispersystems.textsecuregcm.push.APNSender;
import org.whispersystems.textsecuregcm.push.ApnMessage; import org.whispersystems.textsecuregcm.push.ApnMessage;
import org.whispersystems.textsecuregcm.push.GCMSender; import org.whispersystems.textsecuregcm.push.GCMSender;
import org.whispersystems.textsecuregcm.push.GcmMessage; import org.whispersystems.textsecuregcm.push.GcmMessage;
import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient; import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
import org.whispersystems.textsecuregcm.sms.SmsSender; import org.whispersystems.textsecuregcm.sms.SmsSender;
import org.whispersystems.textsecuregcm.sms.TwilioVerifyExperimentEnrollmentManager; import org.whispersystems.textsecuregcm.sms.TwilioVerifyExperimentEnrollmentManager;
import org.whispersystems.textsecuregcm.storage.AbusiveHostRule; import org.whispersystems.textsecuregcm.storage.AbusiveHostRule;
@ -116,7 +116,7 @@ public class AccountController {
private final DynamicConfigurationManager dynamicConfigurationManager; private final DynamicConfigurationManager dynamicConfigurationManager;
private final TurnTokenGenerator turnTokenGenerator; private final TurnTokenGenerator turnTokenGenerator;
private final Map<String, Integer> testDevices; private final Map<String, Integer> testDevices;
private final LegacyRecaptchaClient legacyRecaptchaClient; private final RecaptchaClient recaptchaClient;
private final GCMSender gcmSender; private final GCMSender gcmSender;
private final APNSender apnSender; private final APNSender apnSender;
private final ExternalServiceCredentialGenerator backupServiceCredentialGenerator; private final ExternalServiceCredentialGenerator backupServiceCredentialGenerator;
@ -132,7 +132,7 @@ public class AccountController {
DynamicConfigurationManager dynamicConfigurationManager, DynamicConfigurationManager dynamicConfigurationManager,
TurnTokenGenerator turnTokenGenerator, TurnTokenGenerator turnTokenGenerator,
Map<String, Integer> testDevices, Map<String, Integer> testDevices,
LegacyRecaptchaClient legacyRecaptchaClient, RecaptchaClient recaptchaClient,
GCMSender gcmSender, GCMSender gcmSender,
APNSender apnSender, APNSender apnSender,
ExternalServiceCredentialGenerator backupServiceCredentialGenerator, ExternalServiceCredentialGenerator backupServiceCredentialGenerator,
@ -147,7 +147,7 @@ public class AccountController {
this.dynamicConfigurationManager = dynamicConfigurationManager; this.dynamicConfigurationManager = dynamicConfigurationManager;
this.testDevices = testDevices; this.testDevices = testDevices;
this.turnTokenGenerator = turnTokenGenerator; this.turnTokenGenerator = turnTokenGenerator;
this.legacyRecaptchaClient = legacyRecaptchaClient; this.recaptchaClient = recaptchaClient;
this.gcmSender = gcmSender; this.gcmSender = gcmSender;
this.apnSender = apnSender; this.apnSender = apnSender;
this.backupServiceCredentialGenerator = backupServiceCredentialGenerator; this.backupServiceCredentialGenerator = backupServiceCredentialGenerator;
@ -595,7 +595,7 @@ public class AccountController {
{ {
if (captchaToken.isPresent()) { if (captchaToken.isPresent()) {
boolean validToken = legacyRecaptchaClient.verify(captchaToken.get(), requester); boolean validToken = recaptchaClient.verify(captchaToken.get(), requester);
if (validToken) { if (validToken) {
captchaSuccessMeter.mark(); captchaSuccessMeter.mark();

View File

@ -1,13 +1,15 @@
package org.whispersystems.textsecuregcm.limits; package org.whispersystems.textsecuregcm.limits;
import static com.codahale.metrics.MetricRegistry.name;
import com.vdurmont.semver4j.Semver; import com.vdurmont.semver4j.Semver;
import io.micrometer.core.instrument.Metrics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import io.micrometer.core.instrument.Metrics;
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException; import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException; import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient; import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.util.Util; import org.whispersystems.textsecuregcm.util.Util;
@ -15,12 +17,10 @@ import org.whispersystems.textsecuregcm.util.ua.UnrecognizedUserAgentException;
import org.whispersystems.textsecuregcm.util.ua.UserAgent; import org.whispersystems.textsecuregcm.util.ua.UserAgent;
import org.whispersystems.textsecuregcm.util.ua.UserAgentUtil; import org.whispersystems.textsecuregcm.util.ua.UserAgentUtil;
import static com.codahale.metrics.MetricRegistry.name;
public class RateLimitChallengeManager { public class RateLimitChallengeManager {
private final PushChallengeManager pushChallengeManager; private final PushChallengeManager pushChallengeManager;
private final LegacyRecaptchaClient legacyRecaptchaClient; private final RecaptchaClient recaptchaClient;
private final PreKeyRateLimiter preKeyRateLimiter; private final PreKeyRateLimiter preKeyRateLimiter;
private final UnsealedSenderRateLimiter unsealedSenderRateLimiter; private final UnsealedSenderRateLimiter unsealedSenderRateLimiter;
@ -39,14 +39,14 @@ public class RateLimitChallengeManager {
public RateLimitChallengeManager( public RateLimitChallengeManager(
final PushChallengeManager pushChallengeManager, final PushChallengeManager pushChallengeManager,
final LegacyRecaptchaClient legacyRecaptchaClient, final RecaptchaClient recaptchaClient,
final PreKeyRateLimiter preKeyRateLimiter, final PreKeyRateLimiter preKeyRateLimiter,
final UnsealedSenderRateLimiter unsealedSenderRateLimiter, final UnsealedSenderRateLimiter unsealedSenderRateLimiter,
final RateLimiters rateLimiters, final RateLimiters rateLimiters,
final DynamicConfigurationManager dynamicConfigurationManager) { final DynamicConfigurationManager dynamicConfigurationManager) {
this.pushChallengeManager = pushChallengeManager; this.pushChallengeManager = pushChallengeManager;
this.legacyRecaptchaClient = legacyRecaptchaClient; this.recaptchaClient = recaptchaClient;
this.preKeyRateLimiter = preKeyRateLimiter; this.preKeyRateLimiter = preKeyRateLimiter;
this.unsealedSenderRateLimiter = unsealedSenderRateLimiter; this.unsealedSenderRateLimiter = unsealedSenderRateLimiter;
this.rateLimiters = rateLimiters; this.rateLimiters = rateLimiters;
@ -69,7 +69,7 @@ public class RateLimitChallengeManager {
rateLimiters.getRecaptchaChallengeAttemptLimiter().validate(account.getNumber()); rateLimiters.getRecaptchaChallengeAttemptLimiter().validate(account.getNumber());
final boolean challengeSuccess = legacyRecaptchaClient.verify(captcha, mostRecentProxyIp); final boolean challengeSuccess = recaptchaClient.verify(captcha, mostRecentProxyIp);
Metrics.counter(RECAPTCHA_ATTEMPT_COUNTER_NAME, Metrics.counter(RECAPTCHA_ATTEMPT_COUNTER_NAME,
SOURCE_COUNTRY_TAG_NAME, Util.getCountryCode(account.getNumber()), SOURCE_COUNTRY_TAG_NAME, Util.getCountryCode(account.getNumber()),

View File

@ -22,7 +22,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicRateLimitChallengeConfiguration; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicRateLimitChallengeConfiguration;
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException; import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient; import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.util.ua.ClientPlatform; import org.whispersystems.textsecuregcm.util.ua.ClientPlatform;
@ -30,7 +30,7 @@ import org.whispersystems.textsecuregcm.util.ua.ClientPlatform;
class RateLimitChallengeManagerTest { class RateLimitChallengeManagerTest {
private PushChallengeManager pushChallengeManager; private PushChallengeManager pushChallengeManager;
private LegacyRecaptchaClient legacyRecaptchaClient; private RecaptchaClient recaptchaClient;
private PreKeyRateLimiter preKeyRateLimiter; private PreKeyRateLimiter preKeyRateLimiter;
private UnsealedSenderRateLimiter unsealedSenderRateLimiter; private UnsealedSenderRateLimiter unsealedSenderRateLimiter;
private DynamicRateLimitChallengeConfiguration rateLimitChallengeConfiguration; private DynamicRateLimitChallengeConfiguration rateLimitChallengeConfiguration;
@ -41,7 +41,7 @@ class RateLimitChallengeManagerTest {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
pushChallengeManager = mock(PushChallengeManager.class); pushChallengeManager = mock(PushChallengeManager.class);
legacyRecaptchaClient = mock(LegacyRecaptchaClient.class); recaptchaClient = mock(RecaptchaClient.class);
preKeyRateLimiter = mock(PreKeyRateLimiter.class); preKeyRateLimiter = mock(PreKeyRateLimiter.class);
unsealedSenderRateLimiter = mock(UnsealedSenderRateLimiter.class); unsealedSenderRateLimiter = mock(UnsealedSenderRateLimiter.class);
rateLimiters = mock(RateLimiters.class); rateLimiters = mock(RateLimiters.class);
@ -55,7 +55,7 @@ class RateLimitChallengeManagerTest {
rateLimitChallengeManager = new RateLimitChallengeManager( rateLimitChallengeManager = new RateLimitChallengeManager(
pushChallengeManager, pushChallengeManager,
legacyRecaptchaClient, recaptchaClient,
preKeyRateLimiter, preKeyRateLimiter,
unsealedSenderRateLimiter, unsealedSenderRateLimiter,
rateLimiters, rateLimiters,
@ -89,7 +89,7 @@ class RateLimitChallengeManagerTest {
final Account account = mock(Account.class); final Account account = mock(Account.class);
when(account.getNumber()).thenReturn("+18005551234"); when(account.getNumber()).thenReturn("+18005551234");
when(legacyRecaptchaClient.verify(any(), any())).thenReturn(successfulChallenge); when(recaptchaClient.verify(any(), any())).thenReturn(successfulChallenge);
when(rateLimiters.getRecaptchaChallengeAttemptLimiter()).thenReturn(mock(RateLimiter.class)); when(rateLimiters.getRecaptchaChallengeAttemptLimiter()).thenReturn(mock(RateLimiter.class));
when(rateLimiters.getRecaptchaChallengeSuccessLimiter()).thenReturn(mock(RateLimiter.class)); when(rateLimiters.getRecaptchaChallengeSuccessLimiter()).thenReturn(mock(RateLimiter.class));

View File

@ -75,7 +75,7 @@ import org.whispersystems.textsecuregcm.push.APNSender;
import org.whispersystems.textsecuregcm.push.ApnMessage; import org.whispersystems.textsecuregcm.push.ApnMessage;
import org.whispersystems.textsecuregcm.push.GCMSender; import org.whispersystems.textsecuregcm.push.GCMSender;
import org.whispersystems.textsecuregcm.push.GcmMessage; import org.whispersystems.textsecuregcm.push.GcmMessage;
import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient; import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
import org.whispersystems.textsecuregcm.sms.SmsSender; import org.whispersystems.textsecuregcm.sms.SmsSender;
import org.whispersystems.textsecuregcm.sms.TwilioVerifyExperimentEnrollmentManager; import org.whispersystems.textsecuregcm.sms.TwilioVerifyExperimentEnrollmentManager;
import org.whispersystems.textsecuregcm.storage.AbusiveHostRule; import org.whispersystems.textsecuregcm.storage.AbusiveHostRule;
@ -131,7 +131,7 @@ class AccountControllerTest {
private static Account senderRegLockAccount = mock(Account.class); private static Account senderRegLockAccount = mock(Account.class);
private static Account senderHasStorage = mock(Account.class); private static Account senderHasStorage = mock(Account.class);
private static Account senderTransfer = mock(Account.class); private static Account senderTransfer = mock(Account.class);
private static LegacyRecaptchaClient legacyRecaptchaClient = mock(LegacyRecaptchaClient.class); private static RecaptchaClient recaptchaClient = mock(RecaptchaClient.class);
private static GCMSender gcmSender = mock(GCMSender.class); private static GCMSender gcmSender = mock(GCMSender.class);
private static APNSender apnSender = mock(APNSender.class); private static APNSender apnSender = mock(APNSender.class);
private static UsernamesManager usernamesManager = mock(UsernamesManager.class); private static UsernamesManager usernamesManager = mock(UsernamesManager.class);
@ -160,7 +160,7 @@ class AccountControllerTest {
dynamicConfigurationManager, dynamicConfigurationManager,
turnTokenGenerator, turnTokenGenerator,
new HashMap<>(), new HashMap<>(),
legacyRecaptchaClient, recaptchaClient,
gcmSender, gcmSender,
apnSender, apnSender,
storageCredentialGenerator, storageCredentialGenerator,
@ -241,8 +241,8 @@ class AccountControllerTest {
when(abusiveHostRules.getAbusiveHostRulesFor(eq(RESTRICTED_HOST))).thenReturn(Collections.singletonList(new AbusiveHostRule(RESTRICTED_HOST, false, Collections.singletonList("+123")))); when(abusiveHostRules.getAbusiveHostRulesFor(eq(RESTRICTED_HOST))).thenReturn(Collections.singletonList(new AbusiveHostRule(RESTRICTED_HOST, false, Collections.singletonList("+123"))));
when(abusiveHostRules.getAbusiveHostRulesFor(eq(NICE_HOST))).thenReturn(Collections.emptyList()); when(abusiveHostRules.getAbusiveHostRulesFor(eq(NICE_HOST))).thenReturn(Collections.emptyList());
when(legacyRecaptchaClient.verify(eq(INVALID_CAPTCHA_TOKEN), anyString())).thenReturn(false); when(recaptchaClient.verify(eq(INVALID_CAPTCHA_TOKEN), anyString())).thenReturn(false);
when(legacyRecaptchaClient.verify(eq(VALID_CAPTCHA_TOKEN), anyString())).thenReturn(true); when(recaptchaClient.verify(eq(VALID_CAPTCHA_TOKEN), anyString())).thenReturn(true);
doThrow(new RateLimitExceededException(SENDER_OVER_PIN, Duration.ZERO)).when(pinLimiter).validate(eq(SENDER_OVER_PIN)); doThrow(new RateLimitExceededException(SENDER_OVER_PIN, Duration.ZERO)).when(pinLimiter).validate(eq(SENDER_OVER_PIN));
@ -273,7 +273,7 @@ class AccountControllerTest {
senderRegLockAccount, senderRegLockAccount,
senderHasStorage, senderHasStorage,
senderTransfer, senderTransfer,
legacyRecaptchaClient, recaptchaClient,
gcmSender, gcmSender,
apnSender, apnSender,
usernamesManager, usernamesManager,
@ -711,7 +711,7 @@ class AccountControllerTest {
assertThat(response.getStatus()).isEqualTo(200); assertThat(response.getStatus()).isEqualTo(200);
verifyNoMoreInteractions(abusiveHostRules); verifyNoMoreInteractions(abusiveHostRules);
verify(legacyRecaptchaClient).verify(eq(VALID_CAPTCHA_TOKEN), eq(ABUSIVE_HOST)); verify(recaptchaClient).verify(eq(VALID_CAPTCHA_TOKEN), eq(ABUSIVE_HOST));
if (enrolledInVerifyExperiment) { if (enrolledInVerifyExperiment) {
verify(smsSender).deliverSmsVerificationWithTwilioVerify(eq(SENDER), eq(Optional.empty()), anyString(), verify(smsSender).deliverSmsVerificationWithTwilioVerify(eq(SENDER), eq(Optional.empty()), anyString(),
eq(Collections.emptyList())); eq(Collections.emptyList()));
@ -742,7 +742,7 @@ class AccountControllerTest {
assertThat(response.getStatus()).isEqualTo(402); assertThat(response.getStatus()).isEqualTo(402);
verifyNoMoreInteractions(abusiveHostRules); verifyNoMoreInteractions(abusiveHostRules);
verify(legacyRecaptchaClient).verify(eq(INVALID_CAPTCHA_TOKEN), eq(ABUSIVE_HOST)); verify(recaptchaClient).verify(eq(INVALID_CAPTCHA_TOKEN), eq(ABUSIVE_HOST));
verifyNoMoreInteractions(smsSender); verifyNoMoreInteractions(smsSender);
} }
@ -772,7 +772,7 @@ class AccountControllerTest {
verify(abusiveHostRules).setBlockedHost(eq(RATE_LIMITED_IP_HOST), eq("Auto-Block")); verify(abusiveHostRules).setBlockedHost(eq(RATE_LIMITED_IP_HOST), eq("Auto-Block"));
verifyNoMoreInteractions(abusiveHostRules); verifyNoMoreInteractions(abusiveHostRules);
verifyNoMoreInteractions(legacyRecaptchaClient); verifyNoMoreInteractions(recaptchaClient);
verifyNoMoreInteractions(smsSender); verifyNoMoreInteractions(smsSender);
} }
@ -802,7 +802,7 @@ class AccountControllerTest {
verify(abusiveHostRules).setBlockedHost(eq(RATE_LIMITED_PREFIX_HOST), eq("Auto-Block")); verify(abusiveHostRules).setBlockedHost(eq(RATE_LIMITED_PREFIX_HOST), eq("Auto-Block"));
verifyNoMoreInteractions(abusiveHostRules); verifyNoMoreInteractions(abusiveHostRules);
verifyNoMoreInteractions(legacyRecaptchaClient); verifyNoMoreInteractions(recaptchaClient);
verifyNoMoreInteractions(smsSender); verifyNoMoreInteractions(smsSender);
} }
@ -831,7 +831,7 @@ class AccountControllerTest {
verify(abusiveHostRules).getAbusiveHostRulesFor(eq(RATE_LIMITED_HOST2)); verify(abusiveHostRules).getAbusiveHostRulesFor(eq(RATE_LIMITED_HOST2));
verifyNoMoreInteractions(abusiveHostRules); verifyNoMoreInteractions(abusiveHostRules);
verifyNoMoreInteractions(legacyRecaptchaClient); verifyNoMoreInteractions(recaptchaClient);
verifyNoMoreInteractions(smsSender); verifyNoMoreInteractions(smsSender);
} }