mirror of
https://github.com/nextcloud/server.git
synced 2026-04-15 22:11:17 -04:00
fix: Renaming does not need update but delete permissions
Renaming is basically copy + delete (a move), so no need to update permissions. Especially if the node is in a invalid directory the node should be moveable but not editable. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
parent
0d41c49918
commit
030c209d22
6 changed files with 18 additions and 15 deletions
|
|
@ -117,8 +117,9 @@ abstract class Node implements \Sabre\DAV\INode {
|
|||
* @throws \Sabre\DAV\Exception\Forbidden
|
||||
*/
|
||||
public function setName($name) {
|
||||
// rename is only allowed if the update privilege is granted
|
||||
if (!($this->info->isUpdateable() || ($this->info->getMountPoint() instanceof MoveableMount && $this->info->getInternalPath() === ''))) {
|
||||
// rename is only allowed if the delete privilege is granted
|
||||
// (basically rename is a copy with delete of the original node)
|
||||
if (!($this->info->isDeletable() || ($this->info->getMountPoint() instanceof MoveableMount && $this->info->getInternalPath() === ''))) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +130,6 @@ abstract class Node implements \Sabre\DAV\INode {
|
|||
// verify path of the target
|
||||
$this->verifyPath($newPath);
|
||||
|
||||
|
||||
if (!$this->fileView->rename($this->path, $newPath)) {
|
||||
throw new \Sabre\DAV\Exception('Failed to rename '. $this->path . ' to ' . $newPath);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export type MoveCopyResult = {
|
|||
|
||||
export const canMove = (nodes: Node[]) => {
|
||||
const minPermission = nodes.reduce((min, node) => Math.min(min, node.permissions), Permission.ALL)
|
||||
return (minPermission & Permission.UPDATE) !== 0
|
||||
return Boolean(minPermission & Permission.DELETE)
|
||||
}
|
||||
|
||||
export const canDownload = (nodes: Node[]) => {
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@ describe('Rename action enabled tests', () => {
|
|||
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
|
||||
owner: 'admin',
|
||||
mime: 'text/plain',
|
||||
permissions: Permission.UPDATE,
|
||||
permissions: Permission.UPDATE | Permission.DELETE,
|
||||
})
|
||||
|
||||
expect(action.enabled).toBeDefined()
|
||||
expect(action.enabled!([file], view)).toBe(true)
|
||||
})
|
||||
|
||||
test('Disabled for node without UPDATE permission', () => {
|
||||
test('Disabled for node without DELETE permission', () => {
|
||||
const file = new File({
|
||||
id: 1,
|
||||
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const action = new FileAction({
|
|||
enabled: (nodes: Node[]) => {
|
||||
return nodes.length > 0 && nodes
|
||||
.map(node => node.permissions)
|
||||
.every(permission => (permission & Permission.UPDATE) !== 0)
|
||||
.every(permission => Boolean(permission & Permission.DELETE))
|
||||
},
|
||||
|
||||
async exec(node: Node) {
|
||||
|
|
|
|||
|
|
@ -432,11 +432,14 @@ class Node implements INode {
|
|||
$targetPath = $this->normalizePath($targetPath);
|
||||
$parent = $this->root->get(dirname($targetPath));
|
||||
if (
|
||||
$parent instanceof Folder and
|
||||
$this->isValidPath($targetPath) and
|
||||
(
|
||||
$parent->isCreatable() ||
|
||||
($parent->getInternalPath() === '' && $parent->getMountPoint() instanceof MoveableMount)
|
||||
($parent instanceof Folder)
|
||||
&& $this->isValidPath($targetPath)
|
||||
&& (
|
||||
$parent->isCreatable()
|
||||
|| (
|
||||
$parent->getInternalPath() === ''
|
||||
&& ($parent->getMountPoint() instanceof MoveableMount)
|
||||
)
|
||||
)
|
||||
) {
|
||||
$nonExisting = $this->createNonExistingNode($targetPath);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use OC\Files\Storage\Temporary;
|
|||
use OC\Files\View;
|
||||
use OC\Memcache\ArrayCache;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\Mount\IMountManager;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IUserManager;
|
||||
|
|
@ -46,8 +47,7 @@ class IntegrationTest extends \Test\TestCase {
|
|||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
/** @var IMountManager $manager */
|
||||
$manager = \OC::$server->get(IMountManager::class);
|
||||
$manager = \OCP\Server::get(IMountManager::class);
|
||||
|
||||
\OC_Hook::clear('OC_Filesystem');
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ class IntegrationTest extends \Test\TestCase {
|
|||
$manager,
|
||||
$this->view,
|
||||
$user,
|
||||
\OC::$server->getUserMountCache(),
|
||||
\OCP\Server::get(IUserMountCache::class),
|
||||
$this->createMock(LoggerInterface::class),
|
||||
$this->createMock(IUserManager::class),
|
||||
$this->createMock(IEventDispatcher::class),
|
||||
|
|
|
|||
Loading…
Reference in a new issue