minor username api refinements

This commit is contained in:
Jonathan Klabunde Tomer 2023-07-19 15:12:47 -07:00 committed by GitHub
parent 67343f6bdc
commit 0188d314ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 20 deletions

View File

@ -91,7 +91,7 @@ public class AccountTest {
final ConfirmUsernameHashRequest confirmUsernameHashRequest = new ConfirmUsernameHashRequest(
reservedUsername.getHash(),
reservedUsername.generateProof(),
new EncryptedUsername("cluck cluck i'm a parrot".getBytes())
"cluck cluck i'm a parrot".getBytes()
);
// try unauthorized
Operations

View File

@ -354,11 +354,11 @@ public class AccountController {
final Account account = accounts.confirmReservedUsernameHash(
auth.getAccount(),
confirmRequest.usernameHash(),
Optional.ofNullable(confirmRequest.encryptedUsername()).map(EncryptedUsername::usernameLinkEncryptedValue).orElse(null));
confirmRequest.encryptedUsername());
final UUID linkHandle = account.getUsernameLinkHandle();
return new UsernameHashResponse(
account.getUsernameHash().orElseThrow(() -> new IllegalStateException("Could not get username after setting")),
linkHandle == null ? null : new UsernameLinkHandle(linkHandle));
linkHandle);
} catch (final UsernameReservationNotFoundException e) {
throw new WebApplicationException(Status.CONFLICT);
} catch (final UsernameHashNotAvailableException e) {

View File

@ -5,9 +5,9 @@
package org.whispersystems.textsecuregcm.entities;
import javax.validation.Valid;
import javax.annotation.Nullable;
import javax.validation.Valid;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@ -27,8 +27,10 @@ public record ConfirmUsernameHashRequest(
@JsonDeserialize(using = ByteArrayBase64UrlAdapter.Deserializing.class)
byte[] zkProof,
@Schema(description = "The encrypted username to be stored for username links")
@Schema(type = "string", description = "The url-safe base64-encoded encrypted username to be stored for username links")
@Nullable
@Valid
EncryptedUsername encryptedUsername
@JsonSerialize(using = ByteArrayBase64UrlAdapter.Serializing.class)
@JsonDeserialize(using = ByteArrayBase64UrlAdapter.Deserializing.class)
@Size(min = 1, max = 128)
byte[] encryptedUsername
) {}

View File

@ -5,8 +5,18 @@
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 javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.whispersystems.textsecuregcm.util.ByteArrayBase64UrlAdapter;
public record EncryptedUsername(@NotNull @Size(min = 1, max = 128) byte[] usernameLinkEncryptedValue) {
public record EncryptedUsername(
@JsonSerialize(using = ByteArrayBase64UrlAdapter.Serializing.class)
@JsonDeserialize(using = ByteArrayBase64UrlAdapter.Deserializing.class)
@NotNull
@Size(min = 1, max = 128)
@Schema(type = "string", description = "the URL-safe base64 encoding of the encrypted username")
byte[] usernameLinkEncryptedValue) {
}

View File

@ -11,7 +11,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import org.whispersystems.textsecuregcm.controllers.AccountController;
import org.whispersystems.textsecuregcm.util.ByteArrayBase64UrlAdapter;
import org.whispersystems.textsecuregcm.util.ExactlySize;
import java.util.UUID;
import javax.annotation.Nullable;
import javax.validation.Valid;
@ -20,11 +20,11 @@ public record UsernameHashResponse(
@JsonSerialize(using = ByteArrayBase64UrlAdapter.Serializing.class)
@JsonDeserialize(using = ByteArrayBase64UrlAdapter.Deserializing.class)
@ExactlySize(AccountController.USERNAME_HASH_LENGTH)
@Schema(description = "The hash of the confirmed username, as supplied in the request")
@Schema(type = "string", description = "The hash of the confirmed username, as supplied in the request")
byte[] usernameHash,
@Nullable
@Valid
@Schema(description = "A handle that can be included in username links to retrieve the stored encrypted username")
UsernameLinkHandle usernameLinkHandle
@Schema(type = "string", description = "A handle that can be included in username links to retrieve the stored encrypted username")
UUID usernameLinkHandle
) {}

View File

@ -7,6 +7,11 @@ package org.whispersystems.textsecuregcm.entities;
import java.util.UUID;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import io.swagger.v3.oas.annotations.media.Schema;
public record UsernameLinkHandle(@NotNull UUID usernameLinkHandle) {
public record UsernameLinkHandle(
@Schema(description = "A handle that can be included in username links to retrieve the stored encrypted username")
@NotNull
UUID usernameLinkHandle) {
}

View File

@ -639,12 +639,12 @@ class AccountControllerTest {
.target("/v1/accounts/username_hash/confirm")
.request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, new EncryptedUsername(ENCRYPTED_USERNAME_1))));
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, ENCRYPTED_USERNAME_1)));
assertThat(response.getStatus()).isEqualTo(200);
final UsernameHashResponse respEntity = response.readEntity(UsernameHashResponse.class);
assertArrayEquals(respEntity.usernameHash(), USERNAME_HASH_1);
assertEquals(respEntity.usernameLinkHandle().usernameLinkHandle(), uuid);
assertEquals(respEntity.usernameLinkHandle(), uuid);
verify(usernameZkProofVerifier).verifyProof(ZK_PROOF, USERNAME_HASH_1);
}
@ -680,7 +680,7 @@ class AccountControllerTest {
.target("/v1/accounts/username_hash/confirm")
.request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, new EncryptedUsername(ENCRYPTED_USERNAME_1))));
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, ENCRYPTED_USERNAME_1)));
assertThat(response.getStatus()).isEqualTo(409);
verify(usernameZkProofVerifier).verifyProof(ZK_PROOF, USERNAME_HASH_1);
}
@ -695,7 +695,7 @@ class AccountControllerTest {
.target("/v1/accounts/username_hash/confirm")
.request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, new EncryptedUsername(ENCRYPTED_USERNAME_1))));
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, ENCRYPTED_USERNAME_1)));
assertThat(response.getStatus()).isEqualTo(410);
verify(usernameZkProofVerifier).verifyProof(ZK_PROOF, USERNAME_HASH_1);
}
@ -727,7 +727,7 @@ class AccountControllerTest {
.target("/v1/accounts/username_hash/confirm")
.request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new ConfirmUsernameHashRequest(usernameHash, ZK_PROOF, new EncryptedUsername(ENCRYPTED_USERNAME_1))));
.put(Entity.json(new ConfirmUsernameHashRequest(usernameHash, ZK_PROOF, ENCRYPTED_USERNAME_1)));
assertThat(response.getStatus()).isEqualTo(422);
verifyNoInteractions(usernameZkProofVerifier);
}
@ -740,7 +740,7 @@ class AccountControllerTest {
.target("/v1/accounts/username_hash/confirm")
.request()
.header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, new EncryptedUsername(ENCRYPTED_USERNAME_1))));
.put(Entity.json(new ConfirmUsernameHashRequest(USERNAME_HASH_1, ZK_PROOF, ENCRYPTED_USERNAME_1)));
assertThat(response.getStatus()).isEqualTo(422);
verify(usernameZkProofVerifier).verifyProof(ZK_PROOF, USERNAME_HASH_1);
}