From 81396e7bc7064361940a8699119c4751907cd552 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Fri, 18 May 2018 17:30:02 +0200
Subject: [PATCH] OO-3487: delete instant message during user deletion process

---
 .../manager/InstantMessageDAO.java            | 12 ++++
 .../manager/InstantMessagePreferencesDAO.java | 15 ++++-
 .../manager/InstantMessagingServiceImpl.java  | 27 +++++---
 .../instantMessaging/manager/RosterDAO.java   | 10 ++-
 .../model/InstantMessageImpl.java             |  4 ++
 .../InstantMessageServiceTest.java            | 67 +++++++++++++------
 6 files changed, 104 insertions(+), 31 deletions(-)

diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java
index 56d671b2007..fa7dc93e9f9 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java
@@ -25,6 +25,7 @@ import java.util.List;
 import javax.persistence.TemporalType;
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
@@ -103,6 +104,17 @@ public class InstantMessageDAO {
 		return count;
 	}
 	
+	public int deleteMessages(IdentityRef identity) {
+		int count = dbInstance.getCurrentEntityManager()
+				.createQuery("delete from instantmessage msg where msg.fromKey=:identityKey")
+				.setParameter("identityKey", identity.getKey())
+				.executeUpdate();
+		if(count > 0) {
+			log.audit(count + " IM messages delete for identity: " + identity.getKey());
+		}
+		return count;
+	}
+	
 	public InstantMessageNotification createNotification(Long fromIdentityKey, Long toIdentityKey, OLATResourceable chatResource) {
 		InstantMessageNotificationImpl notification = new InstantMessageNotificationImpl();
 		notification.setToIdentityKey(toIdentityKey);
diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
index 52712c8950f..1339e5af6a0 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.instantMessaging.model.ImPreferencesImpl;
@@ -93,7 +94,7 @@ public class InstantMessagePreferencesDAO {
 	
 	public Map<Long,String> getBuddyStatus(List<Long> buddies) {
 		if(buddies == null || buddies.isEmpty()) {
-			return new HashMap<Long,String>();
+			return new HashMap<>();
 		}
 		
 		TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager()
@@ -101,7 +102,7 @@ public class InstantMessagePreferencesDAO {
 
 		int hibernateInBatch = 250;
 		int firstResult = 0;
-		Map<Long,String> statusMap = new HashMap<Long,String>();
+		Map<Long,String> statusMap = new HashMap<>();
 		do {
 			int toIndex = Math.min(firstResult + hibernateInBatch, buddies.size());
 			List<Long> inParameter = buddies.subList(firstResult, toIndex);
@@ -157,4 +158,14 @@ public class InstantMessagePreferencesDAO {
 			createPreferences(identity, Presence.available.name(), visible);
 		}
 	}
+	
+	public void deletePreferences(IdentityRef identity) {
+		List<ImPreferencesImpl> prefs = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMPreferencesByIdentity", ImPreferencesImpl.class)
+				.setParameter("identityKey", identity.getKey())
+				.getResultList();
+		for(ImPreferencesImpl pref:prefs) {
+			dbInstance.getCurrentEntityManager().remove(pref);
+		}
+	}
 }
diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
index 4dd2a8bfac3..ff599787a46 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
@@ -19,6 +19,7 @@
  */
 package org.olat.instantMessaging.manager;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -57,6 +58,7 @@ import org.olat.instantMessaging.model.BuddyStats;
 import org.olat.instantMessaging.model.InstantMessageImpl;
 import org.olat.instantMessaging.model.Presence;
 import org.olat.instantMessaging.model.RosterEntryView;
+import org.olat.user.UserDataDeletable;
 import org.olat.user.UserManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -68,7 +70,7 @@ import org.springframework.stereotype.Service;
  *
  */
 @Service
-public class InstantMessagingServiceImpl extends BasicManager implements InstantMessagingService, DeletableGroupData {
+public class InstantMessagingServiceImpl extends BasicManager implements InstantMessagingService, DeletableGroupData, UserDataDeletable {
 	
 	@Autowired
 	private RosterDAO rosterDao;
@@ -97,6 +99,13 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		return true;
 	}
 
+	@Override
+	public void deleteUserData(Identity identity, String newDeletedUserName, File archivePath) {
+		imDao.deleteMessages(identity);
+		rosterDao.deleteEntry(identity);
+		prefsDao.deletePreferences(identity);
+	}
+
 	@Override
 	public String getStatus(Long identityKey) {
 		return prefsDao.getStatus(identityKey);
@@ -130,7 +139,7 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 			resName = identityKey1 + "-" + identityKey2;
 		}
 		long key = identityKey1.longValue() + identityKey2.longValue();
-		return OresHelper.createOLATResourceableInstance(resName, new Long(key));
+		return OresHelper.createOLATResourceableInstance(resName, Long.valueOf(key));
 	}
 
 	@Override
@@ -238,7 +247,7 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		//count all my buddies
 		Collection<Long> buddiesColl = contactDao.getDistinctGroupOwnersParticipants(me);
 		buddiesColl.remove(me.getKey());
-		List<Long> buddies = new ArrayList<Long>(buddiesColl);
+		List<Long> buddies = new ArrayList<>(buddiesColl);
 		stats.setOfflineBuddies(buddies.size());
 
 		//filter online users
@@ -263,9 +272,9 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 
 	@Override
 	public List<BuddyGroup> getBuddyGroups(Identity me, boolean offlineUsers) {
-		List<BuddyGroup> groups = new ArrayList<BuddyGroup>(25);
-		Map<Long,BuddyGroup> groupMap = new HashMap<Long,BuddyGroup>();
-		Map<Long, String> identityKeyToStatus = new HashMap<Long, String>();
+		List<BuddyGroup> groups = new ArrayList<>(25);
+		Map<Long,BuddyGroup> groupMap = new HashMap<>();
+		Map<Long, String> identityKeyToStatus = new HashMap<>();
 		List<ContactViewExtended> contactList = contactDao.getContactWithExtendedInfos(me);
 		collectMembersStatus(contactList, identityKeyToStatus);
 		for(ContactViewExtended contact:contactList) {
@@ -275,7 +284,7 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 	
 	private void collectMembersStatus(List<? extends BusinessGroupMemberView> members, Map<Long, String> identityKeyToStatus) {
-		Set<Long> loadStatus = new HashSet<Long>();
+		Set<Long> loadStatus = new HashSet<>();
 		for(BusinessGroupMemberView member:members) {
 			Long identityKey = member.getIdentityKey();
 			if(!identityKeyToStatus.containsKey(identityKey) && !loadStatus.contains(identityKey)) {
@@ -289,7 +298,7 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		}
 		
 		if(loadStatus.size() > 0) {
-			List<Long> statusToLoadList = new ArrayList<Long>(loadStatus);
+			List<Long> statusToLoadList = new ArrayList<>(loadStatus);
 			Map<Long,String> statusMap = prefsDao.getBuddyStatus(statusToLoadList);
 			for(Long toLoad:statusToLoadList) {
 				String status = statusMap.get(toLoad);
@@ -337,7 +346,7 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	@Override
 	public List<Buddy> getBuddiesListenTo(OLATResourceable chatResource) {
 		List<RosterEntryView> roster = rosterDao.getRosterView(chatResource, 0, -1);
-		List<Buddy> buddies = new ArrayList<Buddy>();
+		List<Buddy> buddies = new ArrayList<>();
 		if(roster != null) {
 			for(RosterEntryView entry:roster) {
 				String name = entry.isAnonym() ? entry.getNickName() : entry.getFullName();
diff --git a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
index e85024fb91f..c7634233418 100644
--- a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
@@ -24,6 +24,7 @@ import java.util.List;
 
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
@@ -138,7 +139,7 @@ public class RosterDAO {
 		return query.getResultList();
 	}
 	
-	public void deleteEntry(Identity identity, OLATResourceable ores) {
+	public void deleteEntry(IdentityRef identity, OLATResourceable ores) {
 		String del = "delete from imrosterentry entry where entry.identityKey=:identityKey and entry.resourceId=:resid and entry.resourceTypeName=:resname";
 		dbInstance.getCurrentEntityManager().createQuery(del)
 				.setParameter("identityKey", identity.getKey())
@@ -146,4 +147,11 @@ public class RosterDAO {
 				.setParameter("resname", ores.getResourceableTypeName())
 				.executeUpdate();
 	}
+	
+	public void deleteEntry(IdentityRef identity) {
+		String del = "delete from imrosterentry entry where entry.identityKey=:identityKey";
+		dbInstance.getCurrentEntityManager().createQuery(del)
+				.setParameter("identityKey", identity.getKey())
+				.executeUpdate();
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java b/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java
index 71336a847e6..df8e869866f 100644
--- a/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java
+++ b/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java
@@ -108,6 +108,7 @@ public class InstantMessageImpl implements InstantMessage, Persistable, CreateIn
 		this.creationDate = creationDate;
 	}
 
+	@Override
 	public Long getFromKey() {
 		return fromKey;
 	}
@@ -138,6 +139,7 @@ public class InstantMessageImpl implements InstantMessage, Persistable, CreateIn
 		this.resourceId = resourceId;
 	}
 
+	@Override
 	public boolean isAnonym() {
 		return anonym;
 	}
@@ -146,6 +148,7 @@ public class InstantMessageImpl implements InstantMessage, Persistable, CreateIn
 		this.anonym = anonym;
 	}
 
+	@Override
 	public String getFromNickName() {
 		return fromNickName;
 	}
@@ -154,6 +157,7 @@ public class InstantMessageImpl implements InstantMessage, Persistable, CreateIn
 		this.fromNickName = fromNickName;
 	}
 
+	@Override
 	public String getBody() {
 		return body;
 	}
diff --git a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
index 8de9c25c030..73e7651251f 100644
--- a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
+++ b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
@@ -24,6 +24,7 @@ import java.util.UUID;
 
 import org.junit.Assert;
 import org.junit.Test;
+import org.olat.admin.user.delete.service.UserDeletionManager;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.control.Event;
@@ -39,6 +40,7 @@ import org.olat.instantMessaging.manager.InstantMessagePreferencesDAO;
 import org.olat.instantMessaging.manager.RosterDAO;
 import org.olat.instantMessaging.model.Buddy;
 import org.olat.instantMessaging.model.BuddyStats;
+import org.olat.instantMessaging.model.RosterEntryImpl;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -54,32 +56,26 @@ public class InstantMessageServiceTest extends OlatTestCase {
 	@Autowired
 	private DB dbInstance;
 	@Autowired
-	private InstantMessageDAO imDao;
-	@Autowired
-	private InstantMessagePreferencesDAO preferencesDao;
-	@Autowired
 	private RosterDAO rosterDao;
 	@Autowired
+	private InstantMessageDAO imDao;
+	@Autowired
 	private InstantMessagingService imService;
 	@Autowired
+	private UserDeletionManager userDeletionManager;
+	@Autowired
 	private BusinessGroupService businessGroupService;
 	@Autowired
 	private BusinessGroupRelationDAO businessGroupRelationDao;
+	@Autowired
+	private InstantMessagePreferencesDAO instantMessagePreferencesDao;
 
-	@Test
-	public void should_service_present() {
-		Assert.assertNotNull(dbInstance);
-		Assert.assertNotNull(imDao);
-		Assert.assertNotNull(preferencesDao);
-		Assert.assertNotNull(rosterDao);
-		Assert.assertNotNull(imService);
-	}
 	
 	@Test
 	public void testGetBuddiesListenTo() {
 		DummyListener dummyListener = new DummyListener();
-		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-1-" + UUID.randomUUID().toString());
-		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-2-" + UUID.randomUUID().toString());
+		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-1-");
+		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-2-");
 		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance(UUID.randomUUID().toString(), chatter1.getKey());
 		imService.listenChat(chatter1, chatResource, null, false, false, dummyListener);
 		imService.listenChat(chatter2, chatResource, "Chatter-2", true, true, dummyListener);
@@ -106,7 +102,7 @@ public class InstantMessageServiceTest extends OlatTestCase {
 	@Test
 	public void testGetBuddyStats_empty() {
 		//create a chat
-		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-3-" + UUID.randomUUID().toString());
+		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-3-");
 		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance(UUID.randomUUID().toString(), chatter1.getKey());
 		imService.listenChat(chatter1, chatResource, null, false, false, new DummyListener());
 		dbInstance.commitAndCloseSession();
@@ -123,8 +119,8 @@ public class InstantMessageServiceTest extends OlatTestCase {
 	@Test
 	public void testGetBuddyStats_mustBeEmpty() {
 		//create a group with owner and participant
-		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-4-" + UUID.randomUUID().toString());
-		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-5-" + UUID.randomUUID().toString());
+		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-4-");
+		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-5-");
 		BusinessGroup group = businessGroupService.createBusinessGroup(null, "Chat-1-", "testGetBuddyStats_mustBeEmpty", 0, 10, false, false, null);
 		businessGroupRelationDao.addRole(chatter1, group, GroupRoles.coach.name());
 		businessGroupRelationDao.addRole(chatter2, group, GroupRoles.participant.name());
@@ -145,8 +141,8 @@ public class InstantMessageServiceTest extends OlatTestCase {
 	@Test
 	public void testGetBuddyStats_visible() {
 		//create a group with owner and participant
-		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-6-" + UUID.randomUUID().toString());
-		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-7-" + UUID.randomUUID().toString());
+		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-6-");
+		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-7-");
 		BusinessGroup group = businessGroupService.createBusinessGroup(null, "Chat-2-", "testGetBuddyStats_visible", 0, 10, false, false, null);
 		businessGroupRelationDao.addRole(chatter1, group, GroupRoles.coach.name());
 		businessGroupRelationDao.addRole(chatter2, group, GroupRoles.participant.name());
@@ -161,6 +157,39 @@ public class InstantMessageServiceTest extends OlatTestCase {
 		Assert.assertEquals(0, stats.getOnlineBuddies());
 	}
 	
+	@Test
+	public void deleteUser() {
+		Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-8");
+		Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Chat-9");
+
+		OLATResourceable chat = imService.getPrivateChatResource(chatter1.getKey(), chatter2.getKey());
+		imService.sendPresence(chatter1, "Me", false, true, chat);
+		imService.sendPresence(chatter2, "Me", false, true, chat);
+		ImPreferences preferences1 = imService.getImPreferences(chatter1);
+		ImPreferences preferences2 = imService.getImPreferences(chatter2);
+		dbInstance.commit();
+		Assert.assertNotNull(preferences1);
+		Assert.assertNotNull(preferences2);
+		InstantMessage message = imService.sendMessage(chatter1, "Me", false, "Hello", chat);
+		dbInstance.commitAndCloseSession();
+		Assert.assertNotNull(message);
+
+		// delete the user
+		userDeletionManager.deleteIdentity(chatter1);
+		dbInstance.commitAndCloseSession();
+		
+		// check preferences are deleted
+		Assert.assertNull(instantMessagePreferencesDao.getStatus(chatter1.getKey()));
+		Assert.assertNotNull(instantMessagePreferencesDao.getStatus(chatter2.getKey()));
+		// check roster
+		List<RosterEntryImpl> entries = rosterDao.getRoster(chat, 0, -1);
+		Assert.assertEquals(1, entries.size());
+		Assert.assertEquals(chatter2.getKey(), entries.get(0).getIdentityKey());
+		// check messages
+		InstantMessage deletedMessage = imDao.loadMessageById(message.getKey());
+		Assert.assertNull(deletedMessage);
+	}
+	
 	
 	private class DummyListener implements GenericEventListener {
 		@Override
-- 
GitLab