Remove deprecated /v1/accounts/turn
This commit is contained in:
parent
a88560e557
commit
1cae841ed6
|
@ -669,8 +669,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
|
||||
final MessageSender messageSender = new MessageSender(messagesManager, pushNotificationManager);
|
||||
final ReceiptSender receiptSender = new ReceiptSender(accountsManager, messageSender, receiptSenderExecutor);
|
||||
final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(dynamicConfigurationManager,
|
||||
config.getTurnConfiguration().secret().value());
|
||||
final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(config.getTurnConfiguration().secret().value());
|
||||
final CloudflareTurnCredentialsManager cloudflareTurnCredentialsManager = new CloudflareTurnCredentialsManager(
|
||||
config.getTurnConfiguration().cloudflare().apiToken().value(),
|
||||
config.getTurnConfiguration().cloudflare().endpoint(),
|
||||
|
@ -1101,7 +1100,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
final PhoneVerificationTokenManager phoneVerificationTokenManager = new PhoneVerificationTokenManager(
|
||||
phoneNumberIdentifiers, registrationServiceClient, registrationRecoveryPasswordsManager, registrationRecoveryChecker);
|
||||
final List<Object> commonControllers = Lists.newArrayList(
|
||||
new AccountController(accountsManager, rateLimiters, turnTokenGenerator, registrationRecoveryPasswordsManager,
|
||||
new AccountController(accountsManager, rateLimiters, registrationRecoveryPasswordsManager,
|
||||
usernameHashZkProofVerifier),
|
||||
new AccountControllerV2(accountsManager, changeNumberManager, phoneVerificationTokenManager,
|
||||
registrationLockVerificationManager, rateLimiters),
|
||||
|
|
|
@ -27,8 +27,6 @@ import org.whispersystems.textsecuregcm.util.WeightedRandomSelect;
|
|||
|
||||
public class TurnTokenGenerator {
|
||||
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||
|
||||
private final byte[] turnSecret;
|
||||
|
||||
private static final String ALGORITHM = "HmacSHA1";
|
||||
|
@ -37,17 +35,10 @@ public class TurnTokenGenerator {
|
|||
|
||||
private static final String WithIpsProtocol = "01";
|
||||
|
||||
public TurnTokenGenerator(final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager,
|
||||
final byte[] turnSecret) {
|
||||
this.dynamicConfigurationManager = dynamicConfigurationManager;
|
||||
public TurnTokenGenerator(final byte[] turnSecret) {
|
||||
this.turnSecret = turnSecret;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public TurnToken generate(final UUID aci) {
|
||||
return generateToken(null, null, urls(aci));
|
||||
}
|
||||
|
||||
public TurnToken generateWithTurnServerOptions(TurnServerOptions options) {
|
||||
return generateToken(options.hostname(), options.urlsWithIps(), options.urlsWithHostname());
|
||||
}
|
||||
|
@ -71,23 +62,4 @@ public class TurnTokenGenerator {
|
|||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> urls(final UUID aci) {
|
||||
final DynamicTurnConfiguration turnConfig = dynamicConfigurationManager.getConfiguration().getTurnConfiguration();
|
||||
|
||||
// Check if number is enrolled to test out specific turn servers
|
||||
final Optional<TurnUriConfiguration> enrolled = turnConfig.getUriConfigs().stream()
|
||||
.filter(config -> config.getEnrolledAcis().contains(aci))
|
||||
.findFirst();
|
||||
|
||||
if (enrolled.isPresent()) {
|
||||
return enrolled.get().getUris();
|
||||
}
|
||||
|
||||
// Otherwise, select from turn server sets by weighted choice
|
||||
return WeightedRandomSelect.select(turnConfig
|
||||
.getUriConfigs()
|
||||
.stream()
|
||||
.map(c -> new Pair<>(c.getUris(), c.getWeight())).toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,11 +35,8 @@ import java.util.UUID;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
import javax.annotation.Nullable;
|
||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||
import org.whispersystems.textsecuregcm.auth.AccountAndAuthenticatedDeviceHolder;
|
||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedDevice;
|
||||
import org.whispersystems.textsecuregcm.auth.SaltedTokenHash;
|
||||
import org.whispersystems.textsecuregcm.auth.TurnToken;
|
||||
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
||||
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||
import org.whispersystems.textsecuregcm.entities.AccountIdentifierResponse;
|
||||
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||
|
@ -61,7 +58,6 @@ import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
|||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.DeviceCapability;
|
||||
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.UsernameHashNotAvailableException;
|
||||
import org.whispersystems.textsecuregcm.storage.UsernameReservationNotFoundException;
|
||||
|
@ -82,33 +78,20 @@ public class AccountController {
|
|||
|
||||
private final AccountsManager accounts;
|
||||
private final RateLimiters rateLimiters;
|
||||
private final TurnTokenGenerator turnTokenGenerator;
|
||||
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager;
|
||||
private final UsernameHashZkProofVerifier usernameHashZkProofVerifier;
|
||||
|
||||
public AccountController(
|
||||
AccountsManager accounts,
|
||||
RateLimiters rateLimiters,
|
||||
TurnTokenGenerator turnTokenGenerator,
|
||||
RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager,
|
||||
UsernameHashZkProofVerifier usernameHashZkProofVerifier) {
|
||||
this.accounts = accounts;
|
||||
this.rateLimiters = rateLimiters;
|
||||
this.turnTokenGenerator = turnTokenGenerator;
|
||||
this.registrationRecoveryPasswordsManager = registrationRecoveryPasswordsManager;
|
||||
this.usernameHashZkProofVerifier = usernameHashZkProofVerifier;
|
||||
}
|
||||
|
||||
// may be removed after 2024-07-16
|
||||
@Deprecated(forRemoval = true)
|
||||
@GET
|
||||
@Path("/turn/")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public TurnToken getTurnToken(@ReadOnly @Auth AuthenticatedDevice auth) throws RateLimitExceededException {
|
||||
rateLimiters.getTurnLimiter().validate(auth.getAccount().getUuid());
|
||||
return turnTokenGenerator.generate(auth.getAccount().getUuid());
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("/gcm/")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import org.signal.chat.calling.GetTurnCredentialsRequest;
|
||||
import org.signal.chat.calling.GetTurnCredentialsResponse;
|
||||
import org.signal.chat.calling.ReactorCallingGrpc;
|
||||
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
||||
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticatedDevice;
|
||||
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticationUtil;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class CallingGrpcService extends ReactorCallingGrpc.CallingImplBase {
|
||||
|
||||
private final TurnTokenGenerator turnTokenGenerator;
|
||||
private final RateLimiters rateLimiters;
|
||||
|
||||
public CallingGrpcService(final TurnTokenGenerator turnTokenGenerator, final RateLimiters rateLimiters) {
|
||||
this.turnTokenGenerator = turnTokenGenerator;
|
||||
this.rateLimiters = rateLimiters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GetTurnCredentialsResponse> getTurnCredentials(final GetTurnCredentialsRequest request) {
|
||||
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
|
||||
|
||||
return rateLimiters.getTurnLimiter().validateReactive(authenticatedDevice.accountIdentifier())
|
||||
.then(Mono.fromSupplier(() -> turnTokenGenerator.generate(authenticatedDevice.accountIdentifier())))
|
||||
.map(turnToken -> GetTurnCredentialsResponse.newBuilder()
|
||||
.setUsername(turnToken.username())
|
||||
.setPassword(turnToken.password())
|
||||
.addAllUrls(turnToken.urls())
|
||||
.build());
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
package org.whispersystems.textsecuregcm.auth;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
|
||||
public class TurnTokenGeneratorTest {
|
||||
@Test
|
||||
public void testAlwaysSelectFirst() throws JsonProcessingException {
|
||||
final String configString = """
|
||||
captcha:
|
||||
scoreFloor: 1.0
|
||||
turn:
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- always1.org
|
||||
- always2.org
|
||||
- uris:
|
||||
- never.org
|
||||
weight: 0
|
||||
""";
|
||||
DynamicConfiguration config = DynamicConfigurationManager
|
||||
.parseConfiguration(configString, DynamicConfiguration.class)
|
||||
.orElseThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
|
||||
when(mockDynamicConfigManager.getConfiguration()).thenReturn(config);
|
||||
|
||||
final TurnTokenGenerator turnTokenGenerator =
|
||||
new TurnTokenGenerator(mockDynamicConfigManager, "bloop".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
final long COUNT = 1000;
|
||||
|
||||
final Map<String, Long> urlCounts = Stream
|
||||
.generate(() -> turnTokenGenerator.generate(UUID.randomUUID()))
|
||||
.limit(COUNT)
|
||||
.flatMap(token -> token.urls().stream())
|
||||
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
|
||||
|
||||
assertThat(urlCounts.get("always1.org")).isEqualTo(COUNT);
|
||||
assertThat(urlCounts.get("always2.org")).isEqualTo(COUNT);
|
||||
assertThat(urlCounts).doesNotContainKey("never.org");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProbabilisticUrls() throws JsonProcessingException {
|
||||
final String configString = """
|
||||
captcha:
|
||||
scoreFloor: 1.0
|
||||
turn:
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- always.org
|
||||
- sometimes1.org
|
||||
weight: 5
|
||||
- uris:
|
||||
- always.org
|
||||
- sometimes2.org
|
||||
weight: 5
|
||||
""";
|
||||
DynamicConfiguration config = DynamicConfigurationManager
|
||||
.parseConfiguration(configString, DynamicConfiguration.class)
|
||||
.orElseThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
|
||||
when(mockDynamicConfigManager.getConfiguration()).thenReturn(config);
|
||||
|
||||
final TurnTokenGenerator turnTokenGenerator =
|
||||
new TurnTokenGenerator(mockDynamicConfigManager, "bloop".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
final long COUNT = 1000;
|
||||
|
||||
final Map<String, Long> urlCounts = Stream
|
||||
.generate(() -> turnTokenGenerator.generate(UUID.randomUUID()))
|
||||
.limit(COUNT)
|
||||
.flatMap(token -> token.urls().stream())
|
||||
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
|
||||
|
||||
assertThat(urlCounts.get("always.org")).isEqualTo(COUNT);
|
||||
assertThat(urlCounts.get("sometimes1.org")).isGreaterThan(0);
|
||||
assertThat(urlCounts.get("sometimes2.org")).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitEnrollment() throws JsonProcessingException {
|
||||
final String configString = """
|
||||
captcha:
|
||||
scoreFloor: 1.0
|
||||
turn:
|
||||
secret: bloop
|
||||
uriConfigs:
|
||||
- uris:
|
||||
- enrolled.org
|
||||
weight: 0
|
||||
enrolledAcis:
|
||||
- 732506d7-d04f-43a4-b1d7-8a3a91ebe8a6
|
||||
- uris:
|
||||
- unenrolled.org
|
||||
weight: 1
|
||||
""";
|
||||
DynamicConfiguration config = DynamicConfigurationManager
|
||||
.parseConfiguration(configString, DynamicConfiguration.class)
|
||||
.orElseThrow();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DynamicConfigurationManager<DynamicConfiguration> mockDynamicConfigManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
|
||||
when(mockDynamicConfigManager.getConfiguration()).thenReturn(config);
|
||||
|
||||
final TurnTokenGenerator turnTokenGenerator =
|
||||
new TurnTokenGenerator(mockDynamicConfigManager, "bloop".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
TurnToken token = turnTokenGenerator.generate(UUID.fromString("732506d7-d04f-43a4-b1d7-8a3a91ebe8a6"));
|
||||
assertThat(token.urls().get(0)).isEqualTo("enrolled.org");
|
||||
token = turnTokenGenerator.generate(UUID.randomUUID());
|
||||
assertThat(token.urls().get(0)).isEqualTo("unenrolled.org");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -159,7 +159,6 @@ class AccountControllerTest {
|
|||
.addResource(new AccountController(
|
||||
accountsManager,
|
||||
rateLimiters,
|
||||
turnTokenGenerator,
|
||||
registrationRecoveryPasswordsManager,
|
||||
usernameZkProofVerifier
|
||||
))
|
||||
|
|
|
@ -34,12 +34,10 @@ import org.whispersystems.textsecuregcm.auth.TurnToken;
|
|||
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
||||
import org.whispersystems.textsecuregcm.calls.routing.TurnCallRouter;
|
||||
import org.whispersystems.textsecuregcm.calls.routing.TurnServerOptions;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import org.whispersystems.textsecuregcm.util.TestRemoteAddressFilterProvider;
|
||||
|
@ -52,12 +50,10 @@ class CallRoutingControllerTest {
|
|||
|
||||
private static final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
private static final RateLimiter getCallEndpointLimiter = mock(RateLimiter.class);
|
||||
private static final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
private static final ExperimentEnrollmentManager experimentEnrollmentManager = mock(
|
||||
ExperimentEnrollmentManager.class);
|
||||
private static final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(dynamicConfigurationManager,
|
||||
"bloop".getBytes(StandardCharsets.UTF_8));
|
||||
private static final TurnTokenGenerator turnTokenGenerator =
|
||||
new TurnTokenGenerator("bloop".getBytes(StandardCharsets.UTF_8));
|
||||
private static final CloudflareTurnCredentialsManager cloudflareTurnCredentialsManager = mock(
|
||||
CloudflareTurnCredentialsManager.class);
|
||||
|
||||
|
@ -81,8 +77,7 @@ class CallRoutingControllerTest {
|
|||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
reset(experimentEnrollmentManager, dynamicConfigurationManager, rateLimiters, getCallEndpointLimiter,
|
||||
turnCallRouter);
|
||||
reset(experimentEnrollmentManager, rateLimiters, getCallEndpointLimiter, turnCallRouter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -63,12 +63,9 @@ class CallRoutingControllerV2Test {
|
|||
|
||||
private static final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
private static final RateLimiter getCallEndpointLimiter = mock(RateLimiter.class);
|
||||
private static final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager = mock(
|
||||
DynamicConfigurationManager.class);
|
||||
private static final ExperimentEnrollmentManager experimentEnrollmentManager = mock(
|
||||
ExperimentEnrollmentManager.class);
|
||||
private static final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(dynamicConfigurationManager,
|
||||
"bloop".getBytes(StandardCharsets.UTF_8));
|
||||
private static final TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator("bloop".getBytes(StandardCharsets.UTF_8));
|
||||
private static final CloudflareTurnCredentialsManager cloudflareTurnCredentialsManager = mock(
|
||||
CloudflareTurnCredentialsManager.class);
|
||||
private static final TurnCallRouter turnCallRouter = mock(TurnCallRouter.class);
|
||||
|
@ -91,8 +88,7 @@ class CallRoutingControllerV2Test {
|
|||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
reset(experimentEnrollmentManager, dynamicConfigurationManager, rateLimiters, getCallEndpointLimiter,
|
||||
turnCallRouter);
|
||||
reset(experimentEnrollmentManager, rateLimiters, getCallEndpointLimiter, turnCallRouter);
|
||||
}
|
||||
|
||||
void initializeMocksWith(Optional<TurnServerOptions> signalTurn, Optional<TurnToken> cloudflare) {
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.whispersystems.textsecuregcm.grpc.GrpcTestUtils.assertRateLimitExceeded;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.signal.chat.calling.CallingGrpc;
|
||||
import org.signal.chat.calling.GetTurnCredentialsRequest;
|
||||
import org.signal.chat.calling.GetTurnCredentialsResponse;
|
||||
import org.whispersystems.textsecuregcm.auth.TurnToken;
|
||||
import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.util.MockUtils;
|
||||
|
||||
class CallingGrpcServiceTest extends SimpleBaseGrpcTest<CallingGrpcService, CallingGrpc.CallingBlockingStub> {
|
||||
|
||||
@Mock
|
||||
private TurnTokenGenerator turnTokenGenerator;
|
||||
|
||||
@Mock
|
||||
private RateLimiter turnCredentialRateLimiter;
|
||||
|
||||
|
||||
@Override
|
||||
protected CallingGrpcService createServiceBeforeEachTest() {
|
||||
final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
when(rateLimiters.getTurnLimiter()).thenReturn(turnCredentialRateLimiter);
|
||||
return new CallingGrpcService(turnTokenGenerator, rateLimiters);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTurnCredentials() {
|
||||
final String username = "test-username";
|
||||
final String password = "test-password";
|
||||
final List<String> urls = List.of("first", "second");
|
||||
final String hostname = "hostname";
|
||||
|
||||
MockUtils.updateRateLimiterResponseToAllow(turnCredentialRateLimiter, AUTHENTICATED_ACI);
|
||||
when(turnTokenGenerator.generate(any())).thenReturn(new TurnToken(username, password, urls, null, hostname));
|
||||
|
||||
final GetTurnCredentialsResponse response = authenticatedServiceStub().getTurnCredentials(GetTurnCredentialsRequest.newBuilder().build());
|
||||
|
||||
final GetTurnCredentialsResponse expectedResponse = GetTurnCredentialsResponse.newBuilder()
|
||||
.setUsername(username)
|
||||
.setPassword(password)
|
||||
.addAllUrls(urls)
|
||||
.build();
|
||||
|
||||
assertEquals(expectedResponse, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTurnCredentialsRateLimited() {
|
||||
final Duration retryAfter = MockUtils.updateRateLimiterResponseToFail(
|
||||
turnCredentialRateLimiter, AUTHENTICATED_ACI, Duration.ofMinutes(19));
|
||||
assertRateLimitExceeded(retryAfter, () -> authenticatedServiceStub().getTurnCredentials(GetTurnCredentialsRequest.newBuilder().build()));
|
||||
verify(turnTokenGenerator, never()).generate(any());
|
||||
verifyNoInteractions(turnTokenGenerator);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue