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