1
0

JSonAccessFilter with initially working (hardcoded) grand parent role

This commit is contained in:
Michael Hoennig
2019-04-24 12:30:26 +02:00
parent a94516b3ce
commit 639ea06243
18 changed files with 468 additions and 87 deletions

View File

@@ -0,0 +1,27 @@
package org.hostsharing.hsadminng.service.accessfilter;
import org.apache.commons.lang3.tuple.ImmutablePair;
public class JSonBuilder {
@SafeVarargs
public static String asJSon(final ImmutablePair<String, Object>... properties) {
final StringBuilder json = new StringBuilder();
for (ImmutablePair<String, Object> prop : properties) {
json.append(inQuotes(prop.left));
json.append(": ");
if (prop.right instanceof Number) {
json.append(prop.right);
} else {
json.append(inQuotes(prop.right));
}
json.append(",\n");
}
return "{\n" + json.substring(0, json.length() - 2) + "\n}";
}
private static String inQuotes(Object value) {
return "\"" + value.toString() + "\"";
}
}

View File

@@ -12,11 +12,13 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.context.ApplicationContext;
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.JSonBuilder.asJSon;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.mockito.BDDMockito.given;
@@ -27,6 +29,9 @@ public class JSonDeserializerWithAccessFilterUnitTest {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
public ApplicationContext ctx;
@Mock
public JsonParser jsonParser;
@@ -52,7 +57,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
ImmutablePair.of("openStringField", "String Value")));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
// then
assertThat(actualDto.openStringField).isEqualTo("String Value");
@@ -66,7 +71,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
ImmutablePair.of("openIntegerField", 1234)));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
// then
assertThat(actualDto.openIntegerField).isEqualTo(1234);
@@ -80,7 +85,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
ImmutablePair.of("openLongField", 1234L)));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
// then
assertThat(actualDto.openLongField).isEqualTo(1234L);
@@ -96,7 +101,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
ImmutablePair.of("restrictedField", "Restricted String Value")));
// when
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
// then
assertThat(actualDto.restrictedField).isEqualTo("Restricted String Value");
@@ -110,7 +115,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
givenJSonTree(asJSon(ImmutablePair.of("restrictedField", "Restricted String Value")));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize());
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize());
// then
assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
@@ -127,7 +132,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenChildDto.class).deserialize());
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenChildDto.class).deserialize());
// then
assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
@@ -144,7 +149,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
// when
final GivenChildDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenChildDto.class).deserialize();
final GivenChildDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenChildDto.class).deserialize();
// then
assertThat(actualDto.parentId).isEqualTo(1111L);
@@ -160,7 +165,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
ImmutablePair.of("restrictedField", "Restricted String Value")));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize());
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize());
// then
assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
@@ -175,7 +180,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
givenJSonTree(asJSon(ImmutablePair.of("id", 1111L)));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDtoWithMultipleSelfId.class).deserialize());
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDtoWithMultipleSelfId.class).deserialize());
// then
assertThat(exception).isInstanceOf(AssertionError.class).hasMessage("multiple @SelfId detected in GivenDtoWithMultipleSelfId");
@@ -183,30 +188,10 @@ public class JSonDeserializerWithAccessFilterUnitTest {
// --- only fixture code below ---
@SafeVarargs
private final String asJSon(final ImmutablePair<String, Object>... properties) {
final StringBuilder json = new StringBuilder();
for (ImmutablePair<String, Object> prop : properties) {
json.append(inQuotes(prop.left));
json.append(": ");
if (prop.right instanceof Number) {
json.append(prop.right);
} else {
json.append(inQuotes(prop.right));
}
json.append(",\n");
}
return "{\n" + json.substring(0, json.length() - 2) + "\n}";
}
private void givenJSonTree(String givenJSon) throws IOException {
given(codec.readTree(jsonParser)).willReturn(new ObjectMapper().readTree(givenJSon));
}
private String inQuotes(Object value) {
return "\"" + value.toString() + "\"";
}
public static class GivenDto {
@SelfId

View File

@@ -10,6 +10,7 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.context.ApplicationContext;
import java.io.IOException;
@@ -23,6 +24,9 @@ public class JSonSerializerWithAccessFilterUnitTest {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
public ApplicationContext ctx;
@Mock
public JsonGenerator jsonGenerator;
@@ -37,7 +41,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
@Test
public void shouldSerializeStringField() throws IOException {
// when
new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
// then
verify(jsonGenerator).writeStringField("openStringField", givenDTO.openStringField);
@@ -51,7 +55,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.FINANCIAL_CONTACT);
// when
new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
// then
verify(jsonGenerator).writeStringField("restrictedField", givenDTO.restrictedField);
@@ -65,7 +69,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.ANY_CUSTOMER_USER);
// when
new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
// then
verify(jsonGenerator, never()).writeStringField("restrictedField", givenDTO.restrictedField);
@@ -84,7 +88,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
final GivenDtoWithUnimplementedFieldType givenDtoWithUnimplementedFieldType = new GivenDtoWithUnimplementedFieldType();
// when
Throwable actual = catchThrowable(() -> new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDtoWithUnimplementedFieldType).serialize());
final Throwable actual = catchThrowable(() -> new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDtoWithUnimplementedFieldType).serialize());
// then
assertThat(actual).isInstanceOf(NotImplementedException.class);

View File

@@ -19,6 +19,9 @@ public class MockSecurityContext {
}
public static void givenUserHavingRole(final Class<?> onClass, final Long onId, final Role role) {
if ((onClass == null || onId == null) && !role.isIndependent()) {
throw new IllegalArgumentException("dependent roles like " + role + " depend on DtoClass and ID");
}
SecurityUtils.addUserRole(onClass, onId, role);
}
}

View File

@@ -0,0 +1,85 @@
package org.hostsharing.hsadminng.service.dto;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.hostsharing.hsadminng.service.accessfilter.JSonDeserializerWithAccessFilter;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.context.ApplicationContext;
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.JSonBuilder.asJSon;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.mockito.BDDMockito.given;
public class MembershipDTOUnitTest {
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
public ApplicationContext ctx;
@Mock
public JsonParser jsonParser;
@Mock
public ObjectCodec codec;
@Mock
public TreeNode treeNode;
@Before
public void init() {
given(jsonParser.getCodec()).willReturn(codec);
}
@Test
public void adminShouldHaveRightToCreate() throws IOException {
givenAuthenticatedUser();
givenUserHavingRole(null, null, Role.ADMIN);
givenJSonTree(asJSon(ImmutablePair.of("customerId", 1234L)));
// when
final MembershipDTO actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, MembershipDTO.class).deserialize();
// then
assertThat(actualDto.getCustomerId()).isEqualTo(1234L);
}
@Test
public void contractualContactShouldNotHaveRightToCreate() throws IOException {
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, 1234L, Role.CONTRACTUAL_CONTACT);
givenJSonTree(asJSon(ImmutablePair.of("customerId", 1234L)));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, MembershipDTO.class).deserialize());
// then
assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
assertThat(badRequestAlertException.getParam()).isEqualTo("MembershipDTO.customerId");
assertThat(badRequestAlertException.getErrorKey()).isEqualTo("referencingProhibited");
});
}
// --- only fixture code below ---
private void givenJSonTree(String givenJSon) throws IOException {
given(codec.readTree(jsonParser)).willReturn(new ObjectMapper().readTree(givenJSon));
}
}

View File

@@ -0,0 +1,163 @@
package org.hostsharing.hsadminng.service.dto;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
import org.hostsharing.hsadminng.service.CustomerService;
import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.accessfilter.JSonDeserializerWithAccessFilter;
import org.hostsharing.hsadminng.service.accessfilter.JSonSerializerWithAccessFilter;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import java.io.IOException;
import java.time.LocalDate;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.hostsharing.hsadminng.service.accessfilter.JSonBuilder.asJSon;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
public class ShareDTOUnitTest {
private static final long SOME_MEMBERSHIP_ID = 12345L;
private static final long SOME_CUSTOMER_ID = 1234L;
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock
private ApplicationContext ctx;
@Mock
private AutowireCapableBeanFactory autowireCapableBeanFactory;
@Mock
private JsonParser jsonParser;
@Mock
private JsonGenerator jsonGenerator;
@Mock
private ObjectCodec codec;
@Mock
private TreeNode treeNode;
@Mock
private CustomerService customerService;
@Mock
private MembershipService membershipService;
@Before
public void init() {
given(jsonParser.getCodec()).willReturn(codec);
given(ctx.getAutowireCapableBeanFactory()).willReturn(autowireCapableBeanFactory);
given(ctx.getAutowireCapableBeanFactory()).willReturn(autowireCapableBeanFactory);
given(autowireCapableBeanFactory.createBean(CustomerService.class)).willReturn(customerService);
given(autowireCapableBeanFactory.createBean(MembershipService.class)).willReturn(membershipService);
given(customerService.findOne(SOME_CUSTOMER_ID)).willReturn(Optional.of(new CustomerDTO()));
given(membershipService.findOne(SOME_MEMBERSHIP_ID)).willReturn(Optional.of(new MembershipDTO().with(dto -> dto.setCustomerId(SOME_CUSTOMER_ID))));
}
@Test
public void adminShouldHaveRightToCreate() throws IOException {
givenAuthenticatedUser();
givenUserHavingRole(null, null, Role.ADMIN);
givenJSonTree(asJSon(ImmutablePair.of("membershipId", SOME_MEMBERSHIP_ID)));
// when
final ShareDTO actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, ShareDTO.class).deserialize();
// then
assertThat(actualDto.getMembershipId()).isEqualTo(SOME_MEMBERSHIP_ID);
}
@Test
public void contractualContactShouldNotHaveRightToCreate() throws IOException {
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, SOME_CUSTOMER_ID, Role.CONTRACTUAL_CONTACT);
givenJSonTree(asJSon(ImmutablePair.of("membershipId", ShareDTOUnitTest.SOME_MEMBERSHIP_ID)));
// when
Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, ShareDTO.class).deserialize());
// then
assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
assertThat(badRequestAlertException.getParam()).isEqualTo("ShareDTO.membershipId");
assertThat(badRequestAlertException.getErrorKey()).isEqualTo("referencingProhibited");
});
}
@Test
public void financialContactShouldHaveRightToReadAllButRemark() throws IOException {
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, SOME_CUSTOMER_ID, Role.FINANCIAL_CONTACT);
final ShareDTO givenDTO = createShareDto();
// when
new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
// then
verify(jsonGenerator).writeNumberField("id", givenDTO.getId());
verify(jsonGenerator).writeNumberField("membershipId", givenDTO.getMembershipId());
verify(jsonGenerator, never()).writeStringField(eq("remark"), anyString());
}
@Test
public void supporterShouldHaveRightToRead() throws IOException {
givenAuthenticatedUser();
givenUserHavingRole(null, null, Role.SUPPORTER);
final ShareDTO givenDTO = createShareDto();
// when
new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
// then
verify(jsonGenerator).writeNumberField("id", givenDTO.getId());
verify(jsonGenerator).writeNumberField("membershipId", givenDTO.getMembershipId());
verify(jsonGenerator).writeStringField("remark", givenDTO.getRemark());
}
// --- only fixture code below ---
private void givenJSonTree(String givenJSon) throws IOException {
given(codec.readTree(jsonParser)).willReturn(new ObjectMapper().readTree(givenJSon));
}
private ShareDTO createShareDto() {
final ShareDTO givenDTO = new ShareDTO();
givenDTO.setId(1234567L);
givenDTO.setMembershipId(SOME_MEMBERSHIP_ID);
givenDTO.setAction(ShareAction.SUBSCRIPTION);
givenDTO.setQuantity(3);
givenDTO.setDocumentDate(LocalDate.parse("2019-04-22"));
givenDTO.setMembershipDocumentDate("2019-04-21"); // TODO: why is this not a LocalDate?
givenDTO.setValueDate(LocalDate.parse("2019-04-30"));
givenDTO.setRemark("Some Remark");
return givenDTO;
}
}