DATAREST-1137 - All patch operations now verify path expressions.
We now make sure that all patch operations now get the path they're supposed to be applied to verified before execution.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,10 +38,10 @@ class AddOperation extends PatchOperation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#perform(java.lang.Object, java.lang.Class)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#doPerform(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
<T> void perform(Object targetObject, Class<T> type) {
|
||||
<T> void doPerform(Object targetObject, Class<T> type) {
|
||||
addValue(targetObject, evaluateValueFromTarget(targetObject, type));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,10 +53,10 @@ class CopyOperation extends FromOperation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#perform(java.lang.Object, java.lang.Class)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#doPerform(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
<T> void perform(Object target, Class<T> type) {
|
||||
<T> void doPerform(Object target, Class<T> type) {
|
||||
addValue(target, pathToExpression(getFrom()).getValue(target));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,10 +44,10 @@ class MoveOperation extends FromOperation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#perform(java.lang.Object, java.lang.Class)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#doPerform(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
<T> void perform(Object target, Class<T> type) {
|
||||
<T> void doPerform(Object target, Class<T> type) {
|
||||
addValue(target, popValueAtPath(target, getFrom()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,11 +209,25 @@ public abstract class PatchOperation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the operation.
|
||||
* Perform the operation in the given target object.
|
||||
*
|
||||
* @param target the target of the operation.
|
||||
* @param target the target of the operation, must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
*/
|
||||
abstract <T> void perform(Object target, Class<T> type);
|
||||
final <T> void perform(Object target, Class<T> type) {
|
||||
|
||||
verifyPath(type);
|
||||
|
||||
doPerform(target, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the actually application of the operation.
|
||||
*
|
||||
* @param target must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
*/
|
||||
abstract <T> void doPerform(Object target, Class<T> type);
|
||||
|
||||
private Integer targetListIndex(String path) {
|
||||
|
||||
@@ -241,7 +255,7 @@ public abstract class PatchOperation {
|
||||
List<String> segments = new ArrayList<String>();
|
||||
|
||||
for (String segment : path.split("/")) {
|
||||
if (!(segment.matches("\\d+") || segment.equals("-") || segment.isEmpty())) {
|
||||
if (!(segment.matches("\\d+") || segment.equals("-") || segment.equals("~") || segment.isEmpty())) {
|
||||
segments.add(segment);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,7 @@ package org.springframework.data.rest.webmvc.json.patch;
|
||||
* @author Craig Walls
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class RemoveOperation extends PatchOperation {
|
||||
class RemoveOperation extends PatchOperation {
|
||||
|
||||
/**
|
||||
* Constructs the remove operation
|
||||
@@ -35,10 +35,10 @@ public class RemoveOperation extends PatchOperation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#perform(java.lang.Object, java.lang.Class)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#doPerform(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
<T> void perform(Object target, Class<T> type) {
|
||||
<T> void doPerform(Object target, Class<T> type) {
|
||||
popValueAtPath(target, path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,9 @@ package org.springframework.data.rest.webmvc.json.patch;
|
||||
* Operation that replaces the value at the given path with a new value.
|
||||
*
|
||||
* @author Craig Walls
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ReplaceOperation extends PatchOperation {
|
||||
class ReplaceOperation extends PatchOperation {
|
||||
|
||||
/**
|
||||
* Constructs the replace operation
|
||||
@@ -34,10 +35,10 @@ public class ReplaceOperation extends PatchOperation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#perform(java.lang.Object, java.lang.Class)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#doPerform(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
<T> void perform(Object target, Class<T> type) {
|
||||
<T> void doPerform(Object target, Class<T> type) {
|
||||
setValueOnTarget(target, evaluateValueFromTarget(target, type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* </p>
|
||||
*
|
||||
* @author Craig Walls
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class TestOperation extends PatchOperation {
|
||||
|
||||
@@ -45,10 +46,10 @@ class TestOperation extends PatchOperation {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#perform(java.lang.Object, java.lang.Class)
|
||||
* @see org.springframework.data.rest.webmvc.json.patch.PatchOperation#doPerform(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
<T> void perform(Object target, Class<T> type) {
|
||||
<T> void doPerform(Object target, Class<T> type) {
|
||||
|
||||
Object expected = normalizeIfNumber(evaluateValueFromTarget(target, type));
|
||||
Object actual = normalizeIfNumber(getValueFromTarget(target));
|
||||
@@ -58,7 +59,7 @@ class TestOperation extends PatchOperation {
|
||||
}
|
||||
}
|
||||
|
||||
private Object normalizeIfNumber(Object expected) {
|
||||
private static Object normalizeIfNumber(Object expected) {
|
||||
|
||||
if (expected instanceof Double || expected instanceof Float) {
|
||||
expected = BigDecimal.valueOf(((Number) expected).doubleValue());
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc.json.patch;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* General unit tests for {@link PatchOperation} implementations.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class PatchOperationUnitTests {
|
||||
|
||||
@Test // DATAREST-1137
|
||||
public void invalidPathGetsRejected() {
|
||||
|
||||
String invalidPath = "/nonExistant";
|
||||
|
||||
verifyIllegalPath(new AddOperation(invalidPath, null));
|
||||
verifyIllegalPath(new CopyOperation(invalidPath, null));
|
||||
verifyIllegalPath(new MoveOperation(invalidPath, null));
|
||||
verifyIllegalPath(new RemoveOperation(invalidPath));
|
||||
verifyIllegalPath(new ReplaceOperation(invalidPath, null));
|
||||
verifyIllegalPath(new TestOperation(invalidPath, null));
|
||||
}
|
||||
|
||||
private static void verifyIllegalPath(PatchOperation operation) {
|
||||
|
||||
try {
|
||||
|
||||
Todo todo = new Todo(1L, "A", false);
|
||||
operation.perform(todo, Todo.class);
|
||||
|
||||
Assert.fail("Expected PatchException!");
|
||||
|
||||
} catch (PatchException o_O) {}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user