mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-19 15:08:04 +01:00
merge GroupController into CertificateController
This commit is contained in:
@@ -86,7 +86,6 @@ import org.whispersystems.textsecuregcm.controllers.DeviceController;
|
||||
import org.whispersystems.textsecuregcm.controllers.DirectoryController;
|
||||
import org.whispersystems.textsecuregcm.controllers.DirectoryV2Controller;
|
||||
import org.whispersystems.textsecuregcm.controllers.DonationController;
|
||||
import org.whispersystems.textsecuregcm.controllers.GroupController;
|
||||
import org.whispersystems.textsecuregcm.controllers.KeepAliveController;
|
||||
import org.whispersystems.textsecuregcm.controllers.KeysController;
|
||||
import org.whispersystems.textsecuregcm.controllers.MessageController;
|
||||
@@ -625,14 +624,13 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
new AttachmentControllerV1(rateLimiters, config.getAwsAttachmentsConfiguration().getAccessKey(), config.getAwsAttachmentsConfiguration().getAccessSecret(), config.getAwsAttachmentsConfiguration().getBucket()),
|
||||
new AttachmentControllerV2(rateLimiters, config.getAwsAttachmentsConfiguration().getAccessKey(), config.getAwsAttachmentsConfiguration().getAccessSecret(), config.getAwsAttachmentsConfiguration().getRegion(), config.getAwsAttachmentsConfiguration().getBucket()),
|
||||
new AttachmentControllerV3(rateLimiters, config.getGcpAttachmentsConfiguration().getDomain(), config.getGcpAttachmentsConfiguration().getEmail(), config.getGcpAttachmentsConfiguration().getMaxSizeInBytes(), config.getGcpAttachmentsConfiguration().getPathPrefix(), config.getGcpAttachmentsConfiguration().getRsaSigningKey()),
|
||||
new CertificateController(new CertificateGenerator(config.getDeliveryCertificate().getCertificate(), config.getDeliveryCertificate().getPrivateKey(), config.getDeliveryCertificate().getExpiresDays()), zkAuthOperations),
|
||||
new CertificateController(new CertificateGenerator(config.getDeliveryCertificate().getCertificate(), config.getDeliveryCertificate().getPrivateKey(), config.getDeliveryCertificate().getExpiresDays()), zkAuthOperations, clock),
|
||||
new ChallengeController(rateLimitChallengeManager),
|
||||
new DeviceController(pendingDevicesManager, accountsManager, messagesManager, keys, rateLimiters, config.getMaxDevices()),
|
||||
new DirectoryController(directoryCredentialsGenerator),
|
||||
new DirectoryV2Controller(directoryV2CredentialsGenerator),
|
||||
new DonationController(clock, zkReceiptOperations, redeemedReceiptsManager, accountsManager, config.getBadges(),
|
||||
ReceiptCredentialPresentation::new, stripeExecutor, config.getDonationConfiguration(), config.getStripe()),
|
||||
new GroupController(zkAuthOperations),
|
||||
new MessageController(rateLimiters, messageSender, receiptSender, accountsManager, deletedAccountsManager,
|
||||
messagesManager, apnFallbackManager, reportMessageManager, multiRecipientMessageExecutor),
|
||||
new PaymentsController(currencyManager, paymentsCredentialsGenerator),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 Signal Messenger, LLC
|
||||
* Copyright 2013-2022 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
@@ -8,13 +8,22 @@ package org.whispersystems.textsecuregcm.controllers;
|
||||
import static com.codahale.metrics.MetricRegistry.name;
|
||||
|
||||
import com.codahale.metrics.annotation.Timed;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.ws.rs.BadRequestException;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
@@ -34,15 +43,22 @@ import org.whispersystems.textsecuregcm.util.Util;
|
||||
@Path("/v1/certificate")
|
||||
public class CertificateController {
|
||||
|
||||
private final CertificateGenerator certificateGenerator;
|
||||
private final CertificateGenerator certificateGenerator;
|
||||
private final ServerZkAuthOperations serverZkAuthOperations;
|
||||
private final Clock clock;
|
||||
|
||||
@VisibleForTesting
|
||||
public static final Duration MAX_REDEMPTION_DURATION = Duration.ofDays(7);
|
||||
private static final String GENERATE_DELIVERY_CERTIFICATE_COUNTER_NAME = name(CertificateGenerator.class, "generateCertificate");
|
||||
private static final String INCLUDE_E164_TAG_NAME = "includeE164";
|
||||
|
||||
public CertificateController(CertificateGenerator certificateGenerator, ServerZkAuthOperations serverZkAuthOperations) {
|
||||
this.certificateGenerator = certificateGenerator;
|
||||
this.serverZkAuthOperations = serverZkAuthOperations;
|
||||
public CertificateController(
|
||||
@Nonnull CertificateGenerator certificateGenerator,
|
||||
@Nonnull ServerZkAuthOperations serverZkAuthOperations,
|
||||
@Nonnull Clock clock) {
|
||||
this.certificateGenerator = Objects.requireNonNull(certificateGenerator);
|
||||
this.serverZkAuthOperations = Objects.requireNonNull(serverZkAuthOperations);
|
||||
this.clock = Objects.requireNonNull(clock);
|
||||
}
|
||||
|
||||
@Timed
|
||||
@@ -76,10 +92,11 @@ public class CertificateController {
|
||||
if (startRedemptionTime > endRedemptionTime) {
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST);
|
||||
}
|
||||
if (endRedemptionTime > Util.currentDaysSinceEpoch() + 7) {
|
||||
final int currentDaysSinceEpoch = Util.currentDaysSinceEpoch(clock);
|
||||
if (endRedemptionTime > currentDaysSinceEpoch + 7) {
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST);
|
||||
}
|
||||
if (startRedemptionTime < Util.currentDaysSinceEpoch()) {
|
||||
if (startRedemptionTime < currentDaysSinceEpoch) {
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@@ -98,4 +115,42 @@ public class CertificateController {
|
||||
return new GroupCredentials(credentials);
|
||||
}
|
||||
|
||||
@Timed
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/auth/group")
|
||||
public GroupCredentials getGroupAuthenticationCredentials(
|
||||
@Auth AuthenticatedAccount auth,
|
||||
@QueryParam("redemptionStartSeconds") int startSeconds,
|
||||
@QueryParam("redemptionEndSeconds") int endSeconds) {
|
||||
|
||||
final Instant startOfDay = clock.instant().truncatedTo(ChronoUnit.DAYS);
|
||||
final Instant redemptionStart = Instant.ofEpochSecond(startSeconds);
|
||||
final Instant redemptionEnd = Instant.ofEpochSecond(endSeconds);
|
||||
|
||||
if (redemptionStart.isAfter(redemptionEnd) ||
|
||||
redemptionStart.isBefore(startOfDay) ||
|
||||
redemptionEnd.isAfter(startOfDay.plus(MAX_REDEMPTION_DURATION)) ||
|
||||
!redemptionStart.equals(redemptionStart.truncatedTo(ChronoUnit.DAYS)) ||
|
||||
!redemptionEnd.equals(redemptionEnd.truncatedTo(ChronoUnit.DAYS))) {
|
||||
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
final List<GroupCredentials.GroupCredential> credentials = new ArrayList<>();
|
||||
|
||||
Instant redemption = redemptionStart;
|
||||
|
||||
UUID aci = auth.getAccount().getUuid();
|
||||
UUID pni = auth.getAccount().getPhoneNumberIdentifier();
|
||||
while (!redemption.isAfter(redemptionEnd)) {
|
||||
credentials.add(new GroupCredentials.GroupCredential(
|
||||
serverZkAuthOperations.issueAuthCredentialWithPni(aci, pni, redemption).serialize(),
|
||||
(int) redemption.getEpochSecond()));
|
||||
|
||||
redemption = redemption.plus(Duration.ofDays(1));
|
||||
}
|
||||
|
||||
return new GroupCredentials(credentials);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.controllers;
|
||||
|
||||
import com.codahale.metrics.annotation.Timed;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.dropwizard.auth.Auth;
|
||||
import javax.ws.rs.BadRequestException;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import org.signal.libsignal.zkgroup.auth.ServerZkAuthOperations;
|
||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
||||
import org.whispersystems.textsecuregcm.entities.GroupCredentials;
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Path("/v1/group")
|
||||
public class GroupController {
|
||||
|
||||
private final ServerZkAuthOperations serverZkAuthOperations;
|
||||
private final Clock clock;
|
||||
|
||||
@VisibleForTesting
|
||||
static final Duration MAX_REDEMPTION_DURATION = Duration.ofDays(7);
|
||||
|
||||
public GroupController(final ServerZkAuthOperations serverZkAuthOperations) {
|
||||
this(serverZkAuthOperations, Clock.systemUTC());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
GroupController(final ServerZkAuthOperations serverZkAuthOperations, final Clock clock) {
|
||||
this.serverZkAuthOperations = serverZkAuthOperations;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Timed
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/auth")
|
||||
public GroupCredentials getGroupAuthenticationCredentials(@Auth AuthenticatedAccount auth,
|
||||
@QueryParam("redemptionStartSeconds") int startSeconds,
|
||||
@QueryParam("redemptionEndSeconds") int endSeconds) {
|
||||
|
||||
final Instant startOfDay = clock.instant().truncatedTo(ChronoUnit.DAYS);
|
||||
final Instant redemptionStart = Instant.ofEpochSecond(startSeconds);
|
||||
final Instant redemptionEnd = Instant.ofEpochSecond(endSeconds);
|
||||
|
||||
if (redemptionStart.isAfter(redemptionEnd) ||
|
||||
redemptionStart.isBefore(startOfDay) ||
|
||||
redemptionEnd.isAfter(startOfDay.plus(MAX_REDEMPTION_DURATION)) ||
|
||||
!redemptionStart.equals(redemptionStart.truncatedTo(ChronoUnit.DAYS)) ||
|
||||
!redemptionEnd.equals(redemptionEnd.truncatedTo(ChronoUnit.DAYS))) {
|
||||
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
final List<GroupCredentials.GroupCredential> credentials = new ArrayList<>();
|
||||
|
||||
Instant redemption = redemptionStart;
|
||||
|
||||
while (!redemption.isAfter(redemptionEnd)) {
|
||||
credentials.add(new GroupCredentials.GroupCredential(serverZkAuthOperations.issueAuthCredentialWithPni(
|
||||
auth.getAccount().getUuid(),
|
||||
auth.getAccount().getPhoneNumberIdentifier(),
|
||||
redemption).serialize(),
|
||||
(int) redemption.getEpochSecond()));
|
||||
|
||||
redemption = redemption.plus(Duration.ofDays(1));
|
||||
}
|
||||
|
||||
return new GroupCredentials(credentials);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class Util {
|
||||
|
||||
@@ -166,8 +167,18 @@ public class Util {
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
public static int currentDaysSinceEpoch(@Nonnull Clock clock) {
|
||||
return toIntExact(clock.millis() / 1000 / 60/ 60 / 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of days since the epoch.
|
||||
*
|
||||
* @deprecated use {@link #currentDaysSinceEpoch(Clock)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static int currentDaysSinceEpoch() {
|
||||
return Util.toIntExact(System.currentTimeMillis() / 1000 / 60 / 60 / 24);
|
||||
return currentDaysSinceEpoch(Clock.systemUTC());
|
||||
}
|
||||
|
||||
public static void sleep(long i) {
|
||||
|
||||
Reference in New Issue
Block a user