update openapi docs for several endpoints, notably those with PQXDH changes
Co-authored-by: Katherine Yen <katherine@signal.org>
This commit is contained in:
parent
098b177bd3
commit
e5f4c17148
|
@ -83,6 +83,7 @@ public class AccountControllerV2 {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Change number", description = "Changes a phone number for an existing account.")
|
||||
@ApiResponse(responseCode = "200", description = "The phone number associated with the authenticated account was changed successfully", useReturnTypeSchema = true)
|
||||
@ApiResponse(responseCode = "401", description = "Account authentication check failed.")
|
||||
@ApiResponse(responseCode = "403", description = "Verification failed for the provided Registration Recovery Password")
|
||||
@ApiResponse(responseCode = "409", description = "Mismatched number of devices or device ids in 'devices to notify' list", content = @Content(schema = @Schema(implementation = MismatchedDevices.class)))
|
||||
@ApiResponse(responseCode = "410", description = "Mismatched registration ids in 'devices to notify' list", content = @Content(schema = @Schema(implementation = StaleDevices.class)))
|
||||
|
@ -159,7 +160,17 @@ public class AccountControllerV2 {
|
|||
@Path("/phone_number_identity_key_distribution")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Updates key material for the phone-number identity for all devices and sends a synchronization message to companion devices")
|
||||
@Operation(summary = "Set phone-number identity keys",
|
||||
description = "Updates key material for the phone-number identity for all devices and sends a synchronization message to companion devices")
|
||||
@ApiResponse(responseCode = "200", description = "Indicates the transaction was successful and returns basic information about this account.", useReturnTypeSchema = true)
|
||||
@ApiResponse(responseCode = "401", description = "Account authentication check failed.")
|
||||
@ApiResponse(responseCode = "403", description = "This endpoint can only be invoked from the account's primary device.")
|
||||
@ApiResponse(responseCode = "422", description = "The request body failed validation.")
|
||||
@ApiResponse(responseCode = "425", description = "Not all of this account's devices support phone-number identities yet.")
|
||||
@ApiResponse(responseCode = "409", description = "The set of devices specified in the request does not match the set of devices active on the account.",
|
||||
content = @Content(schema = @Schema(implementation = MismatchedDevices.class)))
|
||||
@ApiResponse(responseCode = "410", description = "The registration IDs provided for some devices do not match those stored on the server.",
|
||||
content = @Content(schema = @Schema(implementation = StaleDevices.class)))
|
||||
public AccountIdentityResponse distributePhoneNumberIdentityKeys(@Auth final AuthenticatedAccount authenticatedAccount,
|
||||
@NotNull @Valid final PhoneNumberIdentityKeyDistributionRequest request) {
|
||||
|
||||
|
|
|
@ -13,8 +13,10 @@ import io.micrometer.core.instrument.Metrics;
|
|||
import io.micrometer.core.instrument.Tags;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.headers.Header;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
@ -86,7 +88,10 @@ public class KeysController {
|
|||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Returns the number of available one-time prekeys for this device")
|
||||
@Operation(summary = "Get prekey count",
|
||||
description = "Gets the number of one-time prekeys uploaded for this device and still available")
|
||||
@ApiResponse(responseCode = "200", description = "Body contains the number of available one-time prekeys for the device.", useReturnTypeSchema = true)
|
||||
@ApiResponse(responseCode = "401", description = "Account authentication check failed.")
|
||||
public PreKeyCount getStatus(@Auth final AuthenticatedAccount auth,
|
||||
@QueryParam("identity") final Optional<String> identityType) {
|
||||
|
||||
|
@ -101,7 +106,15 @@ public class KeysController {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ChangesDeviceEnabledState
|
||||
@Operation(summary = "Sets the identity key for the account or phone-number identity and/or prekeys for this device")
|
||||
@Operation(summary = "Upload new prekeys",
|
||||
description = """
|
||||
Upload new prekeys for this device. Can also be used, from the primary device only, to set the account's identity
|
||||
key, but this is deprecated now that accounts can be created atomically.
|
||||
""")
|
||||
@ApiResponse(responseCode = "200", description = "Indicates that new keys were successfully stored.")
|
||||
@ApiResponse(responseCode = "401", description = "Account authentication check failed.")
|
||||
@ApiResponse(responseCode = "403", description = "Attempt to change identity key from a non-primary device.")
|
||||
@ApiResponse(responseCode = "422", description = "Invalid request format.")
|
||||
public void setKeys(@Auth final DisabledPermittedAuthenticatedAccount disabledPermittedAuth,
|
||||
@RequestBody @NotNull @Valid final PreKeyState preKeys,
|
||||
|
||||
|
@ -176,8 +189,15 @@ public class KeysController {
|
|||
@GET
|
||||
@Path("/{identifier}/{device_id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Retrieves the public identity key and available device prekeys for a specified account or phone-number identity")
|
||||
public Response getDeviceKeys(@Auth Optional<AuthenticatedAccount> auth,
|
||||
@Operation(summary = "Fetch public keys for another user",
|
||||
description = "Retrieves the public identity key and available device prekeys for a specified account or phone-number identity")
|
||||
@ApiResponse(responseCode = "200", description = "Indicates at least one prekey was available for at least one requested device.", useReturnTypeSchema = true)
|
||||
@ApiResponse(responseCode = "401", description = "Account authentication check failed and unidentified-access key was not supplied or invalid.")
|
||||
@ApiResponse(responseCode = "404", description = "Requested identity or device does not exist, is not active, or has no available prekeys.")
|
||||
@ApiResponse(responseCode = "429", description = "Rate limit exceeded.", headers = @Header(
|
||||
name = "Retry-After",
|
||||
description = "If present, a positive integer indicating the number of seconds before a subsequent attempt could succeed"))
|
||||
public PreKeyResponse getDeviceKeys(@Auth Optional<AuthenticatedAccount> auth,
|
||||
@HeaderParam(OptionalAccess.UNIDENTIFIED) Optional<Anonymous> accessKey,
|
||||
|
||||
@Parameter(description="the account or phone-number identifier to retrieve keys for")
|
||||
|
@ -241,9 +261,9 @@ public class KeysController {
|
|||
final IdentityKey identityKey = usePhoneNumberIdentity ? target.getPhoneNumberIdentityKey() : target.getIdentityKey();
|
||||
|
||||
if (responseItems.isEmpty()) {
|
||||
return Response.status(404).build();
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
return Response.ok().entity(new PreKeyResponse(identityKey, responseItems)).build();
|
||||
return new PreKeyResponse(identityKey, responseItems);
|
||||
}
|
||||
|
||||
@Timed
|
||||
|
@ -251,6 +271,13 @@ public class KeysController {
|
|||
@Path("/signed")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@ChangesDeviceEnabledState
|
||||
@Operation(summary = "Upload a new signed prekey",
|
||||
description = """
|
||||
Upload a new signed elliptic-curve prekey for this device. Deprecated; use PUT /v2/keys with instead.
|
||||
""")
|
||||
@ApiResponse(responseCode = "200", description = "Indicates that new prekey was successfully stored.")
|
||||
@ApiResponse(responseCode = "401", description = "Account authentication check failed.")
|
||||
@ApiResponse(responseCode = "422", description = "Invalid request format.")
|
||||
public void setSignedKey(@Auth final AuthenticatedAccount auth,
|
||||
@Valid final ECSignedPreKey signedPreKey,
|
||||
@QueryParam("identity") final Optional<String> identityType) {
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.whispersystems.textsecuregcm.entities;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -27,8 +28,8 @@ public record ChangeNumberRequest(
|
|||
Must not be combined with `recoveryPassword`.""")
|
||||
String sessionId,
|
||||
|
||||
@Schema(description="""
|
||||
The recovery password for the new phone number, if using a recovery password to authenticate this request.
|
||||
@Schema(type="string", description="""
|
||||
The base64-encoded recovery password for the new phone number, if using a recovery password to authenticate this request.
|
||||
Must not be combined with `sessionId`.""")
|
||||
@JsonDeserialize(using = ByteArrayAdapter.Deserializing.class) byte[] recoveryPassword,
|
||||
|
||||
|
@ -43,10 +44,11 @@ public record ChangeNumberRequest(
|
|||
@JsonDeserialize(using = IdentityKeyAdapter.Deserializer.class)
|
||||
@NotNull IdentityKey pniIdentityKey,
|
||||
|
||||
@Schema(description="""
|
||||
@ArraySchema(
|
||||
arraySchema=@Schema(description="""
|
||||
A list of synchronization messages to send to companion devices to supply the private keysManager
|
||||
associated with the new identity key and their new prekeys.
|
||||
Exactly one message must be supplied for each enabled device other than the sending (primary) device.""")
|
||||
Exactly one message must be supplied for each enabled device other than the sending (primary) device."""))
|
||||
@NotNull @Valid List<@NotNull @Valid IncomingMessage> deviceMessages,
|
||||
|
||||
@Schema(description="""
|
||||
|
|
|
@ -7,13 +7,23 @@ package org.whispersystems.textsecuregcm.entities;
|
|||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||
import org.whispersystems.textsecuregcm.util.ECPublicKeyAdapter;
|
||||
|
||||
public record ECPreKey(long keyId,
|
||||
@JsonSerialize(using = ECPublicKeyAdapter.Serializer.class)
|
||||
@JsonDeserialize(using = ECPublicKeyAdapter.Deserializer.class)
|
||||
ECPublicKey publicKey) implements PreKey<ECPublicKey> {
|
||||
public record ECPreKey(
|
||||
@Schema(description="""
|
||||
An arbitrary ID for this key, which will be provided by peers using this key to encrypt messages so the private key can be looked up.
|
||||
Should not be zero. Should be less than 2^24.
|
||||
""")
|
||||
long keyId,
|
||||
|
||||
@JsonSerialize(using = ECPublicKeyAdapter.Serializer.class)
|
||||
@JsonDeserialize(using = ECPublicKeyAdapter.Deserializer.class)
|
||||
@Schema(type="string", description="""
|
||||
The public key, serialized in libsignal's elliptic-curve public key format and then base64-encoded.
|
||||
""")
|
||||
ECPublicKey publicKey) implements PreKey<ECPublicKey> {
|
||||
|
||||
@Override
|
||||
public byte[] serializedPublicKey() {
|
||||
|
|
|
@ -7,21 +7,33 @@ package org.whispersystems.textsecuregcm.entities;
|
|||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
||||
import org.whispersystems.textsecuregcm.util.ECPublicKeyAdapter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public record ECSignedPreKey(long keyId,
|
||||
public record ECSignedPreKey(
|
||||
@Schema(description="""
|
||||
An arbitrary ID for this key, which will be provided by peers using this key to encrypt messages so the private key can be looked up.
|
||||
Should not be zero. Should be less than 2^24.
|
||||
""")
|
||||
long keyId,
|
||||
|
||||
@JsonSerialize(using = ECPublicKeyAdapter.Serializer.class)
|
||||
@JsonDeserialize(using = ECPublicKeyAdapter.Deserializer.class)
|
||||
ECPublicKey publicKey,
|
||||
@JsonSerialize(using = ECPublicKeyAdapter.Serializer.class)
|
||||
@JsonDeserialize(using = ECPublicKeyAdapter.Deserializer.class)
|
||||
@Schema(type="string", description="""
|
||||
The public key, serialized in libsignal's elliptic-curve public key format and then base64-encoded.
|
||||
""")
|
||||
ECPublicKey publicKey,
|
||||
|
||||
@JsonSerialize(using = ByteArrayAdapter.Serializing.class)
|
||||
@JsonDeserialize(using = ByteArrayAdapter.Deserializing.class)
|
||||
byte[] signature) implements SignedPreKey<ECPublicKey> {
|
||||
@JsonSerialize(using = ByteArrayAdapter.Serializing.class)
|
||||
@JsonDeserialize(using = ByteArrayAdapter.Deserializing.class)
|
||||
@Schema(type="string", description="""
|
||||
The signature of the serialized `publicKey` with the account (or phone-number identity)'s identity key, base64-encoded.
|
||||
""")
|
||||
byte[] signature) implements SignedPreKey<ECPublicKey> {
|
||||
|
||||
@Override
|
||||
public byte[] serializedPublicKey() {
|
||||
|
|
|
@ -7,21 +7,34 @@ package org.whispersystems.textsecuregcm.entities;
|
|||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.signal.libsignal.protocol.kem.KEMPublicKey;
|
||||
import org.whispersystems.textsecuregcm.util.ByteArrayAdapter;
|
||||
import org.whispersystems.textsecuregcm.util.KEMPublicKeyAdapter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public record KEMSignedPreKey(long keyId,
|
||||
public record KEMSignedPreKey(
|
||||
@Schema(description="""
|
||||
An arbitrary ID for this key, which will be provided by peers using this key to encrypt messages so the private key can be looked up.
|
||||
Should not be zero. Should be less than 2^24. The owner of this key must be able to determine from the key ID whether this represents
|
||||
a single-use or last-resort key, but another party should *not* be able to tell.
|
||||
""")
|
||||
long keyId,
|
||||
|
||||
@JsonSerialize(using = KEMPublicKeyAdapter.Serializer.class)
|
||||
@JsonDeserialize(using = KEMPublicKeyAdapter.Deserializer.class)
|
||||
KEMPublicKey publicKey,
|
||||
@JsonSerialize(using = KEMPublicKeyAdapter.Serializer.class)
|
||||
@JsonDeserialize(using = KEMPublicKeyAdapter.Deserializer.class)
|
||||
@Schema(type="string", description="""
|
||||
The public key, serialized in libsignal's Kyber1024 public key format and then base64-encoded.
|
||||
""")
|
||||
KEMPublicKey publicKey,
|
||||
|
||||
@JsonSerialize(using = ByteArrayAdapter.Serializing.class)
|
||||
@JsonDeserialize(using = ByteArrayAdapter.Deserializing.class)
|
||||
byte[] signature) implements SignedPreKey<KEMPublicKey> {
|
||||
@JsonSerialize(using = ByteArrayAdapter.Serializing.class)
|
||||
@JsonDeserialize(using = ByteArrayAdapter.Deserializing.class)
|
||||
@Schema(type="string", description="""
|
||||
The signature of the serialized `publicKey` with the account (or phone-number identity)'s identity key, base64-encoded.
|
||||
""")
|
||||
byte[] signature) implements SignedPreKey<KEMPublicKey> {
|
||||
|
||||
@Override
|
||||
public byte[] serializedPublicKey() {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.whispersystems.textsecuregcm.entities;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -24,10 +25,12 @@ public record PhoneNumberIdentityKeyDistributionRequest(
|
|||
|
||||
@NotNull
|
||||
@Valid
|
||||
@Schema(description="""
|
||||
A list of synchronization messages to send to companion devices to supply the private keysManager
|
||||
associated with the new identity key and their new prekeys.
|
||||
Exactly one message must be supplied for each enabled device other than the sending (primary) device.""")
|
||||
@ArraySchema(
|
||||
arraySchema=@Schema(description="""
|
||||
A list of synchronization messages to send to companion devices to supply the private keys
|
||||
associated with the new identity key and their new prekeys.
|
||||
Exactly one message must be supplied for each enabled device other than the sending (primary) device.
|
||||
"""))
|
||||
List<@NotNull @Valid IncomingMessage> deviceMessages,
|
||||
|
||||
@NotNull
|
||||
|
@ -47,7 +50,7 @@ public record PhoneNumberIdentityKeyDistributionRequest(
|
|||
|
||||
@NotNull
|
||||
@Valid
|
||||
@Schema(description="The new registration ID to use for the phone-number identity of each device")
|
||||
@Schema(description="The new registration ID to use for the phone-number identity of each device, including this one.")
|
||||
Map<Long, Integer> pniRegistrationIds) {
|
||||
|
||||
@AssertTrue
|
||||
|
|
Loading…
Reference in New Issue