|
35 | 35 | namespace OCA\DAV\Connector\Sabre;
|
36 | 36 |
|
37 | 37 | use OC\AppFramework\Http\Request;
|
38 |
| -use OC\FilesMetadata\Model\MetadataValueWrapper; |
39 | 38 | use OCP\Constants;
|
40 | 39 | use OCP\Files\ForbiddenException;
|
41 | 40 | use OCP\Files\StorageNotAvailableException;
|
| 41 | +use OCP\FilesMetadata\Exceptions\FilesMetadataException; |
42 | 42 | use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
|
43 | 43 | use OCP\FilesMetadata\IFilesMetadataManager;
|
44 | 44 | use OCP\FilesMetadata\Model\IMetadataValueWrapper;
|
@@ -530,65 +530,131 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
|
530 | 530 | return true;
|
531 | 531 | });
|
532 | 532 |
|
| 533 | + $this->handleUpdatePropertiesMetadata($propPatch, $node); |
533 | 534 |
|
534 |
| - /** @var IFilesMetadataManager */ |
535 |
| - $filesMetadataManager = \OCP\Server::get(IFilesMetadataManager::class); |
| 535 | + /** |
| 536 | + * Disable modification of the displayname property for files and |
| 537 | + * folders via PROPPATCH. See PROPFIND for more information. |
| 538 | + */ |
| 539 | + $propPatch->handle(self::DISPLAYNAME_PROPERTYNAME, function ($displayName) { |
| 540 | + return 403; |
| 541 | + }); |
| 542 | + } |
| 543 | + |
| 544 | + |
| 545 | + /** |
| 546 | + * handle the update of metadata from PROPPATCH requests |
| 547 | + * |
| 548 | + * @param PropPatch $propPatch |
| 549 | + * @param Node $node |
| 550 | + * |
| 551 | + * @throws FilesMetadataException |
| 552 | + */ |
| 553 | + private function handleUpdatePropertiesMetadata(PropPatch $propPatch, Node $node): void { |
| 554 | + $userId = $this->userSession->getUser()?->getUID(); |
| 555 | + if (null === $userId) { |
| 556 | + return; |
| 557 | + } |
| 558 | + |
| 559 | + $accessRight = $this->getMetadataFileAccessRight($node, $userId); |
| 560 | + $filesMetadataManager = $this->initFilesMetadataManager(); |
536 | 561 | $knownMetadata = $filesMetadataManager->getKnownMetadata();
|
537 | 562 |
|
538 | 563 | foreach ($propPatch->getRemainingMutations() as $mutation) {
|
539 | 564 | if (!str_starts_with($mutation, self::FILE_METADATA_PREFIX)) {
|
540 | 565 | continue;
|
541 | 566 | }
|
542 | 567 |
|
543 |
| - $propPatch->handle($mutation, function (mixed $value) use ($knownMetadata, $node, $mutation, $filesMetadataManager): bool { |
544 |
| - $metadata = $filesMetadataManager->getMetadata((int)$node->getFileId(), true); |
545 |
| - $metadataKey = substr($mutation, strlen(self::FILE_METADATA_PREFIX)); |
| 568 | + $propPatch->handle( |
| 569 | + $mutation, |
| 570 | + function (mixed $value) use ($accessRight, $knownMetadata, $node, $mutation, $filesMetadataManager): bool { |
| 571 | + $metadata = $filesMetadataManager->getMetadata((int)$node->getFileId(), true); |
| 572 | + $metadataKey = substr($mutation, strlen(self::FILE_METADATA_PREFIX)); |
546 | 573 |
|
547 |
| - // If the metadata is unknown, it defaults to string. |
548 |
| - try { |
549 |
| - $type = $knownMetadata->getType($metadataKey); |
550 |
| - } catch (FilesMetadataNotFoundException) { |
551 |
| - $type = IMetadataValueWrapper::TYPE_STRING; |
552 |
| - } |
| 574 | + // confirm metadata key is editable via PROPPATCH |
| 575 | + if ($knownMetadata->getEditPermission($metadataKey) < $accessRight) { |
| 576 | + throw new FilesMetadataException('you do not have enough rights to update \'' . $metadataKey . '\' on this node'); |
| 577 | + } |
| 578 | + |
| 579 | + // If the metadata is unknown, it defaults to string. |
| 580 | + try { |
| 581 | + $type = $knownMetadata->getType($metadataKey); |
| 582 | + } catch (FilesMetadataNotFoundException) { |
| 583 | + $type = IMetadataValueWrapper::TYPE_STRING; |
| 584 | + } |
| 585 | + |
| 586 | + switch ($type) { |
| 587 | + case IMetadataValueWrapper::TYPE_STRING: |
| 588 | + $metadata->setString($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
| 589 | + break; |
| 590 | + case IMetadataValueWrapper::TYPE_INT: |
| 591 | + $metadata->setInt($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
| 592 | + break; |
| 593 | + case IMetadataValueWrapper::TYPE_FLOAT: |
| 594 | + $metadata->setFloat($metadataKey, $value); |
| 595 | + break; |
| 596 | + case IMetadataValueWrapper::TYPE_BOOL: |
| 597 | + $metadata->setBool($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
| 598 | + break; |
| 599 | + case IMetadataValueWrapper::TYPE_ARRAY: |
| 600 | + $metadata->setArray($metadataKey, $value); |
| 601 | + break; |
| 602 | + case IMetadataValueWrapper::TYPE_STRING_LIST: |
| 603 | + $metadata->setStringList( |
| 604 | + $metadataKey, $value, $knownMetadata->isIndex($metadataKey) |
| 605 | + ); |
| 606 | + break; |
| 607 | + case IMetadataValueWrapper::TYPE_INT_LIST: |
| 608 | + $metadata->setIntList( |
| 609 | + $metadataKey, $value, $knownMetadata->isIndex($metadataKey) |
| 610 | + ); |
| 611 | + break; |
| 612 | + } |
| 613 | + |
| 614 | + $filesMetadataManager->saveMetadata($metadata); |
553 | 615 |
|
554 |
| - switch ($type) { |
555 |
| - case IMetadataValueWrapper::TYPE_STRING: |
556 |
| - $metadata->setString($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
557 |
| - break; |
558 |
| - case IMetadataValueWrapper::TYPE_INT: |
559 |
| - $metadata->setInt($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
560 |
| - break; |
561 |
| - case IMetadataValueWrapper::TYPE_FLOAT: |
562 |
| - $metadata->setFloat($metadataKey, $value); |
563 |
| - break; |
564 |
| - case IMetadataValueWrapper::TYPE_BOOL: |
565 |
| - $metadata->setBool($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
566 |
| - break; |
567 |
| - case IMetadataValueWrapper::TYPE_ARRAY: |
568 |
| - $metadata->setArray($metadataKey, $value); |
569 |
| - break; |
570 |
| - case IMetadataValueWrapper::TYPE_STRING_LIST: |
571 |
| - $metadata->setStringList($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
572 |
| - break; |
573 |
| - case IMetadataValueWrapper::TYPE_INT_LIST: |
574 |
| - $metadata->setIntList($metadataKey, $value, $knownMetadata->isIndex($metadataKey)); |
575 |
| - break; |
| 616 | + return true; |
576 | 617 | }
|
| 618 | + ); |
| 619 | + } |
| 620 | + } |
577 | 621 |
|
578 |
| - $filesMetadataManager->saveMetadata($metadata); |
579 |
| - return true; |
580 |
| - }); |
| 622 | + /** |
| 623 | + * init default internal metadata |
| 624 | + * |
| 625 | + * @return IFilesMetadataManager |
| 626 | + */ |
| 627 | + private function initFilesMetadataManager(): IFilesMetadataManager { |
| 628 | + /** @var IFilesMetadataManager $manager */ |
| 629 | + $manager = \OCP\Server::get(IFilesMetadataManager::class); |
| 630 | + $manager->initMetadata('files-live-photo', IMetadataValueWrapper::TYPE_STRING, false, IMetadataValueWrapper::EDIT_REQ_OWNERSHIP); |
| 631 | + |
| 632 | + return $manager; |
| 633 | + } |
| 634 | + |
| 635 | + /** |
| 636 | + * based on owner and shares, returns the bottom limit to update related metadata |
| 637 | + * |
| 638 | + * @param Node $node |
| 639 | + * @param string $userId |
| 640 | + * |
| 641 | + * @return int |
| 642 | + */ |
| 643 | + private function getMetadataFileAccessRight(Node $node, string $userId): int { |
| 644 | + if ($node->getOwner()?->getUID() === $userId) { |
| 645 | + return IMetadataValueWrapper::EDIT_REQ_OWNERSHIP; |
| 646 | + } else { |
| 647 | + $filePermissions = $node->getSharePermissions($userId); |
| 648 | + if ($filePermissions & Constants::PERMISSION_UPDATE) { |
| 649 | + return IMetadataValueWrapper::EDIT_REQ_WRITE_PERMISSION; |
| 650 | + } |
581 | 651 | }
|
582 | 652 |
|
583 |
| - /** |
584 |
| - * Disable modification of the displayname property for files and |
585 |
| - * folders via PROPPATCH. See PROPFIND for more information. |
586 |
| - */ |
587 |
| - $propPatch->handle(self::DISPLAYNAME_PROPERTYNAME, function ($displayName) { |
588 |
| - return 403; |
589 |
| - }); |
| 653 | + return IMetadataValueWrapper::EDIT_REQ_READ_PERMISSION; |
590 | 654 | }
|
591 | 655 |
|
| 656 | + |
| 657 | + |
592 | 658 | /**
|
593 | 659 | * @param string $filePath
|
594 | 660 | * @param \Sabre\DAV\INode $node
|
|
0 commit comments