Accept a captcha score threshold for challenges from the spam filter

This commit is contained in:
Jonathan Klabunde Tomer
2023-10-20 09:09:22 -07:00
committed by GitHub
parent 9c053e20da
commit fd19299ae0
7 changed files with 198 additions and 22 deletions

View File

@@ -13,9 +13,14 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.whispersystems.textsecuregcm.captcha.Action;
import org.whispersystems.textsecuregcm.captcha.AssessmentResult;
@@ -27,6 +32,8 @@ import org.whispersystems.textsecuregcm.storage.Account;
class RateLimitChallengeManagerTest {
private static final float DEFAULT_SCORE_THRESHOLD = 0.1f;
private PushChallengeManager pushChallengeManager;
private CaptchaChecker captchaChecker;
private RateLimiters rateLimiters;
@@ -71,27 +78,39 @@ class RateLimitChallengeManagerTest {
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void answerRecaptchaChallenge(final boolean successfulChallenge) throws RateLimitExceededException, IOException {
@MethodSource
void answerRecaptchaChallenge(Optional<Float> scoreThreshold, float actualScore, boolean expectSuccess)
throws RateLimitExceededException, IOException {
final Account account = mock(Account.class);
when(account.getNumber()).thenReturn("+18005551234");
when(account.getUuid()).thenReturn(UUID.randomUUID());
when(captchaChecker.verify(eq(Action.CHALLENGE), any(), any()))
.thenReturn(successfulChallenge
? AssessmentResult.alwaysValid()
: AssessmentResult.invalid());
.thenReturn(AssessmentResult.fromScore(actualScore, DEFAULT_SCORE_THRESHOLD));
when(rateLimiters.getRecaptchaChallengeAttemptLimiter()).thenReturn(mock(RateLimiter.class));
when(rateLimiters.getRecaptchaChallengeSuccessLimiter()).thenReturn(mock(RateLimiter.class));
when(rateLimiters.getRateLimitResetLimiter()).thenReturn(mock(RateLimiter.class));
rateLimitChallengeManager.answerRecaptchaChallenge(account, "captcha", "10.0.0.1", "Test User-Agent");
rateLimitChallengeManager.answerRecaptchaChallenge(account, "captcha", "10.0.0.1", "Test User-Agent", scoreThreshold);
if (successfulChallenge) {
if (expectSuccess) {
verify(rateLimitChallengeListener).handleRateLimitChallengeAnswered(account, ChallengeType.CAPTCHA);
} else {
verifyNoInteractions(rateLimitChallengeListener);
}
}
private static Stream<Arguments> answerRecaptchaChallenge() {
return Stream.of(
Arguments.of(Optional.empty(), 0.5f, true),
Arguments.of(Optional.empty(), 0.1f, true),
Arguments.of(Optional.empty(), 0.0f, false),
Arguments.of(Optional.of(0.1f), 0.5f, true),
Arguments.of(Optional.of(0.1f), 0.1f, true),
Arguments.of(Optional.of(0.1f), 0.0f, false),
Arguments.of(Optional.of(0.3f), 0.5f, true),
Arguments.of(Optional.of(0.3f), 0.1f, false),
Arguments.of(Optional.of(0.3f), 0.0f, false));
}
}