Skip to content

Commit

Permalink
fix(sharing): Ensure download restrictions are not dropped
Browse files Browse the repository at this point in the history
When a user receives a share with share-permissions but also with

download restrictions (hide download or the modern download permission attribute),

then re-shares of that share must always also include those restrictions.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>

[skip ci]
  • Loading branch information
susnux authored and backportbot[bot] committed Feb 4, 2025
1 parent 3d9d99d commit c5b3868
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 68 deletions.
45 changes: 31 additions & 14 deletions apps/files_sharing/lib/Controller/ShareAPIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ public function createShare(
}

$share->setShareType($shareType);
$this->checkInheritedAttributes($share);

if ($note !== '') {
$share->setNote($note);
Expand Down Expand Up @@ -1261,7 +1262,6 @@ public function updateShare(
if ($attributes !== null) {
$share = $this->setShareAttributes($share, $attributes);
}
$this->checkInheritedAttributes($share);

// Handle mail send
if ($sendMail === 'true' || $sendMail === 'false') {
Expand Down Expand Up @@ -1345,6 +1345,7 @@ public function updateShare(
}

try {
$this->checkInheritedAttributes($share);
$share = $this->shareManager->updateShare($share);
} catch (HintException $e) {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
Expand Down Expand Up @@ -2047,20 +2048,18 @@ private function checkInheritedAttributes(IShare $share): void {
if (!$share->getSharedBy()) {
return; // Probably in a test
}

$canDownload = false;
$hideDownload = true;

$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
$node = $userFolder->getFirstNodeById($share->getNodeId());
if (!$node) {
return;
}
if ($node->getStorage()->instanceOfStorage(SharedStorage::class)) {
$storage = $node->getStorage();
if ($storage instanceof Wrapper) {
$storage = $storage->getInstanceOfStorage(SharedStorage::class);
if ($storage === null) {
throw new \RuntimeException('Should not happen, instanceOfStorage but getInstanceOfStorage return null');
}
} else {
throw new \RuntimeException('Should not happen, instanceOfStorage but not a wrapper');
$nodes = $userFolder->getById($share->getNodeId());
foreach ($nodes as $node) {
// Owner always can download it - so allow it and break
if ($node->getOwner()?->getUID() === $share->getSharedBy()) {
$canDownload = true;
$hideDownload = false;
break;
}
/** @var \OCA\Files_Sharing\SharedStorage $storage */
$inheritedAttributes = $storage->getShare()->getAttributes();
Expand All @@ -2071,6 +2070,24 @@ private function checkInheritedAttributes(IShare $share): void {
$attributes->setAttribute('permissions', 'download', false);
$share->setAttributes($attributes);
}

/** @var SharedStorage $storage */
$originalShare = $storage->getShare();
$inheritedAttributes = $originalShare->getAttributes();
// hide if hidden and also the current share enforces hide (can only be false if one share is false or user is owner)
$hideDownload = $hideDownload && $originalShare->getHideDownload();
// allow download if already allowed by previous share or when the current share allows downloading
$canDownload = $canDownload || $inheritedAttributes === null || $inheritedAttributes->getAttribute('permissions', 'download') !== false;
}
}

if ($hideDownload || !$canDownload) {
$share->setHideDownload(true);

if (!$canDownload) {
$attributes = $share->getAttributes() ?? $share->newAttributes();
$attributes->setAttribute('permissions', 'download', false);
$share->setAttributes($attributes);
}
}
}
Expand Down
Loading

0 comments on commit c5b3868

Please sign in to comment.