@@ -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