1
0

JSonSerializer/DeserializerWithAccessFilter: also use role in parent

This commit is contained in:
Michael Hoennig
2019-04-23 14:37:49 +02:00
parent 1505e7bd66
commit a94516b3ce
12 changed files with 247 additions and 95 deletions

View File

@@ -1,6 +1,5 @@
package org.hostsharing.hsadminng.service.accessfilter;
import com.fasterxml.jackson.annotation.JsonTypeId;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.TreeNode;
@@ -18,7 +17,8 @@ import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenLoginUserWithRole;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.mockito.BDDMockito.given;
@SuppressWarnings("ALL")
@@ -38,7 +38,8 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Before
public void init() {
givenLoginUserWithRole(Role.ANY_CUSTOMER_USER);
givenAuthenticatedUser();
givenUserHavingRole(GivenDto.class, 1234L, Role.ACTUAL_CUSTOMER_USER);
given(jsonParser.getCodec()).willReturn(codec);
}
@@ -46,7 +47,9 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Test
public void shouldDeserializeStringField() throws IOException {
// given
givenJSonTree(asJSon(ImmutablePair.of("openStringField", "String Value")));
givenJSonTree(asJSon(
ImmutablePair.of("id", 1234L),
ImmutablePair.of("openStringField", "String Value")));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
@@ -58,7 +61,9 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Test
public void shouldDeserializeIntegerField() throws IOException {
// given
givenJSonTree(asJSon(ImmutablePair.of("openIntegerField", 1234)));
givenJSonTree(asJSon(
ImmutablePair.of("id", 1234L),
ImmutablePair.of("openIntegerField", 1234)));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
@@ -70,7 +75,9 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Test
public void shouldDeserializeLongField() throws IOException {
// given
givenJSonTree(asJSon(ImmutablePair.of("openLongField", 1234L)));
givenJSonTree(asJSon(
ImmutablePair.of("id", 1234L),
ImmutablePair.of("openLongField", 1234L)));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
@@ -82,8 +89,11 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Test
public void shouldDeserializeStringFieldIfRequiredRoleIsCoveredByUser() throws IOException {
// given
givenLoginUserWithRole(Role.FINANCIAL_CONTACT);
givenJSonTree(asJSon(ImmutablePair.of("restrictedField", "Restricted String Value")));
givenAuthenticatedUser();
givenUserHavingRole(GivenDto.class, 1234L, Role.FINANCIAL_CONTACT);
givenJSonTree(asJSon(
ImmutablePair.of("id", 1234L),
ImmutablePair.of("restrictedField", "Restricted String Value")));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
@@ -95,7 +105,8 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Test
public void shouldInitializeFieldIfRequiredRoleIsNotCoveredByUser() throws IOException {
// given
givenLoginUserWithRole(Role.ANY_CUSTOMER_USER);
givenAuthenticatedUser();
givenUserHavingRole(null, null, Role.ANY_CUSTOMER_USER);
givenJSonTree(asJSon(ImmutablePair.of("restrictedField", "Restricted String Value")));
// when
@@ -109,9 +120,41 @@ public class JSonDeserializerWithAccessFilterUnitTest {
}
@Test
public void shouldUpdateFieldIfRequiredRoleIsNotCoveredByUser() throws IOException {
public void shouldNotCreateIfRoleRequiredByParentEntityIsNotCoveredByUser() throws IOException {
// given
givenLoginUserWithRole(Role.ANY_CUSTOMER_USER);
givenAuthenticatedUser();
givenUserHavingRole(GivenDto.class, 9999L, Role.CONTRACTUAL_CONTACT);
givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenChildDto.class).deserialize());
// then
assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
assertThat(badRequestAlertException.getParam()).isEqualTo("GivenChildDto.parentId");
assertThat(badRequestAlertException.getErrorKey()).isEqualTo("referencingProhibited");
});
}
@Test
public void shouldCreateIfRoleRequiredByReferencedEntityIsCoveredByUser() throws IOException {
// given
givenAuthenticatedUser();
givenUserHavingRole(GivenDto.class, 1111L, Role.CONTRACTUAL_CONTACT);
givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
// when
final GivenChildDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenChildDto.class).deserialize();
// then
assertThat(actualDto.parentId).isEqualTo(1111L);
}
@Test
public void shouldNotUpdateFieldIfRequiredRoleIsNotCoveredByUser() throws IOException {
// given
givenAuthenticatedUser();
givenUserHavingRole(GivenDto.class, 1234L, Role.ANY_CUSTOMER_USER);
givenJSonTree(asJSon(
ImmutablePair.of("id", 1234L),
ImmutablePair.of("restrictedField", "Restricted String Value")));
@@ -183,6 +226,20 @@ public class JSonDeserializerWithAccessFilterUnitTest {
Long openLongField;
}
public static class GivenChildDto {
@SelfId
@AccessFor(read = Role.ANY_CUSTOMER_USER)
Long id;
@AccessFor(init = Role.CONTRACTUAL_CONTACT, update = Role.CONTRACTUAL_CONTACT, read = Role.ACTUAL_CUSTOMER_USER)
@ParentId(GivenDto.class)
Long parentId;
@AccessFor(init = {Role.TECHNICAL_CONTACT, Role.FINANCIAL_CONTACT}, update = {Role.TECHNICAL_CONTACT, Role.FINANCIAL_CONTACT})
String restrictedField;
}
public static class GivenDtoWithMultipleSelfId {
@SelfId

View File

@@ -15,7 +15,6 @@ import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenLoginUserWithRole;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -31,7 +30,8 @@ public class JSonSerializerWithAccessFilterUnitTest {
@Before
public void init() {
givenLoginUserWithRole(Role.ANY_CUSTOMER_USER);
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.ANY_CUSTOMER_USER);
}
@Test
@@ -47,7 +47,8 @@ public class JSonSerializerWithAccessFilterUnitTest {
public void shouldSerializeRestrictedFieldIfRequiredRoleIsCoveredByUser() throws IOException {
// given
givenLoginUserWithRole(Role.FINANCIAL_CONTACT);
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.FINANCIAL_CONTACT);
// when
new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
@@ -60,7 +61,8 @@ public class JSonSerializerWithAccessFilterUnitTest {
public void shouldNotSerializeRestrictedFieldIfRequiredRoleIsNotCoveredByUser() throws IOException {
// given
givenLoginUserWithRole(Role.ANY_CUSTOMER_USER);
MockSecurityContext.givenAuthenticatedUser();
MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.ANY_CUSTOMER_USER);
// when
new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
@@ -92,6 +94,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
private GivenDto createSampleDto() {
final GivenDto dto = new GivenDto();
dto.customerId = 888L;
dto.restrictedField = RandomStringUtils.randomAlphabetic(10);
dto.openStringField = RandomStringUtils.randomAlphabetic(10);
dto.openIntegerField = RandomUtils.nextInt();
@@ -99,7 +102,15 @@ public class JSonSerializerWithAccessFilterUnitTest {
return dto;
}
private static class GivenCustomerDto {
}
private static class GivenDto {
@ParentId(GivenCustomerDto.class)
Long customerId;
@AccessFor(read = {Role.TECHNICAL_CONTACT, Role.FINANCIAL_CONTACT})
String restrictedField;

View File

@@ -5,20 +5,20 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
public class MockSecurityContext {
public static void givenLoginUserWithRole(final Role userRole) {
final String fakeUserName = userRole.name();
public static void givenAuthenticatedUser() {
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken(fakeUserName, "dummy"));
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("dummyUser", "dummyPassword"));
SecurityContextHolder.setContext(securityContext);
Optional<String> login = SecurityUtils.getCurrentUserLogin();
SecurityUtils.clearUserRoles();
assertThat(login).describedAs("precondition failed").contains(fakeUserName);
assertThat(SecurityUtils.getCurrentUserLogin()).describedAs("precondition failed").hasValue("dummyUser");
}
public static void givenUserHavingRole(final Class<?> onClass, final Long onId, final Role role) {
SecurityUtils.addUserRole(onClass, onId, role);
}
}

View File

@@ -2,22 +2,18 @@ package org.hostsharing.hsadminng.service.dto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hostsharing.hsadminng.security.SecurityUtils;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenLoginUserWithRole;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.junit.Assert.assertEquals;
@JsonTest
@@ -31,7 +27,8 @@ public class CustomerDTOUnitTest {
public void testSerializationAsContractualCustomerContact() throws JsonProcessingException {
// given
givenLoginUserWithRole(Role.ANY_CUSTOMER_USER);
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, null, Role.ANY_CUSTOMER_USER);
CustomerDTO given = createSomeCustomerDTO();
// when
@@ -50,7 +47,8 @@ public class CustomerDTOUnitTest {
public void testSerializationAsSupporter() throws JsonProcessingException {
// given
givenLoginUserWithRole(Role.SUPPORTER);
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, null, Role.SUPPORTER);
CustomerDTO given = createSomeCustomerDTO();
// when
@@ -63,7 +61,8 @@ public class CustomerDTOUnitTest {
@Test
public void testDeserializeAsContractualCustomerContact() throws IOException {
// given
givenLoginUserWithRole(Role.CONTRACTUAL_CONTACT);
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, null, Role.CONTRACTUAL_CONTACT);
String json = "{\"id\":1234,\"contractualSalutation\":\"Hallo Updated\",\"billingSalutation\":\"Moin Updated\"}";
// when
@@ -77,6 +76,8 @@ public class CustomerDTOUnitTest {
assertThat(actual).isEqualToComparingFieldByField(expected);
}
// --- only test fixture below ---
private String createExpectedJSon(CustomerDTO dto) {
String json = // the fields in alphanumeric order:
toJSonFieldDefinitionIfPresent("id", dto.getId()) +