JSonDeserializerWithAccessFilter: shouldDetectMultipleSelfIdFields
This commit is contained in:
		@@ -31,6 +31,24 @@ public class JSonDeserializerWithAccessFilter<T> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Jackson deserializes from the JsonParser, thus no input parameter needed.
 | 
					    // Jackson deserializes from the JsonParser, thus no input parameter needed.
 | 
				
			||||||
    public T deserialize() {
 | 
					    public T deserialize() {
 | 
				
			||||||
 | 
					        determineSelfIdField();
 | 
				
			||||||
 | 
					        deserializeValues();
 | 
				
			||||||
 | 
					        checkAccessToModifiedFields();
 | 
				
			||||||
 | 
					        return dto;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     private void determineSelfIdField() {
 | 
				
			||||||
 | 
					        for (Field field : dto.getClass().getDeclaredFields()) {
 | 
				
			||||||
 | 
					            if (field.isAnnotationPresent(SelfId.class)) {
 | 
				
			||||||
 | 
					                if (selfIdField != null) {
 | 
				
			||||||
 | 
					                    throw new AssertionError("multiple @" + SelfId.class.getSimpleName() + " detected in " + field.getDeclaringClass().getSimpleName());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                selfIdField = field;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void deserializeValues() {
 | 
				
			||||||
        treeNode.fieldNames().forEachRemaining(fieldName -> {
 | 
					        treeNode.fieldNames().forEachRemaining(fieldName -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                final Field field = dto.getClass().getDeclaredField(fieldName);
 | 
					                final Field field = dto.getClass().getDeclaredField(fieldName);
 | 
				
			||||||
@@ -41,9 +59,6 @@ public class JSonDeserializerWithAccessFilter<T> {
 | 
				
			|||||||
                throw new RuntimeException("setting field " + fieldName + " failed", e);
 | 
					                throw new RuntimeException("setting field " + fieldName + " failed", e);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        modifiedFields.forEach(this::checkAccess);
 | 
					 | 
				
			||||||
        return dto;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Object readValue(final TreeNode treeNode, final Field field) {
 | 
					    private Object readValue(final TreeNode treeNode, final Field field) {
 | 
				
			||||||
@@ -82,8 +97,9 @@ public class JSonDeserializerWithAccessFilter<T> {
 | 
				
			|||||||
        return ReflectionUtil.getValue(dto, selfIdField);
 | 
					        return ReflectionUtil.getValue(dto, selfIdField);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void checkAccess(final Field field) {
 | 
					    private void checkAccessToModifiedFields() {
 | 
				
			||||||
        if ( !rememberSelfIdField(field) ) {
 | 
					        modifiedFields.forEach(field -> {
 | 
				
			||||||
 | 
					            if ( !field.equals(selfIdField) ) {
 | 
				
			||||||
                if (getId() == null) {
 | 
					                if (getId() == null) {
 | 
				
			||||||
                    if (!getLoginUserRole().isAllowedToInit(field)) {
 | 
					                    if (!getLoginUserRole().isAllowedToInit(field)) {
 | 
				
			||||||
                        throw new BadRequestAlertException("Initialization of field prohibited for current user", toDisplay(field), "initializationProhibited");
 | 
					                        throw new BadRequestAlertException("Initialization of field prohibited for current user", toDisplay(field), "initializationProhibited");
 | 
				
			||||||
@@ -94,17 +110,7 @@ public class JSonDeserializerWithAccessFilter<T> {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    }
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private boolean rememberSelfIdField(final Field field) {
 | 
					 | 
				
			||||||
        if ( field.isAnnotationPresent(SelfId.class) ) {
 | 
					 | 
				
			||||||
            if ( selfIdField != null ) {
 | 
					 | 
				
			||||||
                throw new AssertionError("multiple " + SelfId.class + " detected in " + field.getDeclaringClass().getSimpleName() );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            selfIdField = field;
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String toDisplay(final Field field) {
 | 
					    private String toDisplay(final Field field) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ package org.hostsharing.hsadminng.service.accessfilter;
 | 
				
			|||||||
import java.lang.annotation.*;
 | 
					import java.lang.annotation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Used to mark a field within a DTO as containing the id of a field,
 | 
					 * Used to mark a field within a DTO as containing the own id,
 | 
				
			||||||
 * it's needed to identify an existing entity for update functions.
 | 
					 * it's needed to identify an existing entity for update functions.
 | 
				
			||||||
 * Initialization and update rights have no meaning for such fields,
 | 
					 * Initialization and update rights have no meaning for such fields,
 | 
				
			||||||
 * its initialized automatically and never updated.
 | 
					 * its initialized automatically and never updated.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -127,15 +127,15 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    public void should() throws IOException {
 | 
					    public void shouldDetectMultipleSelfIdFields() throws IOException {
 | 
				
			||||||
        // given
 | 
					        // given
 | 
				
			||||||
        givenJSonTree(asJSon(ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
					        givenJSonTree(asJSon(ImmutablePair.of("id", 1111L)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDtoWithMultipleSelfId.class).deserialize());
 | 
					        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDtoWithMultipleSelfId.class).deserialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(exception).isInstanceOf(AssertionError.class).hasMessageContaining("xx");
 | 
					        assertThat(exception).isInstanceOf(AssertionError.class).hasMessage("multiple @SelfId detected in GivenDtoWithMultipleSelfId");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // --- only fixture code below ---
 | 
					    // --- only fixture code below ---
 | 
				
			||||||
@@ -183,7 +183,6 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        Long openLongField;
 | 
					        Long openLongField;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static class GivenDtoWithMultipleSelfId {
 | 
					    public static class GivenDtoWithMultipleSelfId {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @SelfId
 | 
					        @SelfId
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user