diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php
index e4a4e8f595aef..581d5a1294801 100644
--- a/apps/files/lib/Service/OwnershipTransferService.php
+++ b/apps/files/lib/Service/OwnershipTransferService.php
@@ -18,6 +18,7 @@
use OCA\Files\Exception\TransferOwnershipException;
use OCA\Files_External\Config\ConfigAdapter;
use OCP\Encryption\IManager as IEncryptionManager;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IHomeMountProvider;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\File;
@@ -30,6 +31,7 @@
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Server;
+use OCP\Share\Events\ShareTransferredEvent;
use OCP\Share\IManager as IShareManager;
use OCP\Share\IShare;
use Symfony\Component\Console\Helper\ProgressBar;
@@ -52,6 +54,7 @@ public function __construct(
private IUserManager $userManager,
private IFactory $l10nFactory,
private IRootFolder $rootFolder,
+ private IEventDispatcher $eventDispatcher,
) {
}
@@ -544,6 +547,7 @@ private function restoreShares(
} catch (\Throwable $e) {
$output->writeln('Could not restore share with id ' . $share->getId() . ':' . $e->getMessage() . ' : ' . $e->getTraceAsString() . '');
}
+ $this->eventDispatcher->dispatchTyped(new ShareTransferredEvent($share));
$progress->advance();
}
$progress->finish();
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index 4f0848b60bd33..da4984d378533 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -48,7 +48,6 @@
use OCP\Files\Events\BeforeDirectFileDownloadEvent;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\Events\Node\BeforeNodeReadEvent;
-use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Group\Events\GroupChangedEvent;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\Group\Events\UserAddedEvent;
@@ -57,6 +56,7 @@
use OCP\IGroup;
use OCP\Share\Events\BeforeShareDeletedEvent;
use OCP\Share\Events\ShareCreatedEvent;
+use OCP\Share\Events\ShareTransferredEvent;
use OCP\User\Events\UserChangedEvent;
use OCP\User\Events\UserDeletedEvent;
use OCP\Util;
@@ -117,10 +117,10 @@ function () use ($c) {
// Update mounts
$context->registerEventListener(ShareCreatedEvent::class, SharesUpdatedListener::class);
$context->registerEventListener(BeforeShareDeletedEvent::class, SharesUpdatedListener::class);
+ $context->registerEventListener(ShareTransferredEvent::class, SharesUpdatedListener::class);
$context->registerEventListener(UserAddedEvent::class, SharesUpdatedListener::class);
$context->registerEventListener(UserRemovedEvent::class, SharesUpdatedListener::class);
$context->registerEventListener(UserShareAccessUpdatedEvent::class, SharesUpdatedListener::class);
- $context->registerEventListener(FilesystemTornDownEvent::class, SharesUpdatedListener::class);
$context->registerConfigLexicon(ConfigLexicon::class);
}
diff --git a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php
index b7b85689f8ad7..9cbea36dbaa56 100644
--- a/apps/files_sharing/lib/Listener/SharesUpdatedListener.php
+++ b/apps/files_sharing/lib/Listener/SharesUpdatedListener.php
@@ -11,73 +11,81 @@
use OCA\Files_Sharing\Event\UserShareAccessUpdatedEvent;
use OCA\Files_Sharing\MountProvider;
use OCA\Files_Sharing\ShareTargetValidator;
-use OCP\Cache\CappedMemoryCache;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IUserMountCache;
-use OCP\Files\Events\Node\FilesystemTornDownEvent;
+use OCP\Files\Storage\IStorageFactory;
use OCP\Group\Events\UserAddedEvent;
use OCP\Group\Events\UserRemovedEvent;
use OCP\IUser;
use OCP\Share\Events\BeforeShareDeletedEvent;
use OCP\Share\Events\ShareCreatedEvent;
+use OCP\Share\Events\ShareTransferredEvent;
use OCP\Share\IManager;
/**
* Listen to various events that can change what shares a user has access to
*
- * @template-implements IEventListener
+ * @template-implements IEventListener
*/
class SharesUpdatedListener implements IEventListener {
- private CappedMemoryCache $updatedUsers;
-
public function __construct(
private readonly IManager $shareManager,
private readonly IUserMountCache $userMountCache,
private readonly MountProvider $shareMountProvider,
private readonly ShareTargetValidator $shareTargetValidator,
+ private readonly IStorageFactory $storageFactory,
) {
- $this->updatedUsers = new CappedMemoryCache();
}
public function handle(Event $event): void {
- if ($event instanceof FilesystemTornDownEvent) {
- $this->updatedUsers = new CappedMemoryCache();
- }
if ($event instanceof UserShareAccessUpdatedEvent) {
foreach ($event->getUsers() as $user) {
- $this->updateForUser($user);
+ $this->updateForUser($user, true);
}
}
if ($event instanceof UserAddedEvent || $event instanceof UserRemovedEvent) {
- $this->updateForUser($event->getUser());
+ $this->updateForUser($event->getUser(), true);
}
- if ($event instanceof ShareCreatedEvent || $event instanceof BeforeShareDeletedEvent) {
+ if (
+ $event instanceof ShareCreatedEvent ||
+ $event instanceof ShareTransferredEvent
+ ) {
foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) {
- $this->updateForUser($user);
+ $this->updateForUser($user, true);
}
}
- }
-
- private function updateForUser(IUser $user): void {
- if (isset($this->updatedUsers[$user->getUID()])) {
- return;
+ if ($event instanceof BeforeShareDeletedEvent) {
+ foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) {
+ $this->updateForUser($user, false, [$event->getShare()]);
+ }
}
- $this->updatedUsers[$user->getUID()] = true;
+ }
+ private function updateForUser(IUser $user, bool $verifyMountPoints, array $ignoreShares = []): void {
$cachedMounts = $this->userMountCache->getMountsForUser($user);
+ $shareMounts = array_filter($cachedMounts, fn (ICachedMountInfo $mount) => $mount->getMountProvider() === MountProvider::class);
$mountPoints = array_map(fn (ICachedMountInfo $mount) => $mount->getMountPoint(), $cachedMounts);
$mountsByPath = array_combine($mountPoints, $cachedMounts);
- $shares = $this->shareMountProvider->getSuperSharesForUser($user);
+ $shares = $this->shareMountProvider->getSuperSharesForUser($user, $ignoreShares);
+ $mountsChanged = count($shares) !== count($shareMounts);
foreach ($shares as &$share) {
[$parentShare, $groupedShares] = $share;
$mountPoint = '/' . $user->getUID() . '/files/' . trim($parentShare->getTarget(), '/') . '/';
$mountKey = $parentShare->getNodeId() . '::' . $mountPoint;
if (!isset($cachedMounts[$mountKey])) {
- $this->shareTargetValidator->verifyMountPoint($user, $parentShare, $mountsByPath, $groupedShares);
+ $mountsChanged = true;
+ if ($verifyMountPoints) {
+ $this->shareTargetValidator->verifyMountPoint($user, $parentShare, $mountsByPath, $groupedShares);
+ }
}
}
+
+ if ($mountsChanged) {
+ $newMounts = $this->shareMountProvider->getMountsFromSuperShares($user, $shares, $this->storageFactory);
+ $this->userMountCache->registerMounts($user, $newMounts, [MountProvider::class]);
+ }
}
}
diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php
index e9575dbac26c3..befb4fd0603a7 100644
--- a/apps/files_sharing/lib/MountProvider.php
+++ b/apps/files_sharing/lib/MountProvider.php
@@ -13,6 +13,7 @@
use OCA\Files_Sharing\Event\ShareMountedEvent;
use OCP\Cache\CappedMemoryCache;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Config\IAuthoritativeMountProvider;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Config\IPartialMountProvider;
use OCP\Files\Mount\IMountManager;
@@ -28,7 +29,7 @@
use function count;
-class MountProvider implements IMountProvider, IPartialMountProvider {
+class MountProvider implements IMountProvider, IAuthoritativeMountProvider, IPartialMountProvider {
/**
* @param IConfig $config
* @param IManager $shareManager
@@ -57,9 +58,10 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {
/**
* @param IUser $user
+ * @param list $excludeShares
* @return list}> Tuple of [superShare, groupedShares]
*/
- public function getSuperSharesForUser(IUser $user): array {
+ public function getSuperSharesForUser(IUser $user, array $excludeShares = []): array {
$userId = $user->getUID();
$shares = $this->mergeIterables(
$this->shareManager->getSharedWith($userId, IShare::TYPE_USER, null, -1),
@@ -69,7 +71,8 @@ public function getSuperSharesForUser(IUser $user): array {
$this->shareManager->getSharedWith($userId, IShare::TYPE_DECK, null, -1),
);
- $shares = $this->filterShares($shares, $userId);
+ $excludeShareIds = array_map(fn (IShare $share) => $share->getFullId(), $excludeShares);
+ $shares = $this->filterShares($shares, $userId, $excludeShareIds);
return $this->buildSuperShares($shares, $user);
}
@@ -340,14 +343,16 @@ public function getMountsFromSuperShares(
* user has no permissions.
*
* @param iterable $shares
+ * @param list $excludeShareIds
* @return iterable
*/
- private function filterShares(iterable $shares, string $userId): iterable {
+ private function filterShares(iterable $shares, string $userId, array $excludeShareIds = []): iterable {
foreach ($shares as $share) {
if (
$share->getPermissions() > 0
&& $share->getShareOwner() !== $userId
&& $share->getSharedBy() !== $userId
+ && !in_array($share->getFullId(), $excludeShareIds)
) {
yield $share;
}
diff --git a/lib/public/Share/Events/ShareTransferredEvent.php b/lib/public/Share/Events/ShareTransferredEvent.php
new file mode 100644
index 0000000000000..d5964b780b156
--- /dev/null
+++ b/lib/public/Share/Events/ShareTransferredEvent.php
@@ -0,0 +1,33 @@
+share;
+ }
+}