Update batch check entities from two optional fields to a single field
This commit is contained in:
		
							parent
							
								
									320c5eac53
								
							
						
					
					
						commit
						8b65c11e1e
					
				| 
						 | 
					@ -394,8 +394,15 @@ public class ProfileController {
 | 
				
			||||||
      maybeAccount = accountsManager.getByAccountIdentifier(element.aci());
 | 
					      maybeAccount = accountsManager.getByAccountIdentifier(element.aci());
 | 
				
			||||||
      usePhoneNumberIdentity = false;
 | 
					      usePhoneNumberIdentity = false;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      maybeAccount = accountsManager.getByPhoneNumberIdentifier(element.pni());
 | 
					      final Optional<Account> maybeAciAccount = accountsManager.getByAccountIdentifier(element.uuid());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (maybeAciAccount.isEmpty()) {
 | 
				
			||||||
 | 
					        maybeAccount = accountsManager.getByPhoneNumberIdentifier(element.uuid());
 | 
				
			||||||
        usePhoneNumberIdentity = true;
 | 
					        usePhoneNumberIdentity = true;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        maybeAccount = maybeAciAccount;
 | 
				
			||||||
 | 
					        usePhoneNumberIdentity = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    maybeAccount.ifPresent(account -> {
 | 
					    maybeAccount.ifPresent(account -> {
 | 
				
			||||||
| 
						 | 
					@ -414,7 +421,7 @@ public class ProfileController {
 | 
				
			||||||
      byte[] fingerprint = Util.truncate(digest, 4);
 | 
					      byte[] fingerprint = Util.truncate(digest, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (!Arrays.equals(fingerprint, element.fingerprint())) {
 | 
					      if (!Arrays.equals(fingerprint, element.fingerprint())) {
 | 
				
			||||||
        responseElements.add(new BatchIdentityCheckResponse.Element(element.aci(), element.pni(), identityKeyBytes));
 | 
					        responseElements.add(new BatchIdentityCheckResponse.Element(element.aci(), element.uuid(), identityKeyBytes));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,22 +16,21 @@ import org.whispersystems.textsecuregcm.util.ExactlySize;
 | 
				
			||||||
public record BatchIdentityCheckRequest(@Valid @NotNull @Size(max = 1000) List<Element> elements) {
 | 
					public record BatchIdentityCheckRequest(@Valid @NotNull @Size(max = 1000) List<Element> elements) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Exactly one of {@code aci} and {@code pni} must be non-null
 | 
					   * @param uuid        account id or phone number id
 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @param aci         account id
 | 
					 | 
				
			||||||
   * @param pni         phone number id
 | 
					 | 
				
			||||||
   * @param fingerprint most significant 4 bytes of SHA-256 of the 33-byte identity key field (32-byte curve25519 public
 | 
					   * @param fingerprint most significant 4 bytes of SHA-256 of the 33-byte identity key field (32-byte curve25519 public
 | 
				
			||||||
   *                    key prefixed with 0x05)
 | 
					   *                    key prefixed with 0x05)
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  public record Element(@Nullable UUID aci, @Nullable UUID pni, @NotNull @ExactlySize(4) byte[] fingerprint) {
 | 
					  public record Element(@Deprecated @Nullable UUID aci,
 | 
				
			||||||
 | 
					                        @Nullable UUID uuid,
 | 
				
			||||||
 | 
					                        @NotNull @ExactlySize(4) byte[] fingerprint) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Element {
 | 
					    public Element {
 | 
				
			||||||
      if (aci == null && pni == null) {
 | 
					      if (aci == null && uuid == null) {
 | 
				
			||||||
        throw new IllegalArgumentException("aci and pni cannot both be null");
 | 
					        throw new IllegalArgumentException("aci and uuid cannot both be null");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (aci != null && pni != null) {
 | 
					      if (aci != null && uuid != null) {
 | 
				
			||||||
        throw new IllegalArgumentException("aci and pni cannot both be non-null");
 | 
					        throw new IllegalArgumentException("aci and uuid cannot both be non-null");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.whispersystems.textsecuregcm.entities;
 | 
					package org.whispersystems.textsecuregcm.entities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.annotation.JsonInclude;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.UUID;
 | 
					import java.util.UUID;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
| 
						 | 
					@ -14,18 +15,17 @@ import org.whispersystems.textsecuregcm.util.ExactlySize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public record BatchIdentityCheckResponse(@Valid List<Element> elements) {
 | 
					public record BatchIdentityCheckResponse(@Valid List<Element> elements) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  public record Element(@Deprecated @JsonInclude(JsonInclude.Include.NON_EMPTY) @Nullable UUID aci,
 | 
				
			||||||
   * Exactly one of {@code aci} and {@code pni} must be non-null
 | 
					                        @JsonInclude(JsonInclude.Include.NON_EMPTY) @Nullable UUID uuid,
 | 
				
			||||||
   */
 | 
					                        @NotNull @ExactlySize(33) byte[] identityKey) {
 | 
				
			||||||
  public record Element(@Nullable UUID aci, @Nullable UUID pni, @NotNull @ExactlySize(33) byte[] identityKey) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Element {
 | 
					    public Element {
 | 
				
			||||||
      if (aci == null && pni == null) {
 | 
					      if (aci == null && uuid == null) {
 | 
				
			||||||
        throw new IllegalArgumentException("aci and pni cannot both be null");
 | 
					        throw new IllegalArgumentException("aci and uuid cannot both be null");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (aci != null && pni != null) {
 | 
					      if (aci != null && uuid != null) {
 | 
				
			||||||
        throw new IllegalArgumentException("aci and pni cannot both be non-null");
 | 
					        throw new IllegalArgumentException("aci and uuid cannot both be non-null");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1237,6 +1237,8 @@ class ProfileControllerTest {
 | 
				
			||||||
                convertStringToFingerprint(ACCOUNT_IDENTITY_KEY)),
 | 
					                convertStringToFingerprint(ACCOUNT_IDENTITY_KEY)),
 | 
				
			||||||
            new BatchIdentityCheckRequest.Element(null, AuthHelper.VALID_PNI_TWO,
 | 
					            new BatchIdentityCheckRequest.Element(null, AuthHelper.VALID_PNI_TWO,
 | 
				
			||||||
                convertStringToFingerprint(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY)),
 | 
					                convertStringToFingerprint(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY)),
 | 
				
			||||||
 | 
					            new BatchIdentityCheckRequest.Element(null, AuthHelper.VALID_UUID_TWO,
 | 
				
			||||||
 | 
					                convertStringToFingerprint(ACCOUNT_TWO_IDENTITY_KEY)),
 | 
				
			||||||
            new BatchIdentityCheckRequest.Element(AuthHelper.INVALID_UUID, null,
 | 
					            new BatchIdentityCheckRequest.Element(AuthHelper.INVALID_UUID, null,
 | 
				
			||||||
                convertStringToFingerprint(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY))
 | 
					                convertStringToFingerprint(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY))
 | 
				
			||||||
        ))))) {
 | 
					        ))))) {
 | 
				
			||||||
| 
						 | 
					@ -1250,8 +1252,10 @@ class ProfileControllerTest {
 | 
				
			||||||
    Condition<BatchIdentityCheckResponse.Element> isAnExpectedUuid = new Condition<>(element -> {
 | 
					    Condition<BatchIdentityCheckResponse.Element> isAnExpectedUuid = new Condition<>(element -> {
 | 
				
			||||||
      if (AuthHelper.VALID_UUID.equals(element.aci())) {
 | 
					      if (AuthHelper.VALID_UUID.equals(element.aci())) {
 | 
				
			||||||
        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_IDENTITY_KEY), element.identityKey());
 | 
					        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_IDENTITY_KEY), element.identityKey());
 | 
				
			||||||
      } else if (AuthHelper.VALID_PNI_TWO.equals(element.pni())) {
 | 
					      } else if (AuthHelper.VALID_PNI_TWO.equals(element.uuid())) {
 | 
				
			||||||
        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY), element.identityKey());
 | 
					        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY), element.identityKey());
 | 
				
			||||||
 | 
					      } else if (AuthHelper.VALID_UUID_TWO.equals(element.uuid())) {
 | 
				
			||||||
 | 
					        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_TWO_IDENTITY_KEY), element.identityKey());
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -1262,15 +1266,18 @@ class ProfileControllerTest {
 | 
				
			||||||
            new BatchIdentityCheckRequest.Element(AuthHelper.VALID_UUID, null, convertStringToFingerprint("else1234")),
 | 
					            new BatchIdentityCheckRequest.Element(AuthHelper.VALID_UUID, null, convertStringToFingerprint("else1234")),
 | 
				
			||||||
            new BatchIdentityCheckRequest.Element(null, AuthHelper.VALID_PNI_TWO,
 | 
					            new BatchIdentityCheckRequest.Element(null, AuthHelper.VALID_PNI_TWO,
 | 
				
			||||||
                convertStringToFingerprint("another1")),
 | 
					                convertStringToFingerprint("another1")),
 | 
				
			||||||
 | 
					            new BatchIdentityCheckRequest.Element(null, AuthHelper.VALID_UUID_TWO,
 | 
				
			||||||
 | 
					                convertStringToFingerprint("another2")),
 | 
				
			||||||
            new BatchIdentityCheckRequest.Element(AuthHelper.INVALID_UUID, null, convertStringToFingerprint("456"))
 | 
					            new BatchIdentityCheckRequest.Element(AuthHelper.INVALID_UUID, null, convertStringToFingerprint("456"))
 | 
				
			||||||
        ))))) {
 | 
					        ))))) {
 | 
				
			||||||
      assertThat(response).isNotNull();
 | 
					      assertThat(response).isNotNull();
 | 
				
			||||||
      assertThat(response.getStatus()).isEqualTo(200);
 | 
					      assertThat(response.getStatus()).isEqualTo(200);
 | 
				
			||||||
      BatchIdentityCheckResponse identityCheckResponse = response.readEntity(BatchIdentityCheckResponse.class);
 | 
					      BatchIdentityCheckResponse identityCheckResponse = response.readEntity(BatchIdentityCheckResponse.class);
 | 
				
			||||||
      assertThat(identityCheckResponse).isNotNull();
 | 
					      assertThat(identityCheckResponse).isNotNull();
 | 
				
			||||||
      assertThat(identityCheckResponse.elements()).isNotNull().hasSize(2);
 | 
					      assertThat(identityCheckResponse.elements()).isNotNull().hasSize(3);
 | 
				
			||||||
      assertThat(identityCheckResponse.elements()).element(0).isNotNull().is(isAnExpectedUuid);
 | 
					      assertThat(identityCheckResponse.elements()).element(0).isNotNull().is(isAnExpectedUuid);
 | 
				
			||||||
      assertThat(identityCheckResponse.elements()).element(1).isNotNull().is(isAnExpectedUuid);
 | 
					      assertThat(identityCheckResponse.elements()).element(1).isNotNull().is(isAnExpectedUuid);
 | 
				
			||||||
 | 
					      assertThat(identityCheckResponse.elements()).element(2).isNotNull().is(isAnExpectedUuid);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    List<BatchIdentityCheckRequest.Element> largeElementList = new ArrayList<>(List.of(
 | 
					    List<BatchIdentityCheckRequest.Element> largeElementList = new ArrayList<>(List.of(
 | 
				
			||||||
| 
						 | 
					@ -1294,12 +1301,12 @@ class ProfileControllerTest {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Test
 | 
					  @Test
 | 
				
			||||||
  void testBatchIdentityCheckDeserialization() {
 | 
					  void testBatchIdentityCheckDeserialization() throws Exception {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Condition<BatchIdentityCheckResponse.Element> isAnExpectedUuid = new Condition<>(element -> {
 | 
					    Condition<BatchIdentityCheckResponse.Element> isAnExpectedUuid = new Condition<>(element -> {
 | 
				
			||||||
      if (AuthHelper.VALID_UUID.equals(element.aci())) {
 | 
					      if (AuthHelper.VALID_UUID.equals(element.aci())) {
 | 
				
			||||||
        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_IDENTITY_KEY), element.identityKey());
 | 
					        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_IDENTITY_KEY), element.identityKey());
 | 
				
			||||||
      } else if (AuthHelper.VALID_PNI_TWO.equals(element.pni())) {
 | 
					      } else if (AuthHelper.VALID_PNI_TWO.equals(element.uuid())) {
 | 
				
			||||||
        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY), element.identityKey());
 | 
					        return Arrays.equals(Base64.getDecoder().decode(ACCOUNT_TWO_PHONE_NUMBER_IDENTITY_KEY), element.identityKey());
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
| 
						 | 
					@ -1311,7 +1318,7 @@ class ProfileControllerTest {
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              "elements": [
 | 
					              "elements": [
 | 
				
			||||||
                { "aci": "%s", "fingerprint": "%s" },
 | 
					                { "aci": "%s", "fingerprint": "%s" },
 | 
				
			||||||
                { "pni": "%s", "fingerprint": "%s" },
 | 
					                { "uuid": "%s", "fingerprint": "%s" },
 | 
				
			||||||
                { "aci": "%s", "fingerprint": "%s" }
 | 
					                { "aci": "%s", "fingerprint": "%s" }
 | 
				
			||||||
              ]
 | 
					              ]
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1322,7 +1329,13 @@ class ProfileControllerTest {
 | 
				
			||||||
        .post(Entity.entity(json, "application/json"))) {
 | 
					        .post(Entity.entity(json, "application/json"))) {
 | 
				
			||||||
      assertThat(response).isNotNull();
 | 
					      assertThat(response).isNotNull();
 | 
				
			||||||
      assertThat(response.getStatus()).isEqualTo(200);
 | 
					      assertThat(response.getStatus()).isEqualTo(200);
 | 
				
			||||||
      BatchIdentityCheckResponse identityCheckResponse = response.readEntity(BatchIdentityCheckResponse.class);
 | 
					      String responseJson = response.readEntity(String.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // `null` properties should be omitted from the response
 | 
				
			||||||
 | 
					      assertThat(responseJson).doesNotContain("null");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      BatchIdentityCheckResponse identityCheckResponse = SystemMapper.getMapper()
 | 
				
			||||||
 | 
					          .readValue(responseJson, BatchIdentityCheckResponse.class);
 | 
				
			||||||
      assertThat(identityCheckResponse).isNotNull();
 | 
					      assertThat(identityCheckResponse).isNotNull();
 | 
				
			||||||
      assertThat(identityCheckResponse.elements()).isNotNull().hasSize(2);
 | 
					      assertThat(identityCheckResponse.elements()).isNotNull().hasSize(2);
 | 
				
			||||||
      assertThat(identityCheckResponse.elements()).element(0).isNotNull().is(isAnExpectedUuid);
 | 
					      assertThat(identityCheckResponse.elements()).element(0).isNotNull().is(isAnExpectedUuid);
 | 
				
			||||||
| 
						 | 
					@ -1342,11 +1355,11 @@ class ProfileControllerTest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static Stream<Arguments> testBatchIdentityCheckDeserializationBadRequest() {
 | 
					  static Stream<Arguments> testBatchIdentityCheckDeserializationBadRequest() {
 | 
				
			||||||
    return Stream.of(
 | 
					    return Stream.of(
 | 
				
			||||||
        Arguments.of( // aci and pni cannot both be null
 | 
					        Arguments.of( // aci and uuid cannot both be null
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                  "elements": [
 | 
					                  "elements": [
 | 
				
			||||||
                    { "aci": null, "pni": null, "fingerprint": "%s" }
 | 
					                    { "aci": null, "uuid": null, "fingerprint": "%s" }
 | 
				
			||||||
                  ]
 | 
					                  ]
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                """),
 | 
					                """),
 | 
				
			||||||
| 
						 | 
					@ -1354,7 +1367,7 @@ class ProfileControllerTest {
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                  "elements": [
 | 
					                  "elements": [
 | 
				
			||||||
                    { "aci": "", "pni": null, "fingerprint": "%s" }
 | 
					                    { "aci": "", "uuid": null, "fingerprint": "%s" }
 | 
				
			||||||
                  ]
 | 
					                  ]
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                """
 | 
					                """
 | 
				
			||||||
| 
						 | 
					@ -1363,15 +1376,15 @@ class ProfileControllerTest {
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                  "elements": [
 | 
					                  "elements": [
 | 
				
			||||||
                    { "aci": null, "pni": " ", "fingerprint": "%s" }
 | 
					                    { "aci": null, "uuid": " ", "fingerprint": "%s" }
 | 
				
			||||||
                  ]
 | 
					                  ]
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                """),
 | 
					                """),
 | 
				
			||||||
        Arguments.of( // aci and pni cannot both be non-null
 | 
					        Arguments.of( // aci and uuid cannot both be non-null
 | 
				
			||||||
            String.format("""
 | 
					            String.format("""
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                      "elements": [
 | 
					                      "elements": [
 | 
				
			||||||
                        { "aci": "%s", "pni": "%s", "fingerprint": "%s" }
 | 
					                        { "aci": "%s", "uuid": "%s", "fingerprint": "%s" }
 | 
				
			||||||
                      ]
 | 
					                      ]
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    """, AuthHelper.VALID_UUID, AuthHelper.VALID_PNI,
 | 
					                    """, AuthHelper.VALID_UUID, AuthHelper.VALID_PNI,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue