mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 21:38:06 +01:00
Add tests for WhisperServerService#run
Additionally, `LocalWhisperServerService` may be used for integration testing.
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
|
||||
public class AppConfigConfiguration {
|
||||
@JsonTypeName("default")
|
||||
public class AppConfigConfiguration implements DynamicConfigurationManagerFactory {
|
||||
|
||||
@JsonProperty
|
||||
@NotEmpty
|
||||
@@ -29,4 +33,11 @@ public class AppConfigConfiguration {
|
||||
public String getConfigurationName() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DynamicConfigurationManager<T> build(Class<T> klazz, ScheduledExecutorService scheduledExecutorService,
|
||||
AwsCredentialsProvider awsCredentialsProvider) {
|
||||
return new DynamicConfigurationManager<>(application, environment, configuration, awsCredentialsProvider, klazz,
|
||||
scheduledExecutorService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
*/
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||
|
||||
public record AwsAttachmentsConfiguration(@NotNull SecretString accessKey,
|
||||
@NotNull SecretString accessSecret,
|
||||
public record AwsAttachmentsConfiguration(@NotNull @Valid StaticAwsCredentialsFactory credentials,
|
||||
@NotBlank String bucket,
|
||||
@NotBlank String region) {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = DefaultAwsCredentialsFactory.class)
|
||||
public interface AwsCredentialsProviderFactory extends Discoverable {
|
||||
|
||||
AwsCredentialsProvider build();
|
||||
}
|
||||
@@ -32,9 +32,7 @@ public record BraintreeConfiguration(@NotBlank String merchantId,
|
||||
@NotBlank String graphqlUrl,
|
||||
@NotEmpty Map<String, String> merchantAccounts,
|
||||
@NotNull @Valid CircuitBreakerConfiguration circuitBreaker,
|
||||
@NotBlank String pubSubProject,
|
||||
@NotBlank String pubSubTopic,
|
||||
@NotBlank String pubSubCredentialConfiguration) {
|
||||
@Valid @NotNull PubSubPublisherFactory pubSubPublisher) {
|
||||
|
||||
public BraintreeConfiguration {
|
||||
if (circuitBreaker == null) {
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||
|
||||
public record CdnConfiguration(@NotNull SecretString accessKey,
|
||||
@NotNull SecretString accessSecret,
|
||||
public record CdnConfiguration(@NotNull @Valid StaticAwsCredentialsFactory credentials,
|
||||
@NotBlank String bucket,
|
||||
@NotBlank String region) {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import io.micrometer.statsd.StatsdConfig;
|
||||
import java.time.Duration;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = DogstatsdConfiguration.class)
|
||||
public interface DatadogConfiguration extends StatsdConfig, Discoverable {
|
||||
|
||||
String getEnvironment();
|
||||
|
||||
Duration getShutdownWaitDuration();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.auth.credentials.WebIdentityTokenFileCredentialsProvider;
|
||||
|
||||
@JsonTypeName("default")
|
||||
public record DefaultAwsCredentialsFactory() implements AwsCredentialsProviderFactory {
|
||||
|
||||
public AwsCredentialsProvider build() {
|
||||
return WebIdentityTokenFileCredentialsProvider.create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import com.google.api.gax.batching.BatchingSettings;
|
||||
import com.google.api.gax.batching.FlowControlSettings;
|
||||
import com.google.api.gax.batching.FlowController;
|
||||
import com.google.api.gax.core.FixedCredentialsProvider;
|
||||
import com.google.auth.oauth2.ExternalAccountCredentials;
|
||||
import com.google.cloud.pubsub.v1.Publisher;
|
||||
import com.google.cloud.pubsub.v1.PublisherInterface;
|
||||
import com.google.pubsub.v1.TopicName;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@JsonTypeName("default")
|
||||
public record DefaultPubSubPublisherFactory(@NotBlank String project,
|
||||
@NotBlank String topic,
|
||||
@NotBlank String credentialConfiguration) implements
|
||||
PubSubPublisherFactory {
|
||||
|
||||
@Override
|
||||
public PublisherInterface build() throws IOException {
|
||||
|
||||
final FlowControlSettings flowControlSettings = FlowControlSettings.newBuilder()
|
||||
.setLimitExceededBehavior(FlowController.LimitExceededBehavior.ThrowException)
|
||||
.setMaxOutstandingElementCount(100L)
|
||||
.setMaxOutstandingRequestBytes(16 * 1024 * 1024L) // 16MB
|
||||
.build();
|
||||
|
||||
final BatchingSettings batchingSettings = BatchingSettings.newBuilder()
|
||||
.setFlowControlSettings(flowControlSettings)
|
||||
.setDelayThreshold(org.threeten.bp.Duration.ofMillis(10))
|
||||
// These thresholds are actually the default, setting them explicitly since creating a custom batchingSettings resets them
|
||||
.setElementCountThreshold(100L)
|
||||
.setRequestByteThreshold(5000L)
|
||||
.build();
|
||||
|
||||
try (final ByteArrayInputStream credentialConfigInputStream =
|
||||
new ByteArrayInputStream(credentialConfiguration.getBytes(StandardCharsets.UTF_8))) {
|
||||
|
||||
return Publisher.newBuilder(
|
||||
TopicName.of(project, topic))
|
||||
.setCredentialsProvider(
|
||||
FixedCredentialsProvider.create(ExternalAccountCredentials.fromStream(credentialConfigInputStream)))
|
||||
.setBatchingSettings(batchingSettings)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,14 @@
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.micrometer.statsd.StatsdConfig;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.micrometer.statsd.StatsdFlavor;
|
||||
import java.time.Duration;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class DogstatsdConfiguration implements StatsdConfig {
|
||||
@JsonTypeName("default")
|
||||
public class DogstatsdConfiguration implements DatadogConfiguration {
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
@@ -31,6 +32,7 @@ public class DogstatsdConfiguration implements StatsdConfig {
|
||||
return step;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
@@ -50,4 +52,9 @@ public class DogstatsdConfiguration implements StatsdConfig {
|
||||
public String host() {
|
||||
return host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getShutdownWaitDuration() {
|
||||
return step().plus(step.dividedBy(2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = AppConfigConfiguration.class)
|
||||
public interface DynamicConfigurationManagerFactory extends Discoverable {
|
||||
|
||||
<T> DynamicConfigurationManager<T> build(Class<T> configurationClass,
|
||||
ScheduledExecutorService scheduledExecutorService, AwsCredentialsProvider awsCredentialsProvider);
|
||||
}
|
||||
@@ -9,11 +9,20 @@ import java.time.Duration;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Positive;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
|
||||
import software.amazon.awssdk.http.crt.AwsCrtHttpClient;
|
||||
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
|
||||
|
||||
@JsonTypeName("default")
|
||||
public record DynamoDbClientConfiguration(@NotBlank String region,
|
||||
@NotNull Duration clientExecutionTimeout,
|
||||
@NotNull Duration clientRequestTimeout,
|
||||
@Positive int maxConnections) {
|
||||
@Positive int maxConnections) implements DynamoDbClientFactory {
|
||||
|
||||
public DynamoDbClientConfiguration {
|
||||
if (clientExecutionTimeout == null) {
|
||||
@@ -28,4 +37,32 @@ public record DynamoDbClientConfiguration(@NotBlank String region,
|
||||
maxConnections = 50;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamoDbClient buildSyncClient(final AwsCredentialsProvider credentialsProvider) {
|
||||
return DynamoDbClient.builder()
|
||||
.region(Region.of(region()))
|
||||
.credentialsProvider(credentialsProvider)
|
||||
.overrideConfiguration(ClientOverrideConfiguration.builder()
|
||||
.apiCallTimeout(clientExecutionTimeout())
|
||||
.apiCallAttemptTimeout(clientRequestTimeout())
|
||||
.build())
|
||||
.httpClientBuilder(AwsCrtHttpClient.builder()
|
||||
.maxConcurrency(maxConnections()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamoDbAsyncClient buildAsyncClient(final AwsCredentialsProvider credentialsProvider) {
|
||||
return DynamoDbAsyncClient.builder()
|
||||
.region(Region.of(region()))
|
||||
.credentialsProvider(credentialsProvider)
|
||||
.overrideConfiguration(ClientOverrideConfiguration.builder()
|
||||
.apiCallTimeout(clientExecutionTimeout())
|
||||
.apiCallAttemptTimeout(clientRequestTimeout())
|
||||
.build())
|
||||
.httpClientBuilder(NettyNioAsyncHttpClient.builder()
|
||||
.maxConcurrency(maxConnections()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = DynamoDbClientConfiguration.class)
|
||||
public interface DynamoDbClientFactory extends Discoverable {
|
||||
|
||||
DynamoDbClient buildSyncClient(AwsCredentialsProvider awsCredentialsProvider);
|
||||
|
||||
DynamoDbAsyncClient buildAsyncClient(AwsCredentialsProvider awsCredentialsProvider);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = RedisClusterConfiguration.class)
|
||||
public interface FaultTolerantRedisClusterFactory extends Discoverable {
|
||||
|
||||
FaultTolerantRedisCluster build(String name, ClientResources.Builder clientResourcesBuilder);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import org.whispersystems.textsecuregcm.captcha.HCaptchaClient;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = HCaptchaConfiguration.class)
|
||||
public interface HCaptchaClientFactory extends Discoverable {
|
||||
|
||||
HCaptchaClient build(ScheduledExecutorService retryExecutor,
|
||||
DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager);
|
||||
}
|
||||
@@ -7,9 +7,15 @@ package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.whispersystems.textsecuregcm.captcha.HCaptchaClient;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public class HCaptchaConfiguration {
|
||||
@JsonTypeName("default")
|
||||
public class HCaptchaConfiguration implements HCaptchaClientFactory {
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
@@ -36,4 +42,14 @@ public class HCaptchaConfiguration {
|
||||
return retry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HCaptchaClient build(final ScheduledExecutorService retryExecutor,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager) {
|
||||
return new HCaptchaClient(
|
||||
apiKey.value(),
|
||||
retryExecutor,
|
||||
circuitBreaker,
|
||||
retry,
|
||||
dynamicConfigurationManager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ public class MessageCacheConfiguration {
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
@Valid
|
||||
private RedisClusterConfiguration cluster;
|
||||
private FaultTolerantRedisClusterFactory cluster;
|
||||
|
||||
@JsonProperty
|
||||
private int persistDelayMinutes = 10;
|
||||
|
||||
public RedisClusterConfiguration getRedisClusterConfiguration() {
|
||||
public FaultTolerantRedisClusterFactory getRedisClusterConfiguration() {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,23 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.whispersystems.textsecuregcm.s3.S3ObjectMonitor;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@JsonTypeName("default")
|
||||
public record MonitoredS3ObjectConfiguration(
|
||||
@NotBlank String s3Region,
|
||||
@NotBlank String s3Bucket,
|
||||
@NotBlank String objectKey,
|
||||
Long maxSize,
|
||||
Duration refreshInterval) {
|
||||
Duration refreshInterval) implements S3ObjectMonitorFactory {
|
||||
|
||||
private static long DEFAULT_MAXSIZE = 16*1024*1024;
|
||||
private static Duration DEFAULT_REFRESH_INTERVAL = Duration.ofMinutes(5);
|
||||
private static final long DEFAULT_MAXSIZE = 16 * 1024 * 1024;
|
||||
private static final Duration DEFAULT_REFRESH_INTERVAL = Duration.ofMinutes(5);
|
||||
|
||||
public MonitoredS3ObjectConfiguration {
|
||||
if (maxSize == null) {
|
||||
@@ -26,4 +31,12 @@ public record MonitoredS3ObjectConfiguration(
|
||||
refreshInterval = DEFAULT_REFRESH_INTERVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public S3ObjectMonitor build(final AwsCredentialsProvider awsCredentialsProvider,
|
||||
final ScheduledExecutorService refreshExecutorService) {
|
||||
|
||||
return new S3ObjectMonitor(awsCredentialsProvider, s3Region, s3Bucket, objectKey, maxSize, refreshExecutorService,
|
||||
refreshInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import java.net.http.HttpClient;
|
||||
import java.util.Map;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||
import org.whispersystems.textsecuregcm.currency.CoinMarketCapClient;
|
||||
import org.whispersystems.textsecuregcm.currency.FixerClient;
|
||||
|
||||
@JsonTypeName("default")
|
||||
public record PaymentsServiceClientsConfiguration(@NotNull SecretString coinMarketCapApiKey,
|
||||
@NotNull SecretString fixerApiKey,
|
||||
@NotEmpty Map<@NotBlank String, Integer> coinMarketCapCurrencyIds) implements
|
||||
PaymentsServiceClientsFactory {
|
||||
|
||||
@Override
|
||||
public FixerClient buildFixerClient(final HttpClient httpClient) {
|
||||
return new FixerClient(httpClient, fixerApiKey.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CoinMarketCapClient buildCoinMarketCapClient(final HttpClient httpClient) {
|
||||
return new CoinMarketCapClient(httpClient, coinMarketCapApiKey.value(), coinMarketCapCurrencyIds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import org.whispersystems.textsecuregcm.currency.CoinMarketCapClient;
|
||||
import org.whispersystems.textsecuregcm.currency.FixerClient;
|
||||
import java.net.http.HttpClient;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = PaymentsServiceClientsConfiguration.class)
|
||||
public interface PaymentsServiceClientsFactory extends Discoverable {
|
||||
|
||||
FixerClient buildFixerClient(final HttpClient httpClient);
|
||||
|
||||
CoinMarketCapClient buildCoinMarketCapClient(HttpClient httpClient);
|
||||
}
|
||||
@@ -5,17 +5,15 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||
import java.util.List;
|
||||
|
||||
public record PaymentsServiceConfiguration(@NotNull SecretBytes userAuthenticationTokenSharedSecret,
|
||||
@NotNull SecretString coinMarketCapApiKey,
|
||||
@NotNull SecretString fixerApiKey,
|
||||
@NotEmpty Map<@NotBlank String, Integer> coinMarketCapCurrencyIds,
|
||||
@NotEmpty List<String> paymentCurrencies) {
|
||||
@NotEmpty List<String> paymentCurrencies,
|
||||
@NotNull @Valid PaymentsServiceClientsFactory externalClients) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public record ProvisioningConfiguration(@Valid @NotNull SingletonRedisClientFactory pubsub,
|
||||
@Valid @NotNull CircuitBreakerConfiguration circuitBreaker) {
|
||||
|
||||
public ProvisioningConfiguration {
|
||||
if (circuitBreaker == null) {
|
||||
circuitBreaker = new CircuitBreakerConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.google.cloud.pubsub.v1.PublisherInterface;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import java.io.IOException;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = DefaultPubSubPublisherFactory.class)
|
||||
public interface PubSubPublisherFactory extends Discoverable {
|
||||
|
||||
PublisherInterface build() throws IOException;
|
||||
}
|
||||
@@ -6,13 +6,17 @@
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
import java.time.Duration;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.Duration;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
|
||||
public class RedisClusterConfiguration {
|
||||
@JsonTypeName("default")
|
||||
public class RedisClusterConfiguration implements FaultTolerantRedisClusterFactory {
|
||||
|
||||
@JsonProperty
|
||||
@NotEmpty
|
||||
@@ -32,6 +36,11 @@ public class RedisClusterConfiguration {
|
||||
@Valid
|
||||
private RetryConfiguration retry = new RetryConfiguration();
|
||||
|
||||
@VisibleForTesting
|
||||
void setConfigurationUri(final String configurationUri) {
|
||||
this.configurationUri = configurationUri;
|
||||
}
|
||||
|
||||
public String getConfigurationUri() {
|
||||
return configurationUri;
|
||||
}
|
||||
@@ -47,4 +56,9 @@ public class RedisClusterConfiguration {
|
||||
public RetryConfiguration getRetryConfiguration() {
|
||||
return retry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaultTolerantRedisCluster build(final String name, final ClientResources.Builder clientResourcesBuilder) {
|
||||
return new FaultTolerantRedisCluster(name, this, clientResourcesBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,16 @@ package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.whispersystems.textsecuregcm.redis.RedisUriUtil;
|
||||
|
||||
public class RedisConfiguration {
|
||||
@JsonTypeName("default")
|
||||
public class RedisConfiguration implements SingletonRedisClientFactory {
|
||||
|
||||
@JsonProperty
|
||||
@NotEmpty
|
||||
@@ -22,11 +25,6 @@ public class RedisConfiguration {
|
||||
@NotNull
|
||||
private Duration timeout = Duration.ofSeconds(1);
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
@Valid
|
||||
private CircuitBreakerConfiguration circuitBreaker = new CircuitBreakerConfiguration();
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
@@ -35,7 +33,12 @@ public class RedisConfiguration {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public CircuitBreakerConfiguration getCircuitBreakerConfiguration() {
|
||||
return circuitBreaker;
|
||||
@Override
|
||||
public RedisClient build(final ClientResources clientResources) {
|
||||
final RedisClient redisClient = RedisClient.create(clientResources,
|
||||
RedisUriUtil.createRedisUriWithTimeout(uri, timeout));
|
||||
redisClient.setDefaultTimeout(timeout);
|
||||
|
||||
return redisClient;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.core.setup.Environment;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import org.whispersystems.textsecuregcm.registration.RegistrationServiceClient;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = RegistrationServiceConfiguration.class)
|
||||
public interface RegistrationServiceClientFactory extends Discoverable {
|
||||
|
||||
RegistrationServiceClient build(Environment environment, Executor callbackExecutor,
|
||||
ScheduledExecutorService identityRefreshExecutor);
|
||||
}
|
||||
@@ -1,10 +1,35 @@
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.dropwizard.core.setup.Environment;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import org.whispersystems.textsecuregcm.registration.IdentityTokenCallCredentials;
|
||||
import org.whispersystems.textsecuregcm.registration.RegistrationServiceClient;
|
||||
|
||||
@JsonTypeName("default")
|
||||
public record RegistrationServiceConfiguration(@NotBlank String host,
|
||||
int port,
|
||||
@NotBlank String credentialConfigurationJson,
|
||||
@NotBlank String identityTokenAudience,
|
||||
@NotBlank String registrationCaCertificate) {
|
||||
@NotBlank String registrationCaCertificate) implements
|
||||
RegistrationServiceClientFactory {
|
||||
|
||||
@Override
|
||||
public RegistrationServiceClient build(final Environment environment, final Executor callbackExecutor,
|
||||
final ScheduledExecutorService identityRefreshExecutor) {
|
||||
try {
|
||||
final IdentityTokenCallCredentials callCredentials = IdentityTokenCallCredentials.fromCredentialConfig(
|
||||
credentialConfigurationJson, identityTokenAudience, identityRefreshExecutor);
|
||||
|
||||
environment.lifecycle().manage(callCredentials);
|
||||
|
||||
return new RegistrationServiceClient(host, port, callCredentials, registrationCaCertificate,
|
||||
identityRefreshExecutor);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import org.whispersystems.textsecuregcm.s3.S3ObjectMonitor;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = MonitoredS3ObjectConfiguration.class)
|
||||
public interface S3ObjectMonitorFactory extends Discoverable {
|
||||
|
||||
S3ObjectMonitor build(AwsCredentialsProvider awsCredentialsProvider,
|
||||
ScheduledExecutorService refreshExecutorService);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.dropwizard.jackson.Discoverable;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = RedisConfiguration.class)
|
||||
public interface SingletonRedisClientFactory extends Discoverable {
|
||||
|
||||
RedisClient build(ClientResources clientResources);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
|
||||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = StaticAwsCredentialsFactory.class)
|
||||
@JsonTypeName("static")
|
||||
public record StaticAwsCredentialsFactory(@NotNull SecretString accessKeyId,
|
||||
@NotNull SecretString secretAccessKey) implements
|
||||
AwsCredentialsProviderFactory {
|
||||
|
||||
@Override
|
||||
public AwsCredentialsProvider build() {
|
||||
return StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKeyId.value(), secretAccessKey.value()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user