Start new style messsage api and convert report spam to WebSocket.

This commit is contained in:
Cody Henthorne
2025-03-12 12:52:04 -04:00
committed by Greyson Parrelli
parent f61109391a
commit d2006853c7
11 changed files with 75 additions and 24 deletions

View File

@@ -50,6 +50,7 @@ import org.whispersystems.signalservice.api.cds.CdsApi
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
import org.whispersystems.signalservice.api.keys.KeysApi
import org.whispersystems.signalservice.api.link.LinkDeviceApi
import org.whispersystems.signalservice.api.message.MessageApi
import org.whispersystems.signalservice.api.payments.PaymentsApi
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
import org.whispersystems.signalservice.api.registration.RegistrationApi
@@ -330,6 +331,9 @@ object AppDependencies {
val rateLimitChallengeApi: RateLimitChallengeApi
get() = networkModule.rateLimitChallengeApi
val messageApi: MessageApi
get() = networkModule.messageApi
@JvmStatic
val okHttpClient: OkHttpClient
get() = networkModule.okHttpClient
@@ -406,5 +410,6 @@ object AppDependencies {
fun providePaymentsApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): PaymentsApi
fun provideCdsApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): CdsApi
fun provideRateLimitChallengeApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): RateLimitChallengeApi
fun provideMessageApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): MessageApi
}
}

View File

@@ -89,6 +89,7 @@ import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.keys.KeysApi;
import org.whispersystems.signalservice.api.link.LinkDeviceApi;
import org.whispersystems.signalservice.api.message.MessageApi;
import org.whispersystems.signalservice.api.payments.PaymentsApi;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
@@ -522,6 +523,11 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
return new RateLimitChallengeApi(authWebSocket);
}
@Override
public @NonNull MessageApi provideMessageApi(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket, @NonNull SignalWebSocket.UnauthenticatedWebSocket unauthWebSocket) {
return new MessageApi(authWebSocket, unauthWebSocket);
}
@VisibleForTesting
static class DynamicCredentialsProvider implements CredentialsProvider {

View File

@@ -34,6 +34,7 @@ import org.whispersystems.signalservice.api.cds.CdsApi
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
import org.whispersystems.signalservice.api.keys.KeysApi
import org.whispersystems.signalservice.api.link.LinkDeviceApi
import org.whispersystems.signalservice.api.message.MessageApi
import org.whispersystems.signalservice.api.payments.PaymentsApi
import org.whispersystems.signalservice.api.push.TrustStore
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
@@ -182,6 +183,10 @@ class NetworkDependenciesModule(
provider.provideRateLimitChallengeApi(authWebSocket)
}
val messageApi: MessageApi by lazy {
provider.provideMessageApi(authWebSocket, unauthWebSocket)
}
val okHttpClient: OkHttpClient by lazy {
OkHttpClient.Builder()
.addInterceptor(StandardUserAgentInterceptor())

View File

@@ -3,18 +3,18 @@ package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.Base64;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.MessageTable.ReportSpamData;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.net.SignalNetwork;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.signal.core.util.Base64;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.NetworkResultUtil;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
@@ -92,8 +92,7 @@ public class ReportSpamJob extends BaseJob {
reportSpamData = SignalDatabase.messages().getReportSpamMessageServerData(threadId, timestamp, MAX_MESSAGE_COUNT);
}
int count = 0;
SignalServiceAccountManager signalServiceAccountManager = AppDependencies.getSignalServiceAccountManager();
int count = 0;
for (ReportSpamData data : reportSpamData) {
RecipientId recipientId = data.getRecipientId();
@@ -108,7 +107,7 @@ public class ReportSpamJob extends BaseJob {
reportingTokenEncoded = Base64.encodeWithPadding(reportingTokenBytes);
}
signalServiceAccountManager.reportSpam(serviceId.get(), data.getServerGuid(), reportingTokenEncoded);
NetworkResultUtil.toBasicLegacy(SignalNetwork.message().reportSpam(serviceId.get(), data.getServerGuid(), reportingTokenEncoded));
count++;
} else {
Log.w(TAG, "Unable to report spam without an ACI for " + recipientId);

View File

@@ -13,6 +13,7 @@ import org.whispersystems.signalservice.api.calling.CallingApi
import org.whispersystems.signalservice.api.cds.CdsApi
import org.whispersystems.signalservice.api.keys.KeysApi
import org.whispersystems.signalservice.api.link.LinkDeviceApi
import org.whispersystems.signalservice.api.message.MessageApi
import org.whispersystems.signalservice.api.payments.PaymentsApi
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
import org.whispersystems.signalservice.api.storage.StorageServiceApi
@@ -47,6 +48,11 @@ object SignalNetwork {
val linkDevice: LinkDeviceApi
get() = AppDependencies.linkDeviceApi
@JvmStatic
@get:JvmName("message")
val message: MessageApi
get() = AppDependencies.messageApi
@JvmStatic
@get:JvmName("payments")
val payments: PaymentsApi

View File

@@ -44,6 +44,7 @@ import org.whispersystems.signalservice.api.cds.CdsApi
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
import org.whispersystems.signalservice.api.keys.KeysApi
import org.whispersystems.signalservice.api.link.LinkDeviceApi
import org.whispersystems.signalservice.api.message.MessageApi
import org.whispersystems.signalservice.api.payments.PaymentsApi
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
import org.whispersystems.signalservice.api.registration.RegistrationApi
@@ -270,4 +271,8 @@ class MockApplicationDependencyProvider : AppDependencies.Provider {
override fun provideRateLimitChallengeApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): RateLimitChallengeApi {
return mockk(relaxed = true)
}
override fun provideMessageApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): MessageApi {
return mockk(relaxed = true)
}
}

View File

@@ -171,10 +171,6 @@ public class SignalServiceAccountManager {
this.pushServiceSocket.pingStorageService();
}
public void reportSpam(ServiceId serviceId, String serverGuid, String reportingToken) throws IOException {
this.pushServiceSocket.reportSpam(serviceId, serverGuid, reportingToken);
}
/**
* @return The avatar URL path, if one was written.
*/

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.api.message
import org.whispersystems.signalservice.api.NetworkResult
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
import org.whispersystems.signalservice.internal.post
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
/**
* Collection of endpoints for operating on messages.
*/
class MessageApi(
private val authWebSocket: SignalWebSocket.AuthenticatedWebSocket,
private val unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket
) {
/**
* Report a message sender and message id as spam.
*
* POST /v1/messages/report/[serviceId]/[serverGuid]
* - 200: Success
*/
fun reportSpam(serviceId: ServiceId, serverGuid: String, reportingToken: String?): NetworkResult<Unit> {
val request = WebSocketRequestMessage.post("/v1/messages/report/$serviceId/$serverGuid", SpamTokenMessage(reportingToken))
return NetworkResult.fromWebSocketRequest(authWebSocket, request)
}
}

View File

@@ -0,0 +1,10 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.signalservice.api.message
import com.fasterxml.jackson.annotation.JsonProperty
data class SpamTokenMessage(@JsonProperty val token: String?)

View File

@@ -253,8 +253,6 @@ public class PushServiceSocket {
private static final String SVR2_AUTH = "/v2/backup/auth";
private static final String SVR3_AUTH = "/v3/backup/auth";
private static final String REPORT_SPAM = "/v1/messages/report/%s/%s";
private static final String BACKUP_AUTH_CHECK_V2 = "/v2/backup/auth/check";
private static final String BACKUP_AUTH_CHECK_V3 = "/v3/backup/auth/check";
@@ -2521,12 +2519,6 @@ public class PushServiceSocket {
}
}
public void reportSpam(ServiceId serviceId, String serverGuid, String reportingToken)
throws NonSuccessfulResponseCodeException, MalformedResponseException, PushNetworkException
{
makeServiceRequest(String.format(REPORT_SPAM, serviceId.toString(), serverGuid), "POST", JsonUtil.toJson(new SpamTokenMessage(reportingToken)));
}
/**
* Handler for Google Play Billing purchase token linking
*/

View File

@@ -1,5 +0,0 @@
package org.whispersystems.signalservice.internal.push
import com.fasterxml.jackson.annotation.JsonProperty
data class SpamTokenMessage(@JsonProperty val token: String?)