Moving Account serialization logic to storage-specific classes

This commit is contained in:
Sergey Skrobotov
2023-07-20 11:12:44 -07:00
parent f5c57e5741
commit cf92007f66
7 changed files with 154 additions and 69 deletions

View File

@@ -16,11 +16,15 @@ import static org.mockito.Mockito.when;
import static org.whispersystems.textsecuregcm.tests.util.DevicesHelper.createDevice;
import static org.whispersystems.textsecuregcm.tests.util.DevicesHelper.setEnabled;
import com.fasterxml.jackson.annotation.JsonFilter;
import java.lang.annotation.Annotation;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeEach;
@@ -428,4 +432,16 @@ class AccountTest {
assertThat(badge.isVisible()).isTrue();
});
}
@Test
public void testAccountClassJsonFilterIdMatchesClassName() throws Exception {
// Some logic relies on the @JsonFilter name being equal to the class name.
// This test is just making sure that annotation is there and that the ID matches class name.
final Optional<Annotation> maybeJsonFilterAnnotation = Arrays.stream(Account.class.getAnnotations())
.filter(a -> a.annotationType().equals(JsonFilter.class))
.findFirst();
assertTrue(maybeJsonFilterAnnotation.isPresent());
final JsonFilter jsonFilterAnnotation = (JsonFilter) maybeJsonFilterAnnotation.get();
assertEquals(Account.class.getSimpleName(), jsonFilterAnnotation.value());
}
}

View File

@@ -11,6 +11,7 @@ import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -989,6 +990,24 @@ class AccountsTest {
assertThat(account.getUsernameHash()).isEmpty();
}
@Test
public void testIgnoredFieldsNotAddedToDataAttribute() throws Exception {
final Account account = generateAccount("+18005551234", UUID.randomUUID(), UUID.randomUUID());
account.setUsernameHash(RandomUtils.nextBytes(32));
account.setUsernameLinkDetails(UUID.randomUUID(), RandomUtils.nextBytes(32));
accounts.create(account);
final Map<String, AttributeValue> accountRecord = DYNAMO_DB_EXTENSION.getDynamoDbClient()
.getItem(GetItemRequest.builder()
.tableName(Tables.ACCOUNTS.tableName())
.key(Map.of(Accounts.KEY_ACCOUNT_UUID, AttributeValues.fromUUID(account.getUuid())))
.build())
.item();
final Map<?, ?> dataMap = SystemMapper.jsonMapper()
.readValue(accountRecord.get(Accounts.ATTR_ACCOUNT_DATA).b().asByteArray(), Map.class);
Accounts.ACCOUNT_FIELDS_TO_EXCLUDE_FROM_SERIALIZATION
.forEach(field -> assertFalse(dataMap.containsKey(field)));
}
private static Device generateDevice(long id) {
return DevicesHelper.createDevice(id);
}

View File

@@ -6,13 +6,19 @@
package org.whispersystems.textsecuregcm.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -68,7 +74,6 @@ class SystemMapperTest {
}
}
@ParameterizedTest
@ValueSource(classes = {DataClass.class, DataRecord.class})
public void testOptionalField(final Class<? extends Data> clazz) throws Exception {
@@ -96,4 +101,22 @@ class SystemMapperTest {
Arguments.of(new DataRecord(null), JSON_NO_FIELD)
);
}
public record NotAnnotatedWithJsonFilter(String data) {
}
@JsonFilter("AnnotatedWithJsonFilter")
public record AnnotatedWithJsonFilter(String data, String excluded) {
}
@Test
public void testFiltering() throws Exception {
assertThrows(IllegalStateException.class, () -> SystemMapper.excludingField(NotAnnotatedWithJsonFilter.class, List.of("data")));
final ObjectWriter writer = SystemMapper.jsonMapper()
.writer(SystemMapper.excludingField(AnnotatedWithJsonFilter.class, List.of("excluded")));
final AnnotatedWithJsonFilter obj = new AnnotatedWithJsonFilter("valData", "valExcluded");
final String json = writer.writeValueAsString(obj);
final Map<?, ?> serializedFields = SystemMapper.jsonMapper().readValue(json, Map.class);
assertEquals(Map.of("data", "valData"), serializedFields);
}
}