JSonDeserializerWithAccessFilter: shouldDetectMultipleSelfIdFields
This commit is contained in:
parent
d2b0f477f2
commit
1505e7bd66
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user