Skip to content

Commit 0ffb5e0

Browse files
authored
Merge pull request #1321 from nextcloud/backport-1301-fix-required-permissions-for-webdav-move-and-copy-9
[stable9] Fix required permissions for webdav move and copy
2 parents 83515c9 + 86a673a commit 0ffb5e0

2 files changed

Lines changed: 49 additions & 21 deletions

File tree

apps/dav/lib/connector/sabre/objecttree.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,18 @@ public function move($sourcePath, $destinationPath) {
201201
}
202202

203203
$infoDestination = $this->fileView->getFileInfo(dirname($destinationPath));
204-
$infoSource = $this->fileView->getFileInfo($sourcePath);
205-
$destinationPermission = $infoDestination && $infoDestination->isUpdateable();
206-
$sourcePermission = $infoSource && $infoSource->isDeletable();
204+
if (dirname($destinationPath) === dirname($sourcePath)) {
205+
$sourcePermission = $infoDestination && $infoDestination->isUpdateable();
206+
$destinationPermission = $sourcePermission;
207+
} else {
208+
$infoSource = $this->fileView->getFileInfo($sourcePath);
209+
if ($this->fileView->file_exists($destinationPath)) {
210+
$destinationPermission = $infoDestination && $infoDestination->isUpdateable();
211+
} else {
212+
$destinationPermission = $infoDestination && $infoDestination->isCreatable();
213+
}
214+
$sourcePermission = $infoSource && $infoSource->isDeletable();
215+
}
207216

208217
if (!$destinationPermission || !$sourcePermission) {
209218
throw new Forbidden('No permissions to move object.');
@@ -292,7 +301,12 @@ public function copy($source, $destination) {
292301
}
293302

294303
$info = $this->fileView->getFileInfo(dirname($destination));
295-
if ($info && !$info->isUpdateable()) {
304+
if ($this->fileView->file_exists($destination)) {
305+
$destinationPermission = $info && $info->isUpdateable();
306+
} else {
307+
$destinationPermission = $info && $info->isCreatable();
308+
}
309+
if (!$destinationPermission) {
296310
throw new Forbidden('No permissions to copy object.');
297311
}
298312

apps/dav/tests/unit/connector/sabre/objecttree.php

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,23 @@
3434

3535
class TestDoubleFileView extends \OC\Files\View {
3636

37-
public function __construct($updatables, $deletables, $canRename = true) {
37+
public function __construct($creatables, $updatables, $deletables, $canRename = true) {
38+
$this->creatables = $creatables;
3839
$this->updatables = $updatables;
3940
$this->deletables = $deletables;
4041
$this->canRename = $canRename;
4142
}
4243

4344
public function isUpdatable($path) {
44-
return $this->updatables[$path];
45+
return !empty($this->updatables[$path]);
4546
}
4647

4748
public function isCreatable($path) {
48-
return $this->updatables[$path];
49+
return !empty($this->creatables[$path]);
4950
}
5051

5152
public function isDeletable($path) {
52-
return $this->deletables[$path];
53+
return !empty($this->deletables[$path]);
5354
}
5455

5556
public function rename($path1, $path2) {
@@ -62,7 +63,11 @@ public function getRelativePath($path) {
6263

6364
public function getFileInfo($path, $includeMountPoints = true) {
6465
$objectTreeTest = new ObjectTree();
65-
return $objectTreeTest->getFileInfoMock();
66+
return $objectTreeTest->getFileInfoMock(
67+
$this->isCreatable($path),
68+
$this->isUpdatable($path),
69+
$this->isDeletable($path)
70+
);
6671
}
6772
}
6873

@@ -75,16 +80,22 @@ public function getFileInfo($path, $includeMountPoints = true) {
7580
*/
7681
class ObjectTree extends \Test\TestCase {
7782

78-
public function getFileInfoMock() {
79-
$mock = $this->getMock('\OCP\Files\FileInfo');
83+
public function getFileInfoMock($create = true, $update = true, $delete = true) {
84+
$mock = $this->getMockBuilder('\OCP\Files\FileInfo')
85+
->disableOriginalConstructor()
86+
->getMock();
8087
$mock
8188
->expects($this->any())
82-
->method('isDeletable')
83-
->willReturn(true);
89+
->method('isCreatable')
90+
->willReturn($create);
8491
$mock
8592
->expects($this->any())
8693
->method('isUpdateable')
87-
->willReturn(true);
94+
->willReturn($update);
95+
$mock
96+
->expects($this->any())
97+
->method('isDeletable')
98+
->willReturn($delete);
8899

89100
return $mock;
90101
}
@@ -95,14 +106,14 @@ public function getFileInfoMock() {
95106
* @expectedException \Sabre\DAV\Exception\Forbidden
96107
*/
97108
public function testMoveFailed($source, $destination, $updatables, $deletables) {
98-
$this->moveTest($source, $destination, $updatables, $deletables);
109+
$this->moveTest($source, $destination, $updatables, $updatables, $deletables, true);
99110
}
100111

101112
/**
102113
* @dataProvider moveSuccessProvider
103114
*/
104115
public function testMoveSuccess($source, $destination, $updatables, $deletables) {
105-
$this->moveTest($source, $destination, $updatables, $deletables);
116+
$this->moveTest($source, $destination, $updatables, $updatables, $deletables);
106117
$this->assertTrue(true);
107118
}
108119

@@ -111,7 +122,7 @@ public function testMoveSuccess($source, $destination, $updatables, $deletables)
111122
* @expectedException \OCA\DAV\Connector\Sabre\Exception\InvalidPath
112123
*/
113124
public function testMoveFailedInvalidChars($source, $destination, $updatables, $deletables) {
114-
$this->moveTest($source, $destination, $updatables, $deletables);
125+
$this->moveTest($source, $destination, $updatables, $updatables, $deletables);
115126
}
116127

117128
function moveFailedInvalidCharsProvider() {
@@ -142,10 +153,13 @@ function moveSuccessProvider() {
142153
/**
143154
* @param $source
144155
* @param $destination
156+
* @param $creatables
145157
* @param $updatables
158+
* @param $deletables
159+
* @param $throwsBeforeGetNode
146160
*/
147-
private function moveTest($source, $destination, $updatables, $deletables) {
148-
$view = new TestDoubleFileView($updatables, $deletables);
161+
private function moveTest($source, $destination, $creatables, $updatables, $deletables, $throwsBeforeGetNode = false) {
162+
$view = new TestDoubleFileView($creatables, $updatables, $deletables);
149163

150164
$info = new FileInfo('', null, null, array(), null);
151165

@@ -154,7 +168,7 @@ private function moveTest($source, $destination, $updatables, $deletables) {
154168
array('nodeExists', 'getNodeForPath'),
155169
array($rootDir, $view));
156170

157-
$objectTree->expects($this->once())
171+
$objectTree->expects($throwsBeforeGetNode ? $this->never() : $this->once())
158172
->method('getNodeForPath')
159173
->with($this->identicalTo($source))
160174
->will($this->returnValue(false));
@@ -345,7 +359,7 @@ public function testFailingMove() {
345359
$updatables = array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false);
346360
$deletables = array('a/b' => true);
347361

348-
$view = new TestDoubleFileView($updatables, $deletables);
362+
$view = new TestDoubleFileView($updatables, $updatables, $deletables);
349363

350364
$info = new FileInfo('', null, null, array(), null);
351365

0 commit comments

Comments
 (0)