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 d2d367326c
commit d0641c959f
No known key found for this signature in database
GPG key ID: 42B69D8A64526EFB
4 changed files with 38 additions and 29 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

@ -108,25 +108,7 @@ abstract class Node implements \Sabre\DAV\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());
}
/**
@ -354,11 +336,8 @@ abstract class Node implements \Sabre\DAV\INode {
return null;
}
/**
* @return string
*/
public function getDavPermissions() {
return DavUtil::getDavPermissions($this->info);
public function getDavPermissions(): string {
return DavUtil::getDavPermissions($this->info, $this->node->getParent());
}
public function getOwner() {

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 = null): string {
$permissions = $info->getPermissions();
$p = '';
if ($info->isShared()) {
@ -51,8 +52,17 @@ class DavUtil {
if ($permissions & Constants::PERMISSION_DELETE) {
$p .= 'D';
}
if ($permissions & Constants::PERMISSION_UPDATE) {
$p .= 'NV'; // Renameable, Movable
if ($parent) {
if (self::canRename($info, $parent)) {
$p .= 'N'; // Renamable
}
if ($permissions & Constants::PERMISSION_UPDATE) {
$p .= 'V'; // Movable
}
} else {
if ($permissions & Constants::PERMISSION_UPDATE) {
$p .= 'NV'; // Renamable, Movable
}
}
// since we always add update permissions for the root of movable mounts
@ -76,4 +86,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();
}
}