moving the JSonSerializer to a separate package
This commit is contained in:
		| @@ -0,0 +1,16 @@ | ||||
| package org.hostsharing.hsadminng.service.accessfilter; | ||||
|  | ||||
|  | ||||
| import java.lang.annotation.*; | ||||
|  | ||||
| @Target({ElementType.FIELD, ElementType.TYPE_USE}) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| public @interface AccessFor { | ||||
|     Role[] init() default Role.NOBODY; | ||||
|  | ||||
|     Role[] update() default Role.NOBODY; | ||||
|  | ||||
|     Role[] read() default Role.NOBODY; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,68 @@ | ||||
| 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.hostsharing.hsadminng.service.dto.CustomerDTO; | ||||
| 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; | ||||
|  | ||||
| @JsonComponent | ||||
| public class JSonSerializerWithAccessFilter extends JsonSerializer<Object> { | ||||
|  | ||||
|     @Override | ||||
|     public void serialize(Object dto, JsonGenerator jsonGenerator, | ||||
|                           SerializerProvider serializerProvider) throws IOException { | ||||
|  | ||||
|         jsonGenerator.writeStartObject(); | ||||
|         for (Field prop : CustomerDTO.class.getDeclaredFields()) { | ||||
|             toJSon(dto, jsonGenerator, prop); | ||||
|         } | ||||
|  | ||||
|         jsonGenerator.writeEndObject(); | ||||
|     } | ||||
|  | ||||
|     private void toJSon(Object dto, JsonGenerator jsonGenerator, Field prop) throws IOException { | ||||
|         if (getLoginUserRole().isAllowedToRead(prop)) { | ||||
|             final String fieldName = prop.getName(); | ||||
|             if (Integer.class.isAssignableFrom(prop.getType()) || int.class.isAssignableFrom(prop.getType())) { | ||||
|                 jsonGenerator.writeNumberField(fieldName, (int) get(dto, prop)); | ||||
|             } else if (Long.class.isAssignableFrom(prop.getType()) || long.class.isAssignableFrom(prop.getType())) { | ||||
|                 jsonGenerator.writeNumberField(fieldName, (long) get(dto, prop)); | ||||
|             } else if (String.class.isAssignableFrom(prop.getType())) { | ||||
|                 jsonGenerator.writeStringField(fieldName, (String) get(dto, prop)); | ||||
|             } else { | ||||
|                 throw new NotImplementedException("property type not yet implemented" + prop); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private Object get(Object dto, Field field) { | ||||
|         try { | ||||
|             field.setAccessible(true); | ||||
|             return field.get(dto); | ||||
|         } catch (IllegalAccessException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private Role getLoginUserRole() { | ||||
|         return SecurityUtils.getCurrentUserLogin().map(u -> Role.valueOf(u.toUpperCase())).orElse(Role.ANYBODY); | ||||
|     } | ||||
|  | ||||
|     private Object invoke(Object dto, Method method) { | ||||
|         try { | ||||
|             return method.invoke(dto); | ||||
|         } catch (IllegalAccessException | InvocationTargetException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| package org.hostsharing.hsadminng.service.accessfilter; | ||||
|  | ||||
| import org.hostsharing.hsadminng.security.SecurityUtils; | ||||
|  | ||||
| import java.lang.reflect.Field; | ||||
|  | ||||
| public enum Role { | ||||
|     NOBODY(0), HOSTMASTER(1), ADMIN(2), SUPPORTER(3), | ||||
|     ANY_CUSTOMER_CONTACT(20), CONTRACTUAL_CONTACT(21), FINANCIAL_CONTACT(22), TECHNICAL_CONTACT(22), | ||||
|     ANY_CUSTOMER_USER(80), | ||||
|     ANYBODY(99); | ||||
|  | ||||
|     private final int level; | ||||
|  | ||||
|     Role(final int level) { | ||||
|         this.level = level; | ||||
|     } | ||||
|  | ||||
|     boolean covers(final Role role) { | ||||
|         return this == role || this.level < role.level; | ||||
|     } | ||||
|  | ||||
|     public boolean isAllowedToInit(Field field) { | ||||
|  | ||||
|         final AccessFor accessFor = field.getAnnotation(AccessFor.class); | ||||
|         if (accessFor == null) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return isRoleCovered(accessFor.init()); | ||||
|     } | ||||
|  | ||||
|     public boolean isAllowedToUpdate(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; | ||||
|         } | ||||
|  | ||||
|         return isRoleCovered(accessFor.update()); | ||||
|     } | ||||
|  | ||||
|     public boolean isAllowedToRead(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; | ||||
|         } | ||||
|  | ||||
|         return isRoleCovered(accessFor.read()); | ||||
|     } | ||||
|  | ||||
|     private boolean isRoleCovered(Role[] requiredRoles) { | ||||
|         for (Role accessAllowedForRole : requiredRoles) { | ||||
|             if (this.covers(accessAllowedForRole)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -11,6 +11,8 @@ import com.fasterxml.jackson.databind.node.IntNode; | ||||
| import com.fasterxml.jackson.databind.node.TextNode; | ||||
| import org.apache.commons.lang3.NotImplementedException; | ||||
| import org.hostsharing.hsadminng.security.SecurityUtils; | ||||
| import org.hostsharing.hsadminng.service.accessfilter.AccessFor; | ||||
| import org.hostsharing.hsadminng.service.accessfilter.Role; | ||||
| import org.springframework.boot.jackson.JsonComponent; | ||||
|  | ||||
| import javax.validation.constraints.*; | ||||
| @@ -254,75 +256,3 @@ public class CustomerDTO implements Serializable { | ||||
|     } | ||||
| } | ||||
|  | ||||
| enum Role { | ||||
|     NOBODY(0), HOSTMASTER(1), ADMIN(2), SUPPORTER(3), | ||||
|     ANY_CUSTOMER_CONTACT(20), CONTRACTUAL_CONTACT(21), FINANCIAL_CONTACT(22), TECHNICAL_CONTACT(22), | ||||
|     ANY_CUSTOMER_USER(80), | ||||
|     ANYBODY(99); | ||||
|  | ||||
|     private final int level; | ||||
|  | ||||
|     Role(final int level) { | ||||
|         this.level = level; | ||||
|     } | ||||
|  | ||||
|     boolean covers(final Role role) { | ||||
|         return this == role || this.level < role.level; | ||||
|     } | ||||
|  | ||||
|     public boolean isAllowedToInit(Field field) { | ||||
|  | ||||
|         final AccessFor accessFor = field.getAnnotation(AccessFor.class); | ||||
|         if (accessFor == null) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return isRoleCovered(accessFor.init()); | ||||
|     } | ||||
|  | ||||
|     public boolean isAllowedToUpdate(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; | ||||
|         } | ||||
|  | ||||
|         return isRoleCovered(accessFor.update()); | ||||
|     } | ||||
|  | ||||
|     public boolean isAllowedToRead(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; | ||||
|         } | ||||
|  | ||||
|         return isRoleCovered(accessFor.read()); | ||||
|     } | ||||
|  | ||||
|     private boolean isRoleCovered(Role[] requiredRoles) { | ||||
|         for (Role accessAllowedForRole : requiredRoles) { | ||||
|             if (this.covers(accessAllowedForRole)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @Target({ElementType.FIELD, ElementType.TYPE_USE}) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| @interface AccessFor { | ||||
|     Role[] init() default Role.NOBODY; | ||||
|  | ||||
|     Role[] update() default Role.NOBODY; | ||||
|  | ||||
|     Role[] read() default Role.NOBODY; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,6 @@ import static org.junit.Assert.assertEquals; | ||||
| @RunWith(SpringRunner.class) | ||||
| public class CustomerDTOUnitTest { | ||||
|  | ||||
|  | ||||
|     @Autowired | ||||
|     private ObjectMapper objectMapper; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user