From 692787460d5c9736c9be508042e7c330b8e7029d Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 11 Nov 2020 12:21:39 +0100
Subject: [PATCH] OO-5066: find an administrator to delete resource in the name
 of

---
 .../org/olat/repository/RepositoryModule.java |  2 +-
 .../repository/handlers/CourseHandler.java    |  4 +-
 .../manager/AutomaticLifecycleService.java    | 54 +++++++++++++++++--
 .../AutomaticLifecycleServiceTest.java        | 11 ++++
 .../manager/RepositoryEntryDAOTest.java       |  2 +-
 5 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/olat/repository/RepositoryModule.java b/src/main/java/org/olat/repository/RepositoryModule.java
index b8b83cca8a7..7883bcd6bc7 100644
--- a/src/main/java/org/olat/repository/RepositoryModule.java
+++ b/src/main/java/org/olat/repository/RepositoryModule.java
@@ -101,7 +101,7 @@ public class RepositoryModule extends AbstractSpringModule {
 	private String lifecycleAutoClose;
 	@Value("${repo.lifecycle.auto.delete:}")
 	private String lifecycleAutoDelete;
-	@Value("${repo.lifecycle.auto.definitively.delete:6month}")
+	@Value("${repo.lifecycle.auto.definitively.delete:}")
 	private String lifecycleAutoDefinitivelyDelete;
 	@Value("${repo.lifecylce.notification.close.delete:}")
 	private String lifecycleNotificationByCloseDelete;
diff --git a/src/main/java/org/olat/repository/handlers/CourseHandler.java b/src/main/java/org/olat/repository/handlers/CourseHandler.java
index f9a69bad6a9..592e7ed8485 100644
--- a/src/main/java/org/olat/repository/handlers/CourseHandler.java
+++ b/src/main/java/org/olat/repository/handlers/CourseHandler.java
@@ -648,9 +648,9 @@ public class CourseHandler implements RepositoryHandler {
 		UserManager um = UserManager.getInstance();
 		String charset = um.getUserCharset(identity);
 		try {
-			CourseFactory.archiveCourse(entry.getOlatResource(),charset, locale, identity, roles);
+			CourseFactory.archiveCourse(entry.getOlatResource(), charset, locale, identity, roles);
 		} catch (CorruptedCourseException e) {
-			log.error("The course is corrupted, cannot archive it: " + entry, e);
+			log.error("The course is corrupted, cannot archive it: {}", entry, e);
 		}
 		return true;
 	}
diff --git a/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java b/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java
index 932db11883d..95538aa8410 100644
--- a/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java
+++ b/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java
@@ -22,13 +22,23 @@ package org.olat.repository.manager;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.logging.log4j.Logger;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.OrganisationRoles;
+import org.olat.basesecurity.SearchIdentityParams;
 import org.olat.commons.calendar.CalendarUtils;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.QueryBuilder;
+import org.olat.core.id.Identity;
+import org.olat.core.id.OrganisationRef;
+import org.olat.core.id.Roles;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.i18n.I18nManager;
+import org.olat.repository.ErrorList;
+import org.olat.repository.RepositoryDeletionModule;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryLifeCycleValue;
 import org.olat.repository.RepositoryEntryManagedFlag;
@@ -52,9 +62,13 @@ public class AutomaticLifecycleService {
 	@Autowired
 	private DB dbInstance;
 	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
 	private RepositoryModule repositoryModule;
 	@Autowired
 	private RepositoryService repositoryService;
+	@Autowired
+	private RepositoryDeletionModule repositoryDeletionModule;
 	
 	public void manage() {
 		close();
@@ -116,9 +130,7 @@ public class AutomaticLifecycleService {
 				try {
 					boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.delete);
 					if(!deleteManaged) {
-						log.info(Tracing.M_AUDIT, "Automatic deleting (definitively) course: {} [{}]", entry.getDisplayname(), entry.getKey());
-						repositoryService.deletePermanently(entry, null, null, null);
-						dbInstance.commit();
+						definitivelyDelete(entry);
 					}
 				} catch (Exception e) {
 					log.error("",  e);
@@ -128,6 +140,42 @@ public class AutomaticLifecycleService {
 		}
 	}
 	
+	/**
+	 * @param entry The repository entry to delete
+	 * @return true if the deletion happens without errors
+	 */
+	protected boolean definitivelyDelete(RepositoryEntry entry) {
+		boolean deleted = false;
+		Identity administrator = getDefaultAdministrator(entry);
+		if(administrator != null) {
+			Roles roles = securityManager.getRoles(administrator);
+			Locale locale = I18nManager.getInstance().getLocaleOrDefault(administrator.getUser().getPreferences().getLanguage());
+			log.info(Tracing.M_AUDIT, "Automatic deleting (definitively) course: {} [{}]", entry.getDisplayname(), entry.getKey());
+			ErrorList errors = repositoryService.deletePermanently(entry, administrator, roles, locale);
+			deleted = !errors.hasErrors();
+		} else {
+			log.error("Automatic deleting aborted, no administrator found for archives: {} [{}]", entry.getDisplayname(), entry.getKey());
+		}
+		dbInstance.commit();
+		return deleted;
+	}
+	
+	private Identity getDefaultAdministrator(RepositoryEntry entry) {
+		Identity administrator = repositoryDeletionModule.getAdminUserIdentity();
+		if(administrator == null) {
+			List<OrganisationRef> identityOrgs = repositoryService.getOrganisationReferences(entry);
+			SearchIdentityParams identityParams = new SearchIdentityParams();
+			identityParams.setOrganisations(identityOrgs);
+			identityParams.setRoles(new OrganisationRoles[]{ OrganisationRoles.administrator });
+			identityParams.setStatus(Identity.STATUS_VISIBLE_LIMIT);
+			List<Identity> admins = securityManager.getIdentitiesByPowerSearch(identityParams, 0, -1);
+			if(!admins.isEmpty()) {
+				administrator = admins.get(0);
+			}
+		}
+		return administrator;
+	}
+
 	protected List<RepositoryEntry> getRepositoryEntries(Date date, RepositoryEntryStatusEnum[] states) {
 		QueryBuilder sb = new QueryBuilder(512);
 		sb.append("select v from repositoryentry as v ")
diff --git a/src/test/java/org/olat/repository/manager/AutomaticLifecycleServiceTest.java b/src/test/java/org/olat/repository/manager/AutomaticLifecycleServiceTest.java
index d6bd8049c7b..c4e4039000b 100644
--- a/src/test/java/org/olat/repository/manager/AutomaticLifecycleServiceTest.java
+++ b/src/test/java/org/olat/repository/manager/AutomaticLifecycleServiceTest.java
@@ -25,6 +25,7 @@ import java.util.List;
 import org.junit.Assert;
 import org.junit.Test;
 import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
 import org.olat.core.util.DateUtils;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryStatusEnum;
@@ -177,6 +178,16 @@ public class AutomaticLifecycleServiceTest extends OlatTestCase {
 		Assert.assertEquals(RepositoryEntryStatusEnum.published, reloadEntryInUse.getEntryStatus());
 	}
 	
+	@Test
+	public void deleteCoursePermanentlyByLifecycle() {
+		Identity initialAuthor = JunitTestHelper.createAndPersistIdentityAsRndUser("auth-del-1");
+		RepositoryEntry re = JunitTestHelper.deployDemoCourse(initialAuthor);
+		dbInstance.commitAndCloseSession();
+		
+		boolean deleted = automaticLifecycleService.definitivelyDelete(re);
+		dbInstance.commitAndCloseSession();
+		Assert.assertTrue(deleted);
+	}
 
 	private RepositoryEntry createTrashedRepositoryEntry(String displayName, RepositoryEntryStatusEnum status, int startDays, int endDays, int trashedDays) {
 		RepositoryEntry entry = createRepositoryEntry(displayName, status, startDays, endDays);
diff --git a/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java b/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java
index a3edc1345c2..99a2d0717d1 100644
--- a/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java
+++ b/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java
@@ -413,7 +413,7 @@ public class RepositoryEntryDAOTest extends OlatTestCase {
 	@Test
 	public void getLastUsedRepositoryEntries() {
 		// insert test data
-		OLATResourceable resourceable = OresHelper.createOLATResourceableInstance("Wiki", new Long(CodeHelper.getForeverUniqueID()));
+		OLATResourceable resourceable = OresHelper.createOLATResourceableInstance("Wiki", Long.valueOf(CodeHelper.getForeverUniqueID()));
 		OLATResource resource = resourceManager.createAndPersistOLATResourceInstance(resourceable);
 		Organisation defOrganisation = organisationService.getDefaultOrganisation();
 		RepositoryEntry re = repositoryService.create(null, "Rei Ayanami", "-", "Repository entry DAO Test all", "", resource,
-- 
GitLab