Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions apps/files_sharing/lib/Listener/SharesUpdatedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\Storage\IStorageFactory;
use OCP\Group\Events\UserAddedEvent;
use OCP\Group\Events\UserRemovedEvent;
use OCP\IUser;
Expand All @@ -36,50 +37,64 @@ public function __construct(
private readonly IUserMountCache $userMountCache,
private readonly MountProvider $shareMountProvider,
private readonly ShareTargetValidator $shareTargetValidator,
private readonly IStorageFactory $storageFactory,
) {
}
public function handle(Event $event): void {
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
|| $event instanceof ShareTransferredEvent
) {
foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) {
$this->updateForUser($user);
$this->updateForUser($user, true);
}
}
if ($event instanceof BeforeShareDeletedEvent) {
foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) {
$this->updateForUser($user, false, [$event->getShare()]);
}
}
}

private function updateForUser(IUser $user): void {
private function updateForUser(IUser $user, bool $verifyMountPoints, array $ignoreShares = []): void {
// prevent recursion
if (isset($this->inUpdate[$user->getUID()])) {
return;
}
$this->inUpdate[$user->getUID()] = true;

$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]);
}

unset($this->inUpdate[$user->getUID()]);
}
}
13 changes: 9 additions & 4 deletions apps/files_sharing/lib/MountProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OC\Files\View;
use OCA\Files_Sharing\Event\ShareMountedEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IAuthoritativeMountProvider;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Config\IPartialMountProvider;
use OCP\Files\Mount\IMountManager;
Expand All @@ -28,7 +29,7 @@

use function count;

class MountProvider implements IMountProvider, IPartialMountProvider {
class MountProvider implements IMountProvider, IAuthoritativeMountProvider, IPartialMountProvider {
public function __construct(
protected readonly IConfig $config,
protected readonly IManager $shareManager,
Expand All @@ -46,9 +47,10 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader): array {

/**
* @param IUser $user
* @param list<IShare> $excludeShares
* @return list<array{IShare, array<IShare>}> 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),
Expand All @@ -58,7 +60,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);
}

Expand Down Expand Up @@ -318,14 +321,16 @@ public function getMountsFromSuperShares(
* user has no permissions.
*
* @param iterable<IShare> $shares
* @param list<string> $excludeShareIds
* @return iterable<IShare>
*/
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;
}
Expand Down
Loading