fix: properly expose rename permissions over dav

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2026-03-26 17:20:45 +01:00
parent 005b2b04e8
commit c08592de28
No known key found for this signature in database
GPG key ID: 42B69D8A64526EFB
4 changed files with 30 additions and 24 deletions

View file

@ -76,7 +76,7 @@ class BulkUploadPlugin extends ServerPlugin {
'error' => false,
'etag' => $node->getETag(),
'fileid' => DavUtil::getDavFileId($node->getId()),
'permissions' => DavUtil::getDavPermissions($node),
'permissions' => DavUtil::getDavPermissions($node, $node->getParent()),
];
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), ['path' => $headers['x-file-path']]);

View file

@ -116,25 +116,7 @@ abstract class Node implements INode {
* Check if this node can be renamed
*/
public function canRename(): bool {
// the root of a movable mountpoint can be renamed regardless of the file permissions
if ($this->info->getMountPoint() instanceof MoveableMount && $this->info->getInternalPath() === '') {
return true;
}
// we allow renaming the file if either the file has update permissions
if ($this->info->isUpdateable()) {
return true;
}
// or the file can be deleted and the parent has create permissions
[$parentPath,] = \Sabre\Uri\split($this->path);
if ($parentPath === null) {
// can't rename the users home
return false;
}
$parent = $this->node->getParent();
return $this->info->isDeletable() && $parent->isCreatable();
return DavUtil::canRename($this->node, $this->node->getParent());
}
/**
@ -343,7 +325,7 @@ abstract class Node implements INode {
}
public function getDavPermissions(): string {
return DavUtil::getDavPermissions($this->info);
return DavUtil::getDavPermissions($this->info, $this->node->getParent());
}
/**

View file

@ -42,7 +42,7 @@ class NodeTest extends \Test\TestCase {
[Constants::PERMISSION_ALL, 'file', true, Constants::PERMISSION_ALL, true, '' , 'SRMGDNVW'],
[Constants::PERMISSION_ALL, 'file', true, Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE, true, '' , 'SRMGDNV'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE, 'file', true, Constants::PERMISSION_ALL, false, 'test', 'SGDNVW'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGD'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGDN'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGNVW'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGDNVW'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_READ, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RDNVW'],

View file

@ -7,6 +7,7 @@
namespace OCP\Files;
use OC\Files\Mount\MoveableMount;
use OCP\Constants;
use OCP\Files\Mount\IMovableMount;
@ -33,7 +34,7 @@ class DavUtil {
*
* @since 25.0.0
*/
public static function getDavPermissions(FileInfo $info): string {
public static function getDavPermissions(FileInfo $info, FileInfo $parent): string {
$permissions = $info->getPermissions();
$p = '';
if ($info->isShared()) {
@ -51,8 +52,11 @@ class DavUtil {
if ($permissions & Constants::PERMISSION_DELETE) {
$p .= 'D';
}
if (self::canRename($info, $parent)) {
$p .= 'N'; // Renamable
}
if ($permissions & Constants::PERMISSION_UPDATE) {
$p .= 'NV'; // Renameable, Movable
$p .= 'V'; // Movable
}
// since we always add update permissions for the root of movable mounts
@ -76,4 +80,24 @@ class DavUtil {
}
return $p;
}
public static function canRename(FileInfo $info, FileInfo $parent): bool {
// the root of a movable mountpoint can be renamed regardless of the file permissions
if ($info->getMountPoint() instanceof MoveableMount && $info->getInternalPath() === '') {
return true;
}
// we allow renaming the file if either the file has update permissions
if ($info->isUpdateable()) {
return true;
}
// or the file can be deleted and the parent has create permissions
if ($info->getStorage() instanceof IHomeStorage && $info->getInternalPath() === 'files') {
// can't rename the users home
return false;
}
return $info->isDeletable() && $parent->isCreatable();
}
}