Add field to RestoreAccountRequest for device transfer initialization
This commit is contained in:
parent
ea17eee320
commit
760c5737f9
|
@ -5,8 +5,13 @@
|
|||
|
||||
package org.whispersystems.textsecuregcm.entities;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import javax.annotation.Nullable;
|
||||
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
||||
|
||||
@Schema(description = """
|
||||
Represents a request from a new device to restore account data by some method.
|
||||
|
@ -14,7 +19,14 @@ import jakarta.validation.constraints.NotNull;
|
|||
public record RestoreAccountRequest(
|
||||
@NotNull
|
||||
@Schema(description = "The method by which the new device has requested account data restoration")
|
||||
Method method) {
|
||||
Method method,
|
||||
|
||||
@Schema(description = "Additional data to use to bootstrap a connection between devices, in standard unpadded base64.",
|
||||
implementation = String.class)
|
||||
@JsonSerialize(using = ByteArrayAdapter.Serializing.class)
|
||||
@JsonDeserialize(using = ByteArrayAdapter.Deserializing.class)
|
||||
@Size(max = 4096)
|
||||
@Nullable byte[] deviceTransferBootstrap) {
|
||||
|
||||
public enum Method {
|
||||
@Schema(description = "Restore account data from a remote message history backup")
|
||||
|
|
|
@ -42,6 +42,7 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.glassfish.jersey.server.ServerProperties;
|
||||
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
@ -51,6 +52,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
|||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
@ -1267,7 +1269,7 @@ class DeviceControllerTest {
|
|||
void recordRestoreAccountRequest() {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(16);
|
||||
final RestoreAccountRequest restoreAccountRequest =
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.LOCAL_BACKUP);
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.LOCAL_BACKUP, null);
|
||||
|
||||
when(accountsManager.recordRestoreAccountRequest(token, restoreAccountRequest))
|
||||
.thenReturn(CompletableFuture.completedFuture(null));
|
||||
|
@ -1285,7 +1287,7 @@ class DeviceControllerTest {
|
|||
void recordRestoreAccountRequestBadToken() {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(128);
|
||||
final RestoreAccountRequest restoreAccountRequest =
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.LOCAL_BACKUP);
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.LOCAL_BACKUP, null);
|
||||
|
||||
try (final Response response = resources.getJerseyTest()
|
||||
.target("/v1/devices/restore_account/" + token)
|
||||
|
@ -1299,7 +1301,7 @@ class DeviceControllerTest {
|
|||
@Test
|
||||
void recordRestoreAccountRequestInvalidRequest() {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(16);
|
||||
final RestoreAccountRequest restoreAccountRequest = new RestoreAccountRequest(null);
|
||||
final RestoreAccountRequest restoreAccountRequest = new RestoreAccountRequest(null, null);
|
||||
|
||||
try (final Response response = resources.getJerseyTest()
|
||||
.target("/v1/devices/restore_account/" + token)
|
||||
|
@ -1310,11 +1312,34 @@ class DeviceControllerTest {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"0, true",
|
||||
"4096, true",
|
||||
"4097, false"
|
||||
})
|
||||
void recordRestoreAccountRequestBootstrapLengthLimit(int bootstrapLength, boolean valid) {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(16);
|
||||
|
||||
final byte[] bootstrap = TestRandomUtil.nextBytes(bootstrapLength);
|
||||
final RestoreAccountRequest restoreAccountRequest = new RestoreAccountRequest(
|
||||
RestoreAccountRequest.Method.DEVICE_TRANSFER, bootstrap);
|
||||
|
||||
try (final Response response = resources.getJerseyTest()
|
||||
.target("/v1/devices/restore_account/" + token)
|
||||
.request()
|
||||
.put(Entity.json(restoreAccountRequest))) {
|
||||
|
||||
assertEquals(valid ? 204 : 422, response.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void waitForDeviceTransferRequest() {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(16);
|
||||
final RestoreAccountRequest restoreAccountRequest =
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.LOCAL_BACKUP);
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.LOCAL_BACKUP, null);
|
||||
|
||||
when(accountsManager.waitForRestoreAccountRequest(eq(token), any()))
|
||||
.thenReturn(CompletableFuture.completedFuture(Optional.of(restoreAccountRequest)));
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient;
|
|||
import org.whispersystems.textsecuregcm.redis.RedisServerExtension;
|
||||
import org.whispersystems.textsecuregcm.securestorage.SecureStorageClient;
|
||||
import org.whispersystems.textsecuregcm.securevaluerecovery.SecureValueRecovery2Client;
|
||||
import org.whispersystems.textsecuregcm.util.TestRandomUtil;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Clock;
|
||||
|
@ -33,7 +34,9 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -178,8 +181,9 @@ public class AccountsManagerDeviceTransferIntegrationTest {
|
|||
@Test
|
||||
void waitForRestoreAccountRequest() {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(16);
|
||||
final byte[] deviceTransferBootstrap = TestRandomUtil.nextBytes(100);
|
||||
final RestoreAccountRequest restoreAccountRequest =
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.DEVICE_TRANSFER);
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.DEVICE_TRANSFER, deviceTransferBootstrap);
|
||||
|
||||
final CompletableFuture<Optional<RestoreAccountRequest>> displacedFuture =
|
||||
accountsManager.waitForRestoreAccountRequest(token, Duration.ofSeconds(5));
|
||||
|
@ -191,14 +195,17 @@ public class AccountsManagerDeviceTransferIntegrationTest {
|
|||
|
||||
accountsManager.recordRestoreAccountRequest(token, restoreAccountRequest).join();
|
||||
|
||||
assertEquals(Optional.of(restoreAccountRequest), activeFuture.join());
|
||||
final Optional<RestoreAccountRequest> result = activeFuture.join();
|
||||
assertTrue(result.isPresent());
|
||||
assertEquals(restoreAccountRequest.method(), result.get().method());
|
||||
assertArrayEquals(restoreAccountRequest.deviceTransferBootstrap(), result.get().deviceTransferBootstrap());
|
||||
}
|
||||
|
||||
@Test
|
||||
void waitForRestoreAccountRequestAlreadyRequested() {
|
||||
final String token = RandomStringUtils.secure().nextAlphanumeric(16);
|
||||
final RestoreAccountRequest restoreAccountRequest =
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.DEVICE_TRANSFER);
|
||||
new RestoreAccountRequest(RestoreAccountRequest.Method.DEVICE_TRANSFER, null);
|
||||
|
||||
accountsManager.recordRestoreAccountRequest(token, restoreAccountRequest).join();
|
||||
|
||||
|
|
Loading…
Reference in New Issue