mirror of
https://github.com/signalapp/Signal-Server
synced 2026-10-06 17:38:04 +01:00
Add a metric for duplicate receipt redemption
This commit is contained in:
1 parent
4f4bd431f5
commit
b30fc7aa8b
4 files changed
+26
-6
No files matched your search
+2
-1
@@ -756,7 +756,8 @@ public class SubscriptionController {
|
||||
try {
|
||||
final SubscriptionManager.ReceiptResult receiptCredential = subscriptionManager.createReceiptCredentials(
|
||||
subscriberCredentials, request.receiptCredentialRequest(),
|
||||
r -> SubscriptionsUtil.receiptExpirationWithGracePeriod(subscriptionConfiguration, r));
|
||||
r -> SubscriptionsUtil.receiptExpirationWithGracePeriod(subscriptionConfiguration, r),
|
||||
userAgent);
|
||||
|
||||
final ReceiptCredentialResponse receiptCredentialResponse = receiptCredential.receiptCredentialResponse();
|
||||
final CustomerAwareSubscriptionPaymentProcessor.ReceiptItem receipt = receiptCredential.receiptItem();
|
||||
|
||||
+2
-1
@@ -441,7 +441,8 @@ public class SubscriptionsGrpcService extends SimpleSubscriptionsGrpc.Subscripti
|
||||
try {
|
||||
final SubscriptionManager.ReceiptResult result = subscriptionManager.createReceiptCredentials(
|
||||
subscriberCredentials, request.getReceiptCredentialRequest().toByteArray(),
|
||||
r -> SubscriptionsUtil.receiptExpirationWithGracePeriod(subscriptionConfiguration, r));
|
||||
r -> SubscriptionsUtil.receiptExpirationWithGracePeriod(subscriptionConfiguration, r),
|
||||
RequestAttributesUtil.getUserAgent().orElse(null));
|
||||
Metrics.counter(RECEIPT_ISSUED_COUNTER_NAME,
|
||||
Tags.of(
|
||||
Tag.of(PROCESSOR_TAG_NAME, result.paymentProvider().toString()),
|
||||
|
||||
+19
-1
@@ -4,6 +4,9 @@
|
||||
*/
|
||||
package org.whispersystems.textsecuregcm.storage;
|
||||
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.time.Instant;
|
||||
@@ -15,17 +18,21 @@ import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.VerificationFailedException;
|
||||
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequest;
|
||||
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialResponse;
|
||||
import org.signal.libsignal.zkgroup.receipts.ServerZkReceiptOperations;
|
||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||
import org.whispersystems.textsecuregcm.metrics.MetricsUtil;
|
||||
import org.whispersystems.textsecuregcm.metrics.UserAgentTagUtil;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.AppleAppStoreManager;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.CustomerAwareSubscriptionPaymentProcessor;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.GooglePlayBillingManager;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.PaymentProvider;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.ProcessorCustomer;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.ReceiptLevel;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.SubscriberIdCreationNotPermittedException;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.SubscriptionForbiddenException;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.SubscriptionInformation;
|
||||
@@ -53,6 +60,9 @@ import org.whispersystems.textsecuregcm.util.ua.ClientPlatform;
|
||||
*/
|
||||
public class SubscriptionManager {
|
||||
|
||||
private static final String RECEIPT_ALREADY_REDEEMED_COUNTER_NAME = MetricsUtil.name(SubscriptionManager.class,
|
||||
"receiptAlreadyRedeemed");
|
||||
|
||||
private final Subscriptions subscriptions;
|
||||
private final EnumMap<PaymentProvider, SubscriptionPaymentProcessor> processors;
|
||||
private final ServerZkReceiptOperations zkReceiptOperations;
|
||||
@@ -177,6 +187,7 @@ public class SubscriptionManager {
|
||||
* @param expiration A function that takes a
|
||||
* {@link CustomerAwareSubscriptionPaymentProcessor.ReceiptItem} and returns the
|
||||
* expiration time of the receipt
|
||||
* @param userAgent The requesting client's user agent
|
||||
* @return the requested ZK receipt credential
|
||||
* @throws SubscriptionForbiddenException if the subscriber credentials were incorrect
|
||||
* @throws SubscriptionNotFoundException if the subscriber did not exist or did not have a
|
||||
@@ -193,7 +204,8 @@ public class SubscriptionManager {
|
||||
public ReceiptResult createReceiptCredentials(
|
||||
final SubscriberCredentials subscriberCredentials,
|
||||
final byte[] receiptCredentialRequestBytes,
|
||||
final Function<CustomerAwareSubscriptionPaymentProcessor.ReceiptItem, Instant> expiration)
|
||||
final Function<CustomerAwareSubscriptionPaymentProcessor.ReceiptItem, Instant> expiration,
|
||||
@Nullable final String userAgent)
|
||||
throws SubscriptionForbiddenException, SubscriptionNotFoundException, SubscriptionInvalidArgumentsException, SubscriptionPaymentRequiredException, RateLimitExceededException, SubscriptionReceiptRequestedForOpenPaymentException, SubscriptionReceiptAlreadyRedeemedException {
|
||||
final Subscriptions.Record record = getSubscriber(subscriberCredentials);
|
||||
if (record.subscriptionId == null) {
|
||||
@@ -222,6 +234,12 @@ public class SubscriptionManager {
|
||||
} catch (final VerificationFailedException e) {
|
||||
throw new SubscriptionInvalidArgumentsException("receipt credential request failed verification", e);
|
||||
} catch (final WriteConflictException _) {
|
||||
Metrics.counter(RECEIPT_ALREADY_REDEEMED_COUNTER_NAME, Tags.of(
|
||||
Tag.of("receiptLevel", ReceiptLevel.lookupLevel(receipt.level())
|
||||
.map(ReceiptLevel::name)
|
||||
.orElse("n/a")),
|
||||
UserAgentTagUtil.getPlatformTag(userAgent)))
|
||||
.increment();
|
||||
throw new SubscriptionReceiptAlreadyRedeemedException();
|
||||
}
|
||||
return new ReceiptResult(receiptCredentialResponse, receipt, processor);
|
||||
|
||||
+3
-3
@@ -576,7 +576,7 @@ public class SubscriptionsGrpcServiceTest extends
|
||||
final ReceiptCredentialResponse receiptCredentialResponse = mock(ReceiptCredentialResponse.class);
|
||||
final byte[] responseBytes = TestRandomUtil.nextBytes(16);
|
||||
when(receiptCredentialResponse.serialize()).thenReturn(responseBytes);
|
||||
when(subscriptionManager.createReceiptCredentials(any(), any(), any()))
|
||||
when(subscriptionManager.createReceiptCredentials(any(), any(), any(), any()))
|
||||
.thenReturn(new SubscriptionManager.ReceiptResult(receiptCredentialResponse, new SubscriptionPaymentProcessor.ReceiptItem("test-item-id", null, 5), PaymentProvider.STRIPE));
|
||||
final GetReceiptCredentialsResponse response = unauthenticatedServiceStub().getReceiptCredentials(
|
||||
GetReceiptCredentialsRequest.newBuilder()
|
||||
@@ -602,7 +602,7 @@ public class SubscriptionsGrpcServiceTest extends
|
||||
@MethodSource
|
||||
void getReceiptCredentialsExceptions(final SubscriptionException exception,
|
||||
final GetReceiptCredentialsResponse.ResponseCase expectedCase) throws Exception {
|
||||
doThrow(exception).when(subscriptionManager).createReceiptCredentials(any(), any(), any());
|
||||
doThrow(exception).when(subscriptionManager).createReceiptCredentials(any(), any(), any(), any());
|
||||
final GetReceiptCredentialsResponse response = unauthenticatedServiceStub().getReceiptCredentials(
|
||||
GetReceiptCredentialsRequest.newBuilder()
|
||||
.setSubscriberId(SUBSCRIBER_ID)
|
||||
@@ -615,7 +615,7 @@ public class SubscriptionsGrpcServiceTest extends
|
||||
void getReceiptCredentialsChargeFailure() throws Exception {
|
||||
doThrow(new SubscriptionChargeFailurePaymentRequiredException(PaymentProvider.STRIPE,
|
||||
new ChargeFailure("card_declined", "Insufficient funds", null, null, null)))
|
||||
.when(subscriptionManager).createReceiptCredentials(any(), any(), any());
|
||||
.when(subscriptionManager).createReceiptCredentials(any(), any(), any(), any());
|
||||
final GetReceiptCredentialsResponse response = unauthenticatedServiceStub().getReceiptCredentials(
|
||||
GetReceiptCredentialsRequest.newBuilder()
|
||||
.setSubscriberId(SUBSCRIBER_ID)
|
||||
|
||||
Reference in new issue
Block a user