mirror of
https://github.com/nextcloud/server.git
synced 2026-02-24 10:26:07 -05:00
Merge pull request #57523 from nextcloud/authoritative-share-provider
Make share mount provider authoritative
This commit is contained in:
commit
867ef52cfb
2 changed files with 32 additions and 12 deletions
|
|
@ -15,6 +15,7 @@ use OCP\EventDispatcher\Event;
|
|||
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;
|
||||
|
|
@ -36,50 +37,64 @@ class SharesUpdatedListener implements IEventListener {
|
|||
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()]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use InvalidArgumentException;
|
|||
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;
|
||||
|
|
@ -28,7 +29,7 @@ use Psr\Log\LoggerInterface;
|
|||
|
||||
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,
|
||||
|
|
@ -46,9 +47,10 @@ class MountProvider implements IMountProvider, IPartialMountProvider {
|
|||
|
||||
/**
|
||||
* @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),
|
||||
|
|
@ -58,7 +60,8 @@ class MountProvider implements IMountProvider, IPartialMountProvider {
|
|||
$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);
|
||||
}
|
||||
|
||||
|
|
@ -318,14 +321,16 @@ class MountProvider implements IMountProvider, IPartialMountProvider {
|
|||
* 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue