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