Skip to content

Commit 8155e8c

Browse files
committed
feat: allow users with "native" access to make some changes to shares
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent a150638 commit 8155e8c

2 files changed

Lines changed: 36 additions & 14 deletions

File tree

‎lib/private/Sharing/SharingBackend.php‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ private function list(
603603
} else {
604604
$filterSourceType = null;
605605
}
606+
606607
/** @var array<class-string<IShareRecipientType>, list<string>> $recipientTypeValues */
607608
$recipientTypeValues = [];
608609

@@ -896,9 +897,11 @@ private function list(
896897
if ($share['owner']->isCurrentUser($accessContext)) {
897898
continue;
898899
}
900+
899901
if ($userHasDirectAccess) {
900902
continue;
901903
}
904+
902905
$isAnyMatchingRecipient = false;
903906
foreach ($share['recipients'] as &$recipient) {
904907
$isMatchingRecipient = false;

‎lib/private/Sharing/SharingManager.php‎

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public function updateShareState(ShareAccessContext $accessContext, Share $share
190190
$time = $this->getTime();
191191
$this->backend->setLastUpdated([$share->id], $time);
192192

193-
$this->validateShareOwnerOperation($accessContext, $share->owner);
193+
$this->validateShareEditPermissions($accessContext, $share);
194194

195195
if ($state === ShareState::Active) {
196196
$this->assertShareCanBeActive($share);
@@ -217,7 +217,8 @@ public function updateShareState(ShareAccessContext $accessContext, Share $share
217217
public function addShareSource(ShareAccessContext $accessContext, Share $share, ShareSource $source): Share {
218218
$this->assertInTransaction();
219219

220-
$this->validateShareOwnerOperation($accessContext, $share->owner);
220+
// only the owner can add sources, otherwise a user could add sources others don't have access to, which would remove their access
221+
$this->validateShareEditPermissions($accessContext, $share, true);
221222

222223
if (($sourceType = $this->registry->getSourceTypes()[$source->class] ?? null) === null) {
223224
throw new RuntimeException('The source type is not registered: ' . $source->class);
@@ -260,7 +261,8 @@ public function addShareSource(ShareAccessContext $accessContext, Share $share,
260261
public function removeShareSource(ShareAccessContext $accessContext, Share $share, ShareSource $source): Share {
261262
$this->assertInTransaction();
262263

263-
$this->validateShareOwnerOperation($accessContext, $share->owner);
264+
// only the owner can remove sources, to mirror the "add source" permissions
265+
$this->validateShareEditPermissions($accessContext, $share, true);
264266

265267
$time = $this->getTime();
266268
$this->backend->setLastUpdated([$share->id], $time);
@@ -321,7 +323,7 @@ public function addShareRecipient(ShareAccessContext $accessContext, Share $shar
321323
$this->assertInTransaction();
322324

323325
try {
324-
$this->validateShareOwnerOperation($accessContext, $share->owner);
326+
$this->validateShareEditPermissions($accessContext, $share);
325327
} catch (ShareOperationForbiddenException) {
326328
$this->validatePermission($share, ReshareSharePermissionType::class);
327329
}
@@ -398,7 +400,7 @@ public function removeShareRecipient(ShareAccessContext $accessContext, Share $s
398400
$this->assertInTransaction();
399401

400402
try {
401-
$this->validateShareOwnerOperation($accessContext, $share->owner);
403+
$this->validateShareEditPermissions($accessContext, $share);
402404
} catch (ShareOperationForbiddenException) {
403405
// This does not allow removing own recipients. A user can only reject a share, but not remove it for the recipient.
404406
$this->validateReshareOperation($accessContext, $share, $recipient);
@@ -484,7 +486,7 @@ public function updateShareRecipientSecret(ShareAccessContext $accessContext, Sh
484486
$this->assertInTransaction();
485487

486488
try {
487-
$this->validateShareOwnerOperation($accessContext, $share->owner);
489+
$this->validateShareEditPermissions($accessContext, $share);
488490
} catch (ShareOperationForbiddenException) {
489491
$this->validateReshareOperation($accessContext, $share, $recipient);
490492
}
@@ -540,7 +542,7 @@ public function updateShareRecipientSecret(ShareAccessContext $accessContext, Sh
540542
public function updateShareProperty(ShareAccessContext $accessContext, Share $share, ShareProperty $property): Share {
541543
$this->assertInTransaction();
542544

543-
$this->validateShareOwnerOperation($accessContext, $share->owner);
545+
$this->validateShareEditPermissions($accessContext, $share);
544546

545547
if (($propertyType = $this->registry->getPropertyTypes()[$property->class] ?? null) === null) {
546548
throw new RuntimeException('The property is not registered: ' . $property->class);
@@ -577,7 +579,7 @@ public function updateShareProperty(ShareAccessContext $accessContext, Share $sh
577579
public function updateSharePermission(ShareAccessContext $accessContext, Share $share, SharePermission $permission): Share {
578580
$this->assertInTransaction();
579581

580-
$this->validateShareOwnerOperation($accessContext, $share->owner);
582+
$this->validateShareEditPermissions($accessContext, $share);
581583

582584
if (!isset($this->registry->getPermissionTypes()[$permission->class])) {
583585
throw new RuntimeException('The permission type is not registered: ' . $permission->class);
@@ -614,7 +616,7 @@ public function updateSharePermission(ShareAccessContext $accessContext, Share $
614616
public function selectSharePermissionPreset(ShareAccessContext $accessContext, Share $share, string $permissionPresetClass): Share {
615617
$this->assertInTransaction();
616618

617-
$this->validateShareOwnerOperation($accessContext, $share->owner);
619+
$this->validateShareEditPermissions($accessContext, $share);
618620

619621
if (($this->registry->getPermissionPresetCompatiblePermissionTypeClasses()[$permissionPresetClass] ?? null) === null) {
620622
throw new RuntimeException('The permission preset is not registered: ' . $permissionPresetClass);
@@ -654,7 +656,7 @@ public function deleteShare(ShareAccessContext $accessContext, Share $share): vo
654656

655657
// No need to update the last updated timestamp, because the share will be deleted anyway.
656658

657-
$this->validateShareOwnerOperation($accessContext, $share->owner);
659+
$this->validateShareEditPermissions($accessContext, $share);
658660

659661
$this->backend->deleteShare($share->id);
660662

@@ -710,19 +712,36 @@ private function assertInTransaction(): void {
710712
}
711713
}
712714

713-
// TODO: Support IShareOwnerlessMount
714-
715715
/**
716716
* @throws ShareOperationForbiddenException
717717
*/
718-
private function validateShareOwnerOperation(ShareAccessContext $accessContext, ShareUser $owner): void {
718+
private function validateShareEditPermissions(ShareAccessContext $accessContext, Share $share, bool $onlyOwner = false): void {
719719
if ($accessContext->overrideChecks) {
720720
return;
721721
}
722722

723-
if ($owner->instance !== null || !$accessContext->currentUser instanceof IUser || $owner->userId !== $accessContext->currentUser->getUID()) {
723+
if ($share->owner->instance !== null || !$accessContext->currentUser instanceof IUser) {
724+
throw new ShareOperationForbiddenException();
725+
}
726+
727+
if ($share->owner->userId === $accessContext->currentUser->getUID()) {
728+
return;
729+
}
730+
731+
if ($onlyOwner) {
724732
throw new ShareOperationForbiddenException();
725733
}
734+
735+
foreach ($share->sources as $source) {
736+
$sourceType = $this->registry->getSourceTypes()[$source->class] ?? null;
737+
if (!$sourceType) {
738+
throw new ShareOperationForbiddenException();
739+
}
740+
741+
if (!$sourceType->userHasDirectSharingAccessToSource($accessContext->currentUser, $source->value)) {
742+
throw new ShareOperationForbiddenException();
743+
}
744+
}
726745
}
727746

728747
/**

0 commit comments

Comments
 (0)