From 8a407bc03a813ae4ce268de90504b9bb8a43cf56 Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Mon, 7 Aug 2017 15:27:30 +0200
Subject: [PATCH] Overload patch method with Collection signature

---
 .../thm/arsnova/services/EntityService.java   | 13 +++++
 .../arsnova/services/EntityServiceTest.java   | 51 +++++++++++++++++++
 2 files changed, 64 insertions(+)

diff --git a/src/main/java/de/thm/arsnova/services/EntityService.java b/src/main/java/de/thm/arsnova/services/EntityService.java
index 25e53aa0d..f582665b9 100644
--- a/src/main/java/de/thm/arsnova/services/EntityService.java
+++ b/src/main/java/de/thm/arsnova/services/EntityService.java
@@ -7,8 +7,10 @@ import de.thm.arsnova.entities.Entity;
 import de.thm.arsnova.entities.serialization.View;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.access.prepost.PreFilter;
 
 import java.io.IOException;
+import java.util.Collection;
 import java.util.Map;
 
 public class EntityService<T extends Entity> {
@@ -50,6 +52,17 @@ public class EntityService<T extends Entity> {
 		return repository.save(entity);
 	}
 
+	@PreFilter(value = "hasPermission(filterObject, 'update')", filterTarget = "entities")
+	public Iterable<T> patch(final Collection<T> entities, final Map<String, Object> changes) throws IOException {
+		JsonNode tree = objectMapper.valueToTree(changes);
+		for (T entity : entities) {
+			ObjectReader reader = objectMapper.readerForUpdating(entity).withView(View.Public.class);
+			reader.readValue(tree);
+		}
+
+		return repository.save(entities);
+	}
+
 	@PreAuthorize("hasPermission(#entity, 'delete')")
 	public void delete(final T entity) {
 		repository.delete(entity);
diff --git a/src/test/java/de/thm/arsnova/services/EntityServiceTest.java b/src/test/java/de/thm/arsnova/services/EntityServiceTest.java
index f8523ca3c..e3d3a2b50 100644
--- a/src/test/java/de/thm/arsnova/services/EntityServiceTest.java
+++ b/src/test/java/de/thm/arsnova/services/EntityServiceTest.java
@@ -19,7 +19,9 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.test.context.web.WebAppConfiguration;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import static org.mockito.AdditionalAnswers.*;
@@ -71,4 +73,53 @@ public class EntityServiceTest {
 		assertEquals(patchedActive, session.isActive());
 		assertEquals(originalCreator, session.getCreator());
 	}
+
+	@Test
+	@WithMockUser(username="TestUser")
+	public void testPatchWithList() throws IOException {
+		final ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
+		final EntityService<Session> entityService = new EntityService<>(Session.class, sessionRepository, objectMapper);
+
+		when(sessionRepository.save(any(Session.class))).then(returnsFirstArg());
+
+		List<Session> sessions = new ArrayList<>();
+		final String originalId1 = "d8833f0d78964a9487ded02ba2dfbbad";
+		final String originalName1 = "Test Session 1";
+		final String originalCreator1 = "TestUser";
+		final boolean originalActive1 = false;
+		final Session session1 = new Session();
+		session1.setId(originalId1);
+		session1.setName(originalName1);
+		session1.setActive(originalActive1);
+		session1.setCreator(originalCreator1);
+		sessions.add(session1);
+		final String originalId2 = "3dc8cbff05da49d5980f6c001a6ea867";
+		final String originalName2 = "Test Session 2";
+		final String originalCreator2 = "TestUser";
+		final boolean originalActive2 = false;
+		final Session session2 = new Session();
+		session2.setId(originalId2);
+		session2.setName(originalName2);
+		session2.setActive(originalActive2);
+		session2.setCreator(originalCreator2);
+		sessions.add(session2);
+
+		final String patchedName = "Patched Session";
+		final boolean patchedActive = true;
+		final Map<String, Object> patchedValues = new HashMap<>();
+		patchedValues.put("name", patchedName);
+		patchedValues.put("active", patchedActive);
+		patchedValues.put("creator", "Should not be changeable.");
+
+		entityService.patch(sessions, patchedValues);
+
+		assertEquals(originalId1, session1.getId());
+		assertEquals(patchedName, session1.getName());
+		assertEquals(patchedActive, session1.isActive());
+		assertEquals(originalCreator1, session1.getCreator());
+		assertEquals(originalId2, session2.getId());
+		assertEquals(patchedName, session2.getName());
+		assertEquals(patchedActive, session2.isActive());
+		assertEquals(originalCreator2, session2.getCreator());
+	}
 }
-- 
GitLab