Fix files node API failed rename/copy
Whenever a rename or copy operation failed on the view, we must throw an exception instead of just ignoring. Signed-off-by: Vincent Petry <pvince81@owncloud.com>
This commit is contained in:
parent
eb5ea0e260
commit
e667b28298
|
@ -29,6 +29,16 @@ namespace OC\Files\Node;
|
||||||
use OCP\Files\NotPermittedException;
|
use OCP\Files\NotPermittedException;
|
||||||
|
|
||||||
class File extends Node implements \OCP\Files\File {
|
class File extends Node implements \OCP\Files\File {
|
||||||
|
/**
|
||||||
|
* Creates a Folder that represents a non-existing path
|
||||||
|
*
|
||||||
|
* @param string $path path
|
||||||
|
* @return string non-existing node class
|
||||||
|
*/
|
||||||
|
protected function createNonExistingNode($path) {
|
||||||
|
return new NonExistingFile($this->root, $this->view, $path);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \OCP\Files\NotPermittedException
|
* @throws \OCP\Files\NotPermittedException
|
||||||
|
@ -113,52 +123,6 @@ class File extends Node implements \OCP\Files\File {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $targetPath
|
|
||||||
* @throws \OCP\Files\NotPermittedException
|
|
||||||
* @return \OC\Files\Node\Node
|
|
||||||
*/
|
|
||||||
public function copy($targetPath) {
|
|
||||||
$targetPath = $this->normalizePath($targetPath);
|
|
||||||
$parent = $this->root->get(dirname($targetPath));
|
|
||||||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
|
|
||||||
$nonExisting = new NonExistingFile($this->root, $this->view, $targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting));
|
|
||||||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
|
|
||||||
$this->view->copy($this->path, $targetPath);
|
|
||||||
$targetNode = $this->root->get($targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode));
|
|
||||||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode));
|
|
||||||
return $targetNode;
|
|
||||||
} else {
|
|
||||||
throw new NotPermittedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $targetPath
|
|
||||||
* @throws \OCP\Files\NotPermittedException
|
|
||||||
* @return \OC\Files\Node\Node
|
|
||||||
*/
|
|
||||||
public function move($targetPath) {
|
|
||||||
$targetPath = $this->normalizePath($targetPath);
|
|
||||||
$parent = $this->root->get(dirname($targetPath));
|
|
||||||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
|
|
||||||
$nonExisting = new NonExistingFile($this->root, $this->view, $targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting));
|
|
||||||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
|
|
||||||
$this->view->rename($this->path, $targetPath);
|
|
||||||
$targetNode = $this->root->get($targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'postRename', array($this, $targetNode));
|
|
||||||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode));
|
|
||||||
$this->path = $targetPath;
|
|
||||||
$this->fileInfo = null;
|
|
||||||
return $targetNode;
|
|
||||||
} else {
|
|
||||||
throw new NotPermittedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @param bool $raw
|
* @param bool $raw
|
||||||
|
|
|
@ -35,6 +35,16 @@ use OCP\Files\NotFoundException;
|
||||||
use OCP\Files\NotPermittedException;
|
use OCP\Files\NotPermittedException;
|
||||||
|
|
||||||
class Folder extends Node implements \OCP\Files\Folder {
|
class Folder extends Node implements \OCP\Files\Folder {
|
||||||
|
/**
|
||||||
|
* Creates a Folder that represents a non-existing path
|
||||||
|
*
|
||||||
|
* @param string $path path
|
||||||
|
* @return string non-existing node class
|
||||||
|
*/
|
||||||
|
protected function createNonExistingNode($path) {
|
||||||
|
return new NonExistingFolder($this->root, $this->view, $path);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path path relative to the folder
|
* @param string $path path relative to the folder
|
||||||
* @return string
|
* @return string
|
||||||
|
@ -325,51 +335,6 @@ class Folder extends Node implements \OCP\Files\Folder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $targetPath
|
|
||||||
* @throws \OCP\Files\NotPermittedException
|
|
||||||
* @return \OC\Files\Node\Node
|
|
||||||
*/
|
|
||||||
public function copy($targetPath) {
|
|
||||||
$targetPath = $this->normalizePath($targetPath);
|
|
||||||
$parent = $this->root->get(dirname($targetPath));
|
|
||||||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
|
|
||||||
$nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'preCopy', array($this, $nonExisting));
|
|
||||||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
|
|
||||||
$this->view->copy($this->path, $targetPath);
|
|
||||||
$targetNode = $this->root->get($targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'postCopy', array($this, $targetNode));
|
|
||||||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode));
|
|
||||||
return $targetNode;
|
|
||||||
} else {
|
|
||||||
throw new NotPermittedException('No permission to copy to path');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $targetPath
|
|
||||||
* @throws \OCP\Files\NotPermittedException
|
|
||||||
* @return \OC\Files\Node\Node
|
|
||||||
*/
|
|
||||||
public function move($targetPath) {
|
|
||||||
$targetPath = $this->normalizePath($targetPath);
|
|
||||||
$parent = $this->root->get(dirname($targetPath));
|
|
||||||
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
|
|
||||||
$nonExisting = new NonExistingFolder($this->root, $this->view, $targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'preRename', array($this, $nonExisting));
|
|
||||||
$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
|
|
||||||
$this->view->rename($this->path, $targetPath);
|
|
||||||
$targetNode = $this->root->get($targetPath);
|
|
||||||
$this->root->emit('\OC\Files', 'postRename', array($this, $targetNode));
|
|
||||||
$this->root->emit('\OC\Files', 'postWrite', array($targetNode));
|
|
||||||
$this->path = $targetPath;
|
|
||||||
return $targetNode;
|
|
||||||
} else {
|
|
||||||
throw new NotPermittedException('No permission to move to path');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a suffix to the name in case the file exists
|
* Add a suffix to the name in case the file exists
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,6 +33,7 @@ use OCP\Files\InvalidPathException;
|
||||||
use OCP\Files\NotFoundException;
|
use OCP\Files\NotFoundException;
|
||||||
use OCP\Files\NotPermittedException;
|
use OCP\Files\NotPermittedException;
|
||||||
|
|
||||||
|
// FIXME: this class really should be abstract
|
||||||
class Node implements \OCP\Files\Node {
|
class Node implements \OCP\Files\Node {
|
||||||
/**
|
/**
|
||||||
* @var \OC\Files\View $view
|
* @var \OC\Files\View $view
|
||||||
|
@ -67,6 +68,16 @@ class Node implements \OCP\Files\Node {
|
||||||
$this->fileInfo = $fileInfo;
|
$this->fileInfo = $fileInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Node of the same type that represents a non-existing path
|
||||||
|
*
|
||||||
|
* @param string $path path
|
||||||
|
* @return string non-existing node class
|
||||||
|
*/
|
||||||
|
protected function createNonExistingNode($path) {
|
||||||
|
throw new \Exception('Must be implemented by subclasses');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the matching file info
|
* Returns the matching file info
|
||||||
*
|
*
|
||||||
|
@ -106,27 +117,10 @@ class Node implements \OCP\Files\Node {
|
||||||
return ($this->getPermissions() & $permissions) === $permissions;
|
return ($this->getPermissions() & $permissions) === $permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $targetPath
|
|
||||||
* @throws \OCP\Files\NotPermittedException
|
|
||||||
* @return \OC\Files\Node\Node
|
|
||||||
*/
|
|
||||||
public function move($targetPath) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $targetPath
|
|
||||||
* @return \OC\Files\Node\Node
|
|
||||||
*/
|
|
||||||
public function copy($targetPath) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $mtime
|
* @param int $mtime
|
||||||
* @throws \OCP\Files\NotPermittedException
|
* @throws \OCP\Files\NotPermittedException
|
||||||
|
@ -381,4 +375,54 @@ class Node implements \OCP\Files\Node {
|
||||||
public function unlock($type) {
|
public function unlock($type) {
|
||||||
$this->view->unlockFile($this->path, $type);
|
$this->view->unlockFile($this->path, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $targetPath
|
||||||
|
* @throws \OCP\Files\NotPermittedException if copy not allowed or failed
|
||||||
|
* @return \OC\Files\Node\Node
|
||||||
|
*/
|
||||||
|
public function copy($targetPath) {
|
||||||
|
$targetPath = $this->normalizePath($targetPath);
|
||||||
|
$parent = $this->root->get(dirname($targetPath));
|
||||||
|
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
|
||||||
|
$nonExisting = $this->createNonExistingNode($targetPath);
|
||||||
|
$this->root->emit('\OC\Files', 'preCopy', [$this, $nonExisting]);
|
||||||
|
$this->root->emit('\OC\Files', 'preWrite', [$nonExisting]);
|
||||||
|
if (!$this->view->copy($this->path, $targetPath)) {
|
||||||
|
throw new NotPermittedException('Could not copy ' . $this->path . ' to ' . $targetPath);
|
||||||
|
}
|
||||||
|
$targetNode = $this->root->get($targetPath);
|
||||||
|
$this->root->emit('\OC\Files', 'postCopy', [$this, $targetNode]);
|
||||||
|
$this->root->emit('\OC\Files', 'postWrite', [$targetNode]);
|
||||||
|
return $targetNode;
|
||||||
|
} else {
|
||||||
|
throw new NotPermittedException('No permission to copy to path ' . $targetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $targetPath
|
||||||
|
* @throws \OCP\Files\NotPermittedException if move not allowed or failed
|
||||||
|
* @return \OC\Files\Node\Node
|
||||||
|
*/
|
||||||
|
public function move($targetPath) {
|
||||||
|
$targetPath = $this->normalizePath($targetPath);
|
||||||
|
$parent = $this->root->get(dirname($targetPath));
|
||||||
|
if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
|
||||||
|
$nonExisting = $this->createNonExistingNode($targetPath);
|
||||||
|
$this->root->emit('\OC\Files', 'preRename', [$this, $nonExisting]);
|
||||||
|
$this->root->emit('\OC\Files', 'preWrite', [$nonExisting]);
|
||||||
|
if (!$this->view->rename($this->path, $targetPath)) {
|
||||||
|
throw new NotPermittedException('Could not move ' . $this->path . ' to ' . $targetPath);
|
||||||
|
}
|
||||||
|
$targetNode = $this->root->get($targetPath);
|
||||||
|
$this->root->emit('\OC\Files', 'postRename', [$this, $targetNode]);
|
||||||
|
$this->root->emit('\OC\Files', 'postWrite', [$targetNode]);
|
||||||
|
$this->path = $targetPath;
|
||||||
|
return $targetNode;
|
||||||
|
} else {
|
||||||
|
throw new NotPermittedException('No permission to move to path ' . $targetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,6 @@ namespace Test\Files\Node;
|
||||||
* @package Test\Files\Node
|
* @package Test\Files\Node
|
||||||
*/
|
*/
|
||||||
class FileTest extends NodeTest {
|
class FileTest extends NodeTest {
|
||||||
|
|
||||||
public $viewDeleteMethod = 'unlink';
|
|
||||||
|
|
||||||
protected function createTestNode($root, $view, $path) {
|
protected function createTestNode($root, $view, $path) {
|
||||||
return new \OC\Files\Node\File($root, $view, $path);
|
return new \OC\Files\Node\File($root, $view, $path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -614,7 +614,6 @@ abstract class NodeTest extends \Test\TestCase {
|
||||||
->method('rename');
|
->method('rename');
|
||||||
|
|
||||||
$node = $this->createTestNode($this->root, $this->view, '/bar/foo');
|
$node = $this->createTestNode($this->root, $this->view, '/bar/foo');
|
||||||
$parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar');
|
|
||||||
|
|
||||||
$this->root->expects($this->once())
|
$this->root->expects($this->once())
|
||||||
->method('get')
|
->method('get')
|
||||||
|
@ -641,4 +640,50 @@ abstract class NodeTest extends \Test\TestCase {
|
||||||
|
|
||||||
$node->move('/bar/asd');
|
$node->move('/bar/asd');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Files\NotPermittedException
|
||||||
|
*/
|
||||||
|
public function testMoveFailed() {
|
||||||
|
$this->view->expects($this->any())
|
||||||
|
->method('rename')
|
||||||
|
->with('/bar/foo', '/bar/asd')
|
||||||
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
|
$this->view->expects($this->any())
|
||||||
|
->method('getFileInfo')
|
||||||
|
->will($this->returnValue($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1])));
|
||||||
|
|
||||||
|
$node = $this->createTestNode($this->root, $this->view, '/bar/foo');
|
||||||
|
$parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar');
|
||||||
|
|
||||||
|
$this->root->expects($this->any())
|
||||||
|
->method('get')
|
||||||
|
->will($this->returnValueMap([['/bar', $parentNode], ['/bar/asd', $node]]));
|
||||||
|
|
||||||
|
$node->move('/bar/asd');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \OCP\Files\NotPermittedException
|
||||||
|
*/
|
||||||
|
public function testCopyFailed() {
|
||||||
|
$this->view->expects($this->any())
|
||||||
|
->method('copy')
|
||||||
|
->with('/bar/foo', '/bar/asd')
|
||||||
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
|
$this->view->expects($this->any())
|
||||||
|
->method('getFileInfo')
|
||||||
|
->will($this->returnValue($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL, 'fileid' => 1])));
|
||||||
|
|
||||||
|
$node = $this->createTestNode($this->root, $this->view, '/bar/foo');
|
||||||
|
$parentNode = new \OC\Files\Node\Folder($this->root, $this->view, '/bar');
|
||||||
|
|
||||||
|
$this->root->expects($this->any())
|
||||||
|
->method('get')
|
||||||
|
->will($this->returnValueMap([['/bar', $parentNode], ['/bar/asd', $node]]));
|
||||||
|
|
||||||
|
$node->copy('/bar/asd');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue