From df73a25453a647c697baa88dc00f4f2e985cda29 Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Thu, 27 Oct 2016 17:17:18 +0200
Subject: [PATCH] Delete inactive users in intervals

---
 .../java/de/thm/arsnova/dao/CouchDBDao.java   | 30 +++++++++++++++++++
 .../java/de/thm/arsnova/dao/IDatabaseDao.java |  2 ++
 .../de/thm/arsnova/services/UserService.java  | 20 ++++++++-----
 .../de/thm/arsnova/dao/StubDatabaseDao.java   |  6 ++++
 4 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 875b999c..b2e63abd 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -2212,6 +2212,36 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		return false;
 	}
 
+	@Override
+	public boolean deleteInactiveUsers(long lastActivityBefore) {
+		try {
+			NovaView view = new NovaView("user/inactive_by_creation");
+			view.setEndKey(lastActivityBefore);
+			List<Document> results = this.getDatabase().view(view).getResults();
+
+			final List<Document> newDocs = new ArrayList<Document>();
+			for (Document oldDoc : results) {
+				final Document newDoc = new Document();
+				newDoc.setId(oldDoc.getId());
+				newDoc.setRev(oldDoc.getJSONObject("value").getString("_rev"));
+				newDoc.put("_deleted", true);
+				newDocs.add(newDoc);
+				LOGGER.debug("Marked user document {} for deletion.", oldDoc.getId());
+			}
+
+			if (newDocs.size() > 0) {
+				getDatabase().bulkSaveDocuments(newDocs.toArray(new Document[newDocs.size()]));
+				LOGGER.info("Deleted {} inactive users.", newDocs.size());
+			}
+
+			return true;
+		} catch (IOException e) {
+			LOGGER.error("Could not delete inactive users.");
+		}
+
+		return false;
+	}
+
 	@Override
 	public SessionInfo importSession(User user, ImportExportSession importSession) {
 		final Session session = this.saveSession(user, importSession.generateSessionEntity(user));
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index f5d2d2fb..f1ed7387 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -196,6 +196,8 @@ public interface IDatabaseDao {
 
 	boolean deleteUser(DbUser dbUser);
 
+	boolean deleteInactiveUsers(long lastActivityBefore);
+
 	CourseScore getLearningProgress(Session session);
 
 	List<SessionInfo> getMySessionsInfo(User user, final int start, final int limit);
diff --git a/src/main/java/de/thm/arsnova/services/UserService.java b/src/main/java/de/thm/arsnova/services/UserService.java
index 37d054ca..3ca5022e 100644
--- a/src/main/java/de/thm/arsnova/services/UserService.java
+++ b/src/main/java/de/thm/arsnova/services/UserService.java
@@ -56,15 +56,8 @@ import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 import java.io.UnsupportedEncodingException;
 import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Set;
-import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Pattern;
 
@@ -82,6 +75,9 @@ public class UserService implements IUserService {
 
 	private static final int PASSWORD_RESET_KEY_DURABILITY_MS = 2 * 60 * 60 * 1000;
 
+	private static final long ACTIVATION_KEY_CHECK_INTERVAL_MS = 30 * 60 * 1000L;
+	private static final long ACTIVATION_KEY_DURABILITY_MS = 6 * 60 * 60 * 1000L;
+
 	public static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);
 
 	private static final ConcurrentHashMap<UUID, User> socketid2user = new ConcurrentHashMap<UUID, User>();
@@ -161,6 +157,14 @@ public class UserService implements IUserService {
 		}
 	}
 
+	@Scheduled(fixedDelay = ACTIVATION_KEY_CHECK_INTERVAL_MS)
+	public void deleteInactiveUsers() {
+		LOGGER.info("Delete inactive users.");
+		long unixTime = System.currentTimeMillis();
+		long lastActivityBefore = unixTime - ACTIVATION_KEY_DURABILITY_MS;
+		databaseDao.deleteInactiveUsers(lastActivityBefore);
+	}
+
 	@Override
 	public User getCurrentUser() {
 		final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index c9bae397..675efb8a 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -458,6 +458,12 @@ public class StubDatabaseDao implements IDatabaseDao {
 		return false;
 	}
 
+	@Override
+	public boolean deleteInactiveUsers(long lastActivityBefore) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
 	@Override
 	public List<InterposedQuestion> getInterposedQuestions(Session session, User user, final int start, final int limit) {
 		// TODO Auto-generated method stub
-- 
GitLab