JSonAccessFilter with initially working (hardcoded) grand parent role
This commit is contained in:
		@@ -1,15 +1,12 @@
 | 
				
			|||||||
package org.hostsharing.hsadminng.domain;
 | 
					package org.hostsharing.hsadminng.domain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.persistence.*;
 | 
					import javax.persistence.*;
 | 
				
			||||||
import javax.validation.constraints.*;
 | 
					import javax.validation.constraints.*;
 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Set;
 | 
					 | 
				
			||||||
import java.util.Objects;
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A Customer.
 | 
					 * A Customer.
 | 
				
			||||||
@@ -65,13 +62,21 @@ public class Customer implements Serializable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @OneToMany(mappedBy = "customer")
 | 
					    @OneToMany(mappedBy = "customer")
 | 
				
			||||||
    private Set<Membership> memberships = new HashSet<>();
 | 
					    private Set<Membership> memberships = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @OneToMany(mappedBy = "customer")
 | 
					    @OneToMany(mappedBy = "customer")
 | 
				
			||||||
    private Set<SepaMandate> sepamandates = new HashSet<>();
 | 
					    private Set<SepaMandate> sepamandates = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
 | 
					    // jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Long getId() {
 | 
					    public Long getId() {
 | 
				
			||||||
        return id;
 | 
					        return id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Customer id(long id) {
 | 
				
			||||||
 | 
					        this.id = id;
 | 
				
			||||||
 | 
					        return this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void setId(Long id) {
 | 
					    public void setId(Long id) {
 | 
				
			||||||
        this.id = id;
 | 
					        this.id = id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -229,6 +234,7 @@ public class Customer implements Serializable {
 | 
				
			|||||||
    public void setSepamandates(Set<SepaMandate> sepaMandates) {
 | 
					    public void setSepamandates(Set<SepaMandate> sepaMandates) {
 | 
				
			||||||
        this.sepamandates = sepaMandates;
 | 
					        this.sepamandates = sepaMandates;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
 | 
					    // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,16 @@
 | 
				
			|||||||
package org.hostsharing.hsadminng.domain;
 | 
					package org.hostsharing.hsadminng.domain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 | 
					import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.persistence.*;
 | 
					import javax.persistence.*;
 | 
				
			||||||
import javax.validation.constraints.*;
 | 
					import javax.validation.constraints.NotNull;
 | 
				
			||||||
 | 
					import javax.validation.constraints.Size;
 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
import java.time.LocalDate;
 | 
					import java.time.LocalDate;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Set;
 | 
					 | 
				
			||||||
import java.util.Objects;
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A Membership.
 | 
					 * A Membership.
 | 
				
			||||||
@@ -46,18 +45,26 @@ public class Membership implements Serializable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @OneToMany(mappedBy = "membership")
 | 
					    @OneToMany(mappedBy = "membership")
 | 
				
			||||||
    private Set<Share> shares = new HashSet<>();
 | 
					    private Set<Share> shares = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @OneToMany(mappedBy = "membership")
 | 
					    @OneToMany(mappedBy = "membership")
 | 
				
			||||||
    private Set<Asset> assets = new HashSet<>();
 | 
					    private Set<Asset> assets = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ManyToOne(optional = false)
 | 
					    @ManyToOne(optional = false)
 | 
				
			||||||
    @NotNull
 | 
					    @NotNull
 | 
				
			||||||
    @JsonIgnoreProperties("memberships")
 | 
					    @JsonIgnoreProperties("memberships")
 | 
				
			||||||
    private Customer customer;
 | 
					    private Customer customer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
 | 
					    // jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Long getId() {
 | 
					    public Long getId() {
 | 
				
			||||||
        return id;
 | 
					        return id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Membership id(Long id) {
 | 
				
			||||||
 | 
					        this.id = id;
 | 
				
			||||||
 | 
					        return this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void setId(Long id) {
 | 
					    public void setId(Long id) {
 | 
				
			||||||
        this.id = id;
 | 
					        this.id = id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -176,6 +183,7 @@ public class Membership implements Serializable {
 | 
				
			|||||||
    public void setCustomer(Customer customer) {
 | 
					    public void setCustomer(Customer customer) {
 | 
				
			||||||
        this.customer = customer;
 | 
					        this.customer = customer;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
 | 
					    // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@ import org.hostsharing.hsadminng.service.dto.CustomerDTO;
 | 
				
			|||||||
import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
 | 
					import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
 | 
				
			||||||
import org.slf4j.Logger;
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
import org.slf4j.LoggerFactory;
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.springframework.data.domain.Page;
 | 
					import org.springframework.data.domain.Page;
 | 
				
			||||||
import org.springframework.data.domain.Pageable;
 | 
					import org.springframework.data.domain.Pageable;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
@@ -19,7 +18,7 @@ import java.util.Optional;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
@Service
 | 
					@Service
 | 
				
			||||||
@Transactional
 | 
					@Transactional
 | 
				
			||||||
public class CustomerService {
 | 
					public class CustomerService implements DtoLoader<CustomerDTO> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final Logger log = LoggerFactory.getLogger(CustomerService.class);
 | 
					    private final Logger log = LoggerFactory.getLogger(CustomerService.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package org.hostsharing.hsadminng.service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface DtoLoader<T> {
 | 
				
			||||||
 | 
					    Optional<? extends T> findOne(Long id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -19,7 +19,7 @@ import java.util.Optional;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
@Service
 | 
					@Service
 | 
				
			||||||
@Transactional
 | 
					@Transactional
 | 
				
			||||||
public class MembershipService {
 | 
					public class MembershipService implements DtoLoader<MembershipDTO> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final Logger log = LoggerFactory.getLogger(MembershipService.class);
 | 
					    private final Logger log = LoggerFactory.getLogger(MembershipService.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,6 +73,7 @@ public class MembershipService {
 | 
				
			|||||||
     * @param id the id of the entity
 | 
					     * @param id the id of the entity
 | 
				
			||||||
     * @return the entity
 | 
					     * @return the entity
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
    @Transactional(readOnly = true)
 | 
					    @Transactional(readOnly = true)
 | 
				
			||||||
    public Optional<MembershipDTO> findOne(Long id) {
 | 
					    public Optional<MembershipDTO> findOne(Long id) {
 | 
				
			||||||
        log.debug("Request to get Membership : {}", id);
 | 
					        log.debug("Request to get Membership : {}", id);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,35 +1,33 @@
 | 
				
			|||||||
package org.hostsharing.hsadminng.service.accessfilter;
 | 
					package org.hostsharing.hsadminng.service.accessfilter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.NotImplementedException;
 | 
				
			||||||
import org.hostsharing.hsadminng.security.SecurityUtils;
 | 
					import org.hostsharing.hsadminng.security.SecurityUtils;
 | 
				
			||||||
 | 
					import org.hostsharing.hsadminng.service.CustomerService;
 | 
				
			||||||
 | 
					import org.hostsharing.hsadminng.service.DtoLoader;
 | 
				
			||||||
 | 
					import org.hostsharing.hsadminng.service.MembershipService;
 | 
				
			||||||
 | 
					import org.hostsharing.hsadminng.service.dto.CustomerDTO;
 | 
				
			||||||
 | 
					import org.hostsharing.hsadminng.service.dto.MembershipDTO;
 | 
				
			||||||
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
 | 
					import org.hostsharing.hsadminng.service.util.ReflectionUtil;
 | 
				
			||||||
 | 
					import org.springframework.context.ApplicationContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.annotation.Annotation;
 | 
				
			||||||
import java.lang.reflect.Field;
 | 
					import java.lang.reflect.Field;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class JSonAccessFilter<T> {
 | 
					abstract class JSonAccessFilter<T> {
 | 
				
			||||||
 | 
					    private final ApplicationContext ctx;
 | 
				
			||||||
    final T dto;
 | 
					    final T dto;
 | 
				
			||||||
    Field selfIdField = null;
 | 
					    final Field selfIdField;
 | 
				
			||||||
    Field parentIdField = null;
 | 
					    final Field parentIdField;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    JSonAccessFilter(final T dto) {
 | 
					    JSonAccessFilter(final ApplicationContext ctx, final T dto) {
 | 
				
			||||||
 | 
					        this.ctx = ctx;
 | 
				
			||||||
        this.dto = dto;
 | 
					        this.dto = dto;
 | 
				
			||||||
        determineIdFields();
 | 
					        this.selfIdField = determineFieldWithAnnotation(dto.getClass(), SelfId.class);
 | 
				
			||||||
 | 
					        this.parentIdField = determineFieldWithAnnotation(dto.getClass(), ParentId.class);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void determineIdFields() {
 | 
					    boolean isParentIdField(final Field field) {
 | 
				
			||||||
        for (Field field : dto.getClass().getDeclaredFields()) {
 | 
					        return field.equals(parentIdField);
 | 
				
			||||||
            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() {
 | 
					    Long getId() {
 | 
				
			||||||
@@ -39,27 +37,68 @@ abstract class JSonAccessFilter<T> {
 | 
				
			|||||||
        return (Long) ReflectionUtil.getValue(dto, selfIdField);
 | 
					        return (Long) ReflectionUtil.getValue(dto, selfIdField);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param field to get a display representation for
 | 
				
			||||||
 | 
					     * @return a simplified, decently user readable, display representation of the given field
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    String toDisplay(final Field field) {
 | 
					    String toDisplay(final Field field) {
 | 
				
			||||||
        return field.getDeclaringClass().getSimpleName() + "." + field.getName();
 | 
					        return field.getDeclaringClass().getSimpleName() + "." + field.getName();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return the role of the login user in relation to the dto, this filter is created for.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    Role getLoginUserRole() {
 | 
					    Role getLoginUserRole() {
 | 
				
			||||||
        final Role roleOnSelf = getLoginUserRoleOnSelf();
 | 
					        final Role roleOnSelf = getLoginUserRoleOnSelf();
 | 
				
			||||||
        final Role roleOnParent = getLoginUserRoleOnParent();
 | 
					        if ( roleOnSelf.isIndependent() ) {
 | 
				
			||||||
        return roleOnSelf.covers(roleOnParent) ? roleOnSelf : roleOnParent;
 | 
					            return roleOnSelf;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return getLoginUserRoleOnAncestorOfDtoClassIfHigher(roleOnSelf, dto);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Role getLoginUserRoleOnSelf() {
 | 
					    private Role getLoginUserRoleOnSelf() {
 | 
				
			||||||
        // TODO: find broadest role in self and recursively in parent
 | 
					 | 
				
			||||||
        return SecurityUtils.getLoginUserRoleFor(dto.getClass(), getId() );
 | 
					        return SecurityUtils.getLoginUserRoleFor(dto.getClass(), getId() );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Role getLoginUserRoleOnParent() {
 | 
					    private Role getLoginUserRoleOnAncestorOfDtoClassIfHigher(final Role baseRole, final Object dto) {
 | 
				
			||||||
 | 
					        final Field parentIdField = determineFieldWithAnnotation(dto.getClass(), ParentId.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ( parentIdField == null ) {
 | 
					        if ( parentIdField == null ) {
 | 
				
			||||||
            return Role.ANYBODY;
 | 
					            return baseRole;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        final ParentId parentId = parentIdField.getAnnotation(ParentId.class);
 | 
					
 | 
				
			||||||
        return SecurityUtils.getLoginUserRoleFor(parentId.value(), (Long) ReflectionUtil.getValue(dto, parentIdField) );
 | 
					        final ParentId parentIdAnnot = parentIdField.getAnnotation(ParentId.class);
 | 
				
			||||||
 | 
					        final Class<?> parentDtoClass = parentIdAnnot.value();
 | 
				
			||||||
 | 
					        final Long parentId = (Long) ReflectionUtil.getValue(dto, parentIdField);
 | 
				
			||||||
 | 
					        final Role roleOnParent = SecurityUtils.getLoginUserRoleFor(parentDtoClass, parentId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final Object parentEntity = findParentDto(parentDtoClass, parentId);
 | 
				
			||||||
 | 
					        return Role.broadest(baseRole, getLoginUserRoleOnAncestorOfDtoClassIfHigher(roleOnParent, parentEntity));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Object findParentDto(Class<?> parentDtoClass, Long parentId) {
 | 
				
			||||||
 | 
					        // TODO: generalize, e.g. via "all beans that implement DtoLoader<CustomerDTO>
 | 
				
			||||||
 | 
					        if ( parentDtoClass == MembershipDTO.class ) {
 | 
				
			||||||
 | 
					            final DtoLoader<MembershipDTO> dtoLoader = ctx.getAutowireCapableBeanFactory().createBean(MembershipService.class);
 | 
				
			||||||
 | 
					            return dtoLoader.findOne(parentId).get();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if ( parentDtoClass == CustomerDTO.class ) {
 | 
				
			||||||
 | 
					            final DtoLoader<CustomerDTO> dtoLoader = ctx.getAutowireCapableBeanFactory().createBean(CustomerService.class);
 | 
				
			||||||
 | 
					            return dtoLoader.findOne(parentId).get();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        throw new NotImplementedException("no DtoLoader implemented for " + parentDtoClass);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Field determineFieldWithAnnotation(final Class<?> dtoClass, final Class<? extends Annotation> idAnnotationClass) {
 | 
				
			||||||
 | 
					        Field parentIdField = null;
 | 
				
			||||||
 | 
					        for (Field field : dtoClass.getDeclaredFields()) {
 | 
				
			||||||
 | 
					            if (field.isAnnotationPresent(idAnnotationClass)) {
 | 
				
			||||||
 | 
					                if (parentIdField != null) {
 | 
				
			||||||
 | 
					                    throw new AssertionError("multiple @" + idAnnotationClass.getSimpleName() + " detected in " + field.getDeclaringClass().getSimpleName());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                parentIdField = field;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return parentIdField;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.node.TextNode;
 | 
				
			|||||||
import org.apache.commons.lang3.NotImplementedException;
 | 
					import org.apache.commons.lang3.NotImplementedException;
 | 
				
			||||||
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
 | 
					import org.hostsharing.hsadminng.service.util.ReflectionUtil;
 | 
				
			||||||
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
 | 
					import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
 | 
				
			||||||
 | 
					import org.springframework.context.ApplicationContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.lang.reflect.Field;
 | 
					import java.lang.reflect.Field;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
@@ -21,8 +22,8 @@ public class JSonDeserializerWithAccessFilter<T> extends JSonAccessFilter<T> {
 | 
				
			|||||||
    private final TreeNode treeNode;
 | 
					    private final TreeNode treeNode;
 | 
				
			||||||
    private final Set<Field> modifiedFields = new HashSet<>();
 | 
					    private final Set<Field> modifiedFields = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public JSonDeserializerWithAccessFilter(final JsonParser jsonParser, final DeserializationContext deserializationContext, Class<T> dtoClass) {
 | 
					    public JSonDeserializerWithAccessFilter(final ApplicationContext ctx, final JsonParser jsonParser, final DeserializationContext deserializationContext, Class<T> dtoClass) {
 | 
				
			||||||
        super(unchecked(dtoClass::newInstance));
 | 
					        super(ctx, unchecked(dtoClass::newInstance));
 | 
				
			||||||
        this.treeNode = unchecked(() -> jsonParser.getCodec().readTree(jsonParser));
 | 
					        this.treeNode = unchecked(() -> jsonParser.getCodec().readTree(jsonParser));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,18 +4,21 @@ package org.hostsharing.hsadminng.service.accessfilter;
 | 
				
			|||||||
import com.fasterxml.jackson.core.JsonGenerator;
 | 
					import com.fasterxml.jackson.core.JsonGenerator;
 | 
				
			||||||
import com.fasterxml.jackson.databind.SerializerProvider;
 | 
					import com.fasterxml.jackson.databind.SerializerProvider;
 | 
				
			||||||
import org.apache.commons.lang3.NotImplementedException;
 | 
					import org.apache.commons.lang3.NotImplementedException;
 | 
				
			||||||
 | 
					import org.springframework.context.ApplicationContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.lang.reflect.Field;
 | 
					import java.lang.reflect.Field;
 | 
				
			||||||
 | 
					import java.time.LocalDate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class JSonSerializerWithAccessFilter <T> extends JSonAccessFilter<T> {
 | 
					public class JSonSerializerWithAccessFilter <T> extends JSonAccessFilter<T> {
 | 
				
			||||||
    private final JsonGenerator jsonGenerator;
 | 
					    private final JsonGenerator jsonGenerator;
 | 
				
			||||||
    private final SerializerProvider serializerProvider;
 | 
					    private final SerializerProvider serializerProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public JSonSerializerWithAccessFilter(final JsonGenerator jsonGenerator,
 | 
					    public JSonSerializerWithAccessFilter(final ApplicationContext ctx,
 | 
				
			||||||
 | 
					                                          final JsonGenerator jsonGenerator,
 | 
				
			||||||
                                          final SerializerProvider serializerProvider,
 | 
					                                          final SerializerProvider serializerProvider,
 | 
				
			||||||
                                          final T dto) {
 | 
					                                          final T dto) {
 | 
				
			||||||
        super(dto);
 | 
					        super(ctx, dto);
 | 
				
			||||||
        this.jsonGenerator = jsonGenerator;
 | 
					        this.jsonGenerator = jsonGenerator;
 | 
				
			||||||
        this.serializerProvider = serializerProvider;
 | 
					        this.serializerProvider = serializerProvider;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -42,6 +45,10 @@ public class JSonSerializerWithAccessFilter <T> extends JSonAccessFilter<T> {
 | 
				
			|||||||
                jsonGenerator.writeNumberField(fieldName, (int) get(dto, prop));
 | 
					                jsonGenerator.writeNumberField(fieldName, (int) get(dto, prop));
 | 
				
			||||||
            } else if (Long.class.isAssignableFrom(prop.getType()) || long.class.isAssignableFrom(prop.getType())) {
 | 
					            } else if (Long.class.isAssignableFrom(prop.getType()) || long.class.isAssignableFrom(prop.getType())) {
 | 
				
			||||||
                jsonGenerator.writeNumberField(fieldName, (long) get(dto, prop));
 | 
					                jsonGenerator.writeNumberField(fieldName, (long) get(dto, prop));
 | 
				
			||||||
 | 
					            } else if (LocalDate.class.isAssignableFrom(prop.getType())) {
 | 
				
			||||||
 | 
					                jsonGenerator.writeStringField(fieldName, get(dto, prop).toString()); // TODO proper format
 | 
				
			||||||
 | 
					            } else if (Enum.class.isAssignableFrom(prop.getType())) {
 | 
				
			||||||
 | 
					                jsonGenerator.writeStringField(fieldName, get(dto, prop).toString()); // TODO proper representation
 | 
				
			||||||
            } else if (String.class.isAssignableFrom(prop.getType())) {
 | 
					            } else if (String.class.isAssignableFrom(prop.getType())) {
 | 
				
			||||||
                jsonGenerator.writeStringField(fieldName, (String) get(dto, prop));
 | 
					                jsonGenerator.writeStringField(fieldName, (String) get(dto, prop));
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,26 @@ public enum Role {
 | 
				
			|||||||
        this.level = level;
 | 
					        this.level = level;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return true if this role is independent of a target object, false otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public boolean isIndependent() {
 | 
				
			||||||
 | 
					        return covers(Role.SUPPORTER);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    @return the role with the broadest access rights
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static Role broadest(final Role role, final Role... roles) {
 | 
				
			||||||
 | 
					        Role broadests = role;
 | 
				
			||||||
 | 
					        for ( Role r: roles ) {
 | 
				
			||||||
 | 
					            if ( r.covers(broadests)) {
 | 
				
			||||||
 | 
					                broadests = r;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return broadests;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Determines if the given role is covered by this role.
 | 
					     * Determines if the given role is covered by this role.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -163,5 +183,4 @@ public enum Role {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.JsonSerializer;
 | 
				
			|||||||
import com.fasterxml.jackson.databind.SerializerProvider;
 | 
					import com.fasterxml.jackson.databind.SerializerProvider;
 | 
				
			||||||
import org.hostsharing.hsadminng.service.accessfilter.*;
 | 
					import org.hostsharing.hsadminng.service.accessfilter.*;
 | 
				
			||||||
import org.springframework.boot.jackson.JsonComponent;
 | 
					import org.springframework.boot.jackson.JsonComponent;
 | 
				
			||||||
 | 
					import org.springframework.context.ApplicationContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.validation.constraints.*;
 | 
					import javax.validation.constraints.*;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
@@ -172,24 +173,34 @@ public class CustomerDTO implements Serializable {
 | 
				
			|||||||
    @JsonComponent
 | 
					    @JsonComponent
 | 
				
			||||||
    public static class CustomerJsonSerializer extends JsonSerializer<CustomerDTO> {
 | 
					    public static class CustomerJsonSerializer extends JsonSerializer<CustomerDTO> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private final ApplicationContext ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public CustomerJsonSerializer(final ApplicationContext ctx) {
 | 
				
			||||||
 | 
					            this.ctx = ctx;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public void serialize(final CustomerDTO customerDTO, final JsonGenerator jsonGenerator,
 | 
					        public void serialize(final CustomerDTO customerDTO, final JsonGenerator jsonGenerator,
 | 
				
			||||||
                              final SerializerProvider serializerProvider) throws IOException {
 | 
					                              final SerializerProvider serializerProvider) throws IOException {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
           new JSonSerializerWithAccessFilter<>(jsonGenerator, serializerProvider, customerDTO).serialize();
 | 
					           new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, serializerProvider, customerDTO).serialize();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @JsonComponent
 | 
					    @JsonComponent
 | 
				
			||||||
    public static class CustomerJsonDeserializer extends JsonDeserializer<CustomerDTO> {
 | 
					    public static class CustomerJsonDeserializer extends JsonDeserializer<CustomerDTO> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private final ApplicationContext ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public CustomerJsonDeserializer(final ApplicationContext ctx) {
 | 
				
			||||||
 | 
					            this.ctx = ctx;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public CustomerDTO deserialize(final JsonParser jsonParser,
 | 
					        public CustomerDTO deserialize(final JsonParser jsonParser,
 | 
				
			||||||
                                       final DeserializationContext deserializationContext) {
 | 
					                                       final DeserializationContext deserializationContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new JSonDeserializerWithAccessFilter<>(jsonParser, deserializationContext, CustomerDTO.class).deserialize();
 | 
					            return new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, deserializationContext, CustomerDTO.class).deserialize();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,10 +37,10 @@ public class MembershipDTO implements Serializable {
 | 
				
			|||||||
    private String remark;
 | 
					    private String remark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ParentId(CustomerDTO.class)
 | 
					    @ParentId(CustomerDTO.class)
 | 
				
			||||||
    @AccessFor(init = Role.ADMIN, read = Role.SUPPORTER)
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private Long customerId;
 | 
					    private Long customerId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private String customerPrefix;
 | 
					    private String customerPrefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public MembershipDTO with(
 | 
					    public MembershipDTO with(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,35 +1,51 @@
 | 
				
			|||||||
package org.hostsharing.hsadminng.service.dto;
 | 
					package org.hostsharing.hsadminng.service.dto;
 | 
				
			||||||
import java.time.LocalDate;
 | 
					
 | 
				
			||||||
import javax.validation.constraints.*;
 | 
					 | 
				
			||||||
import java.io.Serializable;
 | 
					 | 
				
			||||||
import java.util.Objects;
 | 
					 | 
				
			||||||
import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
 | 
					import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					import java.time.LocalDate;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A DTO for the Share entity.
 | 
					 * A DTO for the Share entity.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class ShareDTO implements Serializable {
 | 
					public class ShareDTO implements Serializable {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SelfId
 | 
				
			||||||
 | 
					    @AccessFor(read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private Long id;
 | 
					    private Long id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @NotNull
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private LocalDate documentDate;
 | 
					    private LocalDate documentDate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @NotNull
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private LocalDate valueDate;
 | 
					    private LocalDate valueDate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @NotNull
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private ShareAction action;
 | 
					    private ShareAction action;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull
 | 
					    @NotNull
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private Integer quantity;
 | 
					    private Integer quantity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Size(max = 160)
 | 
					    @Size(max = 160)
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = Role.SUPPORTER)
 | 
				
			||||||
    private String remark;
 | 
					    private String remark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ParentId(MembershipDTO.class)
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
 | 
				
			||||||
    private Long membershipId;
 | 
					    private Long membershipId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @AccessFor(init = Role.ADMIN, read = Role.SUPPORTER)
 | 
				
			||||||
    private String membershipDocumentDate;
 | 
					    private String membershipDocumentDate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Long getId() {
 | 
					    public Long getId() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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() + "\"";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,11 +12,13 @@ import org.junit.Test;
 | 
				
			|||||||
import org.mockito.Mock;
 | 
					import org.mockito.Mock;
 | 
				
			||||||
import org.mockito.junit.MockitoJUnit;
 | 
					import org.mockito.junit.MockitoJUnit;
 | 
				
			||||||
import org.mockito.junit.MockitoRule;
 | 
					import org.mockito.junit.MockitoRule;
 | 
				
			||||||
 | 
					import org.springframework.context.ApplicationContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
import static org.assertj.core.api.Assertions.catchThrowable;
 | 
					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.givenAuthenticatedUser;
 | 
				
			||||||
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
 | 
					import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
 | 
				
			||||||
import static org.mockito.BDDMockito.given;
 | 
					import static org.mockito.BDDMockito.given;
 | 
				
			||||||
@@ -27,6 +29,9 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
    @Rule
 | 
					    @Rule
 | 
				
			||||||
    public MockitoRule mockitoRule = MockitoJUnit.rule();
 | 
					    public MockitoRule mockitoRule = MockitoJUnit.rule();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Mock
 | 
				
			||||||
 | 
					    public ApplicationContext ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Mock
 | 
					    @Mock
 | 
				
			||||||
    public JsonParser jsonParser;
 | 
					    public JsonParser jsonParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +57,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
            ImmutablePair.of("openStringField", "String Value")));
 | 
					            ImmutablePair.of("openStringField", "String Value")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
 | 
					        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(actualDto.openStringField).isEqualTo("String Value");
 | 
					        assertThat(actualDto.openStringField).isEqualTo("String Value");
 | 
				
			||||||
@@ -66,7 +71,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
            ImmutablePair.of("openIntegerField", 1234)));
 | 
					            ImmutablePair.of("openIntegerField", 1234)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
 | 
					        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(actualDto.openIntegerField).isEqualTo(1234);
 | 
					        assertThat(actualDto.openIntegerField).isEqualTo(1234);
 | 
				
			||||||
@@ -80,7 +85,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
            ImmutablePair.of("openLongField", 1234L)));
 | 
					            ImmutablePair.of("openLongField", 1234L)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
 | 
					        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(actualDto.openLongField).isEqualTo(1234L);
 | 
					        assertThat(actualDto.openLongField).isEqualTo(1234L);
 | 
				
			||||||
@@ -96,7 +101,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
            ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
					            ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize();
 | 
					        GivenDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(actualDto.restrictedField).isEqualTo("Restricted String Value");
 | 
					        assertThat(actualDto.restrictedField).isEqualTo("Restricted String Value");
 | 
				
			||||||
@@ -110,7 +115,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        givenJSonTree(asJSon(ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
					        givenJSonTree(asJSon(ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize());
 | 
					        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
 | 
					        assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
 | 
				
			||||||
@@ -127,7 +132,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
 | 
					        givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenChildDto.class).deserialize());
 | 
					        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenChildDto.class).deserialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
 | 
					        assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
 | 
				
			||||||
@@ -144,7 +149,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
 | 
					        givenJSonTree(asJSon(ImmutablePair.of("parentId", 1111L)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        final GivenChildDto actualDto = new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenChildDto.class).deserialize();
 | 
					        final GivenChildDto actualDto = new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenChildDto.class).deserialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(actualDto.parentId).isEqualTo(1111L);
 | 
					        assertThat(actualDto.parentId).isEqualTo(1111L);
 | 
				
			||||||
@@ -160,7 +165,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
            ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
					            ImmutablePair.of("restrictedField", "Restricted String Value")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDto.class).deserialize());
 | 
					        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDto.class).deserialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
 | 
					        assertThat(exception).isInstanceOfSatisfying(BadRequestAlertException.class, badRequestAlertException -> {
 | 
				
			||||||
@@ -175,7 +180,7 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        givenJSonTree(asJSon(ImmutablePair.of("id", 1111L)));
 | 
					        givenJSonTree(asJSon(ImmutablePair.of("id", 1111L)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(jsonParser, null, GivenDtoWithMultipleSelfId.class).deserialize());
 | 
					        Throwable exception = catchThrowable(() -> new JSonDeserializerWithAccessFilter<>(ctx, jsonParser, null, GivenDtoWithMultipleSelfId.class).deserialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(exception).isInstanceOf(AssertionError.class).hasMessage("multiple @SelfId detected in GivenDtoWithMultipleSelfId");
 | 
					        assertThat(exception).isInstanceOf(AssertionError.class).hasMessage("multiple @SelfId detected in GivenDtoWithMultipleSelfId");
 | 
				
			||||||
@@ -183,30 +188,10 @@ public class JSonDeserializerWithAccessFilterUnitTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // --- only fixture code below ---
 | 
					    // --- 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 {
 | 
					    private void givenJSonTree(String givenJSon) throws IOException {
 | 
				
			||||||
        given(codec.readTree(jsonParser)).willReturn(new ObjectMapper().readTree(givenJSon));
 | 
					        given(codec.readTree(jsonParser)).willReturn(new ObjectMapper().readTree(givenJSon));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String inQuotes(Object value) {
 | 
					 | 
				
			||||||
        return "\"" + value.toString() + "\"";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static class GivenDto {
 | 
					    public static class GivenDto {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @SelfId
 | 
					        @SelfId
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ import org.junit.Test;
 | 
				
			|||||||
import org.mockito.Mock;
 | 
					import org.mockito.Mock;
 | 
				
			||||||
import org.mockito.junit.MockitoJUnit;
 | 
					import org.mockito.junit.MockitoJUnit;
 | 
				
			||||||
import org.mockito.junit.MockitoRule;
 | 
					import org.mockito.junit.MockitoRule;
 | 
				
			||||||
 | 
					import org.springframework.context.ApplicationContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,6 +24,9 @@ public class JSonSerializerWithAccessFilterUnitTest {
 | 
				
			|||||||
    @Rule
 | 
					    @Rule
 | 
				
			||||||
    public MockitoRule mockitoRule = MockitoJUnit.rule();
 | 
					    public MockitoRule mockitoRule = MockitoJUnit.rule();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Mock
 | 
				
			||||||
 | 
					    public ApplicationContext ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Mock
 | 
					    @Mock
 | 
				
			||||||
    public JsonGenerator jsonGenerator;
 | 
					    public JsonGenerator jsonGenerator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,7 +41,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
 | 
				
			|||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    public void shouldSerializeStringField() throws IOException {
 | 
					    public void shouldSerializeStringField() throws IOException {
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
 | 
					        new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        verify(jsonGenerator).writeStringField("openStringField", givenDTO.openStringField);
 | 
					        verify(jsonGenerator).writeStringField("openStringField", givenDTO.openStringField);
 | 
				
			||||||
@@ -51,7 +55,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.FINANCIAL_CONTACT);
 | 
					        MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.FINANCIAL_CONTACT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
 | 
					        new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        verify(jsonGenerator).writeStringField("restrictedField", givenDTO.restrictedField);
 | 
					        verify(jsonGenerator).writeStringField("restrictedField", givenDTO.restrictedField);
 | 
				
			||||||
@@ -65,7 +69,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.ANY_CUSTOMER_USER);
 | 
					        MockSecurityContext.givenUserHavingRole(GivenCustomerDto.class, 888L, Role.ANY_CUSTOMER_USER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDTO).serialize();
 | 
					        new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDTO).serialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        verify(jsonGenerator, never()).writeStringField("restrictedField", givenDTO.restrictedField);
 | 
					        verify(jsonGenerator, never()).writeStringField("restrictedField", givenDTO.restrictedField);
 | 
				
			||||||
@@ -84,7 +88,7 @@ public class JSonSerializerWithAccessFilterUnitTest {
 | 
				
			|||||||
        final GivenDtoWithUnimplementedFieldType givenDtoWithUnimplementedFieldType = new GivenDtoWithUnimplementedFieldType();
 | 
					        final GivenDtoWithUnimplementedFieldType givenDtoWithUnimplementedFieldType = new GivenDtoWithUnimplementedFieldType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when
 | 
					        // when
 | 
				
			||||||
        Throwable actual = catchThrowable(() -> new JSonSerializerWithAccessFilter<>(jsonGenerator, null, givenDtoWithUnimplementedFieldType).serialize());
 | 
					        final Throwable actual = catchThrowable(() -> new JSonSerializerWithAccessFilter<>(ctx, jsonGenerator, null, givenDtoWithUnimplementedFieldType).serialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then
 | 
					        // then
 | 
				
			||||||
        assertThat(actual).isInstanceOf(NotImplementedException.class);
 | 
					        assertThat(actual).isInstanceOf(NotImplementedException.class);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,9 @@ public class MockSecurityContext {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void givenUserHavingRole(final Class<?> onClass, final Long onId, final Role role) {
 | 
					    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);
 | 
					        SecurityUtils.addUserRole(onClass, onId, role);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user