merge GroupController into CertificateController

This commit is contained in:
Ehren Kret
2022-07-01 13:04:24 -05:00
parent a25e967978
commit 0fdfdabf2a
6 changed files with 181 additions and 240 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}
}