Move score floor to dynamic configuration, add distribution summary
This commit is contained in:
parent
9fc5002619
commit
eee6307789
|
@ -246,7 +246,6 @@ recaptcha:
|
||||||
secret: unset
|
secret: unset
|
||||||
|
|
||||||
recaptchaV2:
|
recaptchaV2:
|
||||||
scoreFloor: 1.0
|
|
||||||
projectPath: projects/example
|
projectPath: projects/example
|
||||||
credentialConfigurationJson: "{ }" # service account configuration for backend authentication
|
credentialConfigurationJson: "{ }" # service account configuration for backend authentication
|
||||||
|
|
||||||
|
|
|
@ -476,11 +476,12 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
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(
|
EnterpriseRecaptchaClient enterpriseRecaptchaClient = new EnterpriseRecaptchaClient(
|
||||||
config.getRecaptchaV2Configuration().getScoreFloor().doubleValue(),
|
|
||||||
config.getRecaptchaV2Configuration().getProjectPath(),
|
config.getRecaptchaV2Configuration().getProjectPath(),
|
||||||
config.getRecaptchaV2Configuration().getCredentialConfigurationJson());
|
config.getRecaptchaV2Configuration().getCredentialConfigurationJson(),
|
||||||
TransitionalRecaptchaClient transitionalRecaptchaClient = new TransitionalRecaptchaClient(legacyRecaptchaClient, enterpriseRecaptchaClient);
|
dynamicConfigurationManager);
|
||||||
PushChallengeManager pushChallengeManager = new PushChallengeManager(apnSender, gcmSender, pushChallengeDynamoDb);
|
TransitionalRecaptchaClient transitionalRecaptchaClient = new TransitionalRecaptchaClient(legacyRecaptchaClient,
|
||||||
|
enterpriseRecaptchaClient);
|
||||||
|
PushChallengeManager pushChallengeManager = new PushChallengeManager(apnSender, gcmSender, pushChallengeDynamoDb);
|
||||||
RateLimitChallengeManager rateLimitChallengeManager = new RateLimitChallengeManager(pushChallengeManager,
|
RateLimitChallengeManager rateLimitChallengeManager = new RateLimitChallengeManager(pushChallengeManager,
|
||||||
transitionalRecaptchaClient, dynamicRateLimiters);
|
transitionalRecaptchaClient, dynamicRateLimiters);
|
||||||
RateLimitChallengeOptionManager rateLimitChallengeOptionManager =
|
RateLimitChallengeOptionManager rateLimitChallengeOptionManager =
|
||||||
|
|
|
@ -5,25 +5,13 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.configuration;
|
package org.whispersystems.textsecuregcm.configuration;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import javax.validation.constraints.DecimalMax;
|
|
||||||
import javax.validation.constraints.DecimalMin;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
public class RecaptchaV2Configuration {
|
public class RecaptchaV2Configuration {
|
||||||
|
|
||||||
private BigDecimal scoreFloor;
|
|
||||||
private String projectPath;
|
private String projectPath;
|
||||||
private String credentialConfigurationJson;
|
private String credentialConfigurationJson;
|
||||||
|
|
||||||
@DecimalMin("0")
|
|
||||||
@DecimalMax("1")
|
|
||||||
@NotNull
|
|
||||||
public BigDecimal getScoreFloor() {
|
|
||||||
return scoreFloor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
public String getProjectPath() {
|
public String getProjectPath() {
|
||||||
return projectPath;
|
return projectPath;
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.whispersystems.textsecuregcm.configuration.dynamic;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.validation.constraints.DecimalMax;
|
||||||
|
import javax.validation.constraints.DecimalMin;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class DynamicCaptchaConfiguration {
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
@DecimalMin("0")
|
||||||
|
@DecimalMax("1")
|
||||||
|
@NotNull
|
||||||
|
private BigDecimal scoreFloor;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
@NotNull
|
||||||
|
private Set<String> signupCountryCodes = Collections.emptySet();
|
||||||
|
|
||||||
|
public Set<String> getSignupCountryCodes() {
|
||||||
|
return signupCountryCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setSignupCountryCodes(Set<String> numbers) {
|
||||||
|
this.signupCountryCodes = numbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getScoreFloor() {
|
||||||
|
return scoreFloor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,8 @@ public class DynamicConfiguration {
|
||||||
private DynamicTwilioConfiguration twilio = new DynamicTwilioConfiguration();
|
private DynamicTwilioConfiguration twilio = new DynamicTwilioConfiguration();
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private DynamicSignupCaptchaConfiguration signupCaptcha = new DynamicSignupCaptchaConfiguration();
|
@Valid
|
||||||
|
private DynamicCaptchaConfiguration captcha = new DynamicCaptchaConfiguration();
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
@Valid
|
@Valid
|
||||||
|
@ -86,8 +87,8 @@ public class DynamicConfiguration {
|
||||||
this.twilio = twilioConfiguration;
|
this.twilio = twilioConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicSignupCaptchaConfiguration getSignupCaptchaConfiguration() {
|
public DynamicCaptchaConfiguration getCaptchaConfiguration() {
|
||||||
return signupCaptcha;
|
return captcha;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicRateLimitChallengeConfiguration getRateLimitChallengeConfiguration() {
|
public DynamicRateLimitChallengeConfiguration getRateLimitChallengeConfiguration() {
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package org.whispersystems.textsecuregcm.configuration.dynamic;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
public class DynamicSignupCaptchaConfiguration {
|
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@NotNull
|
|
||||||
private Set<String> countryCodes = Collections.emptySet();
|
|
||||||
|
|
||||||
public Set<String> getCountryCodes() {
|
|
||||||
return countryCodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public void setCountryCodes(Set<String> numbers) {
|
|
||||||
this.countryCodes = numbers;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -61,8 +61,8 @@ import org.whispersystems.textsecuregcm.auth.StoredRegistrationLock;
|
||||||
import org.whispersystems.textsecuregcm.auth.StoredVerificationCode;
|
import org.whispersystems.textsecuregcm.auth.StoredVerificationCode;
|
||||||
import org.whispersystems.textsecuregcm.auth.TurnToken;
|
import org.whispersystems.textsecuregcm.auth.TurnToken;
|
||||||
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicCaptchaConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicSignupCaptchaConfiguration;
|
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.ApnRegistrationId;
|
import org.whispersystems.textsecuregcm.entities.ApnRegistrationId;
|
||||||
|
@ -770,8 +770,9 @@ public class AccountController {
|
||||||
return new CaptchaRequirement(true, true);
|
return new CaptchaRequirement(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicSignupCaptchaConfiguration signupCaptchaConfig = dynamicConfigurationManager.getConfiguration().getSignupCaptchaConfiguration();
|
DynamicCaptchaConfiguration captchaConfig = dynamicConfigurationManager.getConfiguration()
|
||||||
if (signupCaptchaConfig.getCountryCodes().contains(countryCode)) {
|
.getCaptchaConfiguration();
|
||||||
|
if (captchaConfig.getSignupCountryCodes().contains(countryCode)) {
|
||||||
return new CaptchaRequirement(true, false);
|
return new CaptchaRequirement(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.recaptcha;
|
package org.whispersystems.textsecuregcm.recaptcha;
|
||||||
|
|
||||||
|
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
||||||
|
|
||||||
import com.google.api.gax.core.FixedCredentialsProvider;
|
import com.google.api.gax.core.FixedCredentialsProvider;
|
||||||
import com.google.auth.oauth2.GoogleCredentials;
|
import com.google.auth.oauth2.GoogleCredentials;
|
||||||
import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
|
import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
|
||||||
|
@ -12,36 +14,38 @@ import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceSetting
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.recaptchaenterprise.v1.Assessment;
|
import com.google.recaptchaenterprise.v1.Assessment;
|
||||||
import com.google.recaptchaenterprise.v1.Event;
|
import com.google.recaptchaenterprise.v1.Event;
|
||||||
|
import io.micrometer.core.instrument.Metrics;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.ws.rs.BadRequestException;
|
import javax.ws.rs.BadRequestException;
|
||||||
import org.slf4j.Logger;
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||||
|
|
||||||
public class EnterpriseRecaptchaClient implements RecaptchaClient {
|
public class EnterpriseRecaptchaClient implements RecaptchaClient {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String SEPARATOR = ".";
|
static final String SEPARATOR = ".";
|
||||||
private static final Logger logger = LoggerFactory.getLogger(EnterpriseRecaptchaClient.class);
|
private static final String SCORE_DISTRIBUTION_NAME = name(EnterpriseRecaptchaClient.class, "scoreDistribution");
|
||||||
|
|
||||||
private final double scoreFloor;
|
|
||||||
private final String projectPath;
|
private final String projectPath;
|
||||||
private final RecaptchaEnterpriseServiceClient client;
|
private final RecaptchaEnterpriseServiceClient client;
|
||||||
|
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||||
|
|
||||||
public EnterpriseRecaptchaClient(
|
public EnterpriseRecaptchaClient(
|
||||||
final double scoreFloor,
|
|
||||||
@Nonnull final String projectPath,
|
@Nonnull final String projectPath,
|
||||||
@Nonnull final String recaptchaCredentialConfigurationJson) {
|
@Nonnull final String recaptchaCredentialConfigurationJson,
|
||||||
|
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager) {
|
||||||
try {
|
try {
|
||||||
this.scoreFloor = scoreFloor;
|
|
||||||
this.projectPath = Objects.requireNonNull(projectPath);
|
this.projectPath = Objects.requireNonNull(projectPath);
|
||||||
this.client = RecaptchaEnterpriseServiceClient.create(RecaptchaEnterpriseServiceSettings.newBuilder()
|
this.client = RecaptchaEnterpriseServiceClient.create(RecaptchaEnterpriseServiceSettings.newBuilder()
|
||||||
.setCredentialsProvider(FixedCredentialsProvider.create(GoogleCredentials.fromStream(
|
.setCredentialsProvider(FixedCredentialsProvider.create(GoogleCredentials.fromStream(
|
||||||
new ByteArrayInputStream(recaptchaCredentialConfigurationJson.getBytes(StandardCharsets.UTF_8)))))
|
new ByteArrayInputStream(recaptchaCredentialConfigurationJson.getBytes(StandardCharsets.UTF_8)))))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
this.dynamicConfigurationManager = dynamicConfigurationManager;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
|
@ -89,6 +93,15 @@ public class EnterpriseRecaptchaClient implements RecaptchaClient {
|
||||||
final Event event = eventBuilder.build();
|
final Event event = eventBuilder.build();
|
||||||
final Assessment assessment = client.createAssessment(projectPath, Assessment.newBuilder().setEvent(event).build());
|
final Assessment assessment = client.createAssessment(projectPath, Assessment.newBuilder().setEvent(event).build());
|
||||||
|
|
||||||
return assessment.getTokenProperties().getValid() && assessment.getRiskAnalysis().getScore() >= scoreFloor;
|
if (assessment.getTokenProperties().getValid()) {
|
||||||
|
final float score = assessment.getRiskAnalysis().getScore();
|
||||||
|
Metrics.summary(SCORE_DISTRIBUTION_NAME).record(score);
|
||||||
|
|
||||||
|
return score >= dynamicConfigurationManager.getConfiguration().getCaptchaConfiguration().getScoreFloor()
|
||||||
|
.floatValue();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,15 @@ import org.whispersystems.textsecuregcm.util.ua.ClientPlatform;
|
||||||
|
|
||||||
class DynamicConfigurationTest {
|
class DynamicConfigurationTest {
|
||||||
|
|
||||||
|
private static final String REQUIRED_CONFIG = """
|
||||||
|
captcha:
|
||||||
|
scoreFloor: 1.0
|
||||||
|
""";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParseExperimentConfig() throws JsonProcessingException {
|
void testParseExperimentConfig() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -37,7 +42,7 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String experimentConfigYaml = """
|
final String experimentConfigYaml = REQUIRED_CONFIG.concat("""
|
||||||
experiments:
|
experiments:
|
||||||
percentageOnly:
|
percentageOnly:
|
||||||
enrollmentPercentage: 12
|
enrollmentPercentage: 12
|
||||||
|
@ -49,7 +54,7 @@ class DynamicConfigurationTest {
|
||||||
uuidsOnly:
|
uuidsOnly:
|
||||||
enrolledUuids:
|
enrolledUuids:
|
||||||
- 71618739-114c-4b1f-bb0d-6478a44eb600
|
- 71618739-114c-4b1f-bb0d-6478a44eb600
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final DynamicConfiguration config =
|
final DynamicConfiguration config =
|
||||||
DynamicConfigurationManager.parseConfiguration(experimentConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(experimentConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
@ -78,7 +83,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParsePreRegistrationExperiments() throws JsonProcessingException {
|
void testParsePreRegistrationExperiments() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -86,7 +91,7 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String experimentConfigYaml = """
|
final String experimentConfigYaml = REQUIRED_CONFIG.concat("""
|
||||||
preRegistrationExperiments:
|
preRegistrationExperiments:
|
||||||
percentageOnly:
|
percentageOnly:
|
||||||
enrollmentPercentage: 17
|
enrollmentPercentage: 17
|
||||||
|
@ -107,7 +112,7 @@ class DynamicConfigurationTest {
|
||||||
- +120255551212
|
- +120255551212
|
||||||
excludedCountryCodes:
|
excludedCountryCodes:
|
||||||
- 47
|
- 47
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final DynamicConfiguration config =
|
final DynamicConfiguration config =
|
||||||
DynamicConfigurationManager.parseConfiguration(experimentConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(experimentConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
@ -160,7 +165,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParseRemoteDeprecationConfig() throws JsonProcessingException {
|
void testParseRemoteDeprecationConfig() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -168,7 +173,7 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String remoteDeprecationConfig = """
|
final String remoteDeprecationConfig = REQUIRED_CONFIG.concat("""
|
||||||
remoteDeprecation:
|
remoteDeprecation:
|
||||||
minimumVersions:
|
minimumVersions:
|
||||||
IOS: 1.2.3
|
IOS: 1.2.3
|
||||||
|
@ -178,7 +183,7 @@ class DynamicConfigurationTest {
|
||||||
blockedVersions:
|
blockedVersions:
|
||||||
DESKTOP:
|
DESKTOP:
|
||||||
- 1.4.0-beta.2
|
- 1.4.0-beta.2
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final DynamicConfiguration config =
|
final DynamicConfiguration config =
|
||||||
DynamicConfigurationManager.parseConfiguration(remoteDeprecationConfig, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(remoteDeprecationConfig, DynamicConfiguration.class).orElseThrow();
|
||||||
|
@ -199,7 +204,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParseFeatureFlags() throws JsonProcessingException {
|
void testParseFeatureFlags() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -207,10 +212,10 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String featureFlagYaml = """
|
final String featureFlagYaml = REQUIRED_CONFIG.concat("""
|
||||||
featureFlags:
|
featureFlags:
|
||||||
- testFlag
|
- testFlag
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(featureFlagYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(featureFlagYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
@ -222,7 +227,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParseTwilioConfiguration() throws JsonProcessingException {
|
void testParseTwilioConfiguration() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -230,12 +235,12 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String twilioConfigYaml = """
|
final String twilioConfigYaml = REQUIRED_CONFIG.concat("""
|
||||||
twilio:
|
twilio:
|
||||||
numbers:
|
numbers:
|
||||||
- 2135551212
|
- 2135551212
|
||||||
- 2135551313
|
- 2135551313
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final DynamicTwilioConfiguration config =
|
final DynamicTwilioConfiguration config =
|
||||||
DynamicConfigurationManager.parseConfiguration(twilioConfigYaml, DynamicConfiguration.class).orElseThrow()
|
DynamicConfigurationManager.parseConfiguration(twilioConfigYaml, DynamicConfiguration.class).orElseThrow()
|
||||||
|
@ -248,7 +253,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParsePaymentsConfiguration() throws JsonProcessingException {
|
void testParsePaymentsConfiguration() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -256,11 +261,11 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String paymentsConfigYaml = """
|
final String paymentsConfigYaml = REQUIRED_CONFIG.concat("""
|
||||||
payments:
|
payments:
|
||||||
disallowedPrefixes:
|
disallowedPrefixes:
|
||||||
- +44
|
- +44
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final DynamicPaymentsConfiguration config =
|
final DynamicPaymentsConfiguration config =
|
||||||
DynamicConfigurationManager.parseConfiguration(paymentsConfigYaml, DynamicConfiguration.class).orElseThrow()
|
DynamicConfigurationManager.parseConfiguration(paymentsConfigYaml, DynamicConfiguration.class).orElseThrow()
|
||||||
|
@ -271,34 +276,47 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParseSignupCaptchaConfiguration() throws JsonProcessingException {
|
void testParseCaptchaConfiguration() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = "test: true";
|
||||||
final DynamicConfiguration emptyConfig =
|
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
|
||||||
|
|
||||||
assertTrue(emptyConfig.getSignupCaptchaConfiguration().getCountryCodes().isEmpty());
|
assertTrue(DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).isEmpty(),
|
||||||
|
"empty config should not validate");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String signupCaptchaConfig = """
|
final String captchaConfig = """
|
||||||
signupCaptcha:
|
captcha:
|
||||||
countryCodes:
|
signupCountryCodes:
|
||||||
- 1
|
- 1
|
||||||
|
scoreFloor: null
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final DynamicSignupCaptchaConfiguration config =
|
assertTrue(DynamicConfigurationManager.parseConfiguration(captchaConfig, DynamicConfiguration.class).isEmpty(),
|
||||||
DynamicConfigurationManager.parseConfiguration(signupCaptchaConfig, DynamicConfiguration.class).orElseThrow()
|
"score floor must not be null");
|
||||||
.getSignupCaptchaConfiguration();
|
}
|
||||||
|
|
||||||
assertEquals(Set.of("1"), config.getCountryCodes());
|
{
|
||||||
|
final String captchaConfig = """
|
||||||
|
captcha:
|
||||||
|
signupCountryCodes:
|
||||||
|
- 1
|
||||||
|
scoreFloor: 0.9
|
||||||
|
""";
|
||||||
|
|
||||||
|
final DynamicCaptchaConfiguration config =
|
||||||
|
DynamicConfigurationManager.parseConfiguration(captchaConfig, DynamicConfiguration.class).orElseThrow()
|
||||||
|
.getCaptchaConfiguration();
|
||||||
|
|
||||||
|
assertEquals(Set.of("1"), config.getSignupCountryCodes());
|
||||||
|
assertEquals(0.9f, config.getScoreFloor().floatValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParseLimits() throws JsonProcessingException {
|
void testParseLimits() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -307,12 +325,12 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String limitsConfig = """
|
final String limitsConfig = REQUIRED_CONFIG.concat("""
|
||||||
limits:
|
limits:
|
||||||
rateLimitReset:
|
rateLimitReset:
|
||||||
bucketSize: 17
|
bucketSize: 17
|
||||||
leakRatePerMinute: 44
|
leakRatePerMinute: 44
|
||||||
""";
|
""");
|
||||||
|
|
||||||
final RateLimitConfiguration resetRateLimitConfiguration =
|
final RateLimitConfiguration resetRateLimitConfiguration =
|
||||||
DynamicConfigurationManager.parseConfiguration(limitsConfig, DynamicConfiguration.class).orElseThrow()
|
DynamicConfigurationManager.parseConfiguration(limitsConfig, DynamicConfiguration.class).orElseThrow()
|
||||||
|
@ -326,7 +344,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParseRateLimitReset() throws JsonProcessingException {
|
void testParseRateLimitReset() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -334,13 +352,13 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String rateLimitChallengeConfig = """
|
final String rateLimitChallengeConfig = REQUIRED_CONFIG.concat("""
|
||||||
rateLimitChallenge:
|
rateLimitChallenge:
|
||||||
clientSupportedVersions:
|
clientSupportedVersions:
|
||||||
IOS: 5.1.0
|
IOS: 5.1.0
|
||||||
ANDROID: 5.2.0
|
ANDROID: 5.2.0
|
||||||
DESKTOP: 5.0.0
|
DESKTOP: 5.0.0
|
||||||
""";
|
""");
|
||||||
|
|
||||||
DynamicRateLimitChallengeConfiguration rateLimitChallengeConfiguration =
|
DynamicRateLimitChallengeConfiguration rateLimitChallengeConfiguration =
|
||||||
DynamicConfigurationManager.parseConfiguration(rateLimitChallengeConfig, DynamicConfiguration.class).orElseThrow()
|
DynamicConfigurationManager.parseConfiguration(rateLimitChallengeConfig, DynamicConfiguration.class).orElseThrow()
|
||||||
|
@ -357,7 +375,7 @@ class DynamicConfigurationTest {
|
||||||
@Test
|
@Test
|
||||||
void testParseDirectoryReconciler() throws JsonProcessingException {
|
void testParseDirectoryReconciler() throws JsonProcessingException {
|
||||||
{
|
{
|
||||||
final String emptyConfigYaml = "test: true";
|
final String emptyConfigYaml = REQUIRED_CONFIG.concat("test: true");
|
||||||
final DynamicConfiguration emptyConfig =
|
final DynamicConfiguration emptyConfig =
|
||||||
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
DynamicConfigurationManager.parseConfiguration(emptyConfigYaml, DynamicConfiguration.class).orElseThrow();
|
||||||
|
|
||||||
|
@ -365,10 +383,10 @@ class DynamicConfigurationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final String directoryReconcilerConfig = """
|
final String directoryReconcilerConfig = REQUIRED_CONFIG.concat("""
|
||||||
directoryReconciler:
|
directoryReconciler:
|
||||||
enabled: false
|
enabled: false
|
||||||
""";
|
""");
|
||||||
|
|
||||||
DynamicDirectoryReconcilerConfiguration directoryReconcilerConfiguration =
|
DynamicDirectoryReconcilerConfiguration directoryReconcilerConfiguration =
|
||||||
DynamicConfigurationManager.parseConfiguration(directoryReconcilerConfig, DynamicConfiguration.class).orElseThrow()
|
DynamicConfigurationManager.parseConfiguration(directoryReconcilerConfig, DynamicConfiguration.class).orElseThrow()
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package org.whispersystems.textsecuregcm.storage;
|
package org.whispersystems.textsecuregcm.storage;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.Timeout;
|
|
||||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||||
import software.amazon.awssdk.core.SdkBytes;
|
import software.amazon.awssdk.core.SdkBytes;
|
||||||
import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
|
import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
|
||||||
|
@ -14,10 +15,15 @@ import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfiguratio
|
||||||
import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse;
|
import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse;
|
||||||
import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest;
|
import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest;
|
||||||
import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionResponse;
|
import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionResponse;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
class DynamicConfigurationManagerTest {
|
class DynamicConfigurationManagerTest {
|
||||||
|
|
||||||
|
private static final SdkBytes VALID_CONFIG = SdkBytes.fromUtf8String("""
|
||||||
|
test: true
|
||||||
|
captcha:
|
||||||
|
scoreFloor: 1.0
|
||||||
|
""");
|
||||||
|
|
||||||
private DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
private DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||||
private AppConfigDataClient appConfig;
|
private AppConfigDataClient appConfig;
|
||||||
private StartConfigurationSessionRequest startConfigurationSession;
|
private StartConfigurationSessionRequest startConfigurationSession;
|
||||||
|
@ -35,7 +41,7 @@ class DynamicConfigurationManagerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetInitalConfig() {
|
void testGetInitialConfig() {
|
||||||
when(appConfig.startConfigurationSession(startConfigurationSession))
|
when(appConfig.startConfigurationSession(startConfigurationSession))
|
||||||
.thenReturn(StartConfigurationSessionResponse.builder()
|
.thenReturn(StartConfigurationSessionResponse.builder()
|
||||||
.initialConfigurationToken("initial")
|
.initialConfigurationToken("initial")
|
||||||
|
@ -45,7 +51,7 @@ class DynamicConfigurationManagerTest {
|
||||||
when(appConfig.getLatestConfiguration(GetLatestConfigurationRequest.builder()
|
when(appConfig.getLatestConfiguration(GetLatestConfigurationRequest.builder()
|
||||||
.configurationToken("initial").build()))
|
.configurationToken("initial").build()))
|
||||||
.thenReturn(GetLatestConfigurationResponse.builder()
|
.thenReturn(GetLatestConfigurationResponse.builder()
|
||||||
.configuration(SdkBytes.fromUtf8String("test: true"))
|
.configuration(VALID_CONFIG)
|
||||||
.nextPollConfigurationToken("next").build());
|
.nextPollConfigurationToken("next").build());
|
||||||
|
|
||||||
// subsequent config calls will return empty (no update)
|
// subsequent config calls will return empty (no update)
|
||||||
|
@ -55,8 +61,10 @@ class DynamicConfigurationManagerTest {
|
||||||
.configuration(SdkBytes.fromUtf8String(""))
|
.configuration(SdkBytes.fromUtf8String(""))
|
||||||
.nextPollConfigurationToken("next").build());
|
.nextPollConfigurationToken("next").build());
|
||||||
|
|
||||||
dynamicConfigurationManager.start();
|
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> {
|
||||||
assertThat(dynamicConfigurationManager.getConfiguration()).isNotNull();
|
dynamicConfigurationManager.start();
|
||||||
|
assertThat(dynamicConfigurationManager.getConfiguration()).isNotNull();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -77,7 +85,7 @@ class DynamicConfigurationManagerTest {
|
||||||
when(appConfig.getLatestConfiguration(GetLatestConfigurationRequest.builder().
|
when(appConfig.getLatestConfiguration(GetLatestConfigurationRequest.builder().
|
||||||
configurationToken("goodconfig").build()))
|
configurationToken("goodconfig").build()))
|
||||||
.thenReturn(GetLatestConfigurationResponse.builder()
|
.thenReturn(GetLatestConfigurationResponse.builder()
|
||||||
.configuration(SdkBytes.fromUtf8String("test: true"))
|
.configuration(VALID_CONFIG)
|
||||||
.nextPollConfigurationToken("next").build());
|
.nextPollConfigurationToken("next").build());
|
||||||
|
|
||||||
// all subsequent config calls will return an empty config (no update)
|
// all subsequent config calls will return an empty config (no update)
|
||||||
|
@ -86,13 +94,15 @@ class DynamicConfigurationManagerTest {
|
||||||
.thenReturn(GetLatestConfigurationResponse.builder()
|
.thenReturn(GetLatestConfigurationResponse.builder()
|
||||||
.configuration(SdkBytes.fromUtf8String(""))
|
.configuration(SdkBytes.fromUtf8String(""))
|
||||||
.nextPollConfigurationToken("next").build());
|
.nextPollConfigurationToken("next").build());
|
||||||
dynamicConfigurationManager.start();
|
|
||||||
assertThat(dynamicConfigurationManager.getConfiguration()).isNotNull();
|
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> {
|
||||||
|
dynamicConfigurationManager.start();
|
||||||
|
assertThat(dynamicConfigurationManager.getConfiguration()).isNotNull();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Timeout(value=5, unit= TimeUnit.SECONDS)
|
void testGetConfigMultiple() {
|
||||||
void testGetConfigMultiple() throws InterruptedException {
|
|
||||||
when(appConfig.startConfigurationSession(startConfigurationSession))
|
when(appConfig.startConfigurationSession(startConfigurationSession))
|
||||||
.thenReturn(StartConfigurationSessionResponse.builder()
|
.thenReturn(StartConfigurationSessionResponse.builder()
|
||||||
.initialConfigurationToken("0")
|
.initialConfigurationToken("0")
|
||||||
|
@ -102,7 +112,7 @@ class DynamicConfigurationManagerTest {
|
||||||
when(appConfig.getLatestConfiguration(GetLatestConfigurationRequest.builder().
|
when(appConfig.getLatestConfiguration(GetLatestConfigurationRequest.builder().
|
||||||
configurationToken("0").build()))
|
configurationToken("0").build()))
|
||||||
.thenReturn(GetLatestConfigurationResponse.builder()
|
.thenReturn(GetLatestConfigurationResponse.builder()
|
||||||
.configuration(SdkBytes.fromUtf8String("test: true"))
|
.configuration(VALID_CONFIG)
|
||||||
.nextPollConfigurationToken("1").build());
|
.nextPollConfigurationToken("1").build());
|
||||||
|
|
||||||
// config update with a real config
|
// config update with a real config
|
||||||
|
@ -112,6 +122,8 @@ class DynamicConfigurationManagerTest {
|
||||||
.configuration(SdkBytes.fromUtf8String("""
|
.configuration(SdkBytes.fromUtf8String("""
|
||||||
featureFlags:
|
featureFlags:
|
||||||
- testFlag
|
- testFlag
|
||||||
|
captcha:
|
||||||
|
scoreFloor: 1.0
|
||||||
"""))
|
"""))
|
||||||
.nextPollConfigurationToken("2").build());
|
.nextPollConfigurationToken("2").build());
|
||||||
|
|
||||||
|
@ -122,11 +134,16 @@ class DynamicConfigurationManagerTest {
|
||||||
.configuration(SdkBytes.fromUtf8String(""))
|
.configuration(SdkBytes.fromUtf8String(""))
|
||||||
.nextPollConfigurationToken("2").build());
|
.nextPollConfigurationToken("2").build());
|
||||||
|
|
||||||
// we should eventually get the updated config (or the test will timeout)
|
// the internal waiting done by dynamic configuration manager catches the InterruptedException used
|
||||||
dynamicConfigurationManager.start();
|
// by JUnit’s @Timeout, so we use assertTimeoutPreemptively
|
||||||
while (dynamicConfigurationManager.getConfiguration().getActiveFeatureFlags().isEmpty()) {
|
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> {
|
||||||
Thread.sleep(100);
|
// we should eventually get the updated config (or the test will timeout)
|
||||||
}
|
dynamicConfigurationManager.start();
|
||||||
assertThat(dynamicConfigurationManager.getConfiguration().getActiveFeatureFlags()).containsExactly("testFlag");
|
while (dynamicConfigurationManager.getConfiguration().getActiveFeatureFlags().isEmpty()) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
assertThat(dynamicConfigurationManager.getConfiguration().getActiveFeatureFlags()).containsExactly("testFlag");
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
||||||
import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials;
|
import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials;
|
||||||
|
@ -61,8 +60,8 @@ import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialGenerator;
|
||||||
import org.whispersystems.textsecuregcm.auth.StoredRegistrationLock;
|
import org.whispersystems.textsecuregcm.auth.StoredRegistrationLock;
|
||||||
import org.whispersystems.textsecuregcm.auth.StoredVerificationCode;
|
import org.whispersystems.textsecuregcm.auth.StoredVerificationCode;
|
||||||
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicCaptchaConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicSignupCaptchaConfiguration;
|
|
||||||
import org.whispersystems.textsecuregcm.controllers.AccountController;
|
import org.whispersystems.textsecuregcm.controllers.AccountController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||||
|
@ -263,9 +262,9 @@ class AccountControllerTest {
|
||||||
when(dynamicConfigurationManager.getConfiguration())
|
when(dynamicConfigurationManager.getConfiguration())
|
||||||
.thenReturn(dynamicConfiguration);
|
.thenReturn(dynamicConfiguration);
|
||||||
|
|
||||||
DynamicSignupCaptchaConfiguration signupCaptchaConfig = new DynamicSignupCaptchaConfiguration();
|
DynamicCaptchaConfiguration signupCaptchaConfig = new DynamicCaptchaConfiguration();
|
||||||
|
|
||||||
when(dynamicConfiguration.getSignupCaptchaConfiguration()).thenReturn(signupCaptchaConfig);
|
when(dynamicConfiguration.getCaptchaConfiguration()).thenReturn(signupCaptchaConfig);
|
||||||
}
|
}
|
||||||
when(abusiveHostRules.getAbusiveHostRulesFor(eq(ABUSIVE_HOST))).thenReturn(Collections.singletonList(new AbusiveHostRule(ABUSIVE_HOST, true, Collections.emptyList())));
|
when(abusiveHostRules.getAbusiveHostRulesFor(eq(ABUSIVE_HOST))).thenReturn(Collections.singletonList(new AbusiveHostRule(ABUSIVE_HOST, true, Collections.emptyList())));
|
||||||
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"))));
|
||||||
|
@ -1741,9 +1740,9 @@ class AccountControllerTest {
|
||||||
when(dynamicConfigurationManager.getConfiguration())
|
when(dynamicConfigurationManager.getConfiguration())
|
||||||
.thenReturn(dynamicConfiguration);
|
.thenReturn(dynamicConfiguration);
|
||||||
|
|
||||||
DynamicSignupCaptchaConfiguration signupCaptchaConfig = new DynamicSignupCaptchaConfiguration();
|
DynamicCaptchaConfiguration signupCaptchaConfig = new DynamicCaptchaConfiguration();
|
||||||
signupCaptchaConfig.setCountryCodes(countryCodes);
|
signupCaptchaConfig.setSignupCountryCodes(countryCodes);
|
||||||
when(dynamicConfiguration.getSignupCaptchaConfiguration())
|
when(dynamicConfiguration.getCaptchaConfiguration())
|
||||||
.thenReturn(signupCaptchaConfig);
|
.thenReturn(signupCaptchaConfig);
|
||||||
|
|
||||||
Response response =
|
Response response =
|
||||||
|
|
Loading…
Reference in New Issue