From f9f568a85b350c2b302212afa77d16524b40b32a Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt <code@dgerhardt.net> Date: Tue, 26 Sep 2017 12:53:05 +0200 Subject: [PATCH] Extract interface from EntityService --- .../thm/arsnova/services/CommentService.java | 2 +- .../arsnova/services/CommentServiceImpl.java | 2 +- .../thm/arsnova/services/ContentService.java | 2 +- .../arsnova/services/ContentServiceImpl.java | 2 +- .../services/DefaultEntityServiceImpl.java | 80 +++++++++++++++++++ .../thm/arsnova/services/EntityService.java | 59 ++------------ .../de/thm/arsnova/services/MotdService.java | 2 +- .../thm/arsnova/services/MotdServiceImpl.java | 2 +- .../thm/arsnova/services/SessionService.java | 2 +- .../arsnova/services/SessionServiceImpl.java | 3 +- ...java => DefaultEntityServiceImplTest.java} | 6 +- 11 files changed, 98 insertions(+), 64 deletions(-) create mode 100644 src/main/java/de/thm/arsnova/services/DefaultEntityServiceImpl.java rename src/test/java/de/thm/arsnova/services/{EntityServiceTest.java => DefaultEntityServiceImplTest.java} (93%) diff --git a/src/main/java/de/thm/arsnova/services/CommentService.java b/src/main/java/de/thm/arsnova/services/CommentService.java index 6ffc38c91..4713dfb8d 100644 --- a/src/main/java/de/thm/arsnova/services/CommentService.java +++ b/src/main/java/de/thm/arsnova/services/CommentService.java @@ -6,7 +6,7 @@ import de.thm.arsnova.entities.User; import java.util.List; -public interface CommentService { +public interface CommentService extends EntityService<Comment> { boolean save(Comment comment); int count(String sessionKey); diff --git a/src/main/java/de/thm/arsnova/services/CommentServiceImpl.java b/src/main/java/de/thm/arsnova/services/CommentServiceImpl.java index 82eaca02d..0066191a7 100644 --- a/src/main/java/de/thm/arsnova/services/CommentServiceImpl.java +++ b/src/main/java/de/thm/arsnova/services/CommentServiceImpl.java @@ -24,7 +24,7 @@ import java.util.List; * Performs all comment related operations. */ @Service -public class CommentServiceImpl extends EntityService<Comment> implements CommentService, ApplicationEventPublisherAware { +public class CommentServiceImpl extends DefaultEntityServiceImpl<Comment> implements CommentService, ApplicationEventPublisherAware { private UserService userService; private CommentRepository commentRepository; diff --git a/src/main/java/de/thm/arsnova/services/ContentService.java b/src/main/java/de/thm/arsnova/services/ContentService.java index 6a66cc999..d7735b75c 100644 --- a/src/main/java/de/thm/arsnova/services/ContentService.java +++ b/src/main/java/de/thm/arsnova/services/ContentService.java @@ -27,7 +27,7 @@ import java.util.Map; /** * The functionality the question service should provide. */ -public interface ContentService { +public interface ContentService extends EntityService<Content> { Content save(Content content); Content get(String id); diff --git a/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java b/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java index 167b31863..ad8874c84 100644 --- a/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java +++ b/src/main/java/de/thm/arsnova/services/ContentServiceImpl.java @@ -63,7 +63,7 @@ import java.util.stream.Collectors; * Performs all content and answer related operations. */ @Service -public class ContentServiceImpl extends EntityService<Content> implements ContentService, ApplicationEventPublisherAware { +public class ContentServiceImpl extends DefaultEntityServiceImpl<Content> implements ContentService, ApplicationEventPublisherAware { private UserService userService; private LogEntryRepository dbLogger; diff --git a/src/main/java/de/thm/arsnova/services/DefaultEntityServiceImpl.java b/src/main/java/de/thm/arsnova/services/DefaultEntityServiceImpl.java new file mode 100644 index 000000000..3ca52edf2 --- /dev/null +++ b/src/main/java/de/thm/arsnova/services/DefaultEntityServiceImpl.java @@ -0,0 +1,80 @@ +package de.thm.arsnova.services; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +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 DefaultEntityServiceImpl<T extends Entity> implements EntityService<T> { + protected Class<T> type; + protected CrudRepository<T, String> repository; + private ObjectMapper objectMapper; + + public DefaultEntityServiceImpl(Class<T> type, CrudRepository<T, String> repository, ObjectMapper objectMapper) { + this.type = type; + this.repository = repository; + this.objectMapper = objectMapper; + } + + @Override + @PreAuthorize("hasPermission(#id, #this.this.getTypeName(), 'read')") + public T get(final String id) { + return repository.findOne(id); + } + + @Override + @PreAuthorize("hasPermission(#entity, 'create')") + public T create(final T entity) { + if (entity.getId() != null || entity.getRevision() != null) { + throw new IllegalArgumentException("Entity is not new."); + } + return repository.save(entity); + } + + @Override + @PreAuthorize("hasPermission(#oldEntity, 'update')") + public T update(final T oldEntity, final T newEntity) { + newEntity.setId(oldEntity.getId()); + return repository.save(newEntity); + } + + @Override + @PreAuthorize("hasPermission(#entity, 'update')") + public T patch(final T entity, final Map<String, Object> changes) throws IOException { + ObjectReader reader = objectMapper.readerForUpdating(entity).withView(View.Public.class); + JsonNode tree = objectMapper.valueToTree(changes); + reader.readValue(tree); + + return repository.save(entity); + } + + @Override + @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); + } + + @Override + @PreAuthorize("hasPermission(#entity, 'delete')") + public void delete(final T entity) { + repository.delete(entity); + } + + public String getTypeName() { + return type.getSimpleName().toLowerCase(); + } +} diff --git a/src/main/java/de/thm/arsnova/services/EntityService.java b/src/main/java/de/thm/arsnova/services/EntityService.java index 28315ebcf..42f258765 100644 --- a/src/main/java/de/thm/arsnova/services/EntityService.java +++ b/src/main/java/de/thm/arsnova/services/EntityService.java @@ -1,11 +1,6 @@ package de.thm.arsnova.services; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; 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; @@ -13,62 +8,22 @@ import java.io.IOException; import java.util.Collection; import java.util.Map; -public class EntityService<T extends Entity> { - protected Class<T> type; - protected CrudRepository<T, String> repository; - private ObjectMapper objectMapper; - - public EntityService(Class<T> type, CrudRepository<T, String> repository, ObjectMapper objectMapper) { - this.type = type; - this.repository = repository; - this.objectMapper = objectMapper; - } - +public interface EntityService<T extends Entity> { @PreAuthorize("hasPermission(#id, #this.this.getTypeName(), 'read')") - public T get(final String id) { - return repository.findOne(id); - } + T get(String id); @PreAuthorize("hasPermission(#entity, 'create')") - public T create(final T entity) { - if (entity.getId() != null || entity.getRevision() != null) { - throw new IllegalArgumentException("Entity is not new."); - } - return repository.save(entity); - } + T create(T entity); @PreAuthorize("hasPermission(#oldEntity, 'update')") - public T update(final T oldEntity, final T newEntity) { - newEntity.setId(oldEntity.getId()); - return repository.save(newEntity); - } + T update(T oldEntity, T newEntity); @PreAuthorize("hasPermission(#entity, 'update')") - public T patch(final T entity, final Map<String, Object> changes) throws IOException { - ObjectReader reader = objectMapper.readerForUpdating(entity).withView(View.Public.class); - JsonNode tree = objectMapper.valueToTree(changes); - reader.readValue(tree); - - return repository.save(entity); - } + T patch(T entity, Map<String, Object> changes) throws IOException; @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); - } + Iterable<T> patch(Collection<T> entities, Map<String, Object> changes) throws IOException; @PreAuthorize("hasPermission(#entity, 'delete')") - public void delete(final T entity) { - repository.delete(entity); - } - - public String getTypeName() { - return type.getSimpleName().toLowerCase(); - } + void delete(T entity); } diff --git a/src/main/java/de/thm/arsnova/services/MotdService.java b/src/main/java/de/thm/arsnova/services/MotdService.java index 177e721d5..91303a43e 100644 --- a/src/main/java/de/thm/arsnova/services/MotdService.java +++ b/src/main/java/de/thm/arsnova/services/MotdService.java @@ -26,7 +26,7 @@ import java.util.List; /** * The functionality the motd service should provide. */ -public interface MotdService { +public interface MotdService extends EntityService<Motd> { Motd getByKey(String keyword); List<Motd> getAdminMotds(); //all w/o the sessionmotds diff --git a/src/main/java/de/thm/arsnova/services/MotdServiceImpl.java b/src/main/java/de/thm/arsnova/services/MotdServiceImpl.java index 4c699c696..f2b6613f2 100644 --- a/src/main/java/de/thm/arsnova/services/MotdServiceImpl.java +++ b/src/main/java/de/thm/arsnova/services/MotdServiceImpl.java @@ -41,7 +41,7 @@ import java.util.StringTokenizer; * Performs all question, interposed question, and answer related operations. */ @Service -public class MotdServiceImpl extends EntityService<Motd> implements MotdService { +public class MotdServiceImpl extends DefaultEntityServiceImpl<Motd> implements MotdService { private UserService userService; private SessionService sessionService; diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java index 58f687791..d1ea50a71 100644 --- a/src/main/java/de/thm/arsnova/services/SessionService.java +++ b/src/main/java/de/thm/arsnova/services/SessionService.java @@ -31,7 +31,7 @@ import java.util.UUID; /** * The functionality the session service should provide. */ -public interface SessionService { +public interface SessionService extends EntityService<Session> { Session getByKey(String keyword); Session getForAdmin(final String keyword); diff --git a/src/main/java/de/thm/arsnova/services/SessionServiceImpl.java b/src/main/java/de/thm/arsnova/services/SessionServiceImpl.java index 78dbf631e..c504763c5 100644 --- a/src/main/java/de/thm/arsnova/services/SessionServiceImpl.java +++ b/src/main/java/de/thm/arsnova/services/SessionServiceImpl.java @@ -43,7 +43,6 @@ import de.thm.arsnova.exceptions.BadRequestException; import de.thm.arsnova.exceptions.ForbiddenException; import de.thm.arsnova.exceptions.NotFoundException; import de.thm.arsnova.exceptions.PayloadTooLargeException; -import de.thm.arsnova.exceptions.UnauthorizedException; import de.thm.arsnova.persistance.SessionRepository; import de.thm.arsnova.persistance.VisitedSessionRepository; import org.ektorp.UpdateConflictException; @@ -71,7 +70,7 @@ import java.util.UUID; * Performs all session related operations. */ @Service -public class SessionServiceImpl extends EntityService<Session> implements SessionService, ApplicationEventPublisherAware { +public class SessionServiceImpl extends DefaultEntityServiceImpl<Session> implements SessionService, ApplicationEventPublisherAware { private static final long SESSION_INACTIVITY_CHECK_INTERVAL_MS = 30 * 60 * 1000L; private static final Logger logger = LoggerFactory.getLogger(SessionServiceImpl.class); diff --git a/src/test/java/de/thm/arsnova/services/EntityServiceTest.java b/src/test/java/de/thm/arsnova/services/DefaultEntityServiceImplTest.java similarity index 93% rename from src/test/java/de/thm/arsnova/services/EntityServiceTest.java rename to src/test/java/de/thm/arsnova/services/DefaultEntityServiceImplTest.java index e3d3a2b50..a7708c9ee 100644 --- a/src/test/java/de/thm/arsnova/services/EntityServiceTest.java +++ b/src/test/java/de/thm/arsnova/services/DefaultEntityServiceImplTest.java @@ -33,7 +33,7 @@ import static org.junit.Assert.*; @WebAppConfiguration @ContextConfiguration(classes = {AppConfig.class, TestAppConfig.class, TestPersistanceConfig.class, TestSecurityConfig.class}) @ActiveProfiles("test") -public class EntityServiceTest { +public class DefaultEntityServiceImplTest { @Autowired @Qualifier("defaultJsonMessageConverter") private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter; @@ -45,7 +45,7 @@ public class EntityServiceTest { @WithMockUser(username="TestUser") public void testPatch() throws IOException { final ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper(); - final EntityService<Session> entityService = new EntityService<>(Session.class, sessionRepository, objectMapper); + final DefaultEntityServiceImpl<Session> entityService = new DefaultEntityServiceImpl<>(Session.class, sessionRepository, objectMapper); when(sessionRepository.save(any(Session.class))).then(returnsFirstArg()); @@ -78,7 +78,7 @@ public class EntityServiceTest { @WithMockUser(username="TestUser") public void testPatchWithList() throws IOException { final ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper(); - final EntityService<Session> entityService = new EntityService<>(Session.class, sessionRepository, objectMapper); + final DefaultEntityServiceImpl<Session> entityService = new DefaultEntityServiceImpl<>(Session.class, sessionRepository, objectMapper); when(sessionRepository.save(any(Session.class))).then(returnsFirstArg()); -- GitLab