From c91d5c2fdb7fdfc308df94a6a28dd3f1a5d23327 Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Mon, 18 Oct 2021 15:14:36 -0400 Subject: [PATCH] Count reported messages per sender --- .../WhisperServerConfiguration.java | 10 +++++ .../textsecuregcm/WhisperServerService.java | 4 +- .../ReportMessageConfiguration.java | 29 +++++++++++++ .../storage/ReportMessageDynamoDb.java | 8 ++-- .../storage/ReportMessageManager.java | 42 ++++++++++++++++++- .../workers/DeleteUserCommand.java | 9 ++-- .../SetUserDiscoverabilityCommand.java | 9 ++-- .../storage/ReportMessageDynamoDbTest.java | 3 +- .../storage/ReportMessageManagerTest.java | 9 ++-- 9 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/configuration/ReportMessageConfiguration.java diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index 2e347b1c1..15551c5be 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -43,6 +43,7 @@ import org.whispersystems.textsecuregcm.configuration.RecaptchaV2Configuration; import org.whispersystems.textsecuregcm.configuration.RedisClusterConfiguration; import org.whispersystems.textsecuregcm.configuration.RedisConfiguration; import org.whispersystems.textsecuregcm.configuration.RemoteConfigConfiguration; +import org.whispersystems.textsecuregcm.configuration.ReportMessageConfiguration; import org.whispersystems.textsecuregcm.configuration.SecureBackupServiceConfiguration; import org.whispersystems.textsecuregcm.configuration.SecureStorageServiceConfiguration; import org.whispersystems.textsecuregcm.configuration.StripeConfiguration; @@ -318,6 +319,11 @@ public class WhisperServerConfiguration extends Configuration { // TODO: Mark as @NotNull when enabled for production. private SubscriptionConfiguration subscription; + @Valid + @NotNull + @JsonProperty + private ReportMessageConfiguration reportMessage; + private Map transparentDataIndex = new HashMap<>(); public StripeConfiguration getStripe() { @@ -545,4 +551,8 @@ public class WhisperServerConfiguration extends Configuration { public SubscriptionConfiguration getSubscription() { return subscription; } + + public ReportMessageConfiguration getReportMessageConfiguration() { + return reportMessage; + } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index f5e16ef2f..f6435370d 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -364,7 +364,7 @@ public class WhisperServerService extends Application { + final String reportedSenderKey = getReportedSenderKey(sourceNumber); + + connection.sync().pfadd(reportedSenderKey, sourceNumber); + connection.sync().expire(reportedSenderKey, counterTtl.toSeconds()); + }); + Counter.builder(REPORT_COUNTER_NAME) .tag("countryCode", Util.getCountryCode(sourceNumber)) .register(meterRegistry) @@ -54,6 +73,23 @@ public class ReportMessageManager { } } + /** + * Returns the number of times messages from the given number have been reported by recipients as abusive. Note that + * this method makes a call to an external service, and callers should take care to memoize calls where possible and + * avoid unnecessary calls. + * + * @param number the number to check for recent reports + * + * @return the number of times the given number has been reported recently + */ + public int getRecentReportCount(final String number) { + try { + return rateLimitCluster.withCluster(connection -> connection.sync().pfcount(getReportedSenderKey(number)).intValue()); + } catch (final RedisException e) { + return 0; + } + } + private byte[] hash(UUID messageGuid, String otherId) { final MessageDigest sha256; try { @@ -67,4 +103,8 @@ public class ReportMessageManager { return sha256.digest(); } + + private static String getReportedSenderKey(final String senderNumber) { + return "reported_number::" + senderNumber; + } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java b/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java index 9ed44128d..7b36f93ae 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/workers/DeleteUserCommand.java @@ -172,6 +172,8 @@ public class DeleteUserCommand extends EnvironmentCommand reportMessageManager.store(null, messageGuid)); + assertDoesNotThrow(() -> reportMessageManager.store(null, messageGuid)); verifyZeroInteractions(reportMessageDynamoDb); @@ -37,7 +40,7 @@ class ReportMessageManagerTest { verify(reportMessageDynamoDb).store(any()); doThrow(RuntimeException.class) - .when(reportMessageDynamoDb).store(any()); + .when(reportMessageDynamoDb).store(any()); assertDoesNotThrow(() -> reportMessageManager.store(number, messageGuid)); }