diff --git a/src/main/java/org/olat/commons/calendar/CalendarWebDAVProvider.java b/src/main/java/org/olat/commons/calendar/CalendarWebDAVProvider.java index 63a6f7f6d6bb972454d861b18b5ffe8ef8b697b0..28474840361ff3f80706fc8cf624827cfc33810c 100644 --- a/src/main/java/org/olat/commons/calendar/CalendarWebDAVProvider.java +++ b/src/main/java/org/olat/commons/calendar/CalendarWebDAVProvider.java @@ -28,7 +28,7 @@ package org.olat.commons.calendar; import java.io.File; import org.olat.core.commons.services.webdav.WebDAVProvider; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.LocalFileImpl; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VirtualContainer; @@ -38,12 +38,12 @@ public class CalendarWebDAVProvider implements WebDAVProvider { private static final String MOUNT_POINT = "calendars"; - public VFSContainer getContainer(Identity identity) { + public VFSContainer getContainer(IdentityEnvironment identityEnv) { VirtualContainer calendars = new VirtualContainer("calendars"); calendars.setLocalSecurityCallback(new ReadOnlyCallback()); // get private calendar CalendarManager calendarManager = CalendarManagerFactory.getInstance().getCalendarManager(); - File fPersonalCalendar = calendarManager.getCalendarICalFile(CalendarManager.TYPE_USER, identity.getName()); + File fPersonalCalendar = calendarManager.getCalendarICalFile(CalendarManager.TYPE_USER, identityEnv.getIdentity().getName()); calendars.addItem(new LocalFileImpl(fPersonalCalendar)); return calendars; } diff --git a/src/main/java/org/olat/commons/file/filechooser/FileChooserController.java b/src/main/java/org/olat/commons/file/filechooser/FileChooserController.java index c4a5cb6bc4f7686b45044e7aaa37680d3e90abb6..7046f845c91a1c3753ace707eab62d077cff0652 100644 --- a/src/main/java/org/olat/commons/file/filechooser/FileChooserController.java +++ b/src/main/java/org/olat/commons/file/filechooser/FileChooserController.java @@ -179,7 +179,7 @@ public class FileChooserController extends BasicController { } selectedContainer = null; if (selectedFolder == 0) { // personal folder - selectedContainer = PersonalFolderManager.getInstance().getContainer(ureq.getIdentity()); + selectedContainer = PersonalFolderManager.getInstance().getContainer(ureq.getUserSession().getIdentityEnvironment()); } else { // process other folders selectedContainer = containerRefs.get(selectedFolder - 1); } diff --git a/src/main/java/org/olat/core/commons/modules/bc/BriefcaseWebDAVProvider.java b/src/main/java/org/olat/core/commons/modules/bc/BriefcaseWebDAVProvider.java index 8111a26ee74cc66d48190d3da3c24c8f147ef7c9..47dbbb2c85f60ccd0c1078444f31d63cd4a28fae 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/BriefcaseWebDAVProvider.java +++ b/src/main/java/org/olat/core/commons/modules/bc/BriefcaseWebDAVProvider.java @@ -28,6 +28,7 @@ package org.olat.core.commons.modules.bc; import org.olat.core.commons.services.webdav.WebDAVProvider; import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.VFSContainer; /** * @@ -39,13 +40,19 @@ public class BriefcaseWebDAVProvider implements WebDAVProvider { public String getMountPoint() { return MOUNTPOINT; } + + public VFSContainer getContainer(Identity identity) { + // merge /public and /private + return new BriefcaseWebDAVMergeSource(identity); + } /** * @see org.olat.core.commons.services.webdav.WebDAVProvider#getContainer(org.olat.core.id.Identity) */ - public VFSContainer getContainer(Identity identity) { + @Override + public VFSContainer getContainer(IdentityEnvironment identityEnv) { // merge /public and /private - return new BriefcaseWebDAVMergeSource(identity); + return getContainer(identityEnv.getIdentity()); } protected String getRootPathFor(Identity identity) { diff --git a/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java b/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java index ec0b089f5cd7049e2ec9997b37466a20616a8005..1400accfc9bca726b53f1d758b9fec86449ae11e 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java +++ b/src/main/java/org/olat/core/commons/services/webdav/WebDAVModule.java @@ -26,34 +26,47 @@ package org.olat.core.commons.services.webdav; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.olat.core.configuration.AbstractOLATModule; +import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.configuration.ConfigOnOff; -import org.olat.core.configuration.PersistedProperties; -import org.olat.core.logging.AssertException; -import org.olat.core.logging.OLog; -import org.olat.core.logging.Tracing; 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; -public class WebDAVModule extends AbstractOLATModule implements ConfigOnOff { - - private static final OLog log = Tracing.createLoggerFor(WebDAVModule.class); +@Service("webdavModule") +public class WebDAVModule extends AbstractSpringModule implements ConfigOnOff { private static final String WEBDAV_ENABLED = "webdav.enabled"; private static final String WEBDAV_LINKS_ENABLED = "webdav.links.enabled"; private static final String DIGEST_AUTH_ENABLED = "auth.digest.enabled"; private static final String TERMS_FOLDERS_ENABLED = "webdav.termsfolders.enabled"; + private static final String LEARNERS_BOOKMARKS_COURSE = "webdav.learners.bookmarks.courses"; + private static final String LEARNERS_PARTICIPATING_COURSES = "webdav.learners.participating.courses"; - private Map<String, WebDAVProvider> webdavProviders; + @Autowired + private List<WebDAVProvider> webdavProviders; + @Value("${webdav.enabled:true}") private boolean enabled; + @Value("${webdav.links.enabled:true}") private boolean linkEnabled; + @Value("${auth.digest.enabled:true}") private boolean digestAuthenticationEnabled; + @Value("${webdav.termsfolders.enabled:true}") private boolean termsFoldersEnabled; + + private boolean enableLearnersBookmarksCourse; + private boolean enableLearnersParticipatingCourses; + + @Autowired + public WebDAVModule(CoordinatorManager coordinatorManager) { + super(coordinatorManager); + } @Override public void init() { @@ -77,33 +90,25 @@ public class WebDAVModule extends AbstractOLATModule implements ConfigOnOff { if(StringHelper.containsNonWhitespace(termsFoldersEnabledObj)) { termsFoldersEnabled = "true".equals(termsFoldersEnabledObj); } - + + String learnersBookmarksCourseObj = getStringPropertyValue(LEARNERS_BOOKMARKS_COURSE, true); + enableLearnersBookmarksCourse = "true".equals(learnersBookmarksCourseObj); + String learnersParticipatingCoursesObj = getStringPropertyValue(LEARNERS_PARTICIPATING_COURSES, true); + enableLearnersParticipatingCourses = "true".equals(learnersParticipatingCoursesObj); } - @Override - protected void initDefaultProperties() { - enabled = getBooleanConfigParameter(WEBDAV_ENABLED, true); - linkEnabled = getBooleanConfigParameter(WEBDAV_LINKS_ENABLED, true); - digestAuthenticationEnabled = getBooleanConfigParameter(DIGEST_AUTH_ENABLED, true); - termsFoldersEnabled = getBooleanConfigParameter(TERMS_FOLDERS_ENABLED, true); - } - @Override protected void initFromChangedProperties() { init(); } - - @Override - public void setPersistedProperties(PersistedProperties persistedProperties) { - this.moduleConfigProperties = persistedProperties; - } - + @Override public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { + this.enabled = enabled; String enabledStr = enabled ? "true" : "false"; setStringProperty(WEBDAV_ENABLED, enabledStr, true); } @@ -113,6 +118,7 @@ public class WebDAVModule extends AbstractOLATModule implements ConfigOnOff { } public void setLinkEnabled(boolean linkEnabled) { + this.linkEnabled = linkEnabled; String enabledStr = linkEnabled ? "true" : "false"; setStringProperty(WEBDAV_LINKS_ENABLED, enabledStr, true); } @@ -122,52 +128,50 @@ public class WebDAVModule extends AbstractOLATModule implements ConfigOnOff { } public void setDigestAuthenticationEnabled(boolean digestAuthenticationEnabled) { + this.digestAuthenticationEnabled = digestAuthenticationEnabled; String enabledStr = digestAuthenticationEnabled ? "true" : "false"; setStringProperty(DIGEST_AUTH_ENABLED, enabledStr, true); } + public boolean isTermsFoldersEnabled() { + return termsFoldersEnabled; + } public void setTermsFoldersEnabled(boolean termsFoldersEnabled) { + this.termsFoldersEnabled = termsFoldersEnabled; String enabledStr = termsFoldersEnabled ? "true" : "false"; setStringProperty(TERMS_FOLDERS_ENABLED, enabledStr, true); } - public boolean isTermsFoldersEnabled() { - return termsFoldersEnabled; + public boolean isEnableLearnersBookmarksCourse() { + return enableLearnersBookmarksCourse; } + public void setEnableLearnersBookmarksCourse(boolean enabled) { + this.enableLearnersBookmarksCourse = enabled; + setStringProperty(LEARNERS_BOOKMARKS_COURSE, enabled ? "true" : "false", true); + } + + public boolean isEnableLearnersParticipatingCourses() { + return enableLearnersParticipatingCourses; + } + + public void setEnableLearnersParticipatingCourses(boolean enabled) { + this.enableLearnersParticipatingCourses = enabled; + setStringProperty(LEARNERS_PARTICIPATING_COURSES, enabled ? "true" : "false", true); + } /** * Return an unmodifiable map * @return */ public Map<String, WebDAVProvider> getWebDAVProviders() { - return Collections.unmodifiableMap(webdavProviders); - } - - /** - * Set the list of webdav providers. - * @param webdavProviders - */ - public void setWebdavProviderList(List<WebDAVProvider> webdavProviders) { - if (webdavProviders == null) return;//nothing to do - - for (WebDAVProvider provider : webdavProviders) { - addWebdavProvider(provider); - } - } - - /** - * Add a new webdav provider. - * @param provider - */ - public void addWebdavProvider(WebDAVProvider provider) { - if (webdavProviders == null) { - webdavProviders = new HashMap<String, WebDAVProvider>(); + Map<String,WebDAVProvider> providerMap = new HashMap<>(); + if(webdavProviders != null) { + for(WebDAVProvider webdavProvider:webdavProviders) { + providerMap.put(webdavProvider.getMountPoint(), webdavProvider); + } } - if (webdavProviders.containsKey(provider.getMountPoint())) - throw new AssertException("May not add two providers with the same mount point."); - webdavProviders.put(provider.getMountPoint(), provider); - log.info("Adding webdav mountpoint '" + provider.getMountPoint() + "'."); + return providerMap; } } \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/webdav/WebDAVProvider.java b/src/main/java/org/olat/core/commons/services/webdav/WebDAVProvider.java index 010e902f966dddca2a0aa53d8c2f8802e13576e4..e0901275e1930931ccd16d5827417c7c44113cb3 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/WebDAVProvider.java +++ b/src/main/java/org/olat/core/commons/services/webdav/WebDAVProvider.java @@ -26,7 +26,7 @@ package org.olat.core.commons.services.webdav; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.VFSContainer; public interface WebDAVProvider { @@ -41,6 +41,6 @@ public interface WebDAVProvider { * @param identity * @return */ - public VFSContainer getContainer(Identity identity); + public VFSContainer getContainer(IdentityEnvironment identityEnv); } diff --git a/src/main/java/org/olat/core/commons/services/webdav/_spring/webdavContext.xml b/src/main/java/org/olat/core/commons/services/webdav/_spring/webdavContext.xml index d10b16247735f82672dc9cbb80b7140c86861f67..17cae7aa32efdf7201bfce29dea7e334e157f2ba 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/_spring/webdavContext.xml +++ b/src/main/java/org/olat/core/commons/services/webdav/_spring/webdavContext.xml @@ -1,64 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd"> - - <!-- WebDAV module --> - <bean id="webdavModule" class="org.olat.core.commons.services.webdav.WebDAVModule" depends-on="org.olat.core.util.WebappHelper"> - <property name="persistedProperties"> - <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" - depends-on="coordinatorManager,org.olat.core.util.WebappHelper"> - <constructor-arg index="0" ref="coordinatorManager"/> - <constructor-arg index="1" ref="webdavModule" /> - </bean> - </property> - <property name="webdavProviderList"> - <list> - <ref bean="webdav_briefcase"/> - <ref bean="webdav_coursefolders"/> - <ref bean="webdav_sharedfolders"/> - <ref bean="webdav_groupfolders"/> - </list> - </property> - </bean> + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> - <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> - <property name="targetObject" ref="webdavModule" /> - <property name="targetMethod" value="init" /> - <property name="arguments"> - <value> - webdav.enabled=${webdav.enabled} - webdav.links.enabled=${webdav.links.enabled} - auth.digest.enabled=${auth.digest.enabled} - webdav.termsfolders.enabled=${webdav.termsfolders.enabled} - </value> - </property> - </bean> - - <bean id="webDAVManager" class="org.olat.core.commons.services.webdav.manager.WebDAVManagerImpl" init-method="init"> - <constructor-arg ref="coordinatorManager"/> - <property name="sessionManager" ref="userSessionManager" /> - <property name="webDAVAuthManager" ref="webDAVAuthenticationSpi" /> - <property name="webDAVModule" ref="webdavModule" /> - </bean> - - <bean id="webDAVDispatcher" class="org.olat.core.commons.services.webdav.servlets.WebDAVDispatcherImpl"> - <property name="lockManager" ref="vfsLockManager" /> - <property name="webDAVManager" ref="webDAVManager" /> - <property name="webDAVModule" ref="webdavModule" /> - </bean> - - <bean id="webDAVAuthenticationSpi" class="org.olat.core.commons.services.webdav.manager.WebDAVAuthManager" > - <property name="securityManager" ref="baseSecurityManager" /> - <property name="olatAuthenticationSpi" ref="olatAuthenticationSpi" /> - <property name="webDAVModule" ref="webdavModule" /> - </bean> + <context:component-scan base-package="org.olat.core.commons.services.webdav" /> - <bean id="webdav_briefcase" class="org.olat.core.commons.modules.bc.BriefcaseWebDAVProvider" scope="prototype" /> - <bean id="webdav_coursefolders" class="org.olat.course.CoursefolderWebDAVProvider" scope="prototype" /> - <bean id="webdav_sharedfolders" class="org.olat.modules.sharedfolder.SharedFolderWebDAVProvider" scope="prototype" > + <bean id="webdav_briefcase" class="org.olat.core.commons.modules.bc.BriefcaseWebDAVProvider" /> + <bean id="webdav_coursefolders" class="org.olat.course.CoursefolderWebDAVProvider" /> + <bean id="webdav_sharedfolders" class="org.olat.modules.sharedfolder.SharedFolderWebDAVProvider" > <!-- Optional configuration: specify shared folder that should be visible to normal users. By default, shared folders are only mounted for shared folder owners (read/write). By @@ -84,7 +38,7 @@ </property> --> </bean> - <bean id="webdav_groupfolders" class="org.olat.group.GroupfoldersWebDAVProvider" scope="prototype"> + <bean id="webdav_groupfolders" class="org.olat.group.GroupfoldersWebDAVProvider"> <property name="collaborationManager" ref="collaborationManager" /> </bean> diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManager.java b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManager.java index b7d781086df972820bbf092e0e03f3767a3fa9a2..6a7fd75d55127b3b07e9e3bfa8ce9916437d210f 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManager.java +++ b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVAuthManager.java @@ -32,6 +32,8 @@ import org.olat.core.util.Encoder.Algorithm; import org.olat.login.LoginModule; import org.olat.login.auth.AuthenticationSPI; import org.olat.login.auth.OLATAuthManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; /** @@ -43,6 +45,7 @@ import org.olat.login.auth.OLATAuthManager; * Initial Date: 13 apr. 2010 <br> * @author srosse, stephane.rosse@frentix.com */ +@Service("webDAVAuthenticationSpi") public class WebDAVAuthManager implements AuthenticationSPI { public static final String PROVIDER_WEBDAV = "WEBDAV"; @@ -50,34 +53,13 @@ public class WebDAVAuthManager implements AuthenticationSPI { private static final OLog log = Tracing.createLoggerFor(WebDAVAuthManager.class); + @Autowired private WebDAVModule webDAVModule; + @Autowired private BaseSecurity securityManager; + @Autowired private OLATAuthManager olatAuthenticationSpi; - /** - * [used by Spring] - * @param webDAVModule - */ - public void setWebDAVModule(WebDAVModule webDAVModule) { - this.webDAVModule = webDAVModule; - } - - /** - * [used by Spring] - * @param securityManager - */ - public void setSecurityManager(BaseSecurity securityManager) { - this.securityManager = securityManager; - } - - /** - * [used by Spring] - * @param olatAuthenticationSpi - */ - public void setOlatAuthenticationSpi(OLATAuthManager olatAuthenticationSpi) { - this.olatAuthenticationSpi = olatAuthenticationSpi; - } - public Identity digestAuthentication(String httpMethod, DigestAuthentication digestAuth) { String username = digestAuth.getUsername(); diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java index 91cdde54f838561b148349b841f96e909256e32c..c9d042f2246628c4ef902a0ecd9bf03b4e32ec6c 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java +++ b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVManagerImpl.java @@ -43,6 +43,7 @@ import org.olat.core.commons.services.webdav.WebDAVProvider; import org.olat.core.commons.services.webdav.servlets.WebResourceRoot; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.Roles; import org.olat.core.id.User; import org.olat.core.id.UserConstants; @@ -56,6 +57,9 @@ import org.olat.core.util.vfs.MergeSource; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VirtualContainer; import org.olat.core.util.vfs.callbacks.ReadOnlyCallback; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; /** * Initial Date: 16.04.2003 @@ -66,50 +70,29 @@ import org.olat.core.util.vfs.callbacks.ReadOnlyCallback; * Comment: * */ -public class WebDAVManagerImpl implements WebDAVManager { +@Service("webDAVManager") +public class WebDAVManagerImpl implements WebDAVManager, InitializingBean { private static boolean enabled = true; public static final String BASIC_AUTH_REALM = "OLAT WebDAV Access"; private CoordinatorManager coordinatorManager; private CacheWrapper<CacheKey,UserSession> timedSessionCache; - + + @Autowired private UserSessionManager sessionManager; + @Autowired private WebDAVAuthManager webDAVAuthManager; + @Autowired private WebDAVModule webdavModule; - /** - * [spring] - */ - private WebDAVManagerImpl(CoordinatorManager coordinatorManager) { + @Autowired + public WebDAVManagerImpl(CoordinatorManager coordinatorManager) { this.coordinatorManager = coordinatorManager; } - /** - * [used by Spring] - * @param sessionManager - */ - public void setSessionManager(UserSessionManager sessionManager) { - this.sessionManager = sessionManager; - } - - /** - * [used by Spring] - * @param webDAVAuthManager - */ - public void setWebDAVAuthManager(WebDAVAuthManager webDAVAuthManager) { - this.webDAVAuthManager = webDAVAuthManager; - } - - /** - * [used by Spring] - * @param webdavModule - */ - public void setWebDAVModule(WebDAVModule webdavModule) { - this.webdavModule = webdavModule; - } - - public void init() { + @Override + public void afterPropertiesSet() throws Exception { timedSessionCache = coordinatorManager.getCoordinator().getCacher().getCache(WebDAVManager.class.getSimpleName(), "webdav"); } @@ -126,15 +109,15 @@ public class WebDAVManagerImpl implements WebDAVManager { return fdc; } - Identity identity = usess.getIdentity(); - VFSContainer webdavContainer = getMountableRoot(identity); + IdentityEnvironment identityEnv = usess.getIdentityEnvironment(); + VFSContainer webdavContainer = getMountableRoot(identityEnv); //create the / folder VirtualContainer rootContainer = new VirtualContainer(""); rootContainer.addItem(webdavContainer); rootContainer.setLocalSecurityCallback(new ReadOnlyCallback()); - fdc = new VFSResourceRoot(identity, rootContainer); + fdc = new VFSResourceRoot(identityEnv.getIdentity(), rootContainer); usess.putEntry("_DIRCTX", fdc); return fdc; } @@ -143,11 +126,11 @@ public class WebDAVManagerImpl implements WebDAVManager { * Returns a mountable root containing all entries which will be exposed to the webdav mount. * @return */ - private VFSContainer getMountableRoot(Identity identity) { + private VFSContainer getMountableRoot(IdentityEnvironment identityEnv) { MergeSource vfsRoot = new MergeSource(null, "webdav"); for (Map.Entry<String, WebDAVProvider> entry : webdavModule.getWebDAVProviders().entrySet()) { WebDAVProvider provider = entry.getValue(); - vfsRoot.addContainer(new WebDAVProviderNamedContainer(identity, provider)); + vfsRoot.addContainer(new WebDAVProviderNamedContainer(identityEnv, provider)); } return vfsRoot; } diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVProviderNamedContainer.java b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVProviderNamedContainer.java index d1d9589fdaf9c3bd8e4c02a0860c6760adc74617..f1dfd83c336de220774e1704edcaff3e4b47a0bb 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVProviderNamedContainer.java +++ b/src/main/java/org/olat/core/commons/services/webdav/manager/WebDAVProviderNamedContainer.java @@ -20,7 +20,7 @@ package org.olat.core.commons.services.webdav.manager; import org.olat.core.commons.services.webdav.WebDAVProvider; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.NamedContainerImpl; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.filters.VFSItemFilter; @@ -31,25 +31,25 @@ import org.olat.core.util.vfs.filters.VFSItemFilter; */ public class WebDAVProviderNamedContainer extends NamedContainerImpl { - private Identity identity; + private IdentityEnvironment identityEnv; private final WebDAVProvider provider; private VFSContainer parentContainer; - public WebDAVProviderNamedContainer(Identity identity, WebDAVProvider provider) { + public WebDAVProviderNamedContainer(IdentityEnvironment identityEnv, WebDAVProvider provider) { super(provider.getMountPoint(), null); this.provider = provider; - this.identity = identity; + this.identityEnv = identityEnv; } @Override public VFSContainer getDelegate() { if(super.getDelegate() == null) { - setDelegate(provider.getContainer(identity)); + setDelegate(provider.getContainer(identityEnv)); if(parentContainer != null) { super.setParentContainer(parentContainer); parentContainer = null; } - identity = null; + identityEnv = null; } return super.getDelegate(); } diff --git a/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java b/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java index 7d6d535ae1d5f766eb69172285e9ebfe2ac9d54d..137a9b6761a392f0e4db587ec6b0f322bf78421a 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java +++ b/src/main/java/org/olat/core/commons/services/webdav/servlets/WebDAVDispatcherImpl.java @@ -59,6 +59,8 @@ import org.olat.core.util.vfs.QuotaExceededException; import org.olat.core.util.vfs.VFSItem; import org.olat.core.util.vfs.lock.LockInfo; import org.olat.core.util.vfs.lock.VFSLockManagerImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -130,7 +132,7 @@ import org.xml.sax.SAXException; * @author Remy Maucherat * @version $Id$ */ - +@Service("webDAVDispatcher") public class WebDAVDispatcherImpl extends DefaultDispatcher implements WebDAVDispatcher, Dispatcher { @@ -225,37 +227,16 @@ public class WebDAVDispatcherImpl */ private boolean allowSpecialPaths = false; + @Autowired private VFSLockManagerImpl lockManager; + @Autowired private WebDAVManager webDAVManager; + @Autowired private WebDAVModule webDAVModule; public WebDAVDispatcherImpl() { // } - - /** - * [used by Spring] - * @param lockManager - */ - public void setLockManager(VFSLockManagerImpl lockManager) { - this.lockManager = lockManager; - } - - /** - * [used by Spring] - * @param webDAVManager - */ - public void setWebDAVManager(WebDAVManager webDAVManager) { - this.webDAVManager = webDAVManager; - } - - /** - * [used by Spring] - * @param webDAVModule - */ - public void setWebDAVModule(WebDAVModule webDAVModule) { - this.webDAVModule = webDAVModule; - } @Override protected WebResourceRoot getResources(HttpServletRequest req) { diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java b/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java index 7093868a9c469f828cdcc65eeb8d28795520b323..0b9a4a83f389ecda567f80568adf95bdb8b48e47 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java +++ b/src/main/java/org/olat/core/commons/services/webdav/ui/WebDAVAdminController.java @@ -37,7 +37,9 @@ import org.olat.core.gui.control.WindowControl; */ public class WebDAVAdminController extends FormBasicController { - private MultipleSelectionElement enableModuleEl, enableLinkEl, enableDigestEl, enableTermsFoldersEl; + private MultipleSelectionElement enableModuleEl, enableLinkEl, enableDigestEl, enableTermsFoldersEl, + learnersAsParticipantEl, learnersBookmarkEl; + private final WebDAVModule webDAVModule; public WebDAVAdminController(UserRequest ureq, WindowControl wControl) { @@ -76,8 +78,18 @@ public class WebDAVAdminController extends FormBasicController { enableTermsFoldersEl.select("xx", webDAVModule.isTermsFoldersEnabled()); enableTermsFoldersEl.addActionListener(FormEvent.ONCHANGE); enableTermsFoldersEl.setEnabled(enabled); + + uifactory.addSpacerElement("spacer2", formLayout, false); + learnersAsParticipantEl = uifactory.addCheckboxesHorizontal("learnersParticipants", "webdav.for.learners.participants", formLayout, new String[]{"xx"}, values); + learnersAsParticipantEl.select("xx", webDAVModule.isEnableLearnersParticipatingCourses()); + learnersAsParticipantEl.addActionListener(FormEvent.ONCHANGE); + learnersAsParticipantEl.setEnabled(enabled); + learnersBookmarkEl = uifactory.addCheckboxesHorizontal("learnerBookmarks", "webdav.for.learners.bookmarks", formLayout, new String[]{"xx"}, values); + learnersBookmarkEl.select("xx", webDAVModule.isEnableLearnersBookmarksCourse()); + learnersBookmarkEl.addActionListener(FormEvent.ONCHANGE); + learnersBookmarkEl.setEnabled(enabled); } @Override @@ -93,6 +105,8 @@ public class WebDAVAdminController extends FormBasicController { enableLinkEl.setEnabled(enabled); enableDigestEl.setEnabled(enabled); enableTermsFoldersEl.setEnabled(enabled); + learnersAsParticipantEl.setEnabled(enabled); + learnersBookmarkEl.setEnabled(enabled); } else if(source == enableLinkEl) { boolean enabled = enableLinkEl.isAtLeastSelected(1); webDAVModule.setLinkEnabled(enabled); @@ -102,6 +116,12 @@ public class WebDAVAdminController extends FormBasicController { } else if(source == enableTermsFoldersEl) { boolean enabled = enableTermsFoldersEl.isAtLeastSelected(1); webDAVModule.setTermsFoldersEnabled(enabled); + } else if(source == learnersAsParticipantEl) { + boolean enabled = learnersAsParticipantEl.isAtLeastSelected(1); + webDAVModule.setEnableLearnersParticipatingCourses(enabled); + } else if(source == learnersBookmarkEl) { + boolean enabled = learnersBookmarkEl.isAtLeastSelected(1); + webDAVModule.setEnableLearnersBookmarksCourse(enabled); } super.formInnerEvent(ureq, source, event); } diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties index 90ed339901602774ca4f6151522c55e8a7e00356..d5261b439323b7e6701fb3389aafda422818ccb2 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties @@ -18,3 +18,5 @@ webdav.link=WebDAV Links anzeigen webdav.module=WebDAV Zugang webdav.on=ein webdav.termsfolders=Kurse nach Semesterdaten gruppieren +webdav.for.learners.participants=Zugriff für Studenten Kursen +webdav.for.learners.bookmarks=Zugriff für Studenten Favoriten diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties index e7f3ad82c50ed0c14cc606b46709592c38fbd4df..e7d2f00badde999f63b25c5b35d43551b3471ec3 100644 --- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties @@ -18,4 +18,6 @@ webdav.link=Show WebDAV links webdav.module=WebDAV access webdav.on=enabled webdav.termsfolders=Group courses by semester terms +webdav.for.learners.participants=Enable access for courses where user is participant +webdav.for.learners.bookmarks=Enable for courses that users marked as favorite diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java index d10df68b53c5f1678213104b0cee2743e4721de6..d7883276dff975d82dd919efd7981d98e4220866 100644 --- a/src/main/java/org/olat/course/CourseFactory.java +++ b/src/main/java/org/olat/course/CourseFactory.java @@ -429,7 +429,7 @@ public class CourseFactory extends BasicManager { targetCourse.saveEditorTreeModel(); // copy course folder - File fSourceCourseFolder = sourceCourse.getIsolatedCourseFolder().getBasefile(); + File fSourceCourseFolder = sourceCourse.getIsolatedCourseBaseFolder(); if (fSourceCourseFolder.exists()) FileUtils.copyDirToDir(fSourceCourseFolder, fTargetCourseBasePath, false, "copy course folder"); // copy folder nodes directories diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java index 49907ab320f6aced80bd5e54af4e82084f140757..363f6eb095f553c87a028a41439873bd9aee4bd8 100644 --- a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java +++ b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java @@ -21,14 +21,16 @@ package org.olat.course; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.webdav.WebDAVModule; import org.olat.core.commons.services.webdav.manager.WebDAVMergeSource; import org.olat.core.commons.services.webdav.servlets.RequestUtil; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.NamedContainerImpl; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VirtualContainer; @@ -42,21 +44,27 @@ import org.olat.repository.model.RepositoryEntryLifecycle; * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -class CoursefolderWebDAVMergeSource extends WebDAVMergeSource { - public CoursefolderWebDAVMergeSource(Identity identity) { - super(identity); +class CoursefolderWebDAVMergeSource extends WebDAVMergeSource { + + private final IdentityEnvironment identityEnv; + + private final WebDAVModule webDAVModule; + private final RepositoryManager repositoryManager; + + public CoursefolderWebDAVMergeSource(IdentityEnvironment identityEnv) { + super(identityEnv.getIdentity()); + this.identityEnv = identityEnv; + webDAVModule = CoreSpringFactory.getImpl(WebDAVModule.class); + repositoryManager = CoreSpringFactory.getImpl(RepositoryManager.class); } @Override protected List<VFSContainer> loadMergedContainers() { - RepositoryManager rm = RepositoryManager.getInstance(); - List<RepositoryEntry> courseEntries = rm.queryByEditor(getIdentity(), CourseModule.getCourseTypeName()); List<VFSContainer> containers = new ArrayList<>(); Map<String, VFSContainer> terms = null; VirtualContainer noTermContainer = null; - WebDAVModule webDAVModule = CoreSpringFactory.getImpl(WebDAVModule.class); boolean useTerms = webDAVModule.isTermsFoldersEnabled(); if (useTerms) { // prepare no-terms folder for all resources without semester term info or private date @@ -64,10 +72,45 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource { noTermContainer = new VirtualContainer("other"); } + Set<RepositoryEntry> duplicates = new HashSet<>(); + List<RepositoryEntry> editorEntries = repositoryManager.queryByEditor(getIdentity(), "CourseModule"); + appendCourses(editorEntries, true, containers, useTerms, terms, noTermContainer, duplicates); + + //add courses as participant + if(webDAVModule.isEnableLearnersParticipatingCourses()) { + List<RepositoryEntry> participantEntries = repositoryManager.getLearningResourcesAsStudent(getIdentity(), "CourseModule", 0, -1); + appendCourses(participantEntries, false, containers, useTerms, terms, noTermContainer, duplicates); + } + + //add bookmarked courses + if(webDAVModule.isEnableLearnersBookmarksCourse()) { + List<RepositoryEntry> bookmarkedEntries = repositoryManager.getLearningResourcesAsBookmark(getIdentity(), identityEnv.getRoles(), "CourseModule", 0, -1); + appendCourses(bookmarkedEntries, false, containers, useTerms, terms, noTermContainer, duplicates); + } + + if (useTerms) { + // add no-terms folder if any have been found + if (noTermContainer.getItems().size() > 0) { + addContainerToList(noTermContainer, containers); + } + } + + return containers; + } + + private void appendCourses(List<RepositoryEntry> courseEntries, boolean editor, List<VFSContainer> containers, + boolean useTerms, Map<String, VFSContainer> terms, VirtualContainer noTermContainer, + Set<RepositoryEntry> duplicates) { + // Add all found repo entries to merge source for (RepositoryEntry re:courseEntries) { + if(duplicates.contains(re)) { + continue; + } + duplicates.add(re); + String courseTitle = RequestUtil.normalizeFilename(re.getDisplayname()); - NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(courseTitle, re.getOlatResource()); + NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(courseTitle, re.getOlatResource(), editor ? null : identityEnv); if (useTerms) { RepositoryEntryLifecycle lc = re.getLifecycle(); @@ -92,14 +135,5 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource { addContainerToList(cfContainer, containers); } } - - if (useTerms) { - // add no-terms folder if any have been found - if (noTermContainer.getItems().size() > 0) { - addContainerToList(noTermContainer, containers); - } - } - - return containers; } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVNamedContainer.java b/src/main/java/org/olat/course/CoursefolderWebDAVNamedContainer.java index b7895f1f04e48ffb3d3f3d7beffcde9749b1d380..9b33e6266edb87ef57e3160f6c557770195a6f18 100644 --- a/src/main/java/org/olat/course/CoursefolderWebDAVNamedContainer.java +++ b/src/main/java/org/olat/course/CoursefolderWebDAVNamedContainer.java @@ -19,6 +19,7 @@ */ package org.olat.course; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; @@ -37,10 +38,12 @@ class CoursefolderWebDAVNamedContainer extends NamedContainerImpl { private OLATResourceable res; private VFSContainer parentContainer; + private IdentityEnvironment identityEnv; - public CoursefolderWebDAVNamedContainer(String courseTitle, OLATResourceable res) { + public CoursefolderWebDAVNamedContainer(String courseTitle, OLATResourceable res, IdentityEnvironment identityEnv) { super(courseTitle, null); this.res = OresHelper.clone(res); + this.identityEnv = identityEnv; } @Override @@ -53,7 +56,7 @@ class CoursefolderWebDAVNamedContainer extends NamedContainerImpl { if(super.getDelegate() == null) { try { ICourse course = CourseFactory.loadCourse(res.getResourceableId()); - VFSContainer courseFolder = course.getCourseFolderContainer(); + VFSContainer courseFolder = course.getCourseFolderContainer(identityEnv); setDelegate(courseFolder); if(parentContainer != null) { super.setParentContainer(parentContainer); diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVProvider.java b/src/main/java/org/olat/course/CoursefolderWebDAVProvider.java index 9a1f3f062e7142f9ea0d31720ac94083454deb27..52eccf277dc49d53a63433b2396b29a929ef9817 100644 --- a/src/main/java/org/olat/course/CoursefolderWebDAVProvider.java +++ b/src/main/java/org/olat/course/CoursefolderWebDAVProvider.java @@ -26,22 +26,23 @@ package org.olat.course; import org.olat.core.commons.services.webdav.WebDAVProvider; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.VFSContainer; /** * * Description:<br> - * TODO: guido Class Description for CoursefolderWebDAVProvider */ public class CoursefolderWebDAVProvider implements WebDAVProvider { private static final String MOUNTPOINT = "coursefolders"; + @Override public String getMountPoint() { return MOUNTPOINT; } - public VFSContainer getContainer(Identity identity) { - return new CoursefolderWebDAVMergeSource(identity); + @Override + public VFSContainer getContainer(IdentityEnvironment identityEnv) { + return new CoursefolderWebDAVMergeSource(identityEnv); } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/ICourse.java b/src/main/java/org/olat/course/ICourse.java index bb0e53b718dcd2dacae0ada27cd3157b5ba0cbce..5f08b9540fef5484ee4c73337a399a2b974963b6 100644 --- a/src/main/java/org/olat/course/ICourse.java +++ b/src/main/java/org/olat/course/ICourse.java @@ -28,6 +28,7 @@ package org.olat.course; import java.io.File; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.OLATResourceable; import org.olat.core.util.vfs.VFSContainer; import org.olat.course.config.CourseConfig; @@ -88,6 +89,8 @@ public interface ICourse extends OLATResourceable { */ public VFSContainer getCourseFolderContainer(); + public VFSContainer getCourseFolderContainer(IdentityEnvironment identityEnv); + public OlatRootFolderImpl getCourseExportDataDir(); /** diff --git a/src/main/java/org/olat/course/MergedCourseContainer.java b/src/main/java/org/olat/course/MergedCourseContainer.java index ca868725a24a2d3693686b71838d3e039926701a..b06c5f0b40ed86438f8995903cb5d5baaf2af279 100644 --- a/src/main/java/org/olat/course/MergedCourseContainer.java +++ b/src/main/java/org/olat/course/MergedCourseContainer.java @@ -22,6 +22,9 @@ package org.olat.course; import org.olat.core.commons.modules.bc.vfs.OlatNamedContainerImpl; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.commons.services.webdav.servlets.RequestUtil; +import org.olat.core.gui.components.tree.GenericTreeModel; +import org.olat.core.gui.components.tree.TreeNode; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; @@ -34,9 +37,14 @@ import org.olat.core.util.vfs.filters.VFSItemFilter; import org.olat.course.config.CourseConfig; import org.olat.course.nodes.BCCourseNode; import org.olat.course.nodes.CourseNode; +import org.olat.course.run.userview.NodeEvaluation; +import org.olat.course.run.userview.TreeEvaluation; +import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.course.run.userview.UserCourseEnvironmentImpl; import org.olat.modules.sharedfolder.SharedFolderManager; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; +import org.olat.repository.model.RepositoryEntrySecurity; /** * @@ -47,10 +55,16 @@ public class MergedCourseContainer extends MergeSource { private static final OLog log = Tracing.createLoggerFor(MergedCourseContainer.class); private final Long courseId; + private final IdentityEnvironment identityEnv; public MergedCourseContainer(Long courseId, String name) { + this(courseId, name, null); + } + + public MergedCourseContainer(Long courseId, String name, IdentityEnvironment identityEnv) { super(null, name); this.courseId = courseId; + this.identityEnv = identityEnv; } @Override @@ -59,8 +73,16 @@ public class MergedCourseContainer extends MergeSource { ICourse course = CourseFactory.loadCourse(courseId); if(course instanceof PersistingCourseImpl) { PersistingCourseImpl persistingCourse = (PersistingCourseImpl)course; - addContainersChildren(persistingCourse.getIsolatedCourseFolder(), true); - + if(identityEnv == null || identityEnv.getRoles().isOLATAdmin()) { + addContainersChildren(persistingCourse.getIsolatedCourseFolder(), true); + } else { + RepositoryEntry re = course.getCourseEnvironment().getCourseGroupManager().getCourseEntry(); + RepositoryEntrySecurity reSecurity = RepositoryManager.getInstance() + .isAllowed(identityEnv.getIdentity(), identityEnv.getRoles(), re); + if(reSecurity.isEntryAdmin()) { + addContainersChildren(persistingCourse.getIsolatedCourseFolder(), true); + } + } // grab any shared folder that is configured OlatRootFolderImpl sharedFolder = null; String sfSoftkey = persistingCourse.getCourseConfig().getSharedFolderSoftkey(); @@ -69,7 +91,7 @@ public class MergedCourseContainer extends MergeSource { RepositoryEntry re = rm.lookupRepositoryEntryBySoftkey(sfSoftkey, false); if (re != null) { sharedFolder = SharedFolderManager.getInstance().getSharedFolder(re.getOlatResource()); - if (sharedFolder != null){ + if (sharedFolder != null) { sharedFolder.setLocalSecurityCallback(new ReadOnlyCallback()); //add local course folder's children as read/write source and any sharedfolder as subfolder addContainer(new NamedContainerImpl("_sharedfolder", sharedFolder)); @@ -79,13 +101,98 @@ public class MergedCourseContainer extends MergeSource { // add all course building blocks of type BC to a virtual folder MergeSource nodesContainer = new MergeSource(null, "_courseelementdata"); - addFolderBuildingBlocks(persistingCourse, nodesContainer, persistingCourse.getRunStructure().getRootNode()); + if(identityEnv == null) { + CourseNode rootNode = course.getRunStructure().getRootNode(); + addFolderBuildingBlocks(persistingCourse, nodesContainer, rootNode); + } else { + TreeEvaluation treeEval = new TreeEvaluation(); + GenericTreeModel treeModel = new GenericTreeModel(); + UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(identityEnv, course.getCourseEnvironment()); + CourseNode rootCn = userCourseEnv.getCourseEnvironment().getRunStructure().getRootNode(); + NodeEvaluation rootNodeEval = rootCn.eval(userCourseEnv.getConditionInterpreter(), treeEval); + TreeNode treeRoot = rootNodeEval.getTreeNode(); + treeModel.setRootNode(treeRoot); + addFolderBuildingBlocks(persistingCourse, nodesContainer, treeRoot); + } + if (nodesContainer.getItems().size() > 0) { addContainer(nodesContainer); } } } + private void addFolderBuildingBlocks(PersistingCourseImpl course, MergeSource nodesContainer, TreeNode courseNode) { + for (int i = 0; i < courseNode.getChildCount(); i++) { + TreeNode child = (TreeNode)courseNode.getChildAt(i); + + NodeEvaluation nodeEval; + if(child.getUserObject() instanceof NodeEvaluation) { + nodeEval = (NodeEvaluation)child.getUserObject(); + } else { + continue; + } + + if(nodeEval != null && nodeEval.getCourseNode() != null) { + CourseNode courseNodeChild = nodeEval.getCourseNode(); + String folderName = RequestUtil.normalizeFilename(courseNodeChild.getShortTitle()); + MergeSource courseNodeContainer; + if (courseNodeChild instanceof BCCourseNode) { + final BCCourseNode bcNode = (BCCourseNode) courseNodeChild; + // add folder not to merge source. Use name and node id to have unique name + String path = BCCourseNode.getFoldernodePathRelToFolderBase(course.getCourseEnvironment(), bcNode); + OlatRootFolderImpl rootFolder = new OlatRootFolderImpl(path, null); + + boolean canDownload = nodeEval.isCapabilityAccessible("download"); + if(canDownload) { + if(nodeEval.isCapabilityAccessible("upload")) { + //inherit the security callback from the course as for author + } else { + rootFolder.setLocalSecurityCallback(new ReadOnlyCallback()); + } + + // add node ident if multiple files have same name + if (nodesContainer.getItems(new VFSItemFilter() { + @Override + public boolean accept(VFSItem vfsItem) { + return (bcNode.getShortTitle().equals(RequestUtil.normalizeFilename(bcNode.getShortTitle()))); + } + }).size() > 0) { + folderName = folderName + " (" + bcNode.getIdent() + ")"; + } + + // Create a container for this node content and wrap it with a merge source which is attached to tree + VFSContainer nodeContentContainer = new OlatNamedContainerImpl(folderName, rootFolder); + courseNodeContainer = new MergeSource(nodesContainer, folderName); + courseNodeContainer.addContainersChildren(nodeContentContainer, true); + nodesContainer.addContainer(courseNodeContainer); + // Do recursion for all children + addFolderBuildingBlocks(course, courseNodeContainer, child); + + } else { + // For non-folder course nodes, add merge source (no files to show) ... + courseNodeContainer = new MergeSource(null, folderName); + // , then do recursion for all children ... + addFolderBuildingBlocks(course, courseNodeContainer, child); + // ... but only add this container if it contains any children with at least one BC course node + if (courseNodeContainer.getItems().size() > 0) { + nodesContainer.addContainer(courseNodeContainer); + } + } + } else { + // For non-folder course nodes, add merge source (no files to show) ... + courseNodeContainer = new MergeSource(null, folderName); + // , then do recursion for all children ... + addFolderBuildingBlocks(course, courseNodeContainer, child); + // ... but only add this container if it contains any children with at least one BC course node + if (courseNodeContainer.getItems().size() > 0) { + nodesContainer.addContainer(courseNodeContainer); + } + } + } + } + } + + /** * internal method to recursively add all course building blocks of type * BC to a given VFS container. This should only be used for an author view, diff --git a/src/main/java/org/olat/course/PersistingCourseImpl.java b/src/main/java/org/olat/course/PersistingCourseImpl.java index 26c9f60dcbff4acc4bc1c40e49e2d609a46f2779..e8406d6379ea88a5f060274ac4671a428e8996f7 100644 --- a/src/main/java/org/olat/course/PersistingCourseImpl.java +++ b/src/main/java/org/olat/course/PersistingCourseImpl.java @@ -31,6 +31,7 @@ import java.io.Serializable; import org.olat.admin.quota.QuotaConstants; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.commons.persistence.DBFactory; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLATRuntimeException; @@ -163,16 +164,26 @@ public class PersistingCourseImpl implements ICourse, OLATResourceable, Serializ /** * @see org.olat.course.ICourse#getCourseFolderPath() */ + @Override public VFSContainer getCourseFolderContainer() { // add local course folder's children as read/write source and any sharedfolder as subfolder MergedCourseContainer courseFolderContainer = new MergedCourseContainer(resourceableId, getCourseTitle()); courseFolderContainer.init(); return courseFolderContainer; } + + @Override + public VFSContainer getCourseFolderContainer(IdentityEnvironment identityEnv) { + // add local course folder's children as read/write source and any sharedfolder as subfolder + MergedCourseContainer courseFolderContainer = new MergedCourseContainer(resourceableId, getCourseTitle(), identityEnv); + courseFolderContainer.init(); + return courseFolderContainer; + } /** * @see org.olat.course.ICourse#getCourseEnvironment() */ + @Override public CourseEnvironment getCourseEnvironment() { return courseEnvironment; } @@ -207,20 +218,28 @@ public class PersistingCourseImpl implements ICourse, OLATResourceable, Serializ OlatRootFolderImpl isolatedCourseFolder = new OlatRootFolderImpl(courseRootContainer.getRelPath() + File.separator + COURSEFOLDER, null); // generate course folder File fCourseFolder = isolatedCourseFolder.getBasefile(); - if (!fCourseFolder.exists() && !fCourseFolder.mkdirs()) throw new OLATRuntimeException(this.getClass(), - "could not create course's coursefolder path:" + fCourseFolder.getAbsolutePath(), null); + if (!fCourseFolder.exists() && !fCourseFolder.mkdirs()) { + throw new OLATRuntimeException(this.getClass(), + "could not create course's coursefolder path:" + fCourseFolder.getAbsolutePath(), null); + } QuotaManager qm = QuotaManager.getInstance(); Quota q = qm.getCustomQuota(isolatedCourseFolder.getRelPath()); if (q == null){ Quota defQuota = qm.getDefaultQuota(QuotaConstants.IDENTIFIER_DEFAULT_COURSE); - q = QuotaManager.getInstance().createQuota(isolatedCourseFolder.getRelPath(), defQuota.getQuotaKB(), defQuota.getUlLimitKB()); + q = qm.createQuota(isolatedCourseFolder.getRelPath(), defQuota.getQuotaKB(), defQuota.getUlLimitKB()); } FullAccessWithQuotaCallback secCallback = new FullAccessWithQuotaCallback(q); isolatedCourseFolder.setLocalSecurityCallback(secCallback); return isolatedCourseFolder; } + protected File getIsolatedCourseBaseFolder() { + // create local course folder + OlatRootFolderImpl isolatedCourseFolder = new OlatRootFolderImpl(courseRootContainer.getRelPath() + File.separator + COURSEFOLDER, null); + return isolatedCourseFolder.getBasefile(); + } + /** * Save the run structure to disk, persist to the xml file */ @@ -283,7 +302,7 @@ public class PersistingCourseImpl implements ICourse, OLATResourceable, Serializ // fxdiff: export layout-folder FileUtils.copyDirToDir(new OlatRootFolderImpl(courseRootContainer.getRelPath() + File.separator + "layout", null).getBasefile(), exportDirectory, "course export layout folder"); // export course folder - FileUtils.copyDirToDir(getIsolatedCourseFolder().getBasefile(), exportDirectory, "course export folder"); + FileUtils.copyDirToDir(getIsolatedCourseBaseFolder(), exportDirectory, "course export folder"); // export any node data log.info("exportToFilesystem: exporting course "+this+": exporting all nodes..."); Visitor visitor = new NodeExportVisitor(fExportedDataDir, this); diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index cca25898df9bfbbf598ef04813100463cac012e8..feadc681e0d99997bda3e59d763d2468564d50de 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -85,8 +85,8 @@ import org.olat.course.assessment.CoachingGroupAccessAssessmentCallback; import org.olat.course.assessment.EfficiencyStatementManager; import org.olat.course.assessment.FullAccessAssessmentCallback; import org.olat.course.assessment.UserEfficiencyStatement; -import org.olat.course.certificate.ui.CertificatesOptionsController; import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController; +import org.olat.course.certificate.ui.CertificatesOptionsController; import org.olat.course.config.CourseConfig; import org.olat.course.config.CourseConfigEvent; import org.olat.course.config.ui.CourseOptionsController; diff --git a/src/main/java/org/olat/group/GroupfoldersWebDAVProvider.java b/src/main/java/org/olat/group/GroupfoldersWebDAVProvider.java index a5086002366a91f2491e43afa6aa28eb748f3e2e..71f8579d588a664570c5936873eb0ab0423adb27 100644 --- a/src/main/java/org/olat/group/GroupfoldersWebDAVProvider.java +++ b/src/main/java/org/olat/group/GroupfoldersWebDAVProvider.java @@ -27,7 +27,7 @@ package org.olat.group; import org.olat.collaboration.CollaborationManager; import org.olat.core.commons.services.webdav.WebDAVProvider; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.VFSContainer; /** * @@ -47,12 +47,14 @@ public class GroupfoldersWebDAVProvider implements WebDAVProvider { this.collaborationManager = collaborationManager; } + @Override public String getMountPoint() { return MOUNTPOINT; } - public VFSContainer getContainer(Identity identity) { - return new GroupfoldersWebDAVMergeSource(identity, collaborationManager); + @Override + public VFSContainer getContainer(IdentityEnvironment identityEnv) { + return new GroupfoldersWebDAVMergeSource(identityEnv.getIdentity(), collaborationManager); } } diff --git a/src/main/java/org/olat/home/controllerCreators/PersonalFolderControllerCreator.java b/src/main/java/org/olat/home/controllerCreators/PersonalFolderControllerCreator.java index 7218773897aaeeb77bbdc789d200ca9d329f1255..0ac8f3b76687a2c847b785bb8b0a8f6f8002fa2b 100644 --- a/src/main/java/org/olat/home/controllerCreators/PersonalFolderControllerCreator.java +++ b/src/main/java/org/olat/home/controllerCreators/PersonalFolderControllerCreator.java @@ -24,6 +24,7 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.creator.AutoCreator; +import org.olat.core.id.IdentityEnvironment; import org.olat.user.PersonalFolderManager; /** @@ -54,6 +55,7 @@ public class PersonalFolderControllerCreator extends AutoCreator { */ @Override public Controller createController(UserRequest ureq, WindowControl lwControl) { - return new FolderRunController(PersonalFolderManager.getInstance().getContainer(ureq.getIdentity()), true, true, true, ureq, lwControl); + IdentityEnvironment identityEnv = ureq.getUserSession().getIdentityEnvironment(); + return new FolderRunController(PersonalFolderManager.getInstance().getContainer(identityEnv), true, true, true, ureq, lwControl); } } diff --git a/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVProvider.java b/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVProvider.java index deb89ffae254e0e39bfe7f8d6734204918b609ad..8fa86c8ca1632b5be5e1f0ae8e24c5520c172194 100644 --- a/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVProvider.java +++ b/src/main/java/org/olat/modules/sharedfolder/SharedFolderWebDAVProvider.java @@ -28,7 +28,7 @@ package org.olat.modules.sharedfolder; import java.util.List; import org.olat.core.commons.services.webdav.WebDAVProvider; -import org.olat.core.id.Identity; +import org.olat.core.id.IdentityEnvironment; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.callbacks.ReadOnlyCallback; import org.olat.core.util.vfs.callbacks.VFSSecurityCallback; @@ -86,7 +86,8 @@ public class SharedFolderWebDAVProvider implements WebDAVProvider { /** * @see org.olat.core.commons.services.webdav.WebDAVProvider#getContainer(org.olat.core.id.Identity) */ - public VFSContainer getContainer(Identity identity) { - return new SharedFolderWebDAVMergeSource(identity, publiclyReadableFolders); + @Override + public VFSContainer getContainer(IdentityEnvironment identityEnv) { + return new SharedFolderWebDAVMergeSource(identityEnv.getIdentity(), publiclyReadableFolders); } } \ No newline at end of file diff --git a/src/main/java/org/olat/repository/RepositoryManager.java b/src/main/java/org/olat/repository/RepositoryManager.java index 1c9d4be0a80b3f8b324527d4d4a96bd159289296..814b9f63af24f05e3d59477967de38cda5091cb1 100644 --- a/src/main/java/org/olat/repository/RepositoryManager.java +++ b/src/main/java/org/olat/repository/RepositoryManager.java @@ -1766,7 +1766,7 @@ public class RepositoryManager extends BasicManager { * @param identity * @return list of RepositoryEntries */ - public List<RepositoryEntry> getLearningResourcesAsStudent(Identity identity, int firstResult, int maxResults, RepositoryEntryOrder... orderby) { + public List<RepositoryEntry> getLearningResourcesAsStudent(Identity identity, String type, int firstResult, int maxResults, RepositoryEntryOrder... orderby) { StringBuilder sb = new StringBuilder(1200); sb.append("select v from ").append(RepositoryEntry.class.getName()).append(" as v ") .append(" inner join fetch v.olatResource as res ") @@ -1777,6 +1777,10 @@ public class RepositoryManager extends BasicManager { .append(" inner join baseGroup.members as membership") .append(" where (v.access>=3 or (v.access=").append(RepositoryEntry.ACC_OWNERS).append(" and v.membersOnly=true))") .append(" and membership.identity.key=:identityKey and membership.role='").append(GroupRoles.participant.name()).append("'"); + if(StringHelper.containsNonWhitespace(type)) { + sb.append(" and res.resName=:resourceType"); + } + appendOrderBy(sb, "v", orderby); TypedQuery<RepositoryEntry> query = dbInstance.getCurrentEntityManager() @@ -1786,6 +1790,56 @@ public class RepositoryManager extends BasicManager { if(maxResults > 0) { query.setMaxResults(maxResults); } + if(StringHelper.containsNonWhitespace(type)) { + query.setParameter("resourceType", type); + } + List<RepositoryEntry> repoEntries = query.getResultList(); + return repoEntries; + } + + public List<RepositoryEntry> getLearningResourcesAsBookmark(Identity identity, Roles roles, String type, int firstResult, int maxResults, RepositoryEntryOrder... orderby) { + if(roles.isGuestOnly()) { + return Collections.emptyList(); + } + + StringBuilder sb = new StringBuilder(1200); + sb.append("select v from ").append(RepositoryEntry.class.getName()).append(" as v ") + .append(" inner join fetch v.olatResource as res ") + .append(" inner join fetch v.statistics as statistics") + .append(" left join fetch v.lifecycle as lifecycle") + .append(" where exists (select mark.key from ").append(MarkImpl.class.getName()).append(" as mark ") + .append(" where mark.creator.key=:identityKey and mark.resId=v.key and mark.resName='RepositoryEntry'") + .append(" ) "); + if(StringHelper.containsNonWhitespace(type)) { + sb.append(" and res.resName=:resourceType"); + } + sb.append(" and (v.access >= "); + if (roles.isAuthor()) { + sb.append(RepositoryEntry.ACC_OWNERS_AUTHORS); + } else { + sb.append(RepositoryEntry.ACC_USERS); + } + sb.append(" or (") + .append(" v.access=").append(RepositoryEntry.ACC_OWNERS).append(" and v.membersOnly=true") + .append(" and exists (select rel from repoentrytogroup as rel, bgroup as baseGroup, bgroupmember as membership") + .append(" where rel.entry=v and rel.group=baseGroup and membership.group=baseGroup and membership.identity.key=:identityKey") + .append(" and membership.role in ('").append(GroupRoles.owner.name()).append("','").append(GroupRoles.coach.name()).append("','").append(GroupRoles.participant.name()).append("')") + .append(" )") + .append(" )") + .append(")"); + + appendOrderBy(sb, "v", orderby); + + TypedQuery<RepositoryEntry> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), RepositoryEntry.class) + .setParameter("identityKey", identity.getKey()) + .setFirstResult(firstResult); + if(maxResults > 0) { + query.setMaxResults(maxResults); + } + if(StringHelper.containsNonWhitespace(type)) { + query.setParameter("resourceType", type); + } List<RepositoryEntry> repoEntries = query.getResultList(); return repoEntries; } @@ -1795,10 +1849,10 @@ public class RepositoryManager extends BasicManager { sb.append("select v from repoentrylight as v ") .append(" inner join fetch v.olatResource as res ") .append(" where exists (select rel from repoentrytogroup as rel, bgroup as baseGroup, bgroupmember as membership ") - .append(" where rel.entry=v and rel.group=baseGroup and membership.group=baseGroup and membership.identity.key=:identityKey ") - .append(" and membership.role='").append(GroupRoles.participant.name()).append("')") - .append(" )") - .append(" )") + .append(" where rel.entry=v and rel.group=baseGroup and membership.group=baseGroup and membership.identity.key=:identityKey ") + .append(" and membership.role='").append(GroupRoles.participant.name()).append("')") + .append(" )") + .append(" )") .append(" and (v.access>=3 or (v.access=").append(RepositoryEntry.ACC_OWNERS).append(" and v.membersOnly=true))"); appendOrderBy(sb, "v", orderby); diff --git a/src/main/java/org/olat/repository/RepositoryService.java b/src/main/java/org/olat/repository/RepositoryService.java index 169cdf4c4124c6332eeb5421c8cb3ea41c48cb25..98ebfdb60f5cb2d9a40c185e4add5b64e426fe10 100644 --- a/src/main/java/org/olat/repository/RepositoryService.java +++ b/src/main/java/org/olat/repository/RepositoryService.java @@ -141,5 +141,4 @@ public interface RepositoryService { public int countAuthorView(SearchAuthorRepositoryEntryViewParams params); public List<RepositoryEntryAuthorView> searchAuthorView(SearchAuthorRepositoryEntryViewParams params, int firstResult, int maxResults); - } diff --git a/src/main/java/org/olat/repository/controllers/RepositorySearchController.java b/src/main/java/org/olat/repository/controllers/RepositorySearchController.java index d3043a5437dd6c6c6ee2b92bf7c35d823625cc9d..89dae1a9b966831b1c6e48440fe9c1c3f0ef9df8 100644 --- a/src/main/java/org/olat/repository/controllers/RepositorySearchController.java +++ b/src/main/java/org/olat/repository/controllers/RepositorySearchController.java @@ -432,7 +432,7 @@ public class RepositorySearchController extends BasicController implements Activ private void doSearchMyCoursesStudent(UserRequest ureq, String limitType, boolean updateFilters) { searchType = SearchType.myAsStudent; RepositoryManager rm = RepositoryManager.getInstance(); - List<RepositoryEntry> entries = rm.getLearningResourcesAsStudent(ureq.getIdentity(), 0, -1); + List<RepositoryEntry> entries = rm.getLearningResourcesAsStudent(ureq.getIdentity(), null, 0, -1); filterRepositoryEntries(entries); doSearchMyRepositoryEntries(ureq, entries, limitType, updateFilters); } diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryDAO.java index aae66366f94a1d16662dcddec42f78d6186644fe..7073be4b75854b37cc42634c6e1d940781b1c45a 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryEntryDAO.java +++ b/src/main/java/org/olat/repository/manager/RepositoryEntryDAO.java @@ -120,5 +120,4 @@ public class RepositoryEntryDAO { .setMaxResults(maxResults) .getResultList(); } - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/user/restapi/UserCoursesWebService.java b/src/main/java/org/olat/user/restapi/UserCoursesWebService.java index 273c4feef6bc93e2d509b233fa6030def1894bd2..95ae4397ba780742b1a7e5f9d19eae3d6aede3a0 100644 --- a/src/main/java/org/olat/user/restapi/UserCoursesWebService.java +++ b/src/main/java/org/olat/user/restapi/UserCoursesWebService.java @@ -78,7 +78,7 @@ public class UserCoursesWebService { RepositoryManager rm = RepositoryManager.getInstance(); if(MediaTypeVariants.isPaged(httpRequest, request)) { - List<RepositoryEntry> repoEntries = rm.getLearningResourcesAsStudent(identity, start, limit, RepositoryEntryOrder.nameAsc); + List<RepositoryEntry> repoEntries = rm.getLearningResourcesAsStudent(identity, null, start, limit, RepositoryEntryOrder.nameAsc); int totalCount= rm.countLearningResourcesAsStudent(identity); CourseVO[] vos = toCourseVo(repoEntries); @@ -87,7 +87,7 @@ public class UserCoursesWebService { voes.setTotalCount(totalCount); return Response.ok(voes).build(); } else { - List<RepositoryEntry> repoEntries = rm.getLearningResourcesAsStudent(identity, 0, -1, RepositoryEntryOrder.nameAsc); + List<RepositoryEntry> repoEntries = rm.getLearningResourcesAsStudent(identity, null, 0, -1, RepositoryEntryOrder.nameAsc); CourseVO[] vos = toCourseVo(repoEntries); return Response.ok(vos).build(); } diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java index 5278ff015efe7a8c7e87ffa36561c1efca28d3cc..c52d4e80bce89512bc95c1cc8791bd03ed3594b2 100644 --- a/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java +++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVCommandsTest.java @@ -42,6 +42,7 @@ import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; import org.apache.poi.util.IOUtils; +import org.junit.After; import org.junit.Test; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.GroupRoles; @@ -60,6 +61,7 @@ import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryService; +import org.olat.repository.manager.RepositoryEntryRelationDAO; import org.olat.restapi.CoursePublishTest; import org.olat.test.JunitTestHelper; import org.springframework.beans.factory.annotation.Autowired; @@ -76,11 +78,21 @@ public class WebDAVCommandsTest extends WebDAVTestCase { @Autowired private DB dbInstance; @Autowired + private WebDAVModule webDAVModule; + @Autowired + private VFSLockManager lockManager; + @Autowired private BaseSecurity securityManager; @Autowired private RepositoryService repositoryService; @Autowired - private VFSLockManager lockManager; + private RepositoryEntryRelationDAO repositoryEntryRelationDao; + + @After + public void resetWebDAVModule() { + webDAVModule.setEnableLearnersBookmarksCourse(false); + webDAVModule.setEnableLearnersParticipatingCourses(false); + } /** * Check the DAV, Ms-Author and Allow header @@ -587,6 +599,71 @@ public class WebDAVCommandsTest extends WebDAVTestCase { IOUtils.closeQuietly(conn); } + @Test + public void coursePermissions_participant() + throws IOException, URISyntaxException { + webDAVModule.setEnableLearnersBookmarksCourse(true); + webDAVModule.setEnableLearnersParticipatingCourses(true); + + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("auth-webdav"); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("participant-webdav"); + URL courseWithForumsUrl = WebDAVCommandsTest.class.getResource("webdav_course.zip"); + RepositoryEntry course = deployTestCourse(author, null, courseWithForumsUrl); + repositoryEntryRelationDao.addRole(participant, course, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + WebDAVConnection conn = new WebDAVConnection(); + conn.setCredentials(participant.getName(), "A6B7C8"); + + URI courseUri = conn.getBaseURI().path("webdav").path("coursefolders").build(); + String publicXml = conn.propfind(courseUri, 2); + //cannot access course storage + Assert.assertFalse(publicXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/Course%20storage/</D:href>")); + //can access course elements + Assert.assertTrue(publicXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/</D:href>")); + + URI courseElementUri = conn.getBaseURI().path("webdav").path("coursefolders") + .path("other").path("WebDAV%20course").path("_courseelementdata").build(); + String publicElementXml = conn.propfind(courseElementUri, 2); + Assert.assertTrue(publicElementXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/Folder%20for%20all/</D:href>")); + Assert.assertFalse(publicElementXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/Student%20read-only%20%2890600786058954%29/Readonly%20students/</D:href>")); + Assert.assertFalse(publicElementXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/Not%20for%20students%20%2890600786058958%29/Not%20for%20students/</D:href>")); + + conn.close(); + } + + @Test + public void coursePermissions_owner() + throws IOException, URISyntaxException { + webDAVModule.setEnableLearnersBookmarksCourse(true); + webDAVModule.setEnableLearnersParticipatingCourses(true); + + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("auth-webdav"); + URL courseWithForumsUrl = WebDAVCommandsTest.class.getResource("webdav_course.zip"); + deployTestCourse(author, null, courseWithForumsUrl); + dbInstance.commitAndCloseSession(); + + WebDAVConnection conn = new WebDAVConnection(); + conn.setCredentials(author.getName(), "A6B7C8"); + + URI courseUri = conn.getBaseURI().path("webdav").path("coursefolders").build(); + String publicXml = conn.propfind(courseUri, 2); + //cane access course storage + Assert.assertTrue(publicXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/Course%20storage/</D:href>")); + //can access course elements + Assert.assertTrue(publicXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/</D:href>")); + + URI courseElementUri = conn.getBaseURI().path("webdav").path("coursefolders") + .path("other").path("WebDAV%20course").path("_courseelementdata").build(); + String publicElementXml = conn.propfind(courseElementUri, 2); + //can access all 3 course nodes + Assert.assertTrue(publicElementXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/Folder%20for%20all/</D:href>")); + Assert.assertTrue(publicElementXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/Student%20read-only%20%2890600786058954%29/Readonly%20students/</D:href>")); + Assert.assertTrue(publicElementXml.contains("<D:href>/webdav/coursefolders/other/WebDAV%20course/_courseelementdata/Not%20for%20students%20%2890600786058958%29/Not%20for%20students/</D:href>")); + + conn.close(); + } + private VFSItem createFile(VFSContainer container, String filename) throws IOException { VFSLeaf testLeaf = container.createChildLeaf(filename); InputStream in = WebDAVCommandsTest.class.getResourceAsStream("text.txt"); @@ -598,8 +675,14 @@ public class WebDAVCommandsTest extends WebDAVTestCase { return container.resolve(filename); } - private RepositoryEntry deployTestCourse(Identity author, Identity coAuthor) throws URISyntaxException { + private RepositoryEntry deployTestCourse(Identity author, Identity coAuthor) + throws URISyntaxException { URL courseWithForumsUrl = CoursePublishTest.class.getResource("myCourseWS.zip"); + return deployTestCourse(author, coAuthor, courseWithForumsUrl); + } + + private RepositoryEntry deployTestCourse(Identity author, Identity coAuthor, URL courseWithForumsUrl) + throws URISyntaxException { Assert.assertNotNull(courseWithForumsUrl); File courseWithForums = new File(courseWithForumsUrl.toURI()); String softKey = UUID.randomUUID().toString().replace("-", "").substring(0, 30); diff --git a/src/test/java/org/olat/core/commons/services/webdav/webdav_course.zip b/src/test/java/org/olat/core/commons/services/webdav/webdav_course.zip new file mode 100644 index 0000000000000000000000000000000000000000..b216bb6e6aaff6897cfd89bc5d8f5c01c231db4a Binary files /dev/null and b/src/test/java/org/olat/core/commons/services/webdav/webdav_course.zip differ diff --git a/src/test/java/org/olat/repository/RepositoryManagerTest.java b/src/test/java/org/olat/repository/RepositoryManagerTest.java index cc03446ac80aeb185c1000669520455acbae1fa3..6c830df2c73ebb8cb14a266788c9c5b17dcf7a59 100644 --- a/src/test/java/org/olat/repository/RepositoryManagerTest.java +++ b/src/test/java/org/olat/repository/RepositoryManagerTest.java @@ -276,7 +276,7 @@ public class RepositoryManagerTest extends OlatTestCase { repositoryEntryRelationDao.addRole(id, re, GroupRoles.participant.name()); dbInstance.commitAndCloseSession(); - List<RepositoryEntry> entries = repositoryManager.getLearningResourcesAsStudent(id, 0, -1, RepositoryEntryOrder.nameAsc); + List<RepositoryEntry> entries = repositoryManager.getLearningResourcesAsStudent(id, null, 0, -1, RepositoryEntryOrder.nameAsc); Assert.assertNotNull(entries); Assert.assertFalse(entries.isEmpty()); Assert.assertTrue(entries.contains(re)); @@ -298,7 +298,7 @@ public class RepositoryManagerTest extends OlatTestCase { businessGroupRelationDao.addRole(id, group, GroupRoles.participant.name()); dbInstance.commitAndCloseSession(); - List<RepositoryEntry> entries = repositoryManager.getLearningResourcesAsStudent(id, 0, -1); + List<RepositoryEntry> entries = repositoryManager.getLearningResourcesAsStudent(id, null, 0, -1); Assert.assertNotNull(entries); Assert.assertFalse(entries.isEmpty()); Assert.assertTrue(entries.contains(re)); @@ -311,6 +311,41 @@ public class RepositoryManagerTest extends OlatTestCase { } } } + + @Test + public void getLearningResourcesAsBookmark() { + Identity owner = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-courses-1"); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-courses-2"); + RepositoryEntry course = JunitTestHelper.deployBasicCourse(owner); + markManager.setMark(course, participant, null, "[RepositoryEntry:" + course.getKey() + "]"); + dbInstance.commitAndCloseSession(); + + //participant bookmarks + Roles roles = new Roles(false, false, false, false, false, false, false); + List<RepositoryEntry> courses = repositoryManager.getLearningResourcesAsBookmark(participant, roles, "CourseModule", 0, -1); + Assert.assertNotNull(courses); + Assert.assertEquals(1, courses.size()); + } + + /** + * Check that the method return only courses within the permissions of the user. + */ + @Test + public void getLearningResourcesAsBookmark_noPermissions() { + Identity owner = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-courses-1"); + Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-courses-2"); + RepositoryEntry course = JunitTestHelper.deployBasicCourse(owner); + markManager.setMark(course, participant, null, "[RepositoryEntry:" + course.getKey() + "]"); + dbInstance.commitAndCloseSession(); + repositoryManager.setAccess(course, RepositoryEntry.ACC_OWNERS, false); + dbInstance.commitAndCloseSession(); + + //participant bookmarks + Roles roles = new Roles(false, false, false, false, false, false, false); + List<RepositoryEntry> courses = repositoryManager.getLearningResourcesAsBookmark(participant, roles, "CourseModule", 0, -1); + Assert.assertNotNull(courses); + Assert.assertEquals(0, courses.size()); + } @Test public void getParticipantRepositoryEntry() { diff --git a/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java b/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java index 1c8258409ae53b06f996db3b520ce111fd13440d..5ac7201d22c9014b6323713da81e7650f8b7eb7d 100644 --- a/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java +++ b/src/test/java/org/olat/repository/manager/RepositoryEntryDAOTest.java @@ -25,6 +25,7 @@ import junit.framework.Assert; import org.junit.Test; import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.services.mark.MarkManager; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryService; import org.olat.test.OlatTestCase; @@ -41,9 +42,13 @@ public class RepositoryEntryDAOTest extends OlatTestCase { @Autowired private DB dbInstance; @Autowired + private MarkManager markManager; + @Autowired private RepositoryService repositoryService; @Autowired private RepositoryEntryDAO repositoryEntryDao; + @Autowired + private RepositoryEntryRelationDAO repositoryEntryRelationDao; @Test public void loadByKey() { @@ -69,4 +74,6 @@ public class RepositoryEntryDAOTest extends OlatTestCase { Assert.assertFalse(allRes.isEmpty()); Assert.assertTrue(allRes.size() < 26); } + + } \ No newline at end of file diff --git a/src/test/java/org/olat/test/JunitTestHelper.java b/src/test/java/org/olat/test/JunitTestHelper.java index 48c3101a6f262368ebf3c45d2161aa47128d1ccb..d242dc949c5e6da7a8b8d396a73a2b3400eb750b 100644 --- a/src/test/java/org/olat/test/JunitTestHelper.java +++ b/src/test/java/org/olat/test/JunitTestHelper.java @@ -219,4 +219,30 @@ public class JunitTestHelper { } return re; } + + /** + * Deploy a course with only a single page. + * @param initialAuthor + * @return + */ + public static RepositoryEntry deployBasicCourse(Identity initialAuthor) { + String displayname = "Basic course (" + CodeHelper.getForeverUniqueID() + ")"; + String description = "A course with only a single page"; + + RepositoryEntry re = null; + try { + URL courseUrl = JunitTestHelper.class.getResource("file_resources/Basic_course.zip"); + File courseFile = new File(courseUrl.toURI()); + + RepositoryHandler courseHandler = RepositoryHandlerFactory.getInstance() + .getRepositoryHandler(CourseModule.getCourseTypeName()); + re = courseHandler.importResource(initialAuthor, null, displayname, description, true, Locale.ENGLISH, courseFile, null); + + ICourse course = CourseFactory.loadCourse(re.getOlatResource()); + CourseFactory.publishCourse(course, RepositoryEntry.ACC_USERS, false, initialAuthor, Locale.ENGLISH); + } catch (Exception e) { + log.error("", e); + } + return re; + } } diff --git a/src/test/java/org/olat/test/file_resources/Basic_course.zip b/src/test/java/org/olat/test/file_resources/Basic_course.zip new file mode 100644 index 0000000000000000000000000000000000000000..6e887df4e24022d15eb5f85c75d83544892a963e Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/Basic_course.zip differ