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,9 +1,12 @@
package org.hostsharing.hsadminng.security;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
@ -11,6 +14,8 @@ import java.util.Optional;
*/
public final class SecurityUtils {
private static List<UserRoleAssignment> userRoleAssignments = new ArrayList<>();
private SecurityUtils() {
}
@ -73,4 +78,42 @@ public final class SecurityUtils {
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority)))
.orElse(false);
}
public static Role getLoginUserRoleFor(final Class<?> onDtoClass, final Long onId) {
final Role highestRole = userRoleAssignments.stream().
map(ura ->
matches(onDtoClass, onId, ura)
? ura.role
: Role.ANYBODY).
reduce(Role.ANYBODY, (r1, r2) -> r1.covers(r2) ? r1 : r2);
return highestRole;
}
private static boolean matches(Class<?> onDtoClass, Long onId, UserRoleAssignment ura) {
final boolean matches = (ura.onClass == null || onDtoClass == ura.onClass) && (ura.onId == null || onId.equals(ura.onId) );
return matches;
}
// TODO: depends on https://plan.hostsharing.net/project/hsadmin/us/67?milestone=34
public static void addUserRole(final Class<?> onClass, final Long onId, final Role role) {
userRoleAssignments.add(new UserRoleAssignment(onClass, onId, role));
}
public static void clearUserRoles() {
userRoleAssignments.clear();
}
private static class UserRoleAssignment {
final Class<?> onClass;
final Long onId;
final Role role;
UserRoleAssignment(Class<?> onClass, Long onId, Role role) {
this.onClass = onClass;
this.onId = onId;
this.role = role;
}
}
}

View File

@ -0,0 +1,65 @@
package org.hostsharing.hsadminng.service.accessfilter;
import org.hostsharing.hsadminng.security.SecurityUtils;
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
import java.lang.reflect.Field;
abstract class JSonAccessFilter<T> {
final T dto;
Field selfIdField = null;
Field parentIdField = null;
JSonAccessFilter(final T dto) {
this.dto = dto;
determineIdFields();
}
void determineIdFields() {
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;
}
if (field.isAnnotationPresent(ParentId.class)) {
if (parentIdField != null) {
throw new AssertionError("multiple @" + ParentId.class.getSimpleName() + " detected in " + field.getDeclaringClass().getSimpleName());
}
parentIdField = field;
}
}
}
Long getId() {
if (selfIdField == null) {
return null;
}
return (Long) ReflectionUtil.getValue(dto, selfIdField);
}
String toDisplay(final Field field) {
return field.getDeclaringClass().getSimpleName() + "." + field.getName();
}
Role getLoginUserRole() {
final Role roleOnSelf = getLoginUserRoleOnSelf();
final Role roleOnParent = getLoginUserRoleOnParent();
return roleOnSelf.covers(roleOnParent) ? roleOnSelf : roleOnParent;
}
private Role getLoginUserRoleOnSelf() {
// TODO: find broadest role in self and recursively in parent
return SecurityUtils.getLoginUserRoleFor(dto.getClass(), getId() );
}
private Role getLoginUserRoleOnParent() {
if ( parentIdField == null ) {
return Role.ANYBODY;
}
final ParentId parentId = parentIdField.getAnnotation(ParentId.class);
return SecurityUtils.getLoginUserRoleFor(parentId.value(), (Long) ReflectionUtil.getValue(dto, parentIdField) );
}
}

View File

@ -7,7 +7,6 @@ import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.LongNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.apache.commons.lang3.NotImplementedException;
import org.hostsharing.hsadminng.security.SecurityUtils;
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
@ -17,37 +16,23 @@ import java.util.Set;
import static org.hostsharing.hsadminng.service.util.ReflectionUtil.unchecked;
public class JSonDeserializerWithAccessFilter<T> {
public class JSonDeserializerWithAccessFilter<T> extends JSonAccessFilter<T> {
private final T dto;
private final TreeNode treeNode;
private final Set<Field> modifiedFields = new HashSet<>();
private Field selfIdField = null;
public JSonDeserializerWithAccessFilter(final JsonParser jsonParser, final DeserializationContext deserializationContext, Class<T> dtoClass) {
super(unchecked(dtoClass::newInstance));
this.treeNode = unchecked(() -> jsonParser.getCodec().readTree(jsonParser));
this.dto = unchecked(dtoClass::newInstance);
}
// Jackson deserializes from the JsonParser, thus no input parameter needed.
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 -> {
try {
@ -90,34 +75,21 @@ public class JSonDeserializerWithAccessFilter<T> {
modifiedFields.add(field);
}
private Object getId() {
if (selfIdField == null) {
return null;
}
return ReflectionUtil.getValue(dto, selfIdField);
}
private void checkAccessToModifiedFields() {
modifiedFields.forEach(field -> {
if ( !field.equals(selfIdField) ) {
if (getId() == null) {
if (!getLoginUserRole().isAllowedToInit(field)) {
throw new BadRequestAlertException("Initialization of field prohibited for current user", toDisplay(field), "initializationProhibited");
if ( !field.equals(parentIdField)) {
throw new BadRequestAlertException("Initialization of field prohibited for current user", toDisplay(field), "initializationProhibited");
} else {
throw new BadRequestAlertException("Referencing field prohibited for current user", toDisplay(field), "referencingProhibited");
}
}
} else if (getId() != null) {
if (!getLoginUserRole().isAllowedToUpdate(field)) {
} else if (!getLoginUserRole().isAllowedToUpdate(field)) {
throw new BadRequestAlertException("Update of field prohibited for current user", toDisplay(field), "updateProhibited");
}
}
}
});
}
private String toDisplay(final Field field) {
return field.getDeclaringClass().getSimpleName() + "." + field.getName();
}
private Role getLoginUserRole() {
return SecurityUtils.getCurrentUserLogin().map(u -> Role.valueOf(u.toUpperCase())).orElse(Role.ANYBODY);
}
}

View File

@ -2,28 +2,22 @@ package org.hostsharing.hsadminng.service.accessfilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.lang3.NotImplementedException;
import org.hostsharing.hsadminng.security.SecurityUtils;
import org.springframework.boot.jackson.JsonComponent;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class JSonSerializerWithAccessFilter <T> {
public class JSonSerializerWithAccessFilter <T> extends JSonAccessFilter<T> {
private final JsonGenerator jsonGenerator;
private final SerializerProvider serializerProvider;
private final T dto;
public JSonSerializerWithAccessFilter(final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider,
final T dto) {
super(dto);
this.jsonGenerator = jsonGenerator;
this.serializerProvider = serializerProvider;
this.dto = dto;
}
// Jackson serializes into the JsonGenerator, thus no return value needed.
@ -65,7 +59,4 @@ public class JSonSerializerWithAccessFilter <T> {
}
}
private Role getLoginUserRole() {
return SecurityUtils.getCurrentUserLogin().map(u -> Role.valueOf(u.toUpperCase())).orElse(Role.ANYBODY);
}
}

View File

@ -0,0 +1,17 @@
package org.hostsharing.hsadminng.service.accessfilter;
import java.lang.annotation.*;
/**
* Used to mark a field within a DTO as containing the id of a referenced entity,
* it's needed to determine access rights for entity creation.
*
* @see AccessFor
*/
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParentId {
/// The DTO class of the referenced entity.
Class<?> value();
}

View File

@ -1,7 +1,5 @@
package org.hostsharing.hsadminng.service.accessfilter;
import org.hostsharing.hsadminng.security.SecurityUtils;
import java.lang.reflect.Field;
/**
@ -52,7 +50,7 @@ public enum Role {
*/
FINANCIAL_CONTACT(22) {
@Override
boolean covers(final Role role) {
public boolean covers(final Role role) {
if (role == ACTUAL_CUSTOMER_USER) {
return false;
}
@ -94,14 +92,15 @@ public enum Role {
*
* Where 'this' means the Java instance itself as a role of a system user.
*
* @example
* {@code
* Role.HOSTMASTER.covers(Role.ANY_CUSTOMER_USER) == true
* }
*
* @param role The required role for a resource.
*
* @return whether this role comprises the given role
*/
boolean covers(final Role role) {
public boolean covers(final Role role) {
return this == role || this.level < role.level;
}
@ -131,8 +130,6 @@ public enum Role {
*/
public boolean isAllowedToUpdate(final Field field) {
final Role loginUserRole = SecurityUtils.getCurrentUserLogin().map(u -> Role.valueOf(u.toUpperCase())).orElse(Role.ANYBODY);
final AccessFor accessFor = field.getAnnotation(AccessFor.class);
if (accessFor == null) {
return false;
@ -150,8 +147,6 @@ public enum Role {
*/
public boolean isAllowedToRead(final Field field) {
final Role loginUserRole = SecurityUtils.getCurrentUserLogin().map(u -> Role.valueOf(u.toUpperCase())).orElse(Role.ANYBODY);
final AccessFor accessFor = field.getAnnotation(AccessFor.class);
if (accessFor == null) {
return false;

View File

@ -1,7 +1,9 @@
package org.hostsharing.hsadminng.service.dto;
import org.hostsharing.hsadminng.service.accessfilter.AccessFor;
import org.hostsharing.hsadminng.service.accessfilter.ParentId;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.accessfilter.SelfId;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@ -15,6 +17,7 @@ import java.util.function.Consumer;
*/
public class MembershipDTO implements Serializable {
@SelfId
@AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private Long id;
@ -33,8 +36,8 @@ public class MembershipDTO implements Serializable {
@AccessFor(init = Role.ADMIN, read = Role.SUPPORTER)
private String remark;
// TODO @AccessFor(init = Role.ADMIN, read = Role.SUPPORTER)
// @AccessReference(CustomerDTO.class, Role...)
@ParentId(CustomerDTO.class)
@AccessFor(init = Role.ADMIN, read = Role.SUPPORTER)
private Long customerId;
@AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})

View File

@ -1,9 +1,6 @@
package org.hostsharing.hsadminng.service.util;
import com.fasterxml.jackson.core.TreeNode;
import java.lang.reflect.Field;
import java.util.function.Supplier;
public class ReflectionUtil {
@ -26,10 +23,10 @@ public class ReflectionUtil {
}
}
public static <T> Object getValue(T dto, Field field) {
public static <T> T getValue(final T dto, final Field field) {
try {
field.setAccessible(true);
return field.get(dto);
return (T) field.get(dto);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}

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()) +