mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 20:48:43 +00:00
Convert SVR and GV2 auth requests to WebSocket.
This commit is contained in:
@@ -361,7 +361,7 @@ object AppDependencies {
|
||||
interface Provider {
|
||||
fun providePushServiceSocket(signalServiceConfiguration: SignalServiceConfiguration, groupsV2Operations: GroupsV2Operations): PushServiceSocket
|
||||
fun provideGroupsV2Operations(signalServiceConfiguration: SignalServiceConfiguration): GroupsV2Operations
|
||||
fun provideSignalServiceAccountManager(authWebSocket: AccountApi, pushServiceSocket: PushServiceSocket, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager
|
||||
fun provideSignalServiceAccountManager(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, accountApi: AccountApi, pushServiceSocket: PushServiceSocket, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager
|
||||
fun provideSignalServiceMessageSender(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, protocolStore: SignalServiceDataStore, pushServiceSocket: PushServiceSocket, messageApi: MessageApi): SignalServiceMessageSender
|
||||
fun provideSignalServiceMessageReceiver(pushServiceSocket: PushServiceSocket): SignalServiceMessageReceiver
|
||||
fun provideSignalServiceNetworkAccess(): SignalServiceNetworkAccess
|
||||
|
||||
@@ -146,8 +146,8 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SignalServiceAccountManager provideSignalServiceAccountManager(@NonNull AccountApi accountApi, @NonNull PushServiceSocket pushServiceSocket, @NonNull GroupsV2Operations groupsV2Operations) {
|
||||
return new SignalServiceAccountManager(accountApi, pushServiceSocket, groupsV2Operations);
|
||||
public @NonNull SignalServiceAccountManager provideSignalServiceAccountManager(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket, @NonNull AccountApi accountApi, @NonNull PushServiceSocket pushServiceSocket, @NonNull GroupsV2Operations groupsV2Operations) {
|
||||
return new SignalServiceAccountManager(authWebSocket, accountApi, pushServiceSocket, groupsV2Operations);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -95,7 +95,7 @@ class NetworkDependenciesModule(
|
||||
}
|
||||
|
||||
val signalServiceAccountManager: SignalServiceAccountManager by lazy {
|
||||
provider.provideSignalServiceAccountManager(accountApi, pushServiceSocket, groupsV2Operations)
|
||||
provider.provideSignalServiceAccountManager(authWebSocket, accountApi, pushServiceSocket, groupsV2Operations)
|
||||
}
|
||||
|
||||
val libsignalNetwork: Network by lazy {
|
||||
|
||||
@@ -66,7 +66,7 @@ class MockApplicationDependencyProvider : AppDependencies.Provider {
|
||||
return mockk(relaxed = true)
|
||||
}
|
||||
|
||||
override fun provideSignalServiceAccountManager(authWebSocket: AccountApi, pushServiceSocket: PushServiceSocket, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager {
|
||||
override fun provideSignalServiceAccountManager(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, accountApi: AccountApi, pushServiceSocket: PushServiceSocket, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager {
|
||||
return mockk(relaxed = true)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,9 @@ import org.whispersystems.signalservice.api.crypto.SealedSenderAccess;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
|
||||
import org.whispersystems.signalservice.api.payments.CurrencyConversions;
|
||||
import org.whispersystems.signalservice.api.profiles.AvatarUploadParams;
|
||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
@@ -31,8 +28,8 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
|
||||
import org.whispersystems.signalservice.api.registration.RegistrationApi;
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV3;
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||
import org.whispersystems.signalservice.internal.push.AuthCredentials;
|
||||
import org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts;
|
||||
import org.whispersystems.signalservice.internal.push.PaymentAddress;
|
||||
import org.whispersystems.signalservice.internal.push.ProfileAvatarData;
|
||||
@@ -43,7 +40,6 @@ import org.whispersystems.signalservice.internal.push.http.ProfileCipherOutputSt
|
||||
import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -53,6 +49,9 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The main interface for creating, registering, and
|
||||
* managing a Signal Service account.
|
||||
@@ -63,10 +62,11 @@ public class SignalServiceAccountManager {
|
||||
|
||||
private static final String TAG = SignalServiceAccountManager.class.getSimpleName();
|
||||
|
||||
private final PushServiceSocket pushServiceSocket;
|
||||
private final GroupsV2Operations groupsV2Operations;
|
||||
private final SignalServiceConfiguration configuration;
|
||||
private final AccountApi accountApi;
|
||||
private final PushServiceSocket pushServiceSocket;
|
||||
private final GroupsV2Operations groupsV2Operations;
|
||||
private final SignalServiceConfiguration configuration;
|
||||
private final SignalWebSocket.AuthenticatedWebSocket authWebSocket;
|
||||
private final AccountApi accountApi;
|
||||
|
||||
/**
|
||||
* Construct a SignalServiceAccountManager.
|
||||
@@ -91,13 +91,18 @@ public class SignalServiceAccountManager {
|
||||
GroupsV2Operations gv2Operations = new GroupsV2Operations(ClientZkOperations.create(configuration), maxGroupSize);
|
||||
|
||||
return new SignalServiceAccountManager(
|
||||
null,
|
||||
null,
|
||||
new PushServiceSocket(configuration, credentialProvider, signalAgent, gv2Operations.getProfileOperations(), automaticNetworkRetry),
|
||||
gv2Operations
|
||||
);
|
||||
}
|
||||
|
||||
public SignalServiceAccountManager(AccountApi accountApi, PushServiceSocket pushServiceSocket, GroupsV2Operations groupsV2Operations) {
|
||||
public SignalServiceAccountManager(@Nullable SignalWebSocket.AuthenticatedWebSocket authWebSocket,
|
||||
@Nullable AccountApi accountApi,
|
||||
@Nonnull PushServiceSocket pushServiceSocket,
|
||||
@Nonnull GroupsV2Operations groupsV2Operations) {
|
||||
this.authWebSocket = authWebSocket;
|
||||
this.accountApi = accountApi;
|
||||
this.groupsV2Operations = groupsV2Operations;
|
||||
this.pushServiceSocket = pushServiceSocket;
|
||||
@@ -113,11 +118,11 @@ public class SignalServiceAccountManager {
|
||||
}
|
||||
|
||||
public SecureValueRecoveryV2 getSecureValueRecoveryV2(String mrEnclave) {
|
||||
return new SecureValueRecoveryV2(configuration, mrEnclave, pushServiceSocket);
|
||||
return new SecureValueRecoveryV2(configuration, mrEnclave, authWebSocket);
|
||||
}
|
||||
|
||||
public SecureValueRecoveryV3 getSecureValueRecoveryV3(Network network) {
|
||||
return new SecureValueRecoveryV3(network, pushServiceSocket);
|
||||
return new SecureValueRecoveryV3(network, authWebSocket);
|
||||
}
|
||||
|
||||
public WhoAmIResponse getWhoAmI() throws IOException {
|
||||
@@ -243,7 +248,7 @@ public class SignalServiceAccountManager {
|
||||
}
|
||||
|
||||
public GroupsV2Api getGroupsV2Api() {
|
||||
return new GroupsV2Api(pushServiceSocket, groupsV2Operations);
|
||||
return new GroupsV2Api(authWebSocket, pushServiceSocket, groupsV2Operations);
|
||||
}
|
||||
|
||||
public RegistrationApi getRegistrationApi() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.whispersystems.signalservice.api.NetworkResult;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
||||
import org.whispersystems.signalservice.internal.push.exceptions.ForbiddenException;
|
||||
|
||||
@@ -43,10 +44,12 @@ import okio.ByteString;
|
||||
|
||||
public class GroupsV2Api {
|
||||
|
||||
private final PushServiceSocket socket;
|
||||
private final GroupsV2Operations groupsOperations;
|
||||
private final SignalWebSocket.AuthenticatedWebSocket authWebSocket;
|
||||
private final PushServiceSocket socket;
|
||||
private final GroupsV2Operations groupsOperations;
|
||||
|
||||
public GroupsV2Api(PushServiceSocket socket, GroupsV2Operations groupsOperations) {
|
||||
public GroupsV2Api(SignalWebSocket.AuthenticatedWebSocket authWebSocket, PushServiceSocket socket, GroupsV2Operations groupsOperations) {
|
||||
this.authWebSocket = authWebSocket;
|
||||
this.socket = socket;
|
||||
this.groupsOperations = groupsOperations;
|
||||
}
|
||||
@@ -54,10 +57,8 @@ public class GroupsV2Api {
|
||||
/**
|
||||
* Provides 7 days of credentials, which you should cache.
|
||||
*/
|
||||
public CredentialResponseMaps getCredentials(long todaySeconds)
|
||||
throws IOException
|
||||
{
|
||||
return parseCredentialResponse(socket.retrieveGroupsV2Credentials(todaySeconds));
|
||||
public CredentialResponseMaps getCredentials(long todaySeconds) throws IOException {
|
||||
return parseCredentialResponse(GroupsV2ApiHelper.getCredentials(authWebSocket, todaySeconds));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.groupsv2
|
||||
|
||||
import org.whispersystems.signalservice.api.NetworkResult
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.get
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
import java.io.IOException
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
/**
|
||||
* Allow [GroupsV2Api] to have a partial kotlin conversion by putting more kotlin friendly calls here.
|
||||
*/
|
||||
object GroupsV2ApiHelper {
|
||||
/**
|
||||
* Provides 7 days of credentials, which you should cache.
|
||||
*
|
||||
* GET /v1/certificate/auth/group?redemptionStartSeconds=[todaySeconds]&redemptionEndSeconds=`todaySecondsPlus7DaysOfSeconds`
|
||||
* - 200: Success
|
||||
*/
|
||||
@JvmStatic
|
||||
@Throws(IOException::class)
|
||||
fun getCredentials(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, todaySeconds: Long): CredentialResponse {
|
||||
val todayPlus7 = todaySeconds + 7.days.inWholeSeconds
|
||||
val request = WebSocketRequestMessage.get("/v1/certificate/auth/group?redemptionStartSeconds=$todaySeconds&redemptionEndSeconds=$todayPlus7")
|
||||
return NetworkResult.fromWebSocketRequest(authWebSocket, request, CredentialResponse::class).successOrThrow()
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import org.signal.svr2.proto.DeleteRequest
|
||||
import org.signal.svr2.proto.ExposeRequest
|
||||
import org.signal.svr2.proto.Request
|
||||
import org.signal.svr2.proto.RestoreRequest
|
||||
import org.whispersystems.signalservice.api.NetworkResult
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey
|
||||
import org.whispersystems.signalservice.api.kbs.PinHashUtil
|
||||
@@ -21,11 +22,13 @@ import org.whispersystems.signalservice.api.svr.SecureValueRecovery.InvalidReque
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.RestoreResponse
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.SvrVersion
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration
|
||||
import org.whispersystems.signalservice.internal.get
|
||||
import org.whispersystems.signalservice.internal.push.AuthCredentials
|
||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket
|
||||
import org.whispersystems.signalservice.internal.util.Hex
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
import java.io.IOException
|
||||
import org.signal.svr2.proto.BackupResponse as ProtoBackupResponse
|
||||
import org.signal.svr2.proto.ExposeResponse as ProtoExposeResponse
|
||||
@@ -37,7 +40,7 @@ import org.signal.svr2.proto.RestoreResponse as ProtoRestoreResponse
|
||||
class SecureValueRecoveryV2(
|
||||
private val serviceConfiguration: SignalServiceConfiguration,
|
||||
private val mrEnclave: String,
|
||||
private val pushServiceSocket: PushServiceSocket
|
||||
private val authWebSocket: SignalWebSocket.AuthenticatedWebSocket
|
||||
) : SecureValueRecovery {
|
||||
|
||||
companion object {
|
||||
@@ -92,7 +95,8 @@ class SecureValueRecoveryV2(
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun authorization(): AuthCredentials {
|
||||
return pushServiceSocket.svr2Authorization
|
||||
val request = WebSocketRequestMessage.get("/v2/backup/auth")
|
||||
return NetworkResult.fromWebSocketRequest(authWebSocket, request, AuthCredentials::class).successOrThrow()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.libsignal.net.Network
|
||||
import org.whispersystems.signalservice.api.NetworkResult
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse
|
||||
@@ -17,11 +18,13 @@ import org.whispersystems.signalservice.api.svr.SecureValueRecovery.DeleteRespon
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.RestoreResponse
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.SvrVersion
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.get
|
||||
import org.whispersystems.signalservice.internal.push.AuthCredentials
|
||||
import org.whispersystems.signalservice.internal.push.ByteArrayDeserializerBase64
|
||||
import org.whispersystems.signalservice.internal.push.ByteArraySerializerBase64NoPadding
|
||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
@@ -29,7 +32,7 @@ import java.io.IOException
|
||||
*/
|
||||
class SecureValueRecoveryV3(
|
||||
private val network: Network,
|
||||
private val pushServiceSocket: PushServiceSocket
|
||||
private val authWebSocket: SignalWebSocket.AuthenticatedWebSocket
|
||||
) : SecureValueRecovery {
|
||||
|
||||
companion object {
|
||||
@@ -61,7 +64,7 @@ class SecureValueRecoveryV3(
|
||||
|
||||
override fun restoreDataPostRegistration(userPin: String): RestoreResponse {
|
||||
val authorization: Svr3Credentials = try {
|
||||
pushServiceSocket.svr3Authorization
|
||||
svr3Authorization().successOrThrow()
|
||||
} catch (e: NonSuccessfulResponseCodeException) {
|
||||
return RestoreResponse.ApplicationError(e)
|
||||
} catch (e: IOException) {
|
||||
@@ -110,7 +113,12 @@ class SecureValueRecoveryV3(
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun authorization(): AuthCredentials {
|
||||
return pushServiceSocket.svr3Authorization.toAuthCredential()
|
||||
return svr3Authorization().successOrThrow().toAuthCredential()
|
||||
}
|
||||
|
||||
private fun svr3Authorization(): NetworkResult<Svr3Credentials> {
|
||||
val request = WebSocketRequestMessage.get("/v3/backup/auth")
|
||||
return NetworkResult.fromWebSocketRequest(authWebSocket, request, Svr3Credentials::class)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.whispersystems.signalservice.api.account.AccountAttributes;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyUpload;
|
||||
import org.whispersystems.signalservice.api.crypto.SealedSenderAccess;
|
||||
import org.whispersystems.signalservice.api.groupsv2.CredentialResponse;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
|
||||
@@ -51,7 +50,6 @@ import org.whispersystems.signalservice.api.messages.calls.CallingResponse;
|
||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
@@ -218,7 +216,6 @@ public class PushServiceSocket {
|
||||
private static final String STICKER_MANIFEST_PATH = "stickers/%s/manifest.proto";
|
||||
private static final String STICKER_PATH = "stickers/%s/full/%d";
|
||||
|
||||
private static final String GROUPSV2_CREDENTIAL = "/v1/certificate/auth/group?redemptionStartSeconds=%d&redemptionEndSeconds=%d";
|
||||
private static final String GROUPSV2_GROUP = "/v2/groups/";
|
||||
private static final String GROUPSV2_GROUP_PASSWORD = "/v2/groups/?inviteLinkPassword=%s";
|
||||
private static final String GROUPSV2_GROUP_CHANGES = "/v2/groups/logs/%s?maxSupportedChangeEpoch=%d&includeFirstState=%s&includeLastState=false";
|
||||
@@ -251,9 +248,6 @@ public class PushServiceSocket {
|
||||
|
||||
private static final String REGISTRATION_PATH = "/v1/registration";
|
||||
|
||||
private static final String SVR2_AUTH = "/v2/backup/auth";
|
||||
private static final String SVR3_AUTH = "/v3/backup/auth";
|
||||
|
||||
private static final String BACKUP_AUTH_CHECK_V2 = "/v2/backup/auth/check";
|
||||
private static final String BACKUP_AUTH_CHECK_V3 = "/v3/backup/auth/check";
|
||||
|
||||
@@ -416,18 +410,6 @@ public class PushServiceSocket {
|
||||
return JsonUtil.fromJson(response, VerifyAccountResponse.class);
|
||||
}
|
||||
|
||||
public AuthCredentials getSvr2Authorization() throws IOException {
|
||||
String body = makeServiceRequest(SVR2_AUTH, "GET", null);
|
||||
AuthCredentials credentials = JsonUtil.fromJsonResponse(body, AuthCredentials.class);
|
||||
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public Svr3Credentials getSvr3Authorization() throws IOException {
|
||||
String body = makeServiceRequest(SVR3_AUTH, "GET", null);
|
||||
return JsonUtil.fromJsonResponse(body, Svr3Credentials.class);
|
||||
}
|
||||
|
||||
public void setRestoreMethodChosen(@Nonnull String token, @Nonnull RestoreMethodBody request) throws IOException {
|
||||
String body = JsonUtil.toJson(request);
|
||||
makeServiceRequest(String.format(Locale.US, SET_RESTORE_METHOD_PATH, urlEncode(token)), "PUT", body, NO_HEADERS, UNOPINIONATED_HANDLER, SealedSenderAccess.NONE);
|
||||
@@ -2314,20 +2296,6 @@ public class PushServiceSocket {
|
||||
}
|
||||
}
|
||||
|
||||
public CredentialResponse retrieveGroupsV2Credentials(long todaySeconds)
|
||||
throws IOException
|
||||
{
|
||||
long todayPlus7 = todaySeconds + TimeUnit.DAYS.toSeconds(7);
|
||||
String response = makeServiceRequest(String.format(Locale.US, GROUPSV2_CREDENTIAL, todaySeconds, todayPlus7),
|
||||
"GET",
|
||||
null,
|
||||
NO_HEADERS,
|
||||
NO_HANDLER,
|
||||
SealedSenderAccess.NONE);
|
||||
|
||||
return JsonUtil.fromJson(response, CredentialResponse.class);
|
||||
}
|
||||
|
||||
private static final ResponseCodeHandler GROUPS_V2_PUT_RESPONSE_HANDLER = (responseCode, body, getHeader) -> {
|
||||
if (getHeader.apply("X-Signal-Timestamp") == null) {
|
||||
throw new NonSuccessfulResponseCodeException(500, "Missing timestamp header");
|
||||
|
||||
Reference in New Issue
Block a user