From ee120b415f8de2a478ebea50e0795a7352d6ba10 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 27 May 2020 10:41:28 +0200 Subject: [PATCH 01/12] [Task 71143] initial implementation of the preauthorize annotations in the converterservice --- .../app/rest/converter/ConverterService.java | 76 +++++++++++++++++-- .../ExternalSourceHalLinkFactory.java | 1 - .../rest/repository/ItemRestRepository.java | 1 - 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java index 59ee666cfebc..26eae66e65bb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java @@ -7,8 +7,10 @@ */ package org.dspace.app.rest.converter; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -17,6 +19,7 @@ import javax.annotation.Nullable; import javax.annotation.PostConstruct; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.dspace.app.rest.link.HalLinkFactory; import org.dspace.app.rest.link.HalLinkService; @@ -26,17 +29,20 @@ import org.dspace.app.rest.model.hateoas.HALResource; import org.dspace.app.rest.projection.DefaultProjection; import org.dspace.app.rest.projection.Projection; +import org.dspace.app.rest.repository.DSpaceRestRepository; import org.dspace.app.rest.security.DSpacePermissionEvaluator; import org.dspace.app.rest.utils.Utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @@ -94,11 +100,19 @@ public R toRest(M modelObject, Projection projection) { DSpaceConverter converter = requireConverter(modelObject.getClass()); R restObject = converter.convert(transformedModel, projection); if (restObject instanceof BaseObjectRest) { - if (!dSpacePermissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), - restObject, "READ")) { - log.debug("Access denied on " + restObject.getClass() + " with id: " + - ((BaseObjectRest) restObject).getId()); - return null; + String permission = getPermissionForRestObject((BaseObjectRest) restObject); + if (!StringUtils.equalsIgnoreCase(permission, "permitAll")) { + if (StringUtils.equalsIgnoreCase(permission, "admin")) { + //TODO + } else if (StringUtils.equalsIgnoreCase(permission, "authenticated")) { + //TODO + } else { + if (!dSpacePermissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), + restObject, permission)) { + log.info("Access denied on " + restObject.getClass()); + return null; + } + } } } if (restObject instanceof RestModel) { @@ -107,6 +121,58 @@ public R toRest(M modelObject, Projection projection) { return restObject; } + private String getPermissionForRestObject(BaseObjectRest restObject) { + Annotation preAuthorize = getAnnotationForRestObject(restObject); + if (preAuthorize == null) { + preAuthorize = getDefaultFindOnePreAuthorize(); + + } + String permission = "READ"; + permission = parseAnnotation(preAuthorize); + return permission; + } + + private String parseAnnotation(Annotation preAuthorize) { + String permission = ""; + if (preAuthorize != null) { + String annotationValue = (String) AnnotationUtils.getValue(preAuthorize); + if (StringUtils.contains(annotationValue, "permitAll")) { + permission = "permitAll"; + } else if (StringUtils.contains(annotationValue, "hasAuthority")) { + permission = StringUtils.substringBetween(annotationValue, "hasAuthority('", "')"); + } else if (StringUtils.contains(annotationValue,"hasPermission")) { + permission = StringUtils.split(annotationValue, ",")[2]; + permission = StringUtils.substringBetween(permission, "'"); + } + } + return permission; + } + + private Annotation getAnnotationForRestObject(BaseObjectRest restObject) { + BaseObjectRest baseObjectRest = restObject; + DSpaceRestRepository repositoryToUse = utils + .getResourceRepositoryByCategoryAndModel(baseObjectRest.getCategory(), baseObjectRest.getType()); + Annotation preAuthorize = null; + for (Method m : repositoryToUse.getClass().getMethods()) { + if (StringUtils.equalsIgnoreCase(m.getName(), "findOne")) { + preAuthorize = AnnotationUtils.findAnnotation(m, PreAuthorize.class); + } + } + return preAuthorize; + } + + private Annotation getDefaultFindOnePreAuthorize() { + for (Method m : DSpaceRestRepository.class.getMethods()) { + if (StringUtils.equalsIgnoreCase(m.getName(), "findOne")) { + Annotation annotation = AnnotationUtils.findAnnotation(m, PreAuthorize.class); + if (annotation != null) { + return annotation; + } + } + } + return null; + } + /** * Converts a list of model objects to a page of rest objects using the given {@link Projection}. * diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java index e192c95404c1..7931593a3108 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java @@ -26,7 +26,6 @@ public class ExternalSourceHalLinkFactory extends @Override protected void addLinks(ExternalSourceResource halResource, Pageable pageable, LinkedList list) throws Exception { - list.add(buildLink("entries", getMethodOn() .getExternalSourceEntries(halResource.getContent().getName(), "", null, null, null))); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java index c6643496ae42..a3128e0afef4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java @@ -99,7 +99,6 @@ public ItemRestRepository(ItemService dsoService) { } @Override - @PreAuthorize("hasPermission(#id, 'ITEM', 'READ')") public ItemRest findOne(Context context, UUID id) { Item item = null; try { From e068abb87fe2f23f63571c335686edb859ca9c28 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 27 May 2020 10:43:31 +0200 Subject: [PATCH 02/12] undo unnecessary changes --- .../rest/link/externalsources/ExternalSourceHalLinkFactory.java | 1 + .../java/org/dspace/app/rest/repository/ItemRestRepository.java | 1 + 2 files changed, 2 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java index 7931593a3108..e192c95404c1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/externalsources/ExternalSourceHalLinkFactory.java @@ -26,6 +26,7 @@ public class ExternalSourceHalLinkFactory extends @Override protected void addLinks(ExternalSourceResource halResource, Pageable pageable, LinkedList list) throws Exception { + list.add(buildLink("entries", getMethodOn() .getExternalSourceEntries(halResource.getContent().getName(), "", null, null, null))); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java index a3128e0afef4..49b468e298b2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java @@ -99,6 +99,7 @@ public ItemRestRepository(ItemService dsoService) { } @Override + @PreAuthorize("hasPermission(#id, 'ITEM', 'WRITE')") public ItemRest findOne(Context context, UUID id) { Item item = null; try { From 6c0ee98fa616ea63af7aa68f6a500f7ef25be780 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Tue, 2 Jun 2020 14:56:00 +0200 Subject: [PATCH 03/12] SPEL parsing of the preAuthorize annotation in converterService work --- .../app/rest/converter/ConverterService.java | 16 ++++ .../spel/ExpressionValidationException.java | 7 ++ .../app/rest/spel/ExpressionValidator.java | 86 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java index 26eae66e65bb..cbff22f9a213 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java @@ -31,6 +31,8 @@ import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.repository.DSpaceRestRepository; import org.dspace.app.rest.security.DSpacePermissionEvaluator; +import org.dspace.app.rest.spel.ExpressionValidationException; +import org.dspace.app.rest.spel.ExpressionValidator; import org.dspace.app.rest.utils.Utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; @@ -40,8 +42,12 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; +import org.springframework.security.access.expression.SecurityExpressionRoot; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; @@ -136,6 +142,16 @@ private String parseAnnotation(Annotation preAuthorize) { String permission = ""; if (preAuthorize != null) { String annotationValue = (String) AnnotationUtils.getValue(preAuthorize); + ExpressionValidator validator = new ExpressionValidator(); + try { + validator.validate("hasPermission(123, 'ITEM', 'WRITE')", SecurityExpressionRoot.class); + } catch (ExpressionValidationException e) { + e.printStackTrace(); + } + +// ExpressionParser parser = new SpelExpressionParser(); +// Expression exp = parser.parseExpression("hasPermission('123', 'ITEM', 'WRITE')"); +// exp.getValue(SecurityExpressionRoot.class, boolean.class); if (StringUtils.contains(annotationValue, "permitAll")) { permission = "permitAll"; } else if (StringUtils.contains(annotationValue, "hasAuthority")) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java new file mode 100644 index 000000000000..9fbe73f19f4d --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java @@ -0,0 +1,7 @@ +package org.dspace.app.rest.spel; + +public class ExpressionValidationException extends Exception { + public ExpressionValidationException(String message) { + super(message); + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java new file mode 100644 index 000000000000..8cf1dc2a6c05 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java @@ -0,0 +1,86 @@ +package org.dspace.app.rest.spel; + +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.ParseException; +import org.springframework.expression.spel.SpelNode; +import org.springframework.expression.spel.ast.BeanReference; +import org.springframework.expression.spel.ast.MethodReference; +import org.springframework.expression.spel.ast.Operator; +import org.springframework.expression.spel.ast.TypeReference; +import org.springframework.expression.spel.ast.VariableReference; +import org.springframework.expression.spel.standard.SpelExpression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.security.access.expression.SecurityExpressionRoot; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ExpressionValidator { + private final ExpressionParser parser = new SpelExpressionParser(); + + public void validate(String expression, Class expressionRoot) throws ExpressionValidationException, ParseException { + SpelExpression exp = (SpelExpression) parser.parseExpression(expression); + if (expressionRoot != null) { + SpelNode node = exp.getAST(); + handle(node, expressionRoot); + } + } + + private void handle(SpelNode node, Class expressionRoot) throws ExpressionValidationException{ + if (node instanceof MethodReference) { + verify((MethodReference) node, expressionRoot); + } else if (node instanceof Operator) { + Operator operator = (Operator) node; + handle(operator.getLeftOperand(), expressionRoot); + handle(operator.getRightOperand(), expressionRoot); + } else if (node != null) { + for(int i=0; i expressionRoot) throws ExpressionValidationException { + String methodName = node.getName(); + int args = node.getChildCount(); + Method[] methods = expressionRoot.getDeclaredMethods(); + for(Method m : methods) { + if (m.getName().equals(methodName)) { + // exact match on the args + if (args == m.getParameterCount()) { + try { + SecurityExpressionRoot.class.getConstructor(Authentication.class).newInstance( + SecurityContextHolder.getContext().getAuthentication()); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + } + return; + } + Class[] parameterTypes = m.getParameterTypes(); + if (m.getName().equals(methodName) && + parameterTypes != null && + parameterTypes.length>=1 && + parameterTypes[parameterTypes.length-1].isArray()) { + // allow the number of params to be one less or >= the reported length + if(args == m.getParameterCount()-1 || args >= m.getParameterCount()) { + return; + } + } + } + } + // if we get here, then we were unable to match the method call + String pattern = "Unable to match method %s with %d params"; + throw new ExpressionValidationException(String.format(pattern, methodName, args)); + } + +} From 397a156186f33333e83e16bebb3b3940761fe5e7 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Fri, 5 Jun 2020 13:56:39 +0200 Subject: [PATCH 04/12] [Task 71143] Intermediate work on PreAuthorize annotation parsing --- .../app/rest/converter/ConverterService.java | 78 ++++++----------- .../WebSecurityExpressionEvaluator.java | 56 ++++++++++++ .../spel/ExpressionValidationException.java | 7 -- .../app/rest/spel/ExpressionValidator.java | 86 ------------------- 4 files changed, 82 insertions(+), 145 deletions(-) create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java index cbff22f9a213..e1d282fc8bd2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java @@ -31,9 +31,9 @@ import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.repository.DSpaceRestRepository; import org.dspace.app.rest.security.DSpacePermissionEvaluator; -import org.dspace.app.rest.spel.ExpressionValidationException; -import org.dspace.app.rest.spel.ExpressionValidator; +import org.dspace.app.rest.security.WebSecurityExpressionEvaluator; import org.dspace.app.rest.utils.Utils; +import org.dspace.services.RequestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; @@ -42,14 +42,9 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import org.springframework.expression.Expression; -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; -import org.springframework.security.access.expression.SecurityExpressionRoot; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @@ -83,6 +78,12 @@ public class ConverterService { @Autowired private DSpacePermissionEvaluator dSpacePermissionEvaluator; + @Autowired + private WebSecurityExpressionEvaluator webSecurityExpressionEvaluator; + + @Autowired + private RequestService requestService; + /** * Converts the given model object to a rest object, using the appropriate {@link DSpaceConverter} and * the given projection. @@ -106,19 +107,12 @@ public R toRest(M modelObject, Projection projection) { DSpaceConverter converter = requireConverter(modelObject.getClass()); R restObject = converter.convert(transformedModel, projection); if (restObject instanceof BaseObjectRest) { - String permission = getPermissionForRestObject((BaseObjectRest) restObject); - if (!StringUtils.equalsIgnoreCase(permission, "permitAll")) { - if (StringUtils.equalsIgnoreCase(permission, "admin")) { - //TODO - } else if (StringUtils.equalsIgnoreCase(permission, "authenticated")) { - //TODO - } else { - if (!dSpacePermissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), - restObject, permission)) { - log.info("Access denied on " + restObject.getClass()); - return null; - } - } + String preAuthorizeValue = getPreAuthorizeAnnotationForBaseObject((BaseObjectRest) restObject); + if (!webSecurityExpressionEvaluator + .evaluate(preAuthorizeValue, requestService.getCurrentRequest().getHttpServletRequest(), + requestService.getCurrentRequest().getHttpServletResponse())) { + log.info("Access denied on " + restObject.getClass()); + return null; } } if (restObject instanceof RestModel) { @@ -127,41 +121,21 @@ public R toRest(M modelObject, Projection projection) { return restObject; } - private String getPermissionForRestObject(BaseObjectRest restObject) { + private String getPreAuthorizeAnnotationForBaseObject(BaseObjectRest restObject) { Annotation preAuthorize = getAnnotationForRestObject(restObject); if (preAuthorize == null) { preAuthorize = getDefaultFindOnePreAuthorize(); } - String permission = "READ"; - permission = parseAnnotation(preAuthorize); - return permission; + return parseAnnotation(preAuthorize); + } private String parseAnnotation(Annotation preAuthorize) { - String permission = ""; if (preAuthorize != null) { - String annotationValue = (String) AnnotationUtils.getValue(preAuthorize); - ExpressionValidator validator = new ExpressionValidator(); - try { - validator.validate("hasPermission(123, 'ITEM', 'WRITE')", SecurityExpressionRoot.class); - } catch (ExpressionValidationException e) { - e.printStackTrace(); - } - -// ExpressionParser parser = new SpelExpressionParser(); -// Expression exp = parser.parseExpression("hasPermission('123', 'ITEM', 'WRITE')"); -// exp.getValue(SecurityExpressionRoot.class, boolean.class); - if (StringUtils.contains(annotationValue, "permitAll")) { - permission = "permitAll"; - } else if (StringUtils.contains(annotationValue, "hasAuthority")) { - permission = StringUtils.substringBetween(annotationValue, "hasAuthority('", "')"); - } else if (StringUtils.contains(annotationValue,"hasPermission")) { - permission = StringUtils.split(annotationValue, ",")[2]; - permission = StringUtils.substringBetween(permission, "'"); - } + return (String) AnnotationUtils.getValue(preAuthorize); } - return permission; + return null; } private Annotation getAnnotationForRestObject(BaseObjectRest restObject) { @@ -410,19 +384,19 @@ private void initialize() { ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); provider.addIncludeFilter(new AssignableTypeFilter(EntityModel.class)); Set beanDefinitions = provider.findCandidateComponents( - HALResource.class.getPackage().getName().replaceAll("\\.", "/")); + HALResource.class.getPackage().getName().replaceAll("\\.", "/")); for (BeanDefinition beanDefinition : beanDefinitions) { String resourceClassName = beanDefinition.getBeanClassName(); String resourceClassSimpleName = resourceClassName.substring(resourceClassName.lastIndexOf(".") + 1); String restClassSimpleName = resourceClassSimpleName - .replaceAll("ResourceWrapper$", "RestWrapper") - .replaceAll("Resource$", "Rest"); + .replaceAll("ResourceWrapper$", "RestWrapper") + .replaceAll("Resource$", "Rest"); String restClassName = RestModel.class.getPackage().getName() + "." + restClassSimpleName; try { Class restClass = - (Class) Class.forName(restClassName); + (Class) Class.forName(restClassName); Class> resourceClass = - (Class>) Class.forName(resourceClassName); + (Class>) Class.forName(resourceClassName); Constructor compatibleConstructor = null; for (Constructor constructor : resourceClass.getDeclaredConstructors()) { if (constructor.getParameterCount() == 2 && constructor.getParameterTypes()[1] == Utils.class) { @@ -436,11 +410,11 @@ private void initialize() { resourceConstructors.put(restClass, compatibleConstructor); } else { log.warn("Skipping registration of resource class " + resourceClassName - + "; compatible constructor not found"); + + "; compatible constructor not found"); } } catch (ClassNotFoundException e) { log.warn("Skipping registration of resource class " + resourceClassName - + "; rest class not found: " + restClassName); + + "; rest class not found: " + restClassName); } } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java new file mode 100644 index 000000000000..ce8668e89f23 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java @@ -0,0 +1,56 @@ +package org.dspace.app.rest.security; + +import java.util.List; +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.core.GenericTypeResolver; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.security.access.expression.ExpressionUtils; +import org.springframework.security.access.expression.SecurityExpressionHandler; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.FilterInvocation; +import org.springframework.stereotype.Component; + +@Component +public class WebSecurityExpressionEvaluator { + + private static final FilterChain EMPTY_CHAIN = (request, response) -> { + throw new UnsupportedOperationException(); + }; + + private final List securityExpressionHandlers; + + public WebSecurityExpressionEvaluator(List securityExpressionHandlers) { + this.securityExpressionHandlers = securityExpressionHandlers; + } + + public boolean evaluate(String securityExpression, HttpServletRequest request, HttpServletResponse response) { + SecurityExpressionHandler handler = getFilterSecurityHandler(); + + Expression expression = handler.getExpressionParser().parseExpression(securityExpression); + + EvaluationContext evaluationContext = createEvaluationContext(handler, request, response); + + return ExpressionUtils.evaluateAsBoolean(expression, evaluationContext); + } + + @SuppressWarnings("unchecked") + private EvaluationContext createEvaluationContext(SecurityExpressionHandler handler, HttpServletRequest request, HttpServletResponse response) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + FilterInvocation filterInvocation = new FilterInvocation(request, response, EMPTY_CHAIN); + + return handler.createEvaluationContext(authentication, filterInvocation); + } + + private SecurityExpressionHandler getFilterSecurityHandler() { + return securityExpressionHandlers.stream() + .filter(handler -> FilterInvocation.class.equals(GenericTypeResolver + .resolveTypeArgument(handler.getClass(), SecurityExpressionHandler.class))) + .findAny() + .orElseThrow(() -> new IllegalStateException("No filter invocation security expression handler has been found! Handlers: " + securityExpressionHandlers.size())); + } +} \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java deleted file mode 100644 index 9fbe73f19f4d..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.dspace.app.rest.spel; - -public class ExpressionValidationException extends Exception { - public ExpressionValidationException(String message) { - super(message); - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java deleted file mode 100644 index 8cf1dc2a6c05..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/spel/ExpressionValidator.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.dspace.app.rest.spel; - -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.ParseException; -import org.springframework.expression.spel.SpelNode; -import org.springframework.expression.spel.ast.BeanReference; -import org.springframework.expression.spel.ast.MethodReference; -import org.springframework.expression.spel.ast.Operator; -import org.springframework.expression.spel.ast.TypeReference; -import org.springframework.expression.spel.ast.VariableReference; -import org.springframework.expression.spel.standard.SpelExpression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.security.access.expression.SecurityExpressionRoot; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class ExpressionValidator { - private final ExpressionParser parser = new SpelExpressionParser(); - - public void validate(String expression, Class expressionRoot) throws ExpressionValidationException, ParseException { - SpelExpression exp = (SpelExpression) parser.parseExpression(expression); - if (expressionRoot != null) { - SpelNode node = exp.getAST(); - handle(node, expressionRoot); - } - } - - private void handle(SpelNode node, Class expressionRoot) throws ExpressionValidationException{ - if (node instanceof MethodReference) { - verify((MethodReference) node, expressionRoot); - } else if (node instanceof Operator) { - Operator operator = (Operator) node; - handle(operator.getLeftOperand(), expressionRoot); - handle(operator.getRightOperand(), expressionRoot); - } else if (node != null) { - for(int i=0; i expressionRoot) throws ExpressionValidationException { - String methodName = node.getName(); - int args = node.getChildCount(); - Method[] methods = expressionRoot.getDeclaredMethods(); - for(Method m : methods) { - if (m.getName().equals(methodName)) { - // exact match on the args - if (args == m.getParameterCount()) { - try { - SecurityExpressionRoot.class.getConstructor(Authentication.class).newInstance( - SecurityContextHolder.getContext().getAuthentication()); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - e.printStackTrace(); - } - return; - } - Class[] parameterTypes = m.getParameterTypes(); - if (m.getName().equals(methodName) && - parameterTypes != null && - parameterTypes.length>=1 && - parameterTypes[parameterTypes.length-1].isArray()) { - // allow the number of params to be one less or >= the reported length - if(args == m.getParameterCount()-1 || args >= m.getParameterCount()) { - return; - } - } - } - } - // if we get here, then we were unable to match the method call - String pattern = "Unable to match method %s with %d params"; - throw new ExpressionValidationException(String.format(pattern, methodName, args)); - } - -} From 49d40598f0e2ca26f3683128852887c970ee8046 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Mon, 8 Jun 2020 13:04:59 +0200 Subject: [PATCH 05/12] [Task 71143] implemented the PreAuthorize check in ConverterService for the findOne of a BaseObjectRest when the toRest method is called --- .../app/rest/converter/ConverterService.java | 6 ++-- .../rest/model/ExternalSourceEntryRest.java | 2 +- .../rest/repository/BundleRestRepository.java | 6 ++-- .../rest/repository/ItemRestRepository.java | 2 +- .../WebSecurityExpressionEvaluator.java | 12 +++++-- .../rest/AuthorizationRestRepositoryIT.java | 6 ++++ .../app/rest/ProcessRestRepositoryIT.java | 7 ++++ .../rest/converter/ConverterServiceIT.java | 9 +++++ .../repository/MockObjectRestRepository.java | 36 +++++++++++++++++++ 9 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java index e1d282fc8bd2..bf959f719e03 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java @@ -107,10 +107,12 @@ public R toRest(M modelObject, Projection projection) { DSpaceConverter converter = requireConverter(modelObject.getClass()); R restObject = converter.convert(transformedModel, projection); if (restObject instanceof BaseObjectRest) { - String preAuthorizeValue = getPreAuthorizeAnnotationForBaseObject((BaseObjectRest) restObject); + BaseObjectRest baseObjectRest = (BaseObjectRest) restObject; + String preAuthorizeValue = getPreAuthorizeAnnotationForBaseObject(baseObjectRest); if (!webSecurityExpressionEvaluator .evaluate(preAuthorizeValue, requestService.getCurrentRequest().getHttpServletRequest(), - requestService.getCurrentRequest().getHttpServletResponse())) { + requestService.getCurrentRequest().getHttpServletResponse(), + String.valueOf(baseObjectRest.getId()))) { log.info("Access denied on " + restObject.getClass()); return null; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java index aa5dfa8cf22c..06af7e222713 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ExternalSourceEntryRest.java @@ -12,7 +12,7 @@ /** * This class serves as a REST representation for an entry of external data */ -public class ExternalSourceEntryRest extends BaseObjectRest { +public class ExternalSourceEntryRest extends RestAddressableModel { public static final String NAME = "externalSourceEntry"; public static final String PLURAL_NAME = "externalSourceEntries"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java index d26ceeb2bffa..f750743db66e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java @@ -74,11 +74,11 @@ public BundleRestRepository(BundleService dsoService) { this.bundleService = dsoService; } - @PreAuthorize("hasPermission(#uuid, 'BUNDLE', 'READ')") - public BundleRest findOne(Context context, UUID uuid) { + @PreAuthorize("hasPermission(#id, 'BUNDLE', 'READ')") + public BundleRest findOne(Context context, UUID id) { Bundle bundle = null; try { - bundle = bundleService.find(context, uuid); + bundle = bundleService.find(context, id); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java index 49b468e298b2..c6643496ae42 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java @@ -99,7 +99,7 @@ public ItemRestRepository(ItemService dsoService) { } @Override - @PreAuthorize("hasPermission(#id, 'ITEM', 'WRITE')") + @PreAuthorize("hasPermission(#id, 'ITEM', 'READ')") public ItemRest findOne(Context context, UUID id) { Item item = null; try { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java index ce8668e89f23..8d75c24b1c4d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java @@ -1,3 +1,10 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ package org.dspace.app.rest.security; import java.util.List; @@ -28,13 +35,14 @@ public WebSecurityExpressionEvaluator(List securityEx this.securityExpressionHandlers = securityExpressionHandlers; } - public boolean evaluate(String securityExpression, HttpServletRequest request, HttpServletResponse response) { + public boolean evaluate(String securityExpression, HttpServletRequest request, HttpServletResponse response, + String id) { SecurityExpressionHandler handler = getFilterSecurityHandler(); Expression expression = handler.getExpressionParser().parseExpression(securityExpression); EvaluationContext evaluationContext = createEvaluationContext(handler, request, response); - + evaluationContext.setVariable("id", id); return ExpressionUtils.evaluateAsBoolean(expression, evaluationContext); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java index 05631790e383..22188a36af2f 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java @@ -52,6 +52,7 @@ import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -804,6 +805,11 @@ public void findByObjectInternalServerErrorTest() throws Exception { * * @throws Exception */ + // This test currently doesn't work as expected since the AuthorizationFeatureRestRepository#findOne method + // is only exposed to admins. Currently we're performing checks on the individual REST objects with its findOne + // Permission constraints, which is ADMIN in this case. Seeing as we're trying to retrieve it with a normal + // EPerson token in the second test, this will fail. + @Ignore public void findByObjectAndFeatureTest() throws Exception { context.turnOffAuthorisationSystem(); Community com = CommunityBuilder.createCommunity(context).withName("A test community").build(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java index 92c37007b135..de63aaf6cf35 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProcessRestRepositoryIT.java @@ -43,6 +43,13 @@ public class ProcessRestRepositoryIT extends AbstractControllerIntegrationTest { @Before public void setup() throws SQLException { + CollectionUtils.emptyIfNull(processService.findAll(context)).stream().forEach(process -> { + try { + processService.delete(context, process); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); parameters.add(new DSpaceCommandLineParameter("-r", "test")); parameters.add(new DSpaceCommandLineParameter("-i", null)); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java index e1d2e2d089ef..ea1a15dc04e3 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.HashMap; @@ -41,6 +42,9 @@ import org.springframework.hateoas.Link; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; /** * Tests functionality of {@link ConverterService}. @@ -76,6 +80,11 @@ public void setup() { mockHttpServletRequest.setAttribute("dspace.context", new Context()); MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); requestService.startRequest(mockHttpServletRequest, mockHttpServletResponse); + Authentication authentication = mock(Authentication.class); + SecurityContext securityContext = mock(SecurityContext.class); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + when(SecurityContextHolder.getContext().getAuthentication().getPrincipal()).thenReturn(eperson); } /** * When calling {@code toRest} with an object for which an appropriate {@link DSpaceConverter} can't be found, diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java new file mode 100644 index 000000000000..5c12bc1b1403 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java @@ -0,0 +1,36 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.repository; + +import org.dspace.app.rest.model.MockObjectRest; +import org.dspace.core.Context; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +@Component(MockObjectRest.CATEGORY + "." + MockObjectRest.NAME) +public class MockObjectRestRepository extends DSpaceRestRepository { + + @Override + @PreAuthorize("permitAll()") + public MockObjectRest findOne(Context context, Long aLong) { + return null; + } + + @Override + @PreAuthorize("permitAll()") + public Page findAll(Context context, Pageable pageable) { + return null; + } + + @Override + public Class getDomainClass() { + return MockObjectRest.class; + } +} From 7be092813903c4e59f27109fd6702e5d281a1966 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Mon, 8 Jun 2020 15:12:40 +0200 Subject: [PATCH 06/12] [Task 71143] fixed checkstyle --- .../security/WebSecurityExpressionEvaluator.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java index 8d75c24b1c4d..0b1b69e6e132 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java @@ -47,7 +47,8 @@ public boolean evaluate(String securityExpression, HttpServletRequest request, H } @SuppressWarnings("unchecked") - private EvaluationContext createEvaluationContext(SecurityExpressionHandler handler, HttpServletRequest request, HttpServletResponse response) { + private EvaluationContext createEvaluationContext(SecurityExpressionHandler handler, HttpServletRequest request, + HttpServletResponse response) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); FilterInvocation filterInvocation = new FilterInvocation(request, response, EMPTY_CHAIN); @@ -56,9 +57,13 @@ private EvaluationContext createEvaluationContext(SecurityExpressionHandler hand private SecurityExpressionHandler getFilterSecurityHandler() { return securityExpressionHandlers.stream() - .filter(handler -> FilterInvocation.class.equals(GenericTypeResolver - .resolveTypeArgument(handler.getClass(), SecurityExpressionHandler.class))) + .filter(handler -> + FilterInvocation.class.equals( + GenericTypeResolver.resolveTypeArgument(handler.getClass(), + SecurityExpressionHandler.class))) .findAny() - .orElseThrow(() -> new IllegalStateException("No filter invocation security expression handler has been found! Handlers: " + securityExpressionHandlers.size())); + .orElseThrow(() -> new IllegalStateException("No filter invocation security" + + " expression handler has been found! Handlers: " + + securityExpressionHandlers.size())); } } \ No newline at end of file From 4a40b8d1028aaa37f712fd53243696650a99763b Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Tue, 9 Jun 2020 09:25:06 +0200 Subject: [PATCH 07/12] [Task 71308] applied feedback to the PreAuthorize parsing in converterService feature --- .../app/rest/converter/ConverterService.java | 6 ++++- .../WebSecurityExpressionEvaluator.java | 26 +++++++++++++++++++ .../rest/converter/ConverterServiceIT.java | 4 +++ .../repository/MockObjectRestRepository.java | 5 ++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java index bf959f719e03..fc786bfc851a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ConverterService.java @@ -108,12 +108,16 @@ public R toRest(M modelObject, Projection projection) { R restObject = converter.convert(transformedModel, projection); if (restObject instanceof BaseObjectRest) { BaseObjectRest baseObjectRest = (BaseObjectRest) restObject; + // This section will verify whether the current user has permissions to retrieve the + // rest object. It'll only return the REST object if the permission is granted. + // If permission isn't granted, it'll return null String preAuthorizeValue = getPreAuthorizeAnnotationForBaseObject(baseObjectRest); if (!webSecurityExpressionEvaluator .evaluate(preAuthorizeValue, requestService.getCurrentRequest().getHttpServletRequest(), requestService.getCurrentRequest().getHttpServletResponse(), String.valueOf(baseObjectRest.getId()))) { - log.info("Access denied on " + restObject.getClass()); + log.debug("Access denied on " + restObject.getClass() + " with id: " + + ((BaseObjectRest) restObject).getId()); return null; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java index 0b1b69e6e132..364e93e297d8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WebSecurityExpressionEvaluator.java @@ -22,6 +22,17 @@ import org.springframework.security.web.FilterInvocation; import org.springframework.stereotype.Component; +/** + * This class will contain the logic to allow us to evaluate an expression given through a String. + * This will be used by the {@link org.dspace.app.rest.converter.ConverterService} for parsing + * the {@link org.springframework.security.access.prepost.PreAuthorize} annotations used on the findOne + * methods of RestRepositories. A String will be given to the evaluate method and that String will then + * be parsed and a boolean will be returned based on the condition in the String. + * For example: "hasPermission(#id, 'ITEM', 'READ')" is such a String + * This will be evaluated and if the current user has the permission to read an item with the given id, + * a true will be returned, if not it'll be false. + * This works on all the methods in {@link org.springframework.security.access.expression.SecurityExpressionRoot} + */ @Component public class WebSecurityExpressionEvaluator { @@ -31,10 +42,25 @@ public class WebSecurityExpressionEvaluator { private final List securityExpressionHandlers; + /** + * Constructor for this class that sets all the {@link SecurityExpressionHandler} objects in a list + * @param securityExpressionHandlers The {@link SecurityExpressionHandler} for this class + */ public WebSecurityExpressionEvaluator(List securityExpressionHandlers) { this.securityExpressionHandlers = securityExpressionHandlers; } + /** + * This method will have to be used to evaluate the String given. It'll parse the String and resolve + * it to a method in {@link org.springframework.security.access.expression.SecurityExpressionRoot} + * and evaluate it to then return a boolean + * @param securityExpression The String that resembles the expression that has to be parsed + * @param request The current request + * @param response The current response + * @param id The id for the Object that is the subject of the permission + * @return A boolean indicating whether the currentUser adheres to the + * permissions in the securityExpression String or not + */ public boolean evaluate(String securityExpression, HttpServletRequest request, HttpServletResponse response, String id) { SecurityExpressionHandler handler = getFilterSecurityHandler(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java index ea1a15dc04e3..685bd5dbfdbe 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/converter/ConverterServiceIT.java @@ -112,6 +112,10 @@ public void toRestWrongReturnType() { /** * When calling {@code toRest} with the default projection, the converter should run and no changes should be made. + * This converter.toRest will now also check permissions through the PreAuthorize annotation on the + * Repository's findOne method. Therefor a repository has been added for this MockObjectRest namely + * {@link org.dspace.app.rest.repository.MockObjectRestRepository} and added PreAuthorize annotations + * on the methods of this Repository */ @Test public void toRestWithDefaultProjection() { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java index 5c12bc1b1403..0c5481124924 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/repository/MockObjectRestRepository.java @@ -14,9 +14,14 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; +/** + * This class has been added to allow the MockObjectRest to act as an actual BaseObjectRest since they're + * expected to have a RestRepository + */ @Component(MockObjectRest.CATEGORY + "." + MockObjectRest.NAME) public class MockObjectRestRepository extends DSpaceRestRepository { + // Added a permitAll preAuthorize annotation to allow the object to be used in tests by every user @Override @PreAuthorize("permitAll()") public MockObjectRest findOne(Context context, Long aLong) { From faef05258a60e04bfcdaed9d8e81a0ec266b4a29 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 10 Jun 2020 11:51:44 +0200 Subject: [PATCH 08/12] [Task 71335] removed unneeded PermissionEvaluatorPlugins and changed PreAuthorize annotations where necessary --- .../AuthorizationFeatureRestRepository.java | 6 +-- .../BitstreamFormatRestRepository.java | 1 + .../repository/EntityTypeRestRepository.java | 3 ++ .../TemplateItemRestRepository.java | 2 + ...onStatusRestPermissionEvaluatorPlugin.java | 31 -------------- .../AuthnRestPermissionEvaluatorPlugin.java | 31 -------------- ...nFeatureRestPermissionEvaluatorPlugin.java | 31 -------------- ...amFormatRestPermissionEvaluatorPlugin.java | 31 -------------- ...wseIndexRestPermissionEvaluatorPlugin.java | 31 -------------- ...ryResultRestPermissionEvaluatorPlugin.java | 31 -------------- ...tityTypeRestPermissionEvaluatorPlugin.java | 31 -------------- ...rceEntryRestPermissionEvaluatorPlugin.java | 31 -------------- ...alSourceRestPermissionEvaluatorPlugin.java | 31 -------------- ...gurationRestPermissionEvaluatorPlugin.java | 31 -------------- ...llectionRestPermissionEvaluatorPlugin.java | 31 -------------- ...MetadataRestPermissionEvaluatorPlugin.java | 31 -------------- ...ataFieldRestPermissionEvaluatorPlugin.java | 31 -------------- ...taSchemaRestPermissionEvaluatorPlugin.java | 31 -------------- ...tionshipRestPermissionEvaluatorPlugin.java | 31 -------------- ...shipTypeRestPermissionEvaluatorPlugin.java | 31 -------------- .../ScriptRestPermissionEvaluatorPlugin.java | 30 -------------- ...gurationRestPermissionEvaluatorPlugin.java | 31 -------------- ...rchEventRestPermissionEvaluatorPlugin.java | 31 -------------- ...hResultsRestPermissionEvaluatorPlugin.java | 31 -------------- ...hSupportRestPermissionEvaluatorPlugin.java | 31 -------------- .../SiteRestPermissionEvaluatorPlugin.java | 31 -------------- ...sSupportRestPermissionEvaluatorPlugin.java | 31 -------------- ...finitionRestPermissionEvaluatorPlugin.java | 31 -------------- ...sionFormRestPermissionEvaluatorPlugin.java | 31 -------------- ...onUploadRestPermissionEvaluatorPlugin.java | 31 -------------- ...nSectionRestPermissionEvaluatorPlugin.java | 31 -------------- ...lateItemRestPermissionEvaluatorPlugin.java | 31 -------------- ...iewEventRestPermissionEvaluatorPlugin.java | 31 -------------- ...owActionRestPermissionEvaluatorPlugin.java | 31 -------------- ...finitionRestPermissionEvaluatorPlugin.java | 31 -------------- ...flowStepRestPermissionEvaluatorPlugin.java | 31 -------------- .../AuthorizationFeatureRestRepositoryIT.java | 41 +++---------------- 37 files changed, 15 insertions(+), 1029 deletions(-) delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthenticationStatusRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthnRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthorizationFeatureRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BitstreamFormatRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BrowseIndexRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DiscoveryResultRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EntityTypeRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceEntryRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/FacetConfigurationRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvestedCollectionRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvesterMetadataRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataFieldRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataSchemaRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipTypeRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ScriptRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchConfigurationRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchEventRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchResultsRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchSupportRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SiteRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatisticsSupportRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionDefinitionRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionFormRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionUploadRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissonSectionRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/TemplateItemRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ViewEventRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowActionRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowDefinitionRestPermissionEvaluatorPlugin.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowStepRestPermissionEvaluatorPlugin.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java index 0048898e228a..b5d102215c43 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java @@ -42,13 +42,13 @@ public Class getDomainClass() { return AuthorizationFeatureRest.class; } - @PreAuthorize("hasAuthority('ADMIN')") + @PreAuthorize("permitAll()") @Override public Page findAll(Context context, Pageable pageable) { return converter.toRestPage(authorizationFeatureService.findAll(), pageable, utils.obtainProjection()); } - @PreAuthorize("hasAuthority('ADMIN')") + @PreAuthorize("permitAll()") @Override public AuthorizationFeatureRest findOne(Context context, String id) { AuthorizationFeature authzFeature = authorizationFeatureService.find(id); @@ -58,7 +58,7 @@ public AuthorizationFeatureRest findOne(Context context, String id) { return null; } - @PreAuthorize("hasAuthority('ADMIN')") + @PreAuthorize("permitAll()") @SearchRestMethod(name = "resourcetype") public Page findByResourceType(@Parameter(value = "type", required = true) String type, Pageable pageable) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java index 49585ee9db5a..e63069233e0f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java @@ -57,6 +57,7 @@ public BitstreamFormatRest findOne(Context context, Integer id) { } @Override + @PreAuthorize("permitAll()") public Page findAll(Context context, Pageable pageable) { try { List bit = bitstreamFormatService.findAll(context); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRestRepository.java index e6c6fcea53de..29db39d879bd 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EntityTypeRestRepository.java @@ -30,6 +30,7 @@ public class EntityTypeRestRepository extends DSpaceRestRepository findAll(Context context, Pageable pageable) { try { List entityTypes = entityTypeService.findAll(context); @@ -52,6 +54,7 @@ public Page findAll(Context context, Pageable pageable) { } } + @Override public Class getDomainClass() { return EntityTypeRest.class; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/TemplateItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/TemplateItemRestRepository.java index 2e1436d4fbdc..ad801404819b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/TemplateItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/TemplateItemRestRepository.java @@ -28,6 +28,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; /** @@ -49,6 +50,7 @@ public class TemplateItemRestRepository extends DSpaceRestRepository resourcePatch; @Override + @PreAuthorize("permitAll()") public TemplateItemRest findOne(Context context, UUID uuid) { Item item = null; try { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthenticationStatusRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthenticationStatusRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 220c75d8939f..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthenticationStatusRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.AuthenticationStatusRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to AuthenticationStatusRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class AuthenticationStatusRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(AuthenticationStatusRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthnRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthnRestPermissionEvaluatorPlugin.java deleted file mode 100644 index d310e781b4b7..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthnRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.AuthnRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to AuthnRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class AuthnRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(AuthnRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthorizationFeatureRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthorizationFeatureRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 2a2dec065595..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/AuthorizationFeatureRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.AuthorizationFeatureRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to AuthorizationRest endpoints. It will return true because access can be granted - * anytime it's linked from another resource. - */ -@Component -public class AuthorizationFeatureRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(AuthorizationFeatureRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BitstreamFormatRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BitstreamFormatRestPermissionEvaluatorPlugin.java deleted file mode 100644 index f5027a5f146a..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BitstreamFormatRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.BitstreamFormatRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to BitstreamFormatRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class BitstreamFormatRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(BitstreamFormatRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BrowseIndexRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BrowseIndexRestPermissionEvaluatorPlugin.java deleted file mode 100644 index a4f57e1ea79d..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/BrowseIndexRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.BrowseIndexRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to BrowseIndexRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class BrowseIndexRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(BrowseIndexRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DiscoveryResultRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DiscoveryResultRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 04207e4a9322..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/DiscoveryResultRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.DiscoveryResultsRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to DiscoveryResultsRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class DiscoveryResultRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(DiscoveryResultsRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EntityTypeRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EntityTypeRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 017e0c2b5617..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/EntityTypeRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.EntityTypeRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to EntityTypeRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class EntityTypeRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(EntityTypeRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceEntryRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceEntryRestPermissionEvaluatorPlugin.java deleted file mode 100644 index fc050b4d3e95..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceEntryRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.ExternalSourceEntryRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to ExternalSourceEntryRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class ExternalSourceEntryRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(ExternalSourceEntryRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 5340251f0db5..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ExternalSourceRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.ExternalSourceRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to ExternalSourceRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class ExternalSourceRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(ExternalSourceRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/FacetConfigurationRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/FacetConfigurationRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 5a9432d46601..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/FacetConfigurationRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.FacetConfigurationRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to FacetConfigurationRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class FacetConfigurationRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(FacetConfigurationRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvestedCollectionRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvestedCollectionRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 9f78f5a0433f..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvestedCollectionRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.HarvestedCollectionRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to HarvestedCollectionRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class HarvestedCollectionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(HarvestedCollectionRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvesterMetadataRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvesterMetadataRestPermissionEvaluatorPlugin.java deleted file mode 100644 index ec0e3e202b95..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/HarvesterMetadataRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.HarvesterMetadataRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to HarvesterMetadataRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class HarvesterMetadataRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(HarvesterMetadataRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataFieldRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataFieldRestPermissionEvaluatorPlugin.java deleted file mode 100644 index c53fffe5d031..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataFieldRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.MetadataFieldRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to MetadataFieldRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class MetadataFieldRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(MetadataFieldRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataSchemaRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataSchemaRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 07da54a17083..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/MetadataSchemaRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.MetadataSchemaRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to MetadataSchemaRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class MetadataSchemaRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(MetadataSchemaRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 690a8bde9fb2..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.RelationshipRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to RelationshipRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class RelationshipRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(RelationshipRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipTypeRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipTypeRestPermissionEvaluatorPlugin.java deleted file mode 100644 index b371c8a5168c..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/RelationshipTypeRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.RelationshipTypeRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to RelationshipTypeRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class RelationshipTypeRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(RelationshipTypeRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ScriptRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ScriptRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 3672ad47c47c..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ScriptRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.ScriptRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle Permissions for the {@link ScriptRest} object and its calls - */ -@Component -public class ScriptRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(ScriptRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchConfigurationRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchConfigurationRestPermissionEvaluatorPlugin.java deleted file mode 100644 index b540b4d8551f..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchConfigurationRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SearchConfigurationRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SearchConfigurationRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SearchConfigurationRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SearchConfigurationRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchEventRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchEventRestPermissionEvaluatorPlugin.java deleted file mode 100644 index e7124b834ecf..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchEventRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SearchEventRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SearchEventRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SearchEventRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SearchEventRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchResultsRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchResultsRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 8e1ef2ada747..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchResultsRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SearchResultsRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SearchResultsRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SearchResultsRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SearchResultsRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchSupportRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchSupportRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 6ad65351c6ff..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SearchSupportRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SearchSupportRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SearchSupportRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SearchSupportRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SearchSupportRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SiteRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SiteRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 6385b2c75125..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SiteRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SiteRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SiteRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SiteRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SiteRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatisticsSupportRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatisticsSupportRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 190afafe1428..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/StatisticsSupportRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.StatisticsSupportRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to StatisticsSupportRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class StatisticsSupportRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(StatisticsSupportRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionDefinitionRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionDefinitionRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 7efb24a6eef8..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionDefinitionRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SubmissionDefinitionRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SubmissionDefinitionRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SubmissionDefinitionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SubmissionDefinitionRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionFormRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionFormRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 19db77ca570d..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionFormRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SubmissionFormRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SubmissionFormRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SubmissionFormRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SubmissionFormRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionUploadRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionUploadRestPermissionEvaluatorPlugin.java deleted file mode 100644 index aa15522a1c30..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissionUploadRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SubmissionUploadRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SubmissionUploadRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SubmissionUploadRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SubmissionUploadRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissonSectionRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissonSectionRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 7c998d48d05b..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/SubmissonSectionRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.SubmissionSectionRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to SubmissionSectionRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class SubmissonSectionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(SubmissionSectionRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/TemplateItemRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/TemplateItemRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 192bdf040bea..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/TemplateItemRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.TemplateItemRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to TemplateItemRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class TemplateItemRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(TemplateItemRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ViewEventRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ViewEventRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 097bfc1e3a9b..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ViewEventRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.ViewEventRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to ViewEventRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class ViewEventRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(ViewEventRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowActionRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowActionRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 4f4180e96052..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowActionRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.WorkflowActionRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to WorkflowActionRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class WorkflowActionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(WorkflowActionRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowDefinitionRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowDefinitionRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 6168b3b37060..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowDefinitionRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.WorkflowDefinitionRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to WorkflowDefinitionRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class WorkflowDefinitionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(WorkflowDefinitionRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowStepRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowStepRestPermissionEvaluatorPlugin.java deleted file mode 100644 index 8c8216c41273..000000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowStepRestPermissionEvaluatorPlugin.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.rest.security; - -import java.io.Serializable; - -import org.apache.commons.lang3.StringUtils; -import org.dspace.app.rest.model.WorkflowStepRest; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -/** - * This class will handle calls made to WorkflowStepRest endpoints. - * It will return true because access can be granted anytime it's linked from another resource - */ -@Component -public class WorkflowStepRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin { - @Override - public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, - DSpaceRestPermission restPermission) { - if (!StringUtils.equalsIgnoreCase(WorkflowStepRest.NAME, targetType)) { - return false; - } - return true; - } -} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java index a3556ad50335..bffcbcb54f87 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java @@ -46,19 +46,12 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte public void findAllTest() throws Exception { int featuresNum = authzFeatureService.findAll().size(); int expReturn = featuresNum > 20 ? 20 : featuresNum; - String adminToken = getAuthToken(admin.getEmail(), password); - // verify that only the admin can access the endpoint (see subsequent call in the method) - getClient(adminToken).perform(get("/api/authz/features")).andExpect(status().isOk()) + getClient().perform(get("/api/authz/features")).andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(expReturn)))) .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features"))) .andExpect(jsonPath("$.page.size", is(20))) .andExpect(jsonPath("$.page.totalElements", is(featuresNum))); - // verify that anonymous user cannot access - getClient().perform(get("/api/authz/features")).andExpect(status().isUnauthorized()); - // verify that normal user cannot access - String epersonAuthToken = getAuthToken(eperson.getEmail(), password); - getClient(epersonAuthToken).perform(get("/api/authz/features")).andExpect(status().isForbidden()); } @@ -108,30 +101,17 @@ public void findAllWithPaginationTest() throws Exception { * @throws Exception */ public void findOneTest() throws Exception { - String adminToken = getAuthToken(admin.getEmail(), password); - // verify that only the admin can access the endpoint (see subsequent call in the method) - getClient(adminToken).perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk()) + getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk()) .andExpect(jsonPath("$.id", is("withdrawItem"))) .andExpect(jsonPath("$.description", Matchers.any(String.class))) .andExpect(jsonPath("$.resourcetypes", Matchers.contains("core.item"))) .andExpect(jsonPath("$.type", is("feature"))); - // verify that anonymous user cannot access - getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isUnauthorized()); - // verify that normal user cannot access - String epersonAuthToken = getAuthToken(eperson.getEmail(), password); - getClient(epersonAuthToken).perform(get("/api/authz/features/withdrawItem")).andExpect(status().isForbidden()); } @Test public void findOneNotFoundTest() throws Exception { - String adminToken = getAuthToken(admin.getEmail(), password); - // verify that only the admin can access the endpoint and get the not found response code - // (see subsequent calls in the method for unauthorized and forbidden attempts) - getClient(adminToken).perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isNotFound()); - // verify that anonymous user cannot access, without information disclosure - getClient().perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isUnauthorized()); - // verify that normal user cannot access, without information disclosure - getClient(adminToken).perform(get("/api/authz/features/1")).andExpect(status().isNotFound()); + getClient().perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isNotFound()); + getClient().perform(get("/api/authz/features/1")).andExpect(status().isNotFound()); } @Test @@ -142,10 +122,8 @@ public void findOneNotFoundTest() throws Exception { */ public void findByResourceTypeTest() throws Exception { AuthorizationFeature alwaysTrueFeature = authzFeatureService.find(AlwaysTrueFeature.NAME); - String adminToken = getAuthToken(admin.getEmail(), password); for (String type : alwaysTrueFeature.getSupportedTypes()) { - // verify that only the admin can access the endpoint (see subsequent call in the method) - getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", type)) + getClient().perform(get("/api/authz/features/search/resourcetype").param("type", type)) .andExpect(status().isOk()) .andExpect(jsonPath("$", JsonPathMatchers.hasJsonPath("$._embedded.features", @@ -158,15 +136,8 @@ public void findByResourceTypeTest() throws Exception { Matchers.containsString("/api/authz/features/search/resourcetype"))); } // verify that the right response code is returned also for not existing types - getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", "NOT-EXISTING")) + getClient().perform(get("/api/authz/features/search/resourcetype").param("type", "NOT-EXISTING")) .andExpect(status().isOk()).andExpect(jsonPath("$.page.totalElements", is(0))); - // verify that anonymous user cannot access, without information disclosure - getClient().perform(get("/api/authz/features/search/resourcetype").param("type", "core.item")) - .andExpect(status().isUnauthorized()); - // verify that normal user cannot access, without information disclosure - String epersonAuthToken = getAuthToken(eperson.getEmail(), password); - getClient(epersonAuthToken).perform(get("/api/authz/features/search/resourcetype").param("type", "core.item")) - .andExpect(status().isForbidden()); } From 56629fd34e82b9a29ada8b65a7b1a41557b99f7f Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 10 Jun 2020 11:53:24 +0200 Subject: [PATCH 09/12] [Task 71335] removed wrongly added preAuthorize on bitstreamFormatRestRepository#findAll --- .../app/rest/repository/BitstreamFormatRestRepository.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java index e63069233e0f..49585ee9db5a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamFormatRestRepository.java @@ -57,7 +57,6 @@ public BitstreamFormatRest findOne(Context context, Integer id) { } @Override - @PreAuthorize("permitAll()") public Page findAll(Context context, Pageable pageable) { try { List bit = bitstreamFormatService.findAll(context); From 5f44fe11f7da5885f7f6f285fac23fd3a5c2605e Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 10 Jun 2020 13:50:17 +0200 Subject: [PATCH 10/12] Undo findall preauthorize annotation change on AuthorizationFeatureRestRepository --- .../AuthorizationFeatureRestRepository.java | 4 +- .../AuthorizationFeatureRestRepositoryIT.java | 95 +++++++++++-------- 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java index b5d102215c43..62781fe8e891 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorizationFeatureRestRepository.java @@ -42,7 +42,7 @@ public Class getDomainClass() { return AuthorizationFeatureRest.class; } - @PreAuthorize("permitAll()") + @PreAuthorize("hasAuthority('ADMIN')") @Override public Page findAll(Context context, Pageable pageable) { return converter.toRestPage(authorizationFeatureService.findAll(), pageable, utils.obtainProjection()); @@ -58,7 +58,7 @@ public AuthorizationFeatureRest findOne(Context context, String id) { return null; } - @PreAuthorize("permitAll()") + @PreAuthorize("hasAuthority('ADMIN')") @SearchRestMethod(name = "resourcetype") public Page findByResourceType(@Parameter(value = "type", required = true) String type, Pageable pageable) { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java index bffcbcb54f87..0aadff7a9927 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationFeatureRestRepositoryIT.java @@ -29,7 +29,7 @@ /** * Test suite for the Authorization Feature endpoint - * + * * @author Andrea Bollini (andrea.bollini at 4science.it) * */ @@ -46,12 +46,19 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte public void findAllTest() throws Exception { int featuresNum = authzFeatureService.findAll().size(); int expReturn = featuresNum > 20 ? 20 : featuresNum; + String adminToken = getAuthToken(admin.getEmail(), password); - getClient().perform(get("/api/authz/features")).andExpect(status().isOk()) - .andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(expReturn)))) - .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features"))) - .andExpect(jsonPath("$.page.size", is(20))) - .andExpect(jsonPath("$.page.totalElements", is(featuresNum))); + // verify that only the admin can access the endpoint (see subsequent call in the method) + getClient(adminToken).perform(get("/api/authz/features")).andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(expReturn)))) + .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features"))) + .andExpect(jsonPath("$.page.size", is(20))) + .andExpect(jsonPath("$.page.totalElements", is(featuresNum))); + // verify that anonymous user cannot access + getClient().perform(get("/api/authz/features")).andExpect(status().isUnauthorized()); + // verify that normal user cannot access + String epersonAuthToken = getAuthToken(eperson.getEmail(), password); + getClient(epersonAuthToken).perform(get("/api/authz/features")).andExpect(status().isForbidden()); } @@ -71,21 +78,21 @@ public void findAllWithPaginationTest() throws Exception { AtomicReference idRef = new AtomicReference(); getClient(adminToken) - .perform(get("/api/authz/features").param("page", String.valueOf(page)).param("size", "1")) - .andExpect(status().isOk()).andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(1)))) - .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features"))) - .andExpect( - (page == 0) ? jsonPath("$._links.prev.href").doesNotExist() - : jsonPath("$._links.prev.href", Matchers.containsString("/api/authz/features"))) - .andExpect((page == featuresNum - 1) - ? jsonPath("$._links.next.href").doesNotExist() - : jsonPath("$._links.next.href", Matchers.containsString("/api/authz/features"))) - .andExpect(jsonPath("$._links.first.href", Matchers.containsString("/api/authz/features"))) - .andExpect(jsonPath("$._links.last.href", Matchers.containsString("/api/authz/features"))) - .andExpect(jsonPath("$.page.size", is(1))) - .andExpect(jsonPath("$.page.totalElements", is(Integer.valueOf(featuresNum)))) - .andDo(result -> idRef - .set(read(result.getResponse().getContentAsString(), "$._embedded.features[0].id"))); + .perform(get("/api/authz/features").param("page", String.valueOf(page)).param("size", "1")) + .andExpect(status().isOk()).andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(1)))) + .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features"))) + .andExpect( + (page == 0) ? jsonPath("$._links.prev.href").doesNotExist() + : jsonPath("$._links.prev.href", Matchers.containsString("/api/authz/features"))) + .andExpect((page == featuresNum - 1) + ? jsonPath("$._links.next.href").doesNotExist() + : jsonPath("$._links.next.href", Matchers.containsString("/api/authz/features"))) + .andExpect(jsonPath("$._links.first.href", Matchers.containsString("/api/authz/features"))) + .andExpect(jsonPath("$._links.last.href", Matchers.containsString("/api/authz/features"))) + .andExpect(jsonPath("$.page.size", is(1))) + .andExpect(jsonPath("$.page.totalElements", is(Integer.valueOf(featuresNum)))) + .andDo(result -> idRef + .set(read(result.getResponse().getContentAsString(), "$._embedded.features[0].id"))); if (idRef.get() == null || featureIDs.contains(idRef.get())) { fail("Duplicate feature " + idRef.get() + " returned at page " + page); @@ -102,16 +109,16 @@ public void findAllWithPaginationTest() throws Exception { */ public void findOneTest() throws Exception { getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is("withdrawItem"))) - .andExpect(jsonPath("$.description", Matchers.any(String.class))) - .andExpect(jsonPath("$.resourcetypes", Matchers.contains("core.item"))) - .andExpect(jsonPath("$.type", is("feature"))); + .andExpect(jsonPath("$.id", is("withdrawItem"))) + .andExpect(jsonPath("$.description", Matchers.any(String.class))) + .andExpect(jsonPath("$.resourcetypes", Matchers.contains("core.item"))) + .andExpect(jsonPath("$.type", is("feature"))); } @Test public void findOneNotFoundTest() throws Exception { getClient().perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isNotFound()); - getClient().perform(get("/api/authz/features/1")).andExpect(status().isNotFound()); + } @Test @@ -122,22 +129,32 @@ public void findOneNotFoundTest() throws Exception { */ public void findByResourceTypeTest() throws Exception { AuthorizationFeature alwaysTrueFeature = authzFeatureService.find(AlwaysTrueFeature.NAME); + String adminToken = getAuthToken(admin.getEmail(), password); for (String type : alwaysTrueFeature.getSupportedTypes()) { - getClient().perform(get("/api/authz/features/search/resourcetype").param("type", type)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$", - JsonPathMatchers.hasJsonPath("$._embedded.features", - Matchers.everyItem( - JsonPathMatchers.hasJsonPath("$.resourcetypes", - Matchers.hasItem(is(type)))) - ))) - .andExpect( - jsonPath("$._links.self.href", - Matchers.containsString("/api/authz/features/search/resourcetype"))); + // verify that only the admin can access the endpoint (see subsequent call in the method) + getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", type)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", + JsonPathMatchers.hasJsonPath("$._embedded.features", + Matchers.everyItem( + JsonPathMatchers.hasJsonPath( + "$.resourcetypes", + Matchers.hasItem(is(type)))) + ))) + .andExpect( + jsonPath("$._links.self.href", + Matchers.containsString("/api/authz/features/search/resourcetype"))); } // verify that the right response code is returned also for not existing types - getClient().perform(get("/api/authz/features/search/resourcetype").param("type", "NOT-EXISTING")) - .andExpect(status().isOk()).andExpect(jsonPath("$.page.totalElements", is(0))); + getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", "NOT-EXISTING")) + .andExpect(status().isOk()).andExpect(jsonPath("$.page.totalElements", is(0))); + // verify that anonymous user cannot access, without information disclosure + getClient().perform(get("/api/authz/features/search/resourcetype").param("type", "core.item")) + .andExpect(status().isUnauthorized()); + // verify that normal user cannot access, without information disclosure + String epersonAuthToken = getAuthToken(eperson.getEmail(), password); + getClient(epersonAuthToken).perform(get("/api/authz/features/search/resourcetype").param("type", "core.item")) + .andExpect(status().isForbidden()); } From 8172dd5fb0688ef2539af96b5a470b6187a4f937 Mon Sep 17 00:00:00 2001 From: benbosman Date: Thu, 18 Jun 2020 17:05:31 +0200 Subject: [PATCH 11/12] Re-enable findByObjectAndFeatureTest The findByObjectAndFeatureTest can be used again thanks to https://github.com/DSpace/DSpace/pull/2778/files#diff-311a7e07c257d9c869f4de1347f5f761R51 --- .../org/dspace/app/rest/AuthorizationRestRepositoryIT.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java index 22188a36af2f..7092bb62d7e8 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java @@ -805,11 +805,6 @@ public void findByObjectInternalServerErrorTest() throws Exception { * * @throws Exception */ - // This test currently doesn't work as expected since the AuthorizationFeatureRestRepository#findOne method - // is only exposed to admins. Currently we're performing checks on the individual REST objects with its findOne - // Permission constraints, which is ADMIN in this case. Seeing as we're trying to retrieve it with a normal - // EPerson token in the second test, this will fail. - @Ignore public void findByObjectAndFeatureTest() throws Exception { context.turnOffAuthorisationSystem(); Community com = CommunityBuilder.createCommunity(context).withName("A test community").build(); From 559001cf431a987ee03563c392003195f141baf8 Mon Sep 17 00:00:00 2001 From: benbosman Date: Thu, 18 Jun 2020 17:16:56 +0200 Subject: [PATCH 12/12] Removing unused import --- .../java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java index 7092bb62d7e8..05631790e383 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/AuthorizationRestRepositoryIT.java @@ -52,7 +52,6 @@ import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired;