Skip to content

Commit 3e49c70

Browse files
committed
fix: handle share moves
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent 83a9ccf commit 3e49c70

File tree

10 files changed

+106
-6
lines changed

10 files changed

+106
-6
lines changed

apps/files_sharing/lib/AppInfo/Application.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
use OCP\IGroup;
5858
use OCP\Share\Events\BeforeShareDeletedEvent;
5959
use OCP\Share\Events\ShareCreatedEvent;
60+
use OCP\Share\Events\ShareMovedEvent;
6061
use OCP\Share\Events\ShareTransferredEvent;
6162
use OCP\User\Events\UserChangedEvent;
6263
use OCP\User\Events\UserDeletedEvent;
@@ -125,6 +126,7 @@ function () use ($c) {
125126
$context->registerEventListener(BeforeGroupDeletedEvent::class, SharesUpdatedListener::class);
126127
$context->registerEventListener(GroupDeletedEvent::class, SharesUpdatedListener::class);
127128
$context->registerEventListener(UserShareAccessUpdatedEvent::class, SharesUpdatedListener::class);
129+
$context->registerEventListener(ShareMovedEvent::class, SharesUpdatedListener::class);
128130
$context->registerEventListener(UserHomeSetupEvent::class, UserHomeSetupListener::class);
129131

130132
$context->registerConfigLexicon(ConfigLexicon::class);

apps/files_sharing/lib/Listener/SharesUpdatedListener.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use OCP\IUser;
2424
use OCP\Share\Events\BeforeShareDeletedEvent;
2525
use OCP\Share\Events\ShareCreatedEvent;
26+
use OCP\Share\Events\ShareMovedEvent;
2627
use OCP\Share\Events\ShareTransferredEvent;
2728
use OCP\Share\IManager;
2829
use Psr\Clock\ClockInterface;
@@ -31,7 +32,7 @@
3132
* Listen to various events that can change what shares a user has access to
3233
*
3334
* @psalm-type GroupEvents = UserAddedEvent|UserRemovedEvent|GroupDeletedEvent|BeforeGroupDeletedEvent
34-
* @template-implements IEventListener<GroupEvents|ShareCreatedEvent|ShareTransferredEvent|BeforeShareDeletedEvent|UserShareAccessUpdatedEvent>
35+
* @template-implements IEventListener<GroupEvents|ShareCreatedEvent|ShareTransferredEvent|BeforeShareDeletedEvent|UserShareAccessUpdatedEvent|ShareMovedEvent>
3536
*/
3637
class SharesUpdatedListener implements IEventListener {
3738
/**
@@ -87,6 +88,14 @@ public function handle(Event $event): void {
8788
}
8889
}
8990
}
91+
if ($event instanceof ShareMovedEvent) {
92+
$share = $event->getShare();
93+
foreach ($this->shareManager->getUsersForShare($share) as $user) {
94+
$this->markOrRun($user, function () use ($user, $share) {
95+
$this->shareUpdater->updateForMovedShare($user, $share);
96+
});
97+
}
98+
}
9099
if ($event instanceof BeforeShareDeletedEvent) {
91100
$share = $event->getShare();
92101
foreach ($this->shareManager->getUsersForShare($share) as $user) {

apps/files_sharing/lib/ShareRecipientUpdater.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function updateForUser(IUser $user): void {
4747
$mountsChanged = count($shares) !== count($shareMounts);
4848
foreach ($shares as $share) {
4949
[$parentShare, $groupedShares] = $share;
50-
$mountPoint = '/' . $user->getUID() . '/files/' . trim($parentShare->getTarget(), '/') . '/';
50+
$mountPoint = $this->getMountPointFromTarget($user, $parentShare->getTarget());
5151
$mountKey = $parentShare->getNodeId() . '::' . $mountPoint;
5252
if (!isset($cachedMounts[$mountKey])) {
5353
$mountsChanged = true;
@@ -72,17 +72,34 @@ public function updateForAddedShare(IUser $user, IShare $share): void {
7272
$mountsByPath = array_combine($mountPoints, $cachedMounts);
7373

7474
$target = $this->shareTargetValidator->verifyMountPoint($user, $share, $mountsByPath, [$share]);
75-
$mountPoint = '/' . $user->getUID() . '/files/' . trim($target, '/') . '/';
75+
$mountPoint = $this->getMountPointFromTarget($user, $target);
7676

7777
$this->userMountCache->addMount($user, $mountPoint, $share->getNode()->getData(), MountProvider::class);
7878
}
7979

80+
private function getMountPointFromTarget(IUser $user, string $target): string {
81+
return '/' . $user->getUID() . '/files/' . trim($target, '/') . '/';
82+
}
83+
8084
/**
8185
* Process a single deleted share for a user
8286
*/
8387
public function updateForDeletedShare(IUser $user, IShare $share): void {
84-
$mountPoint = '/' . $user->getUID() . '/files/' . trim($share->getTarget(), '/') . '/';
88+
$this->userMountCache->removeMount($this->getMountPointFromTarget($user, $share->getTarget()));
89+
}
8590

86-
$this->userMountCache->removeMount($mountPoint);
91+
/**
92+
* Process a single moved share for a user
93+
*/
94+
public function updateForMovedShare(IUser $user, IShare $share): void {
95+
$originalTarget = $share->getOriginalTarget();
96+
if ($originalTarget != null) {
97+
$newMountPoint = $this->getMountPointFromTarget($user, $share->getTarget());
98+
$oldMountPoint = $this->getMountPointFromTarget($user, $originalTarget);
99+
$this->userMountCache->removeMount($oldMountPoint);
100+
$this->userMountCache->addMount($user, $newMountPoint, $share->getNode()->getData(), MountProvider::class);
101+
} else {
102+
$this->updateForUser($user);
103+
}
87104
}
88105
}

build/integration/sharing_features/sharing-v1-part4.feature

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,15 @@ Scenario: User added/removed to group share with marking
414414
| /user0/files/textfile0 (2).txt/ |
415415
When Connecting to dav endpoint
416416
Then Share mounts for "user0" are empty
417+
418+
Scenario: Share moved without marking
419+
Given As an "admin"
420+
And user "user0" exists
421+
And user "user1" exists
422+
And file "textfile0.txt" of user "user1" is shared with user "user0"
423+
And As an "user0"
424+
Then Share mounts for "user0" match
425+
| /user0/files/textfile0 (2).txt/ |
426+
When User "user0" moves file "/textfile0 (2).txt" to "/target.txt"
427+
Then Share mounts for "user0" match
428+
| /user0/files/target.txt/ |

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,7 @@
851851
'OCP\\Share\\Events\\ShareCreatedEvent' => $baseDir . '/lib/public/Share/Events/ShareCreatedEvent.php',
852852
'OCP\\Share\\Events\\ShareDeletedEvent' => $baseDir . '/lib/public/Share/Events/ShareDeletedEvent.php',
853853
'OCP\\Share\\Events\\ShareDeletedFromSelfEvent' => $baseDir . '/lib/public/Share/Events/ShareDeletedFromSelfEvent.php',
854+
'OCP\\Share\\Events\\ShareMovedEvent' => $baseDir . '/lib/public/Share/Events/ShareMovedEvent.php',
854855
'OCP\\Share\\Events\\ShareTransferredEvent' => $baseDir . '/lib/public/Share/Events/ShareTransferredEvent.php',
855856
'OCP\\Share\\Events\\VerifyMountPointEvent' => $baseDir . '/lib/public/Share/Events/VerifyMountPointEvent.php',
856857
'OCP\\Share\\Exceptions\\AlreadySharedException' => $baseDir . '/lib/public/Share/Exceptions/AlreadySharedException.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
892892
'OCP\\Share\\Events\\ShareCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareCreatedEvent.php',
893893
'OCP\\Share\\Events\\ShareDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareDeletedEvent.php',
894894
'OCP\\Share\\Events\\ShareDeletedFromSelfEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareDeletedFromSelfEvent.php',
895+
'OCP\\Share\\Events\\ShareMovedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareMovedEvent.php',
895896
'OCP\\Share\\Events\\ShareTransferredEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareTransferredEvent.php',
896897
'OCP\\Share\\Events\\VerifyMountPointEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/VerifyMountPointEvent.php',
897898
'OCP\\Share\\Exceptions\\AlreadySharedException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/AlreadySharedException.php',

lib/private/Share20/Manager.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
use OCP\Share\Events\ShareCreatedEvent;
5252
use OCP\Share\Events\ShareDeletedEvent;
5353
use OCP\Share\Events\ShareDeletedFromSelfEvent;
54+
use OCP\Share\Events\ShareMovedEvent;
5455
use OCP\Share\Exceptions\AlreadySharedException;
5556
use OCP\Share\Exceptions\GenericShareException;
5657
use OCP\Share\Exceptions\ShareNotFound;
@@ -1200,7 +1201,11 @@ public function moveShare(IShare $share, string $recipientId): IShare {
12001201
[$providerId,] = $this->splitFullId($share->getFullId());
12011202
$provider = $this->factory->getProvider($providerId);
12021203

1203-
return $provider->move($share, $recipientId);
1204+
$result = $provider->move($share, $recipientId);
1205+
1206+
$this->dispatchEvent(new ShareMovedEvent($share), 'share moved');
1207+
1208+
return $result;
12041209
}
12051210

12061211
#[Override]

lib/private/Share20/Share.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class Share implements IShare {
6161
private ?int $parent = null;
6262
/** @var string */
6363
private $target;
64+
/** @var string */
65+
private ?string $originalTarget = null;
6466
/** @var \DateTime */
6567
private $shareTime;
6668
/** @var bool */
@@ -513,10 +515,21 @@ public function getParent(): ?int {
513515
* @inheritdoc
514516
*/
515517
public function setTarget($target) {
518+
// if the target is changed, save the original target
519+
if ($this->target && !$this->originalTarget) {
520+
$this->originalTarget = $this->target;
521+
}
516522
$this->target = $target;
517523
return $this;
518524
}
519525

526+
/**
527+
* Return the original target, if this share was moved
528+
*/
529+
public function getOriginalTarget(): ?string {
530+
return $this->originalTarget;
531+
}
532+
520533
/**
521534
* @inheritdoc
522535
*/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OCP\Share\Events;
10+
11+
use OCP\EventDispatcher\Event;
12+
use OCP\Share\IShare;
13+
14+
/**
15+
* @since 33.0.0
16+
*/
17+
class ShareMovedEvent extends Event {
18+
/**
19+
* @since 33.0.0
20+
*/
21+
public function __construct(
22+
private readonly IShare $share,
23+
) {
24+
parent::__construct();
25+
}
26+
27+
/**
28+
* @since 33.0.0
29+
*/
30+
public function getShare(): IShare {
31+
return $this->share;
32+
}
33+
}

lib/public/Share/IShare.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,13 @@ public function getParent(): ?int;
545545
*/
546546
public function setTarget($target);
547547

548+
/**
549+
* Return the original target, if this share was moved
550+
*
551+
* @since 33.0.0
552+
*/
553+
public function getOriginalTarget(): ?string;
554+
548555
/**
549556
* Get the target path of this share relative to the recipients user folder.
550557
*

0 commit comments

Comments
 (0)