Retire REST-based message deletion

This commit is contained in:
Jon Chambers
2025-11-26 09:34:55 -05:00
committed by Jon Chambers
parent 92e133b21f
commit 7604306818
4 changed files with 13 additions and 138 deletions

View File

@@ -4,8 +4,8 @@
*/
package org.whispersystems.textsecuregcm;
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
import static java.util.Objects.requireNonNull;
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
import com.google.common.collect.Lists;
import com.webauthn4j.appattest.DeviceCheckManager;
@@ -1085,7 +1085,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
ReceiptCredentialPresentation::new),
new KeysController(rateLimiters, keysManager, accountsManager, zkSecretParams, Clock.systemUTC()),
new KeyTransparencyController(keyTransparencyServiceClient),
new MessageController(rateLimiters, messageByteLimitCardinalityEstimator, messageSender, receiptSender,
new MessageController(rateLimiters, messageByteLimitCardinalityEstimator, messageSender,
accountsManager, messagesManager, phoneNumberIdentifiers, pushNotificationManager, pushNotificationScheduler,
reportMessageManager, messageDeliveryScheduler, clientReleaseManager,
zkSecretParams, spamChecker, messageMetrics, messageDeliveryLoopMonitor,

View File

@@ -21,7 +21,6 @@ import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
@@ -74,7 +73,6 @@ import org.whispersystems.textsecuregcm.entities.AccountStaleDevices;
import org.whispersystems.textsecuregcm.entities.IncomingMessage;
import org.whispersystems.textsecuregcm.entities.IncomingMessageList;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type;
import org.whispersystems.textsecuregcm.entities.MismatchedDevicesResponse;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntityList;
@@ -97,7 +95,6 @@ import org.whispersystems.textsecuregcm.push.MessageTooLargeException;
import org.whispersystems.textsecuregcm.push.MessageUtil;
import org.whispersystems.textsecuregcm.push.PushNotificationManager;
import org.whispersystems.textsecuregcm.push.PushNotificationScheduler;
import org.whispersystems.textsecuregcm.push.ReceiptSender;
import org.whispersystems.textsecuregcm.spam.MessageType;
import org.whispersystems.textsecuregcm.spam.SpamCheckResult;
import org.whispersystems.textsecuregcm.spam.SpamChecker;
@@ -123,7 +120,6 @@ public class MessageController {
private final RateLimiters rateLimiters;
private final CardinalityEstimator messageByteLimitEstimator;
private final MessageSender messageSender;
private final ReceiptSender receiptSender;
private final AccountsManager accountsManager;
private final MessagesManager messagesManager;
private final PhoneNumberIdentifiers phoneNumberIdentifiers;
@@ -177,7 +173,6 @@ public class MessageController {
RateLimiters rateLimiters,
CardinalityEstimator messageByteLimitEstimator,
MessageSender messageSender,
ReceiptSender receiptSender,
AccountsManager accountsManager,
MessagesManager messagesManager,
PhoneNumberIdentifiers phoneNumberIdentifiers,
@@ -194,7 +189,6 @@ public class MessageController {
this.rateLimiters = rateLimiters;
this.messageByteLimitEstimator = messageByteLimitEstimator;
this.messageSender = messageSender;
this.receiptSender = receiptSender;
this.accountsManager = accountsManager;
this.messagesManager = messagesManager;
this.phoneNumberIdentifiers = phoneNumberIdentifiers;
@@ -843,37 +837,6 @@ public class MessageController {
return size;
}
@DELETE
@Path("/uuid/{uuid}")
public CompletableFuture<Response> removePendingMessage(@Auth AuthenticatedDevice auth, @PathParam("uuid") UUID uuid) {
final Account account = accountsManager.getByAccountIdentifier(auth.accountIdentifier())
.orElseThrow(() -> new WebApplicationException(Status.UNAUTHORIZED));
final Device device = account.getDevice(auth.deviceId())
.orElseThrow(() -> new WebApplicationException(Status.UNAUTHORIZED));
return messagesManager.delete(auth.accountIdentifier(), device, uuid, null)
.thenAccept(maybeRemovedMessage -> maybeRemovedMessage.ifPresent(removedMessage -> {
if (removedMessage.sourceServiceId().isPresent()
&& removedMessage.envelopeType() != Type.SERVER_DELIVERY_RECEIPT) {
if (removedMessage.sourceServiceId().get() instanceof AciServiceIdentifier aciServiceIdentifier) {
try {
receiptSender.sendReceipt(removedMessage.destinationServiceId(), auth.deviceId(),
aciServiceIdentifier, removedMessage.clientTimestamp());
} catch (Exception e) {
logger.warn("Failed to send delivery receipt", e);
}
} else {
// If source service ID is present and the envelope type is not a server delivery receipt, then
// the source service ID *should always* be an ACI -- PNIs are receive-only, so they can only be the
// "source" via server delivery receipts
logger.warn("Source service ID unexpectedly a PNI service ID");
}
}
}))
.thenApply(Util.ASYNC_EMPTY_RESPONSE);
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/report/{source}/{messageGuid}")

View File

@@ -253,26 +253,17 @@ public class MessagesManager {
return messagesCache.clear(destinationUuid, deviceId);
}
public CompletableFuture<Optional<RemovedMessage>> delete(UUID destinationUuid, Device destinationDevice, UUID guid,
@Nullable Long serverTimestamp) {
public CompletableFuture<Optional<RemovedMessage>> delete(final UUID destinationUuid,
final Device destinationDevice,
final UUID guid,
final long serverTimestamp) {
return messagesCache.remove(destinationUuid, destinationDevice.getId(), guid)
.thenComposeAsync(removed -> {
if (removed.isPresent()) {
return CompletableFuture.completedFuture(removed);
}
final CompletableFuture<Optional<MessageProtos.Envelope>> maybeDeletedEnvelope;
if (serverTimestamp == null) {
maybeDeletedEnvelope = messagesDynamoDb.deleteMessageByDestinationAndGuid(destinationUuid,
destinationDevice, guid);
} else {
maybeDeletedEnvelope = messagesDynamoDb.deleteMessage(destinationUuid, destinationDevice, guid,
serverTimestamp);
}
return maybeDeletedEnvelope.thenApply(maybeEnvelope -> maybeEnvelope.map(RemovedMessage::fromEnvelope));
}, messageDeletionExecutor);
.thenComposeAsync(removed -> removed
.map(_ -> CompletableFuture.completedFuture(removed))
.orElseGet(() -> messagesDynamoDb.deleteMessage(destinationUuid, destinationDevice, guid, serverTimestamp)
.thenApply(maybeEnvelope -> maybeEnvelope.map(RemovedMessage::fromEnvelope))
), messageDeletionExecutor);
}
/**