diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2023-11-14 10:01:29 -0100 |
---|---|---|
committer | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2023-11-14 14:38:53 +0100 |
commit | 847c687a06ccd968936e5e6ed249840180c8e187 (patch) | |
tree | 4eb88b1ca5b212712cc7435e9cb3e1f65f620b79 /apps/dav/lib/Connector/Sabre | |
parent | 281ac508694d66a1598dc76a60480b81e88cab67 (diff) | |
download | nextcloud-server-847c687a06ccd968936e5e6ed249840180c8e187.tar.gz nextcloud-server-847c687a06ccd968936e5e6ed249840180c8e187.zip |
metadata must be set as editable for PROPPATCH
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
Diffstat (limited to 'apps/dav/lib/Connector/Sabre')
-rw-r--r-- | apps/dav/lib/Connector/Sabre/FilesPlugin.php | 154 |
1 files changed, 110 insertions, 44 deletions
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index c52805c9548..8c467f11d0c 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -35,10 +35,10 @@ namespace OCA\DAV\Connector\Sabre; use OC\AppFramework\Http\Request; -use OC\FilesMetadata\Model\MetadataValueWrapper; use OCP\Constants; use OCP\Files\ForbiddenException; use OCP\Files\StorageNotAvailableException; +use OCP\FilesMetadata\Exceptions\FilesMetadataException; use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException; use OCP\FilesMetadata\IFilesMetadataManager; use OCP\FilesMetadata\Model\IMetadataValueWrapper; @@ -530,9 +530,34 @@ class FilesPlugin extends ServerPlugin { return true; }); + $this->handleUpdatePropertiesMetadata($propPatch, $node); - /** @var IFilesMetadataManager */ - $filesMetadataManager = \OCP\Server::get(IFilesMetadataManager::class); + /** + * Disable modification of the displayname property for files and + * folders via PROPPATCH. See PROPFIND for more information. + */ + $propPatch->handle(self::DISPLAYNAME_PROPERTYNAME, function ($displayName) { + return 403; + }); + } + + + /** + * handle the update of metadata from PROPPATCH requests + * + * @param PropPatch $propPatch + * @param Node $node + * + * @throws FilesMetadataException + */ + private function handleUpdatePropertiesMetadata(PropPatch $propPatch, Node $node): void { + $userId = $this->userSession->getUser()?->getUID(); + if (null === $userId) { + return; + } + + $accessRight = $this->getMetadataFileAccessRight($node, $userId); + $filesMetadataManager = $this->initFilesMetadataManager(); $knownMetadata = $filesMetadataManager->getKnownMetadata(); foreach ($propPatch->getRemainingMutations() as $mutation) { @@ -540,55 +565,96 @@ class FilesPlugin extends ServerPlugin { continue; } - $propPatch->handle($mutation, function (mixed $value) use ($knownMetadata, $node, $mutation, $filesMetadataManager): bool { - $metadata = $filesMetadataManager->getMetadata((int)$node->getFileId(), true); - $metadataKey = substr($mutation, strlen(self::FILE_METADATA_PREFIX)); + $propPatch->handle( + $mutation, + function (mixed $value) use ($accessRight, $knownMetadata, $node, $mutation, $filesMetadataManager): bool { + $metadata = $filesMetadataManager->getMetadata((int)$node->getFileId(), true); + $metadataKey = substr($mutation, strlen(self::FILE_METADATA_PREFIX)); - // If the metadata is unknown, it defaults to string. - try { - $type = $knownMetadata->getType($metadataKey); - } catch (FilesMetadataNotFoundException) { - $type = IMetadataValueWrapper::TYPE_STRING; - } + // confirm metadata key is editable via PROPPATCH + if ($knownMetadata->getEditPermission($metadataKey) < $accessRight) { + throw new FilesMetadataException('you do not have enough rights to update \'' . $metadataKey . '\' on this node'); + } + + // If the metadata is unknown, it defaults to string. + try { + $type = $knownMetadata->getType($metadataKey); + } catch (FilesMetadataNotFoundException) { + $type = IMetadataValueWrapper::TYPE_STRING; + } + + switch ($type) { + case IMetadataValueWrapper::TYPE_STRING: + $metadata->setString($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); + break; + case IMetadataValueWrapper::TYPE_INT: + $metadata->setInt($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); + break; + case IMetadataValueWrapper::TYPE_FLOAT: + $metadata->setFloat($metadataKey, $value); + break; + case IMetadataValueWrapper::TYPE_BOOL: + $metadata->setBool($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); + break; + case IMetadataValueWrapper::TYPE_ARRAY: + $metadata->setArray($metadataKey, $value); + break; + case IMetadataValueWrapper::TYPE_STRING_LIST: + $metadata->setStringList( + $metadataKey, $value, $knownMetadata->isIndex($metadataKey) + ); + break; + case IMetadataValueWrapper::TYPE_INT_LIST: + $metadata->setIntList( + $metadataKey, $value, $knownMetadata->isIndex($metadataKey) + ); + break; + } + + $filesMetadataManager->saveMetadata($metadata); - switch ($type) { - case IMetadataValueWrapper::TYPE_STRING: - $metadata->setString($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); - break; - case IMetadataValueWrapper::TYPE_INT: - $metadata->setInt($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); - break; - case IMetadataValueWrapper::TYPE_FLOAT: - $metadata->setFloat($metadataKey, $value); - break; - case IMetadataValueWrapper::TYPE_BOOL: - $metadata->setBool($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); - break; - case IMetadataValueWrapper::TYPE_ARRAY: - $metadata->setArray($metadataKey, $value); - break; - case IMetadataValueWrapper::TYPE_STRING_LIST: - $metadata->setStringList($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); - break; - case IMetadataValueWrapper::TYPE_INT_LIST: - $metadata->setIntList($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); - break; + return true; } + ); + } + } - $filesMetadataManager->saveMetadata($metadata); - return true; - }); + /** + * init default internal metadata + * + * @return IFilesMetadataManager + */ + private function initFilesMetadataManager(): IFilesMetadataManager { + /** @var IFilesMetadataManager $manager */ + $manager = \OCP\Server::get(IFilesMetadataManager::class); + $manager->initMetadata('files-live-photo', IMetadataValueWrapper::TYPE_STRING, false, IMetadataValueWrapper::EDIT_REQ_OWNERSHIP); + + return $manager; + } + + /** + * based on owner and shares, returns the bottom limit to update related metadata + * + * @param Node $node + * @param string $userId + * + * @return int + */ + private function getMetadataFileAccessRight(Node $node, string $userId): int { + if ($node->getOwner()?->getUID() === $userId) { + return IMetadataValueWrapper::EDIT_REQ_OWNERSHIP; + } else { + $filePermissions = $node->getSharePermissions($userId); + if ($filePermissions & Constants::PERMISSION_UPDATE) { + return IMetadataValueWrapper::EDIT_REQ_WRITE_PERMISSION; + } } - /** - * Disable modification of the displayname property for files and - * folders via PROPPATCH. See PROPFIND for more information. - */ - $propPatch->handle(self::DISPLAYNAME_PROPERTYNAME, function ($displayName) { - return 403; - }); + return IMetadataValueWrapper::EDIT_REQ_READ_PERMISSION; } + + /** * @param string $filePath * @param \Sabre\DAV\INode $node |