JSonSerializer/DeserializerWithAccessFilter: also use role in parent
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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()) +
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user