From 747f9b62cb5584c02fa749d9d6f3f5c1adb4bedf Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Sun, 16 Jul 2017 01:09:01 +0200
Subject: [PATCH] Introduce new abstractions for services and repositories

Repositories now implement Spring Data interfaces. Basic CouchDB
operations are now implemented once by `CouchDbCrudRepository` instead
of having redundant methods to handle each design document.
---
 pom.xml                                       |   4 +
 .../arsnova/persistance/AnswerRepository.java |   3 +-
 .../persistance/CommentRepository.java        |   3 +-
 .../persistance/ContentRepository.java        |   3 +-
 .../arsnova/persistance/MotdRepository.java   |   3 +-
 .../persistance/SessionRepository.java        |   3 +-
 .../arsnova/persistance/UserRepository.java   |   7 +-
 .../couchdb/CouchDbAnswerRepository.java      |   5 +-
 .../couchdb/CouchDbCommentRepository.java     |   5 +-
 .../couchdb/CouchDbContentRepository.java     |   5 +-
 .../couchdb/CouchDbCrudRepository.java        | 122 ++++++++++++++++++
 .../couchdb/CouchDbMotdRepository.java        |   5 +-
 .../couchdb/CouchDbSessionRepository.java     |   5 +-
 .../couchdb/CouchDbUserRepository.java        |  15 +--
 .../security/DbUserDetailsService.java        |   2 +-
 .../thm/arsnova/services/UserServiceImpl.java |  12 +-
 16 files changed, 163 insertions(+), 39 deletions(-)
 create mode 100644 src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCrudRepository.java

diff --git a/pom.xml b/pom.xml
index aa4a9b35e..8e65c40e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,6 +143,10 @@
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-webmvc</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.data</groupId>
+			<artifactId>spring-data-commons</artifactId>
+		</dependency>
 		<dependency>
 			<groupId>org.springframework.integration</groupId>
 			<artifactId>spring-integration-mail</artifactId>
diff --git a/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java b/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java
index 34f363c34..303dfce94 100644
--- a/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/AnswerRepository.java
@@ -21,10 +21,11 @@ import de.thm.arsnova.entities.Answer;
 import de.thm.arsnova.entities.Content;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
+import org.springframework.data.repository.CrudRepository;
 
 import java.util.List;
 
-public interface AnswerRepository {
+public interface AnswerRepository extends CrudRepository<Answer, String> {
 	Answer get(String id);
 	Answer getMyAnswer(User me, String questionId, int piRound);
 	List<Answer> getAnswers(String contentId, int piRound);
diff --git a/src/main/java/de/thm/arsnova/persistance/CommentRepository.java b/src/main/java/de/thm/arsnova/persistance/CommentRepository.java
index 182066fec..fb8a4dcd2 100644
--- a/src/main/java/de/thm/arsnova/persistance/CommentRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/CommentRepository.java
@@ -3,10 +3,11 @@ package de.thm.arsnova.persistance;
 import de.thm.arsnova.entities.Comment;
 import de.thm.arsnova.entities.CommentReadingCount;
 import de.thm.arsnova.entities.User;
+import org.springframework.data.repository.CrudRepository;
 
 import java.util.List;
 
-public interface CommentRepository {
+public interface CommentRepository extends CrudRepository<Comment, String> {
 	int getInterposedCount(String sessionKey);
 	CommentReadingCount getInterposedReadingCount(String sessionId);
 	CommentReadingCount getInterposedReadingCount(String sessionId, User user);
diff --git a/src/main/java/de/thm/arsnova/persistance/ContentRepository.java b/src/main/java/de/thm/arsnova/persistance/ContentRepository.java
index e2438013e..3c8d138cd 100644
--- a/src/main/java/de/thm/arsnova/persistance/ContentRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/ContentRepository.java
@@ -2,10 +2,11 @@ package de.thm.arsnova.persistance;
 
 import de.thm.arsnova.entities.Content;
 import de.thm.arsnova.entities.User;
+import org.springframework.data.repository.CrudRepository;
 
 import java.util.List;
 
-public interface ContentRepository {
+public interface ContentRepository extends CrudRepository<Content, String> {
 	List<Content> getQuestions(Object... keys);
 	Content getQuestion(String id);
 	Content saveQuestion(String sessionId, Content content);
diff --git a/src/main/java/de/thm/arsnova/persistance/MotdRepository.java b/src/main/java/de/thm/arsnova/persistance/MotdRepository.java
index 1c3714698..7b47069d8 100644
--- a/src/main/java/de/thm/arsnova/persistance/MotdRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/MotdRepository.java
@@ -18,10 +18,11 @@
 package de.thm.arsnova.persistance;
 
 import de.thm.arsnova.entities.Motd;
+import org.springframework.data.repository.CrudRepository;
 
 import java.util.List;
 
-public interface MotdRepository {
+public interface MotdRepository extends CrudRepository<Motd, String> {
 	List<Motd> getAdminMotds();
 	List<Motd> getMotdsForAll();
 	List<Motd> getMotdsForLoggedIn();
diff --git a/src/main/java/de/thm/arsnova/persistance/SessionRepository.java b/src/main/java/de/thm/arsnova/persistance/SessionRepository.java
index a248b2ab4..9b41a6bcd 100644
--- a/src/main/java/de/thm/arsnova/persistance/SessionRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/SessionRepository.java
@@ -23,10 +23,11 @@ import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.SessionInfo;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.entities.transport.ImportExportSession;
+import org.springframework.data.repository.CrudRepository;
 
 import java.util.List;
 
-public interface SessionRepository {
+public interface SessionRepository extends CrudRepository<Session, String> {
 	Session getSessionFromId(String sessionId);
 	Session getSessionFromKeyword(String keyword);
 	Session saveSession(User user, Session session);
diff --git a/src/main/java/de/thm/arsnova/persistance/UserRepository.java b/src/main/java/de/thm/arsnova/persistance/UserRepository.java
index 7807f66aa..c4480fac9 100644
--- a/src/main/java/de/thm/arsnova/persistance/UserRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/UserRepository.java
@@ -18,10 +18,9 @@
 package de.thm.arsnova.persistance;
 
 import de.thm.arsnova.entities.DbUser;
+import org.springframework.data.repository.CrudRepository;
 
-public interface UserRepository {
-	DbUser findUserByUsername(String username);
-	DbUser createOrUpdateUser(DbUser user);
-	boolean deleteUser(DbUser user);
+public interface UserRepository extends CrudRepository<DbUser, String> {
+	DbUser findByUsername(String username);
 	int deleteInactiveUsers(long lastActivityBefore);
 }
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java
index 673767d4f..7fae98121 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbAnswerRepository.java
@@ -20,7 +20,6 @@ import org.ektorp.DbAccessException;
 import org.ektorp.DocumentOperationResult;
 import org.ektorp.UpdateConflictException;
 import org.ektorp.ViewResult;
-import org.ektorp.support.CouchDbRepositorySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,7 +34,7 @@ import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.stream.Collectors;
 
-public class CouchDbAnswerRepository extends CouchDbRepositorySupport<Answer> implements AnswerRepository, ApplicationEventPublisherAware {
+public class CouchDbAnswerRepository extends CouchDbCrudRepository<Answer> implements AnswerRepository, ApplicationEventPublisherAware {
 	private static final int BULK_PARTITION_SIZE = 500;
 	private static final Logger logger = LoggerFactory.getLogger(CouchDbAnswerRepository.class);
 
@@ -53,7 +52,7 @@ public class CouchDbAnswerRepository extends CouchDbRepositorySupport<Answer> im
 	private ApplicationEventPublisher publisher;
 
 	public CouchDbAnswerRepository(final CouchDbConnector db, final boolean createIfNotExists) {
-		super(Answer.class, db, createIfNotExists);
+		super(Answer.class, db, "by_sessionid", createIfNotExists);
 	}
 
 	@Scheduled(fixedDelay = 5000)
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCommentRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCommentRepository.java
index 92ac64fea..1d4f333d7 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCommentRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCommentRepository.java
@@ -14,14 +14,13 @@ import org.ektorp.CouchDbConnector;
 import org.ektorp.DocumentNotFoundException;
 import org.ektorp.UpdateConflictException;
 import org.ektorp.ViewResult;
-import org.ektorp.support.CouchDbRepositorySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import java.util.List;
 
-public class CouchDbCommentRepository extends CouchDbRepositorySupport<Comment> implements CommentRepository {
+public class CouchDbCommentRepository extends CouchDbCrudRepository<Comment> implements CommentRepository {
 	private static final Logger logger = LoggerFactory.getLogger(CouchDbCommentRepository.class);
 
 	@Autowired
@@ -31,7 +30,7 @@ public class CouchDbCommentRepository extends CouchDbRepositorySupport<Comment>
 	private SessionRepository sessionRepository;
 
 	public CouchDbCommentRepository(final CouchDbConnector db, final boolean createIfNotExists) {
-		super(Comment.class, db, createIfNotExists);
+		super(Comment.class, db, "by_sessionid", createIfNotExists);
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbContentRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbContentRepository.java
index 2062894b7..e849580ed 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbContentRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbContentRepository.java
@@ -12,7 +12,6 @@ import org.ektorp.DocumentNotFoundException;
 import org.ektorp.UpdateConflictException;
 import org.ektorp.ViewQuery;
 import org.ektorp.ViewResult;
-import org.ektorp.support.CouchDbRepositorySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -29,7 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-public class CouchDbContentRepository extends CouchDbRepositorySupport<Content> implements ContentRepository {
+public class CouchDbContentRepository extends CouchDbCrudRepository<Content> implements ContentRepository {
 	private static final Logger logger = LoggerFactory.getLogger(CouchDbContentRepository.class);
 
 	@Autowired
@@ -39,7 +38,7 @@ public class CouchDbContentRepository extends CouchDbRepositorySupport<Content>
 	private AnswerRepository answerRepository;
 
 	public CouchDbContentRepository(final CouchDbConnector db, final boolean createIfNotExists) {
-		super(Content.class, db, createIfNotExists);
+		super(Content.class, db, "by_sessionid", createIfNotExists);
 	}
 
 	@Cacheable("skillquestions")
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCrudRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCrudRepository.java
new file mode 100644
index 000000000..7166c93da
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbCrudRepository.java
@@ -0,0 +1,122 @@
+package de.thm.arsnova.persistance.couchdb;
+
+import de.thm.arsnova.entities.Entity;
+import org.ektorp.BulkDeleteDocument;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.support.CouchDbRepositorySupport;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.NoRepositoryBean;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@NoRepositoryBean
+abstract class CouchDbCrudRepository<T extends Entity> extends CouchDbRepositorySupport<T> implements CrudRepository<T, String> {
+	private String countableAllViewName;
+
+	protected CouchDbCrudRepository(
+			final Class<T> type,
+			final CouchDbConnector db,
+			final String designDocName,
+			final String countableAllViewName,
+			final boolean createIfNotExists) {
+		super(type, db, designDocName, createIfNotExists);
+		this.countableAllViewName = countableAllViewName;
+	}
+
+	protected CouchDbCrudRepository(
+			final Class<T> type,
+			final CouchDbConnector db,
+			final String countableAllViewName,
+			final boolean createIfNotExists) {
+		super(type, db, createIfNotExists);
+		this.countableAllViewName = countableAllViewName;
+	}
+
+	protected String getCountableAllViewName() {
+		return countableAllViewName;
+	}
+
+	@Override
+	public <S extends T> S save(final S entity) {
+		final String id = entity.getId();
+		if (id != null) {
+			db.update(entity);
+		} else {
+			db.create(entity);
+		}
+
+		return entity;
+	}
+
+	@Override
+	public <S extends T> Iterable<S> save(final Iterable<S> entities) {
+		if (!(entities instanceof Collection)) {
+			throw new IllegalArgumentException("Implementation only supports Collections.");
+		}
+		db.executeBulk((Collection<S>) entities);
+
+		return entities;
+	}
+
+	@Override
+	public T findOne(final String id) {
+		return get(id);
+	}
+
+	@Override
+	public boolean exists(final String id) {
+		return contains(id);
+	}
+
+	@Override
+	public Iterable<T> findAll() {
+		return db.queryView(createQuery(countableAllViewName).includeDocs(true), type);
+	}
+
+	@Override
+	public Iterable<T> findAll(final Iterable<String> strings) {
+		if (!(strings instanceof Collection)) {
+			throw new IllegalArgumentException("Implementation only supports Collections.");
+		}
+
+		return db.queryView(createQuery(countableAllViewName)
+						.keys((Collection<String>) strings)
+						.includeDocs(true),
+				type);
+	}
+
+	@Override
+	public long count() {
+		return db.queryView(createQuery(countableAllViewName).reduce(true)).getRows().get(0).getValueAsInt();
+	}
+
+	@Override
+	public void delete(final String id) {
+		T entity = get(id);
+		db.delete(id, entity.getRevision());
+	}
+
+	@Override
+	public void delete(final T entity) {
+		db.delete(entity);
+	}
+
+	@Override
+	public void delete(final Iterable<? extends T> entities) {
+		if (!(entities instanceof Collection)) {
+			throw new IllegalArgumentException("Implementation only supports Collections.");
+		}
+
+		final List<BulkDeleteDocument> docs = ((Collection<? extends T>) entities).stream()
+				.map(entity -> new BulkDeleteDocument(entity.getId(), entity.getRevision()))
+				.collect(Collectors.toList());
+		db.executeBulk(docs);
+	}
+
+	@Override
+	public void deleteAll() {
+		throw new UnsupportedOperationException("Deletion of all entities is not supported for security reasons.");
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdRepository.java
index dc5f4ee9f..d8478f838 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbMotdRepository.java
@@ -21,7 +21,6 @@ import de.thm.arsnova.entities.Motd;
 import de.thm.arsnova.persistance.MotdRepository;
 import de.thm.arsnova.services.SessionService;
 import org.ektorp.CouchDbConnector;
-import org.ektorp.support.CouchDbRepositorySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -31,14 +30,14 @@ import org.springframework.cache.annotation.Cacheable;
 import java.util.ArrayList;
 import java.util.List;
 
-public class CouchDbMotdRepository extends CouchDbRepositorySupport<Motd> implements MotdRepository {
+public class CouchDbMotdRepository extends CouchDbCrudRepository<Motd> implements MotdRepository {
 	private static final Logger logger = LoggerFactory.getLogger(CouchDbMotdRepository.class);
 
 	@Autowired
 	private SessionService sessionService;
 
 	public CouchDbMotdRepository(final CouchDbConnector db, final boolean createIfNotExists) {
-		super(Motd.class, db, createIfNotExists);
+		super(Motd.class, db, "by_sessionkey", createIfNotExists);
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionRepository.java
index 0858de683..e451be0e7 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbSessionRepository.java
@@ -36,7 +36,6 @@ import org.ektorp.DocumentNotFoundException;
 import org.ektorp.UpdateConflictException;
 import org.ektorp.ViewQuery;
 import org.ektorp.ViewResult;
-import org.ektorp.support.CouchDbRepositorySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -55,7 +54,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-public class CouchDbSessionRepository extends CouchDbRepositorySupport<Session> implements SessionRepository {
+public class CouchDbSessionRepository extends CouchDbCrudRepository<Session> implements SessionRepository {
 	private static final Logger logger = LoggerFactory.getLogger(CouchDbSessionRepository.class);
 
 	@Autowired
@@ -68,7 +67,7 @@ public class CouchDbSessionRepository extends CouchDbRepositorySupport<Session>
 	private MotdRepository motdRepository;
 
 	public CouchDbSessionRepository(final CouchDbConnector db, final boolean createIfNotExists) {
-		super(Session.class, db, createIfNotExists);
+		super(Session.class, db, "by_keyword", createIfNotExists);
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbUserRepository.java b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbUserRepository.java
index 6aec2b929..e2e5e9134 100644
--- a/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbUserRepository.java
+++ b/src/main/java/de/thm/arsnova/persistance/couchdb/CouchDbUserRepository.java
@@ -22,23 +22,23 @@ import de.thm.arsnova.entities.DbUser;
 import de.thm.arsnova.persistance.UserRepository;
 import org.ektorp.BulkDeleteDocument;
 import org.ektorp.CouchDbConnector;
+import org.ektorp.DbAccessException;
 import org.ektorp.DocumentOperationResult;
 import org.ektorp.ViewQuery;
 import org.ektorp.ViewResult;
-import org.ektorp.support.CouchDbRepositorySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class CouchDbUserRepository extends CouchDbRepositorySupport<DbUser> implements UserRepository {
+public class CouchDbUserRepository extends CouchDbCrudRepository<DbUser> implements UserRepository {
 	private static final int BULK_PARTITION_SIZE = 500;
 
 	private static final Logger logger = LoggerFactory.getLogger(CouchDbUserRepository.class);
 
 	public CouchDbUserRepository(final CouchDbConnector db, final boolean createIfNotExists) {
-		super(DbUser.class, db, createIfNotExists);
+		super(DbUser.class, db, "by_username", createIfNotExists);
 	}
 
 	private void log(Object... strings) {
@@ -46,7 +46,7 @@ public class CouchDbUserRepository extends CouchDbRepositorySupport<DbUser> impl
 	}
 
 	@Override
-	public DbUser createOrUpdateUser(final DbUser user) {
+	public DbUser save(final DbUser user) {
 		final String id = user.getId();
 
 		if (null != id) {
@@ -59,20 +59,19 @@ public class CouchDbUserRepository extends CouchDbRepositorySupport<DbUser> impl
 	}
 
 	@Override
-	public DbUser findUserByUsername(final String username) {
+	public DbUser findByUsername(final String username) {
 		final List<DbUser> users = queryView("by_username", username);
 
 		return !users.isEmpty() ? users.get(0) : null;
 	}
 
 	@Override
-	public boolean deleteUser(final DbUser user) {
+	public void delete(final DbUser user) {
 		if (db.delete(user) != null) {
 			log("delete", "type", "user", "id", user.getId());
-			return true;
 		} else {
 			logger.error("Could not delete user {}", user.getId());
-			return false;
+			throw new DbAccessException("Could not delete document.");
 		}
 	}
 
diff --git a/src/main/java/de/thm/arsnova/security/DbUserDetailsService.java b/src/main/java/de/thm/arsnova/security/DbUserDetailsService.java
index 8e3b308cb..5351d98c5 100644
--- a/src/main/java/de/thm/arsnova/security/DbUserDetailsService.java
+++ b/src/main/java/de/thm/arsnova/security/DbUserDetailsService.java
@@ -48,7 +48,7 @@ public class DbUserDetailsService implements UserDetailsService {
 	public UserDetails loadUserByUsername(String username) {
 		String uid = username.toLowerCase();
 		logger.debug("Load user: " + uid);
-		DbUser dbUser = userRepository.findUserByUsername(uid);
+		DbUser dbUser = userRepository.findByUsername(uid);
 		if (null == dbUser) {
 			throw new UsernameNotFoundException("User does not exist.");
 		}
diff --git a/src/main/java/de/thm/arsnova/services/UserServiceImpl.java b/src/main/java/de/thm/arsnova/services/UserServiceImpl.java
index 17ff05b0b..08fdf672d 100644
--- a/src/main/java/de/thm/arsnova/services/UserServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/services/UserServiceImpl.java
@@ -339,7 +339,7 @@ public class UserServiceImpl implements UserService {
 
 	@Override
 	public DbUser getDbUser(String username) {
-		return userRepository.findUserByUsername(username.toLowerCase());
+		return userRepository.findByUsername(username.toLowerCase());
 	}
 
 	@Override
@@ -360,7 +360,7 @@ public class UserServiceImpl implements UserService {
 			return null;
 		}
 
-		if (null != userRepository.findUserByUsername(lcUsername)) {
+		if (null != userRepository.findByUsername(lcUsername)) {
 			logger.info("User registration failed. {} already exists.", lcUsername);
 
 			return null;
@@ -372,7 +372,7 @@ public class UserServiceImpl implements UserService {
 		dbUser.setActivationKey(RandomStringUtils.randomAlphanumeric(32));
 		dbUser.setCreation(System.currentTimeMillis());
 
-		DbUser result = userRepository.createOrUpdateUser(dbUser);
+		DbUser result = userRepository.save(dbUser);
 		if (null != result) {
 			sendActivationEmail(result);
 		} else {
@@ -436,7 +436,7 @@ public class UserServiceImpl implements UserService {
 	@Override
 	public DbUser updateDbUser(DbUser dbUser) {
 		if (null != dbUser.getId()) {
-			return userRepository.createOrUpdateUser(dbUser);
+			return userRepository.save(dbUser);
 		}
 
 		return null;
@@ -456,7 +456,7 @@ public class UserServiceImpl implements UserService {
 			throw new NotFoundException();
 		}
 
-		userRepository.deleteUser(dbUser);
+		userRepository.delete(dbUser);
 
 		return dbUser;
 	}
@@ -478,7 +478,7 @@ public class UserServiceImpl implements UserService {
 		dbUser.setPasswordResetKey(RandomStringUtils.randomAlphanumeric(32));
 		dbUser.setPasswordResetTime(System.currentTimeMillis());
 
-		if (null == userRepository.createOrUpdateUser(dbUser)) {
+		if (null == userRepository.save(dbUser)) {
 			logger.error("Password reset failed. {} could not be updated.", username);
 		}
 
-- 
GitLab