From 3e09ac924df887fa2d807e07ad050db15af1fcd7 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 21 Nov 2017 10:47:15 +0100
Subject: [PATCH] OO-3153: check the competence and type configuration to
 access the document pool, remove the security callback, implements
 enable/disable flags in the taxonomy module and the document pool module

---
 .../modules/docpool/DocumentPoolManager.java  |  40 ++++
 .../manager/DocumentPoolManagerImpl.java      |  83 +++++++
 .../docpool/site/DocumentPoolSiteDef.java     |  19 +-
 .../olat/modules/taxonomy/TaxonomyModule.java |  19 +-
 .../manager/DocumentPoolManagerTest.java      | 217 ++++++++++++++++++
 .../java/org/olat/test/AllTestsJunit4.java    |   1 +
 6 files changed, 363 insertions(+), 16 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/docpool/DocumentPoolManager.java
 create mode 100644 src/main/java/org/olat/modules/docpool/manager/DocumentPoolManagerImpl.java
 create mode 100644 src/test/java/org/olat/modules/docpool/manager/DocumentPoolManagerTest.java

diff --git a/src/main/java/org/olat/modules/docpool/DocumentPoolManager.java b/src/main/java/org/olat/modules/docpool/DocumentPoolManager.java
new file mode 100644
index 00000000000..2cd06ef7568
--- /dev/null
+++ b/src/main/java/org/olat/modules/docpool/DocumentPoolManager.java
@@ -0,0 +1,40 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.docpool;
+
+import org.olat.basesecurity.IdentityRef;
+
+/**
+ * 
+ * Initial date: 21 nov. 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public interface DocumentPoolManager {
+	
+	/**
+	 * Has a valid competence to see the document pool.
+	 * 
+	 * @param identity The identity which want to access the document pool
+	 * @return true/false
+	 */
+	public boolean hasValidCompetence(IdentityRef identity);
+
+}
diff --git a/src/main/java/org/olat/modules/docpool/manager/DocumentPoolManagerImpl.java b/src/main/java/org/olat/modules/docpool/manager/DocumentPoolManagerImpl.java
new file mode 100644
index 00000000000..6c6f681b589
--- /dev/null
+++ b/src/main/java/org/olat/modules/docpool/manager/DocumentPoolManagerImpl.java
@@ -0,0 +1,83 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.docpool.manager;
+
+import java.util.List;
+
+import javax.persistence.FlushModeType;
+
+import org.olat.basesecurity.IdentityRef;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.util.StringHelper;
+import org.olat.modules.docpool.DocumentPoolManager;
+import org.olat.modules.docpool.DocumentPoolModule;
+import org.olat.modules.taxonomy.TaxonomyCompetenceTypes;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 21 nov. 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class DocumentPoolManagerImpl implements DocumentPoolManager {
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private DocumentPoolModule documentPoolModule;
+
+	@Override
+	public boolean hasValidCompetence(IdentityRef identity) {
+		String taxonomyKey = documentPoolModule.getTaxonomyTreeKey();
+		if(!StringHelper.isLong(taxonomyKey)) {
+			return false;
+		}
+
+		StringBuilder sb = new StringBuilder(256);
+		sb.append("select competence.key from ctaxonomycompetence competence")
+		  .append(" inner join competence.identity ident")
+		  .append(" inner join competence.taxonomyLevel taxonomyLevel")
+		  .append(" inner join taxonomyLevel.type type")
+		  .append(" where taxonomyLevel.taxonomy.key=:taxonomyKey and ident.key=:identityKey")
+		  .append(" and (")
+		  .append("  (competence.type='").append(TaxonomyCompetenceTypes.manage.name()).append("' and type.documentsLibraryManagerCompetenceEnabled=true)")
+		  .append("  or")
+		  .append("  (competence.type='").append(TaxonomyCompetenceTypes.teach.name()).append("' and (type.documentsLibraryTeachCompetenceReadEnabled=true or type.documentsLibraryTeachCompetenceWriteEnabled=true))")
+		  .append("  or")
+		  .append("  (competence.type='").append(TaxonomyCompetenceTypes.have.name()).append("' and type.documentsLibraryHaveCompetenceReadEnabled=true)")
+		  .append("  or")
+		  .append("  (competence.type='").append(TaxonomyCompetenceTypes.target.name()).append("' and type.documentsLibraryTargetCompetenceReadEnabled=true)")
+		  .append(")");
+		
+		List<Long> competenceKeys = dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), Long.class)
+			.setFlushMode(FlushModeType.COMMIT)//don't flush for this query
+			.setParameter("taxonomyKey", new Long(taxonomyKey))
+			.setParameter("identityKey", identity.getKey())
+			.setFirstResult(0)
+			.setMaxResults(1)
+			.getResultList();
+		return competenceKeys != null && competenceKeys.size() > 0
+				&& competenceKeys.get(0) != null && competenceKeys.get(0).longValue() > 0;
+	}
+}
diff --git a/src/main/java/org/olat/modules/docpool/site/DocumentPoolSiteDef.java b/src/main/java/org/olat/modules/docpool/site/DocumentPoolSiteDef.java
index 3812d168718..84f12bcd8a2 100644
--- a/src/main/java/org/olat/modules/docpool/site/DocumentPoolSiteDef.java
+++ b/src/main/java/org/olat/modules/docpool/site/DocumentPoolSiteDef.java
@@ -28,13 +28,9 @@ import org.olat.core.gui.control.navigation.SiteDefinition;
 import org.olat.core.gui.control.navigation.SiteInstance;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
-import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
+import org.olat.modules.docpool.DocumentPoolManager;
 import org.olat.modules.docpool.DocumentPoolModule;
-import org.olat.modules.taxonomy.TaxonomyModule;
-import org.olat.modules.taxonomy.TaxonomyRef;
-import org.olat.modules.taxonomy.TaxonomyService;
-import org.olat.modules.taxonomy.model.TaxonomyRefImpl;
 
 /**
  * 
@@ -48,9 +44,9 @@ public class DocumentPoolSiteDef extends AbstractSiteDefinition implements SiteD
 	protected SiteInstance createSite(UserRequest ureq, WindowControl wControl, SiteConfiguration config) {
 		UserSession usess = ureq.getUserSession();
 		Roles roles = usess.getRoles();
-		if(StringHelper.containsNonWhitespace(config.getSecurityCallbackBeanId()) || roles.isOLATAdmin()) {
+		if(roles.isOLATAdmin()) {
 			return new DocumentPoolSite(this, ureq.getLocale());
-		} else if(roles.isGuestOnly() || !roles.isInvitee()) {
+		} else if(roles.isGuestOnly() || roles.isInvitee()) {
 			return null;
 		} else if(hasCompetence(usess.getIdentity())) {
 			return new DocumentPoolSite(this, ureq.getLocale());
@@ -59,17 +55,12 @@ public class DocumentPoolSiteDef extends AbstractSiteDefinition implements SiteD
 	}
 	
 	private boolean hasCompetence(Identity identity) {
-		String taxonomyKey = CoreSpringFactory.getImpl(DocumentPoolModule.class).getTaxonomyTreeKey();
-		if(StringHelper.isLong(taxonomyKey)) {
-			TaxonomyRef taxonomy = new TaxonomyRefImpl(new Long(taxonomyKey));
-			return CoreSpringFactory.getImpl(TaxonomyService.class).hasTaxonomyCompetences(taxonomy, identity);
-		}
-		return false;
+		return CoreSpringFactory.getImpl(DocumentPoolManager.class).hasValidCompetence(identity);
 	}
 	
 	@Override
 	public boolean isEnabled() {
-		TaxonomyModule module = CoreSpringFactory.getImpl(TaxonomyModule.class);
+		DocumentPoolModule module = CoreSpringFactory.getImpl(DocumentPoolModule.class);
 		return module.isEnabled() && super.isEnabled();
 	}
 }
diff --git a/src/main/java/org/olat/modules/taxonomy/TaxonomyModule.java b/src/main/java/org/olat/modules/taxonomy/TaxonomyModule.java
index 9180b5c43bb..22684a4b3dc 100644
--- a/src/main/java/org/olat/modules/taxonomy/TaxonomyModule.java
+++ b/src/main/java/org/olat/modules/taxonomy/TaxonomyModule.java
@@ -21,8 +21,10 @@ package org.olat.modules.taxonomy;
 
 import org.olat.core.configuration.AbstractSpringModule;
 import org.olat.core.configuration.ConfigOnOff;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.coordinate.CoordinatorManager;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 /**
@@ -33,6 +35,11 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class TaxonomyModule extends AbstractSpringModule implements ConfigOnOff {
+
+	private static final String TAXONOMY_ENABLED = "docpool.enabled";
+
+	@Value("${taxonomy.enabled:true}")
+	private boolean enabled;
 	
 	@Autowired
 	public TaxonomyModule(CoordinatorManager coordinatorManager) {
@@ -46,14 +53,22 @@ public class TaxonomyModule extends AbstractSpringModule implements ConfigOnOff
 
 	@Override
 	protected void initFromChangedProperties() {
-
+		String enabledObj = getStringPropertyValue(TAXONOMY_ENABLED, true);
+		if(StringHelper.containsNonWhitespace(enabledObj)) {
+			enabled = "true".equals(enabledObj);
+		}
 	}
 	
 	@Override
 	public boolean isEnabled() {
-		return true;
+		return enabled;
 	}
 
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+		setStringProperty(TAXONOMY_ENABLED, Boolean.toString(enabled), true);
+	}
+	
 	public boolean isManagedTaxonomyLevels() {
 		return true;
 	}
diff --git a/src/test/java/org/olat/modules/docpool/manager/DocumentPoolManagerTest.java b/src/test/java/org/olat/modules/docpool/manager/DocumentPoolManagerTest.java
new file mode 100644
index 00000000000..be3f9fb2508
--- /dev/null
+++ b/src/test/java/org/olat/modules/docpool/manager/DocumentPoolManagerTest.java
@@ -0,0 +1,217 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.docpool.manager;
+
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.core.util.StringHelper;
+import org.olat.modules.docpool.DocumentPoolManager;
+import org.olat.modules.docpool.DocumentPoolModule;
+import org.olat.modules.taxonomy.Taxonomy;
+import org.olat.modules.taxonomy.TaxonomyCompetence;
+import org.olat.modules.taxonomy.TaxonomyCompetenceTypes;
+import org.olat.modules.taxonomy.TaxonomyLevel;
+import org.olat.modules.taxonomy.TaxonomyLevelType;
+import org.olat.modules.taxonomy.manager.TaxonomyCompetenceDAO;
+import org.olat.modules.taxonomy.manager.TaxonomyDAO;
+import org.olat.modules.taxonomy.manager.TaxonomyLevelDAO;
+import org.olat.modules.taxonomy.manager.TaxonomyLevelTypeDAO;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 21 nov. 2017<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class DocumentPoolManagerTest extends OlatTestCase {
+
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private TaxonomyDAO taxonomyDao;
+	@Autowired
+	private TaxonomyLevelDAO taxonomyLevelDao;
+	@Autowired
+	private DocumentPoolModule documentPoolModule;
+	@Autowired
+	private DocumentPoolManager documentPoolManager;
+	@Autowired
+	private TaxonomyLevelTypeDAO taxonomyLevelTypeDao;
+	@Autowired
+	private TaxonomyCompetenceDAO taxonomyCompetenceDao;
+	
+	@Before
+	public void setUpDocumentPool() {
+		String taxonomyTreeKey = documentPoolModule.getTaxonomyTreeKey();
+		if(!StringHelper.isLong(taxonomyTreeKey)) {
+			Taxonomy taxonomy = taxonomyDao.createTaxonomy("DP-1", "Doc-pool", "Taxonomy for document pool", null);
+			dbInstance.commitAndCloseSession();
+			documentPoolModule.setTaxonomyTreeKey(taxonomy.getKey().toString());
+		}
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_manage() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.manage);
+		// set read for teach competence
+		type.setDocumentsLibraryManageCompetenceEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertTrue(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_teachRead() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.teach);
+		// set read for teach competence
+		type.setDocumentsLibraryTeachCompetenceReadEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertTrue(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_teachWrite() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.teach);
+		// set read for teach competence
+		type.setDocumentsLibraryTeachCompetenceWriteEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertTrue(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_teach_negative() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.teach);
+		// set read for teach competence
+		type.setDocumentsLibraryManageCompetenceEnabled(true);
+		type.setDocumentsLibraryHaveCompetenceReadEnabled(true);
+		type.setDocumentsLibraryTargetCompetenceReadEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertFalse(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_have() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.have);
+		// set read for teach competence
+		type.setDocumentsLibraryHaveCompetenceReadEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertTrue(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_have_negative() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.have);
+		// set read for teach competence
+		type.setDocumentsLibraryTeachCompetenceReadEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertFalse(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_target() {
+		// create a level and competence with a type teach
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		TaxonomyLevelType type = createTypeLevelCompetence(id, TaxonomyCompetenceTypes.target);
+		// set read for teach competence
+		type.setDocumentsLibraryTargetCompetenceReadEnabled(true);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commitAndCloseSession();
+
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertTrue(hasCompetence);
+	}
+	
+	@Test
+	public void hasCompetenceByTaxonomy_negative() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("competent-8");
+		String levelId = "DP-Lev. " + UUID.randomUUID();
+		Taxonomy taxonomy = getDocumentPoolTaxonomy();
+		TaxonomyLevel level = taxonomyLevelDao.createTaxonomyLevel(levelId, "Competence level", "A competence", null, null, null, null, taxonomy);
+		dbInstance.commitAndCloseSession();
+		Assert.assertNotNull(level);
+		
+		boolean hasCompetence = documentPoolManager.hasValidCompetence(id);
+		Assert.assertFalse(hasCompetence);
+	}
+	
+	private TaxonomyLevelType createTypeLevelCompetence(Identity id, TaxonomyCompetenceTypes competenceType) {
+		String levelId = "DP-Lev. " + UUID.randomUUID();
+		Taxonomy taxonomy = getDocumentPoolTaxonomy();
+		TaxonomyLevelType type = taxonomyLevelTypeDao.createTaxonomyLevelType("Type-docpool", "A type for document pool", "Typed", "TYP-0", taxonomy);
+		TaxonomyLevel level = taxonomyLevelDao.createTaxonomyLevel(levelId, "Competence level", "A competence", null, null, null, type, taxonomy);
+		TaxonomyCompetence competenceTarget = taxonomyCompetenceDao.createTaxonomyCompetence(competenceType, level, id);
+		dbInstance.commit();
+		type.setDocumentsLibraryManageCompetenceEnabled(false);
+		type.setDocumentsLibraryTeachCompetenceWriteEnabled(false);
+		type.setDocumentsLibraryTeachCompetenceReadEnabled(false);
+		type.setDocumentsLibraryHaveCompetenceReadEnabled(false);
+		type.setDocumentsLibraryTargetCompetenceReadEnabled(false);
+		type = taxonomyLevelTypeDao.updateTaxonomyLevelType(type);
+		dbInstance.commit();
+		Assert.assertNotNull(competenceTarget);
+		return type;
+	}
+	
+	private Taxonomy getDocumentPoolTaxonomy() {
+		String taxonomyTreeKey = documentPoolModule.getTaxonomyTreeKey();
+		if(StringHelper.isLong(taxonomyTreeKey)) {
+			return taxonomyDao.loadByKey(new Long(taxonomyTreeKey));
+		}
+		return null;
+	}
+
+}
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 564e3a27922..fae8c547ce2 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -162,6 +162,7 @@ import org.junit.runners.Suite;
 	org.olat.modules.wiki.gui.components.wikiToHtml.FilterUtilTest.class,
 	org.olat.modules.coach.manager.CoachingDAOTest.class,
 	org.olat.modules.coach.CoachingLargeTest.class,
+	org.olat.modules.docpool.manager.DocumentPoolManagerTest.class,
 	org.olat.modules.gotomeeting.manager.GoToJsonUtilTest.class,
 	org.olat.modules.gotomeeting.manager.GoToMeetingDAOTest.class,
 	org.olat.modules.gotomeeting.manager.GoToOrganizerDAOTest.class,
-- 
GitLab