From 33c9a8afabe51a2fd433875149d4b96cce66e306 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Mon, 2 Mar 2015 21:52:52 +0100
Subject: [PATCH] OO-1455: check the security callback with the recursive
 method of container

---
 .../webdav/manager/VFSResourceRoot.java       |   6 +-
 .../services/webdav/WebDAVCommandsTest.java   | 110 +++++++++++++++++-
 .../services/webdav/WebDAVConnection.java     |  11 +-
 .../core/commons/services/webdav/mkdirs.zip   | Bin 0 -> 12423 bytes
 4 files changed, 122 insertions(+), 5 deletions(-)
 create mode 100644 src/test/java/org/olat/core/commons/services/webdav/mkdirs.zip

diff --git a/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java b/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java
index 0e47b713dea..aa1c835199b 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java
+++ b/src/main/java/org/olat/core/commons/services/webdav/manager/VFSResourceRoot.java
@@ -159,8 +159,10 @@ public class VFSResourceRoot implements WebResourceRoot  {
 		} else if (parentItem instanceof VFSContainer) {
 			String name = path.substring(lastSlash + 1);
 			VFSContainer folder = (VFSContainer)parentItem;
-			VFSContainer dir = folder.createChildContainer(name);
-			return dir != null && dir.exists();
+			if(folder.canWrite() == VFSConstants.YES) {
+				VFSContainer dir = folder.createChildContainer(name);
+				return dir != null && dir.exists();
+			}
 		}
 		return false;
 	}
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 9a74b0c2f25..15fb3804ecc 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
@@ -51,6 +51,8 @@ import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 import org.olat.core.util.FileUtils;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
@@ -75,6 +77,8 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class WebDAVCommandsTest extends WebDAVTestCase {
 	
+	private static final OLog log = Tracing.createLoggerFor(WebDAVCommandsTest.class);
+	
 	@Autowired
 	private DB dbInstance;
 	@Autowired
@@ -520,7 +524,7 @@ public class WebDAVCommandsTest extends WebDAVTestCase {
 		//author check file 
 		URI textUri = conn.getBaseURI().path("webdav").path("home").path("public").path("test.txt").build();
 		String textPropfind = conn.propfind(textUri, 0);
-		System.out.println(textPropfind);
+		log.info(textPropfind);
 		
 		//author lock the file
 		String lockToken = conn.lock(textUri, UUID.randomUUID().toString());
@@ -664,6 +668,101 @@ public class WebDAVCommandsTest extends WebDAVTestCase {
 		conn.close();
 	}
 	
+	/**
+	 * Check that different methods doesn't create directory
+	 * 
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	public void coursePermission_participantDirectory()
+	throws IOException, URISyntaxException {
+		webDAVModule.setEnableLearnersBookmarksCourse(true);
+		webDAVModule.setEnableLearnersParticipatingCourses(true);
+		
+		//create a user
+		Identity auth = JunitTestHelper.createAndPersistIdentityAsAuthor("webdav-4-" + UUID.randomUUID().toString());
+		Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("webdav-5");
+		RepositoryEntry courseEntry = deployMkdirsCourse(auth);
+		repositoryEntryRelationDao.addRole(participant, courseEntry, GroupRoles.participant.name());
+		dbInstance.commitAndCloseSession();
+		
+		//put a reference file there
+		ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource());
+		VFSContainer elements = (VFSContainer)course.getCourseFolderContainer().resolve("_courseelementdata");
+		Assert.assertNotNull(elements);
+		VFSContainer directory = (VFSContainer)elements.resolve("Directory");
+		VFSContainer level_1_Container = directory.createChildContainer("DT_01");
+		
+		VFSLeaf readonlyLeaf = level_1_Container.createChildLeaf("readonly.txt");
+		InputStream in = WebDAVCommandsTest.class.getResourceAsStream("text.txt");
+		OutputStream out = readonlyLeaf.getOutputStream(false);
+		FileUtils.copy(in, out);
+		
+		//check
+		VFSItem readonlyLeafBis = level_1_Container.resolve("readonly.txt");
+		Assert.assertNotNull(readonlyLeafBis);
+		
+		
+		//participant try to put a file
+		WebDAVConnection conn = new WebDAVConnection();
+		conn.setCredentials(participant.getName(), "A6B7C8");
+		URI courseUri = conn.getBaseURI().path("webdav").path("coursefolders").path("other").path("Mkdirs").build();
+		
+		
+		//MKCOL in the folder at the second level
+		URI level2Uri = UriBuilder.fromUri(courseUri).path("_courseelementdata")
+				.path("Directory").path("DT_01").path("DT_11").build();
+		int mkcol2Code = conn.mkcol(level2Uri);
+		Assert.assertEquals(409, mkcol2Code);		
+		//check	
+		VFSItem level2Mkcol = level_1_Container.resolve("DT_11");
+		Assert.assertNull(level2Mkcol);
+		
+		
+		//MKCOL in the folder at the first level
+		URI level1Uri = UriBuilder.fromUri(courseUri).path("_courseelementdata")
+						.path("Directory").path("DT_02").build();
+		int mkcol1Code = conn.mkcol(level1Uri);
+		Assert.assertEquals(409, mkcol1Code);
+		VFSItem level1Mkcol = directory.resolve("DT_02");
+		Assert.assertNull(level1Mkcol);
+		
+		
+		//PROPFIND in second level
+		int propfind2Code = conn.propfindTry(level2Uri, 1);
+		Assert.assertEquals(404, propfind2Code);	
+		//check	
+		VFSItem level2Propfind = level_1_Container.resolve("DT_11");
+		Assert.assertNull(level2Propfind);
+
+		
+		//PROPFIND in first level
+		int propfind1Code = conn.propfindTry(level2Uri, 1);
+		Assert.assertEquals(404, propfind1Code);	
+		//check	
+		VFSItem level1Propfind = level_1_Container.resolve("DT_02");
+		Assert.assertNull(level1Propfind);
+		
+		
+		//LOCK in the second level
+		int lock2Code = conn.lockTry(level2Uri, UUID.randomUUID().toString());
+		Assert.assertEquals(403, lock2Code);	
+		//check	
+		VFSItem level2Lock = level_1_Container.resolve("DT_11");
+		Assert.assertNull(level2Lock);
+
+		
+		//LOCK in the first level
+		int lock1Code = conn.lockTry(level2Uri, UUID.randomUUID().toString());
+		Assert.assertEquals(403, lock1Code);	
+		//check	
+		VFSItem level1Lock = level_1_Container.resolve("DT_02");
+		Assert.assertNull(level1Lock);
+	
+		IOUtils.closeQuietly(conn);
+	}
+	
 	@Test
 	public void customizingFolder()
 	throws IOException, URISyntaxException {
@@ -679,7 +778,8 @@ public class WebDAVCommandsTest extends WebDAVTestCase {
 		Assert.assertTrue(customizingXml.contains("<D:href>/webdav/customizing/</D:href>"));
 
 		//PUT in the folder
-		URI textUri = conn.getBaseURI().path("webdav").path("customizing").path("infos.txt").build();
+		String randomFilename = "infos" + UUID.randomUUID() + ".txt";
+		URI textUri = conn.getBaseURI().path("webdav").path("customizing").path(randomFilename).build();
 		HttpPut put = conn.createPut(textUri);
 		InputStream dataStream = WebDAVCommandsTest.class.getResourceAsStream("text.txt");
 		InputStreamEntity entity = new InputStreamEntity(dataStream, -1);
@@ -727,6 +827,12 @@ public class WebDAVCommandsTest extends WebDAVTestCase {
 		return container.resolve(filename);
 	}
 	
+	private RepositoryEntry deployMkdirsCourse(Identity author) 
+	throws URISyntaxException {
+		URL courseWithForumsUrl = WebDAVCommandsTest.class.getResource("mkdirs.zip");
+		return deployTestCourse(author, null, courseWithForumsUrl);
+	}
+
 	private RepositoryEntry deployTestCourse(Identity author, Identity coAuthor)
 	throws URISyntaxException {
 		URL courseWithForumsUrl = CoursePublishTest.class.getResource("myCourseWS.zip");
diff --git a/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java b/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java
index 39d00bef97a..ec406754edb 100644
--- a/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java
+++ b/src/test/java/org/olat/core/commons/services/webdav/WebDAVConnection.java
@@ -119,8 +119,17 @@ public class WebDAVConnection implements Closeable {
 		HttpPropFind propfind = new HttpPropFind(uri);
 		propfind.addHeader("Depth", Integer.toString(depth));
 		HttpResponse response = execute(propfind);
+		String text = EntityUtils.toString(response.getEntity());
 		Assert.assertEquals(207, response.getStatusLine().getStatusCode());
-		return EntityUtils.toString(response.getEntity());
+		return text;
+	}
+	
+	public int propfindTry(URI uri, int depth) throws IOException, URISyntaxException {
+		HttpPropFind propfind = new HttpPropFind(uri);
+		propfind.addHeader("Depth", Integer.toString(depth));
+		HttpResponse response = execute(propfind);
+		EntityUtils.consumeQuietly(response.getEntity());
+		return response.getStatusLine().getStatusCode();
 	}
 	
 	public int mkcol(URI uri) throws IOException, URISyntaxException {
diff --git a/src/test/java/org/olat/core/commons/services/webdav/mkdirs.zip b/src/test/java/org/olat/core/commons/services/webdav/mkdirs.zip
new file mode 100644
index 0000000000000000000000000000000000000000..d2e11b74d9cbbe1d0ae4a0830ab6bd4da43e3457
GIT binary patch
literal 12423
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

literal 0
HcmV?d00001

-- 
GitLab