Compare commits
2 Commits
folderCont
...
auth-mount
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
573099c47d | ||
|
|
ab40d76c99 |
@@ -70,6 +70,7 @@ return array(
|
||||
'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => $baseDir . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => $baseDir . '/../lib/Listener/ShareInteractionListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\SharesUpdatedListener' => $baseDir . '/../lib/Listener/SharesUpdatedListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => $baseDir . '/../lib/Listener/UserAddedToGroupListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\UserShareAcceptanceListener' => $baseDir . '/../lib/Listener/UserShareAcceptanceListener.php',
|
||||
'OCA\\Files_Sharing\\Middleware\\OCSShareAPIMiddleware' => $baseDir . '/../lib/Middleware/OCSShareAPIMiddleware.php',
|
||||
@@ -96,6 +97,7 @@ return array(
|
||||
'OCA\\Files_Sharing\\Settings\\Personal' => $baseDir . '/../lib/Settings/Personal.php',
|
||||
'OCA\\Files_Sharing\\ShareBackend\\File' => $baseDir . '/../lib/ShareBackend/File.php',
|
||||
'OCA\\Files_Sharing\\ShareBackend\\Folder' => $baseDir . '/../lib/ShareBackend/Folder.php',
|
||||
'OCA\\Files_Sharing\\ShareTargetValidator' => $baseDir . '/../lib/ShareTargetValidator.php',
|
||||
'OCA\\Files_Sharing\\SharedMount' => $baseDir . '/../lib/SharedMount.php',
|
||||
'OCA\\Files_Sharing\\SharedStorage' => $baseDir . '/../lib/SharedStorage.php',
|
||||
'OCA\\Files_Sharing\\SharesReminderJob' => $baseDir . '/../lib/SharesReminderJob.php',
|
||||
|
||||
@@ -85,6 +85,7 @@ class ComposerStaticInitFiles_Sharing
|
||||
'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => __DIR__ . '/..' . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => __DIR__ . '/..' . '/../lib/Listener/ShareInteractionListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\SharesUpdatedListener' => __DIR__ . '/..' . '/../lib/Listener/SharesUpdatedListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => __DIR__ . '/..' . '/../lib/Listener/UserAddedToGroupListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\UserShareAcceptanceListener' => __DIR__ . '/..' . '/../lib/Listener/UserShareAcceptanceListener.php',
|
||||
'OCA\\Files_Sharing\\Middleware\\OCSShareAPIMiddleware' => __DIR__ . '/..' . '/../lib/Middleware/OCSShareAPIMiddleware.php',
|
||||
@@ -111,6 +112,7 @@ class ComposerStaticInitFiles_Sharing
|
||||
'OCA\\Files_Sharing\\Settings\\Personal' => __DIR__ . '/..' . '/../lib/Settings/Personal.php',
|
||||
'OCA\\Files_Sharing\\ShareBackend\\File' => __DIR__ . '/..' . '/../lib/ShareBackend/File.php',
|
||||
'OCA\\Files_Sharing\\ShareBackend\\Folder' => __DIR__ . '/..' . '/../lib/ShareBackend/Folder.php',
|
||||
'OCA\\Files_Sharing\\ShareTargetValidator' => __DIR__ . '/..' . '/../lib/ShareTargetValidator.php',
|
||||
'OCA\\Files_Sharing\\SharedMount' => __DIR__ . '/..' . '/../lib/SharedMount.php',
|
||||
'OCA\\Files_Sharing\\SharedStorage' => __DIR__ . '/..' . '/../lib/SharedStorage.php',
|
||||
'OCA\\Files_Sharing\\SharesReminderJob' => __DIR__ . '/..' . '/../lib/SharesReminderJob.php',
|
||||
|
||||
@@ -14,6 +14,7 @@ use OCA\Files\Event\LoadAdditionalScriptsEvent;
|
||||
use OCA\Files\Event\LoadSidebar;
|
||||
use OCA\Files_Sharing\Capabilities;
|
||||
use OCA\Files_Sharing\Config\ConfigLexicon;
|
||||
use OCA\Files_Sharing\Event\UserShareAccessUpdatedEvent;
|
||||
use OCA\Files_Sharing\External\Manager;
|
||||
use OCA\Files_Sharing\External\MountProvider as ExternalMountProvider;
|
||||
use OCA\Files_Sharing\Helper;
|
||||
@@ -24,6 +25,7 @@ use OCA\Files_Sharing\Listener\LoadAdditionalListener;
|
||||
use OCA\Files_Sharing\Listener\LoadPublicFileRequestAuthListener;
|
||||
use OCA\Files_Sharing\Listener\LoadSidebarListener;
|
||||
use OCA\Files_Sharing\Listener\ShareInteractionListener;
|
||||
use OCA\Files_Sharing\Listener\SharesUpdatedListener;
|
||||
use OCA\Files_Sharing\Listener\UserAddedToGroupListener;
|
||||
use OCA\Files_Sharing\Listener\UserShareAcceptanceListener;
|
||||
use OCA\Files_Sharing\Middleware\OCSShareAPIMiddleware;
|
||||
@@ -49,9 +51,11 @@ use OCP\Files\Events\Node\BeforeNodeReadEvent;
|
||||
use OCP\Group\Events\GroupChangedEvent;
|
||||
use OCP\Group\Events\GroupDeletedEvent;
|
||||
use OCP\Group\Events\UserAddedEvent;
|
||||
use OCP\Group\Events\UserRemovedEvent;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IGroup;
|
||||
use OCP\Share\Events\ShareCreatedEvent;
|
||||
use OCP\Share\Events\ShareDeletedEvent;
|
||||
use OCP\User\Events\UserChangedEvent;
|
||||
use OCP\User\Events\UserDeletedEvent;
|
||||
use OCP\Util;
|
||||
@@ -109,6 +113,13 @@ class Application extends App implements IBootstrap {
|
||||
// File request auth
|
||||
$context->registerEventListener(BeforeTemplateRenderedEvent::class, LoadPublicFileRequestAuthListener::class);
|
||||
|
||||
// Update mounts
|
||||
$context->registerEventListener(ShareCreatedEvent::class, SharesUpdatedListener::class);
|
||||
$context->registerEventListener(ShareDeletedEvent::class, SharesUpdatedListener::class);
|
||||
$context->registerEventListener(UserAddedEvent::class, SharesUpdatedListener::class);
|
||||
$context->registerEventListener(UserRemovedEvent::class, SharesUpdatedListener::class);
|
||||
$context->registerEventListener(UserShareAccessUpdatedEvent::class, SharesUpdatedListener::class);
|
||||
|
||||
$context->registerConfigLexicon(ConfigLexicon::class);
|
||||
}
|
||||
|
||||
|
||||
76
apps/files_sharing/lib/Listener/SharesUpdatedListener.php
Normal file
76
apps/files_sharing/lib/Listener/SharesUpdatedListener.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Robin Appelman <robin@icewind.nl>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Sharing\Listener;
|
||||
|
||||
use OCA\Files_Sharing\Event\UserShareAccessUpdatedEvent;
|
||||
use OCA\Files_Sharing\MountProvider;
|
||||
use OCA\Files_Sharing\ShareTargetValidator;
|
||||
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;
|
||||
use OCP\Share\Events\ShareCreatedEvent;
|
||||
use OCP\Share\Events\ShareDeletedEvent;
|
||||
use OCP\Share\IManager;
|
||||
|
||||
/**
|
||||
* Listen to various events that can change what shares a user has access to
|
||||
*
|
||||
* @template-implements IEventListener<UserAddedEvent|UserRemovedEvent|ShareCreatedEvent|ShareDeletedEvent|UserShareAccessUpdatedEvent>
|
||||
*/
|
||||
class SharesUpdatedListener implements IEventListener {
|
||||
public function __construct(
|
||||
private readonly IManager $shareManager,
|
||||
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 UserAddedEvent || $event instanceof UserRemovedEvent || $event instanceof UserShareAccessUpdatedEvent) {
|
||||
$this->updateForUser($event->getUser());
|
||||
}
|
||||
if ($event instanceof ShareCreatedEvent || $event instanceof ShareDeletedEvent) {
|
||||
foreach ($this->shareManager->getUsersForShare($event->getShare()) as $user) {
|
||||
$this->updateForUser($user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateForUser(IUser $user): 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);
|
||||
|
||||
$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])) {
|
||||
$mountsChanged = true;
|
||||
$this->shareTargetValidator->verifyMountPoint($user, $parentShare, $mountsByPath, $groupedShares);
|
||||
}
|
||||
}
|
||||
|
||||
if ($mountsChanged) {
|
||||
$newMounts = $this->shareMountProvider->getMountsFromSuperShares($user, $shares, $this->storageFactory);
|
||||
$this->userMountCache->registerMounts($user, $newMounts, [MountProvider::class]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use OC\Files\View;
|
||||
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\Mount\IMountManager;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
@@ -26,7 +27,7 @@ use OCP\Share\IShare;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use function count;
|
||||
|
||||
class MountProvider implements IMountProvider {
|
||||
class MountProvider implements IMountProvider, IAuthoritativeMountProvider {
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param IManager $shareManager
|
||||
@@ -50,6 +51,14 @@ class MountProvider implements IMountProvider {
|
||||
* @return IMountPoint[]
|
||||
*/
|
||||
public function getMountsForUser(IUser $user, IStorageFactory $loader) {
|
||||
return $this->getMountsFromSuperShares($user, $this->getSuperSharesForUser($user), $loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @return list<array{IShare, array<IShare>}> Tuple of [superShare, groupedShares]
|
||||
*/
|
||||
public function getSuperSharesForUser(IUser $user): array {
|
||||
$userId = $user->getUID();
|
||||
$shares = array_merge(
|
||||
$this->shareManager->getSharedWith($userId, IShare::TYPE_USER, null, -1),
|
||||
@@ -60,9 +69,7 @@ class MountProvider implements IMountProvider {
|
||||
);
|
||||
|
||||
$shares = $this->filterShares($shares, $userId);
|
||||
$superShares = $this->buildSuperShares($shares, $user);
|
||||
|
||||
return $this->getMountsFromSuperShares($userId, $superShares, $loader, $user);
|
||||
return $this->buildSuperShares($shares, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,18 +252,18 @@ class MountProvider implements IMountProvider {
|
||||
}
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param array $superShares
|
||||
* @param list<array{IShare, array<IShare>}> $superShares
|
||||
* @param IStorageFactory $loader
|
||||
* @param IUser $user
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getMountsFromSuperShares(
|
||||
string $userId,
|
||||
public function getMountsFromSuperShares(
|
||||
IUser $user,
|
||||
array $superShares,
|
||||
IStorageFactory $loader,
|
||||
IUser $user,
|
||||
): array {
|
||||
$userId = $user->getUID();
|
||||
$allMounts = $this->mountManager->getAll();
|
||||
$mounts = [];
|
||||
$view = new View('/' . $userId . '/files');
|
||||
@@ -289,7 +296,6 @@ class MountProvider implements IMountProvider {
|
||||
$shareId = (int)$parentShare->getId();
|
||||
$mount = new SharedMount(
|
||||
'\OCA\Files_Sharing\SharedStorage',
|
||||
$allMounts,
|
||||
[
|
||||
'user' => $userId,
|
||||
// parent share
|
||||
@@ -300,11 +306,8 @@ class MountProvider implements IMountProvider {
|
||||
'sharingDisabledForUser' => $sharingDisabledForUser
|
||||
],
|
||||
$loader,
|
||||
$view,
|
||||
$foldersExistCache,
|
||||
$this->eventDispatcher,
|
||||
$user,
|
||||
$shareId <= $maxValidatedShare,
|
||||
);
|
||||
|
||||
$newMaxValidatedShare = max($shareId, $newMaxValidatedShare);
|
||||
|
||||
141
apps/files_sharing/lib/ShareTargetValidator.php
Normal file
141
apps/files_sharing/lib/ShareTargetValidator.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Robin Appelman <robin@icewind.nl>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Sharing;
|
||||
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\SetupManager;
|
||||
use OC\Files\View;
|
||||
use OCP\Cache\CappedMemoryCache;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\Files\Mount\IMountManager;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\IUser;
|
||||
use OCP\Share\Events\VerifyMountPointEvent;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IShare;
|
||||
|
||||
/**
|
||||
* Validate that mount target is valid
|
||||
*/
|
||||
class ShareTargetValidator {
|
||||
private CappedMemoryCache $folderExistsCache;
|
||||
|
||||
public function __construct(
|
||||
private readonly IManager $shareManager,
|
||||
private readonly IEventDispatcher $eventDispatcher,
|
||||
private readonly SetupManager $setupManager,
|
||||
private readonly IMountManager $mountManager,
|
||||
) {
|
||||
$this->folderExistsCache = new CappedMemoryCache();
|
||||
}
|
||||
|
||||
private function getViewForUser(IUser $user): View {
|
||||
/**
|
||||
* @psalm-suppress InternalClass
|
||||
* @psalm-suppress InternalMethod
|
||||
*/
|
||||
return new View('/' . $user->getUID() . '/files');
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the parent folder exists otherwise move the mount point up
|
||||
*
|
||||
* @param array<string, ICachedMountInfo> $allCachedMounts Other mounts for the user, indexed by path
|
||||
* @param IShare[] $childShares
|
||||
* @return string
|
||||
*/
|
||||
public function verifyMountPoint(
|
||||
IUser $user,
|
||||
IShare &$share,
|
||||
array $allCachedMounts,
|
||||
array $childShares,
|
||||
): string {
|
||||
$mountPoint = basename($share->getTarget());
|
||||
$parent = dirname($share->getTarget());
|
||||
|
||||
$recipientView = $this->getViewForUser($user);
|
||||
$event = new VerifyMountPointEvent($share, $recipientView, $parent);
|
||||
$this->eventDispatcher->dispatchTyped($event);
|
||||
$parent = $event->getParent();
|
||||
|
||||
/** @psalm-suppress InternalMethod */
|
||||
$absoluteParent = $recipientView->getAbsolutePath($parent);
|
||||
$this->setupManager->setupForPath($absoluteParent);
|
||||
$parentMount = $this->mountManager->find($absoluteParent);
|
||||
|
||||
$cached = $this->folderExistsCache->get($parent);
|
||||
if ($cached) {
|
||||
$parentExists = $cached;
|
||||
} else {
|
||||
$parentCache = $parentMount->getStorage()->getCache();
|
||||
$parentExists = $parentCache->inCache($parentMount->getInternalPath($absoluteParent));
|
||||
$this->folderExistsCache->set($parent, $parentExists);
|
||||
}
|
||||
if (!$parentExists) {
|
||||
$parent = Helper::getShareFolder($recipientView, $user->getUID());
|
||||
/** @psalm-suppress InternalMethod */
|
||||
$absoluteParent = $recipientView->getAbsolutePath($parent);
|
||||
}
|
||||
|
||||
$newAbsoluteMountPoint = $this->generateUniqueTarget(
|
||||
Filesystem::normalizePath($absoluteParent . '/' . $mountPoint),
|
||||
$parentMount,
|
||||
$allCachedMounts,
|
||||
);
|
||||
|
||||
/** @psalm-suppress InternalMethod */
|
||||
$newMountPoint = $recipientView->getRelativePath($newAbsoluteMountPoint);
|
||||
if ($newMountPoint === null) {
|
||||
return $share->getTarget();
|
||||
}
|
||||
|
||||
if ($newMountPoint !== $share->getTarget()) {
|
||||
$this->updateFileTarget($user, $newMountPoint, $share, $childShares);
|
||||
}
|
||||
|
||||
return $newMountPoint;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ICachedMountInfo[] $allCachedMounts
|
||||
*/
|
||||
private function generateUniqueTarget(string $absolutePath, IMountPoint $parentMount, array $allCachedMounts): string {
|
||||
$pathInfo = pathinfo($absolutePath);
|
||||
$ext = isset($pathInfo['extension']) ? '.' . $pathInfo['extension'] : '';
|
||||
$name = $pathInfo['filename'];
|
||||
$dir = $pathInfo['dirname'];
|
||||
|
||||
$i = 2;
|
||||
$parentCache = $parentMount->getStorage()->getCache();
|
||||
$internalPath = $parentMount->getInternalPath($absolutePath);
|
||||
while ($parentCache->inCache($internalPath) || isset($allCachedMounts[$absolutePath . '/'])) {
|
||||
$absolutePath = Filesystem::normalizePath($dir . '/' . $name . ' (' . $i . ')' . $ext);
|
||||
$internalPath = $parentMount->getInternalPath($absolutePath);
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $absolutePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* update fileTarget in the database if the mount point changed
|
||||
*
|
||||
* @param IShare[] $childShares
|
||||
*/
|
||||
private function updateFileTarget(IUser $user, string $newPath, IShare &$share, array $childShares) {
|
||||
$share->setTarget($newPath);
|
||||
|
||||
foreach ($childShares as $tmpShare) {
|
||||
$tmpShare->setTarget($newPath);
|
||||
$this->shareManager->moveShare($tmpShare, $user->getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,13 @@ namespace OCA\Files_Sharing;
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\Mount\MountPoint;
|
||||
use OC\Files\Mount\MoveableMount;
|
||||
use OC\Files\View;
|
||||
use OCA\Files_Sharing\Exceptions\BrokenPath;
|
||||
use OCP\Cache\CappedMemoryCache;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Events\InvalidateMountCacheEvent;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
use OCP\Share\Events\VerifyMountPointEvent;
|
||||
use OCP\Share\IShare;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
@@ -41,73 +38,19 @@ class SharedMount extends MountPoint implements MoveableMount, ISharedMountPoint
|
||||
|
||||
public function __construct(
|
||||
$storage,
|
||||
array $mountpoints,
|
||||
$arguments,
|
||||
IStorageFactory $loader,
|
||||
private View $recipientView,
|
||||
CappedMemoryCache $folderExistCache,
|
||||
private IEventDispatcher $eventDispatcher,
|
||||
private IUser $user,
|
||||
bool $alreadyVerified,
|
||||
) {
|
||||
$this->superShare = $arguments['superShare'];
|
||||
$this->groupedShares = $arguments['groupedShares'];
|
||||
|
||||
$absMountPoint = '/' . $user->getUID() . '/files/' . trim($this->superShare->getTarget(), '/') . '/';
|
||||
|
||||
// after the mountpoint is verified for the first time, only new mountpoints (e.g. groupfolders can overwrite the target)
|
||||
if (!$alreadyVerified || isset($mountpoints[$absMountPoint])) {
|
||||
$newMountPoint = $this->verifyMountPoint($this->superShare, $mountpoints, $folderExistCache);
|
||||
$absMountPoint = '/' . $user->getUID() . '/files/' . trim($newMountPoint, '/') . '/';
|
||||
}
|
||||
|
||||
parent::__construct($storage, $absMountPoint, $arguments, $loader, null, null, MountProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the parent folder exists otherwise move the mount point up
|
||||
*
|
||||
* @param IShare $share
|
||||
* @param SharedMount[] $mountpoints
|
||||
* @param CappedMemoryCache<bool> $folderExistCache
|
||||
* @return string
|
||||
*/
|
||||
private function verifyMountPoint(
|
||||
IShare $share,
|
||||
array $mountpoints,
|
||||
CappedMemoryCache $folderExistCache,
|
||||
) {
|
||||
$mountPoint = basename($share->getTarget());
|
||||
$parent = dirname($share->getTarget());
|
||||
|
||||
$event = new VerifyMountPointEvent($share, $this->recipientView, $parent);
|
||||
$this->eventDispatcher->dispatchTyped($event);
|
||||
$parent = $event->getParent();
|
||||
|
||||
$cached = $folderExistCache->get($parent);
|
||||
if ($cached) {
|
||||
$parentExists = $cached;
|
||||
} else {
|
||||
$parentExists = $this->recipientView->is_dir($parent);
|
||||
$folderExistCache->set($parent, $parentExists);
|
||||
}
|
||||
if (!$parentExists) {
|
||||
$parent = Helper::getShareFolder($this->recipientView, $this->user->getUID());
|
||||
}
|
||||
|
||||
$newMountPoint = $this->generateUniqueTarget(
|
||||
Filesystem::normalizePath($parent . '/' . $mountPoint),
|
||||
$this->recipientView,
|
||||
$mountpoints
|
||||
);
|
||||
|
||||
if ($newMountPoint !== $share->getTarget()) {
|
||||
$this->updateFileTarget($newMountPoint, $share);
|
||||
}
|
||||
|
||||
return $newMountPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* update fileTarget in the database if the mount point changed
|
||||
*
|
||||
@@ -126,30 +69,6 @@ class SharedMount extends MountPoint implements MoveableMount, ISharedMountPoint
|
||||
$this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent($this->user));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param View $view
|
||||
* @param SharedMount[] $mountpoints
|
||||
* @return mixed
|
||||
*/
|
||||
private function generateUniqueTarget($path, $view, array $mountpoints) {
|
||||
$pathinfo = pathinfo($path);
|
||||
$ext = isset($pathinfo['extension']) ? '.' . $pathinfo['extension'] : '';
|
||||
$name = $pathinfo['filename'];
|
||||
$dir = $pathinfo['dirname'];
|
||||
|
||||
$i = 2;
|
||||
$absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
|
||||
while ($view->file_exists($path) || isset($mountpoints[$absolutePath])) {
|
||||
$path = Filesystem::normalizePath($dir . '/' . $name . ' (' . $i . ')' . $ext);
|
||||
$absolutePath = $this->recipientView->getAbsolutePath($path) . '/';
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a path to be relative to the /user/files/ directory
|
||||
*
|
||||
@@ -267,4 +186,8 @@ class SharedMount extends MountPoint implements MoveableMount, ISharedMountPoint
|
||||
public function getMountType() {
|
||||
return 'shared';
|
||||
}
|
||||
|
||||
public function getUser(): IUser {
|
||||
return $this->user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,6 +826,8 @@ class ApiTest extends TestCase {
|
||||
$share3->setStatus(IShare::STATUS_ACCEPTED);
|
||||
$this->shareManager->updateShare($share3);
|
||||
|
||||
$this->logout();
|
||||
|
||||
// $request = $this->createRequest(['path' => $this->subfolder]);
|
||||
$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
|
||||
$result1 = $ocs->getShares('false', 'false', 'false', $this->subfolder);
|
||||
|
||||
141
apps/files_sharing/tests/ShareTargetValidatorTest.php
Normal file
141
apps/files_sharing/tests/ShareTargetValidatorTest.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Robin Appelman <robin@icewind.nl>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Sharing\Tests;
|
||||
|
||||
use OCA\Files_Sharing\ShareTargetValidator;
|
||||
use OCP\Constants;
|
||||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
use OCP\Share\IShare;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\Group('DB')]
|
||||
class ShareTargetValidatorTest extends TestCase {
|
||||
private ShareTargetValidator $targetValidator;
|
||||
|
||||
private IUser $user2;
|
||||
protected string $folder2;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->folder = '/folder_share_storage_test';
|
||||
$this->folder2 = '/folder_share_storage_test2';
|
||||
|
||||
$this->filename = '/share-api-storage.txt';
|
||||
|
||||
|
||||
$this->view->mkdir($this->folder);
|
||||
$this->view->mkdir($this->folder2);
|
||||
|
||||
// save file with content
|
||||
$this->view->file_put_contents($this->filename, 'root file');
|
||||
$this->view->file_put_contents($this->folder . $this->filename, 'file in subfolder');
|
||||
$this->view->file_put_contents($this->folder2 . $this->filename, 'file in subfolder2');
|
||||
|
||||
$this->targetValidator = Server::get(ShareTargetValidator::class);
|
||||
$this->user2 = $this->createMock(IUser::class);
|
||||
$this->user2->method('getUID')
|
||||
->willReturn(self::TEST_FILES_SHARING_API_USER2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* test if the mount point moves up if the parent folder no longer exists
|
||||
*/
|
||||
public function testShareMountLoseParentFolder(): void {
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share->setTarget('/foo/bar' . $this->folder);
|
||||
$this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$this->assertSame('/foo/bar' . $this->folder, $share->getTarget());
|
||||
|
||||
$this->targetValidator->verifyMountPoint($this->user2, $share, [], [$share]);
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$this->assertSame($this->folder, $share->getTarget());
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->shareManager->deleteShare($share);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if the mount point gets renamed if a folder exists at the target
|
||||
*/
|
||||
public function testShareMountOverFolder(): void {
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->view2->mkdir('bar');
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share->setTarget('/bar');
|
||||
$this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
|
||||
$this->targetValidator->verifyMountPoint($this->user2, $share, [], [$share]);
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$this->assertSame('/bar (2)', $share->getTarget());
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->shareManager->deleteShare($share);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if the mount point gets renamed if another share exists at the target
|
||||
*/
|
||||
public function testShareMountOverShare(): void {
|
||||
// share to user
|
||||
$share2 = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder2,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share2, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$conflictingMount = $this->createMock(ICachedMountInfo::class);
|
||||
$this->targetValidator->verifyMountPoint($this->user2, $share2, [
|
||||
'/' . $this->user2->getUID() . '/files' . $this->folder2 . '/' => $conflictingMount
|
||||
], [$share2]);
|
||||
|
||||
$share2 = $this->shareManager->getShareById($share2->getFullId());
|
||||
|
||||
$this->assertSame("{$this->folder2} (2)", $share2->getTarget());
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->shareManager->deleteShare($share2);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,8 @@
|
||||
namespace OCA\Files_Sharing\Tests;
|
||||
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\View;
|
||||
use OC\Memcache\ArrayCache;
|
||||
use OCA\Files_Sharing\MountProvider;
|
||||
use OCA\Files_Sharing\SharedMount;
|
||||
use OCP\Constants;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
@@ -25,14 +21,10 @@ use OCP\Share\IShare;
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\Group('SLOWDB')]
|
||||
class SharedMountTest extends TestCase {
|
||||
private IGroupManager $groupManager;
|
||||
private IUserManager $userManager;
|
||||
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
private $folder2;
|
||||
private string $folder2;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
@@ -68,78 +60,6 @@ class SharedMountTest extends TestCase {
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* test if the mount point moves up if the parent folder no longer exists
|
||||
*/
|
||||
public function testShareMountLoseParentFolder(): void {
|
||||
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share->setTarget('/foo/bar' . $this->folder);
|
||||
$this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$this->assertSame('/foo/bar' . $this->folder, $share->getTarget());
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
// share should have moved up
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$this->assertSame($this->folder, $share->getTarget());
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->shareManager->deleteShare($share);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
|
||||
public function testDeleteParentOfMountPoint(): void {
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL
|
||||
);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$user2View = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
$this->assertTrue($user2View->file_exists($this->folder));
|
||||
|
||||
// create a local folder
|
||||
$result = $user2View->mkdir('localfolder');
|
||||
$this->assertTrue($result);
|
||||
|
||||
// move mount point to local folder
|
||||
$result = $user2View->rename($this->folder, '/localfolder/' . $this->folder);
|
||||
$this->assertTrue($result);
|
||||
|
||||
// mount point in the root folder should no longer exist
|
||||
$this->assertFalse($user2View->is_dir($this->folder));
|
||||
|
||||
// delete the local folder
|
||||
$result = $user2View->unlink('/localfolder');
|
||||
$this->assertTrue($result);
|
||||
|
||||
//enforce reload of the mount points
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
//mount point should be back at the root
|
||||
$this->assertTrue($user2View->is_dir($this->folder));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
|
||||
public function testMoveSharedFile(): void {
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
@@ -313,111 +233,6 @@ class SharedMountTest extends TestCase {
|
||||
$testGroup->removeUser($user2);
|
||||
$testGroup->removeUser($user3);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if the mount point gets renamed if a folder exists at the target
|
||||
*/
|
||||
public function testShareMountOverFolder(): void {
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->view2->mkdir('bar');
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share->setTarget('/bar');
|
||||
$this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
// share should have been moved
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$this->assertSame('/bar (2)', $share->getTarget());
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->shareManager->deleteShare($share);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if the mount point gets renamed if another share exists at the target
|
||||
*/
|
||||
public function testShareMountOverShare(): void {
|
||||
// create a shared cache
|
||||
$caches = [];
|
||||
$cacheFactory = $this->createMock(ICacheFactory::class);
|
||||
$cacheFactory->method('createLocal')
|
||||
->willReturnCallback(function (string $prefix) use (&$caches) {
|
||||
if (!isset($caches[$prefix])) {
|
||||
$caches[$prefix] = new ArrayCache($prefix);
|
||||
}
|
||||
return $caches[$prefix];
|
||||
});
|
||||
$cacheFactory->method('createDistributed')
|
||||
->willReturnCallback(function (string $prefix) use (&$caches) {
|
||||
if (!isset($caches[$prefix])) {
|
||||
$caches[$prefix] = new ArrayCache($prefix);
|
||||
}
|
||||
return $caches[$prefix];
|
||||
});
|
||||
|
||||
// hack to overwrite the cache factory, we can't use the proper "overwriteService" since the mount provider is created before this test is called
|
||||
$mountProvider = Server::get(MountProvider::class);
|
||||
$reflectionClass = new \ReflectionClass($mountProvider);
|
||||
$reflectionCacheFactory = $reflectionClass->getProperty('cacheFactory');
|
||||
$reflectionCacheFactory->setValue($mountProvider, $cacheFactory);
|
||||
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share->setTarget('/foobar');
|
||||
$this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
|
||||
// share to user
|
||||
$share2 = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder2,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL);
|
||||
$this->shareManager->acceptShare($share2, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
$share2->setTarget('/foobar');
|
||||
$this->shareManager->moveShare($share2, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
// one of the shares should have been moved
|
||||
|
||||
$share = $this->shareManager->getShareById($share->getFullId());
|
||||
$share2 = $this->shareManager->getShareById($share2->getFullId());
|
||||
|
||||
// we don't know or care which share got the "(2)" just that one of them did
|
||||
$this->assertNotEquals($share->getTarget(), $share2->getTarget());
|
||||
$this->assertSame('/foobar', min($share->getTarget(), $share2->getTarget()));
|
||||
$this->assertSame('/foobar (2)', max($share->getTarget(), $share2->getTarget()));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->shareManager->deleteShare($share);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
}
|
||||
|
||||
class DummyTestClassSharedMount extends SharedMount {
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace OCA\Files_Sharing\Tests;
|
||||
use OC\Files\Cache\FailedCache;
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\Storage\FailedStorage;
|
||||
use OC\Files\Storage\Storage;
|
||||
use OC\Files\Storage\Temporary;
|
||||
use OC\Files\View;
|
||||
use OCA\Files_Sharing\SharedStorage;
|
||||
@@ -60,51 +59,6 @@ class SharedStorageTest extends TestCase {
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* if the parent of the mount point is gone then the mount point should move up
|
||||
*/
|
||||
public function testParentOfMountPointIsGone(): void {
|
||||
|
||||
// share to user
|
||||
$share = $this->share(
|
||||
IShare::TYPE_USER,
|
||||
$this->folder,
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_USER2,
|
||||
Constants::PERMISSION_ALL
|
||||
);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$user2View = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
$this->assertTrue($user2View->file_exists($this->folder));
|
||||
|
||||
// create a local folder
|
||||
$result = $user2View->mkdir('localfolder');
|
||||
$this->assertTrue($result);
|
||||
|
||||
// move mount point to local folder
|
||||
$result = $user2View->rename($this->folder, '/localfolder/' . $this->folder);
|
||||
$this->assertTrue($result);
|
||||
|
||||
// mount point in the root folder should no longer exist
|
||||
$this->assertFalse($user2View->is_dir($this->folder));
|
||||
|
||||
// delete the local folder
|
||||
/** @var Storage $storage */
|
||||
[$storage, $internalPath] = Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/localfolder');
|
||||
$storage->rmdir($internalPath);
|
||||
|
||||
//enforce reload of the mount points
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
//mount point should be back at the root
|
||||
$this->assertTrue($user2View->is_dir($this->folder));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->view->unlink($this->folder);
|
||||
}
|
||||
|
||||
public function testRenamePartFile(): void {
|
||||
|
||||
// share to user
|
||||
@@ -466,57 +420,6 @@ class SharedStorageTest extends TestCase {
|
||||
$this->shareManager->deleteShare($share);
|
||||
}
|
||||
|
||||
public function testNameConflict(): void {
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files');
|
||||
$view1->mkdir('foo');
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||
$view3 = new View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files');
|
||||
$view3->mkdir('foo');
|
||||
|
||||
// share a folder with the same name from two different users to the same user
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
|
||||
$share1 = $this->share(
|
||||
IShare::TYPE_GROUP,
|
||||
'foo',
|
||||
self::TEST_FILES_SHARING_API_USER1,
|
||||
self::TEST_FILES_SHARING_API_GROUP1,
|
||||
Constants::PERMISSION_ALL
|
||||
);
|
||||
$this->shareManager->acceptShare($share1, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||
|
||||
$share2 = $this->share(
|
||||
IShare::TYPE_GROUP,
|
||||
'foo',
|
||||
self::TEST_FILES_SHARING_API_USER3,
|
||||
self::TEST_FILES_SHARING_API_GROUP1,
|
||||
Constants::PERMISSION_ALL
|
||||
);
|
||||
$this->shareManager->acceptShare($share2, self::TEST_FILES_SHARING_API_USER2);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$view2 = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
|
||||
$this->assertTrue($view2->file_exists('/foo'));
|
||||
$this->assertTrue($view2->file_exists('/foo (2)'));
|
||||
|
||||
$mount = $view2->getMount('/foo');
|
||||
$this->assertInstanceOf('\OCA\Files_Sharing\SharedMount', $mount);
|
||||
/** @var SharedStorage $storage */
|
||||
$storage = $mount->getStorage();
|
||||
|
||||
$this->assertEquals(self::TEST_FILES_SHARING_API_USER1, $storage->getOwner(''));
|
||||
|
||||
$this->shareManager->deleteShare($share1);
|
||||
$this->shareManager->deleteShare($share2);
|
||||
}
|
||||
|
||||
public function testOwnerPermissions(): void {
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
|
||||
|
||||
@@ -104,6 +104,8 @@ class VersioningTest extends \Test\TestCase {
|
||||
\OC::registerShareHooks(Server::get(SystemConfig::class));
|
||||
\OC::$server->boot();
|
||||
|
||||
// ensure both users have an up-to-date state
|
||||
self::loginHelper(self::TEST_VERSIONS_USER2);
|
||||
self::loginHelper(self::TEST_VERSIONS_USER);
|
||||
$this->rootView = new View();
|
||||
if (!$this->rootView->file_exists(self::USERS_VERSIONS_ROOT)) {
|
||||
|
||||
@@ -43,7 +43,7 @@ Feature: sharing
|
||||
| item_type | file |
|
||||
| mimetype | text/plain |
|
||||
| storage_id | shared::/textfile0 (2).txt |
|
||||
| file_target | /textfile0.txt |
|
||||
| file_target | /textfile0 (2).txt |
|
||||
| share_with | user2 |
|
||||
| share_with_displayname | user2 |
|
||||
|
||||
@@ -84,7 +84,7 @@ Feature: sharing
|
||||
| item_type | file |
|
||||
| mimetype | text/plain |
|
||||
| storage_id | shared::/textfile0 (2).txt |
|
||||
| file_target | /textfile0.txt |
|
||||
| file_target | /textfile0 (2).txt |
|
||||
| share_with | user2 |
|
||||
| share_with_displayname | user2 |
|
||||
|
||||
@@ -120,7 +120,7 @@ Feature: sharing
|
||||
| share_type | 0 |
|
||||
| share_with | user1 |
|
||||
| file_source | A_NUMBER |
|
||||
| file_target | /textfile0.txt |
|
||||
| file_target | /textfile0 (2).txt |
|
||||
| path | /textfile0.txt |
|
||||
| permissions | 19 |
|
||||
| stime | A_NUMBER |
|
||||
@@ -401,7 +401,7 @@ Feature: sharing
|
||||
| item_type | file |
|
||||
| mimetype | text/plain |
|
||||
| storage_id | shared::/FOLDER/textfile0.txt |
|
||||
| file_target | /textfile0.txt |
|
||||
| file_target | /textfile0 (2).txt |
|
||||
| share_with | user2 |
|
||||
| share_with_displayname | user2 |
|
||||
|
||||
@@ -440,7 +440,7 @@ Feature: sharing
|
||||
| item_type | file |
|
||||
| mimetype | text/plain |
|
||||
| storage_id | shared::/FOLDER/textfile0 (2).txt |
|
||||
| file_target | /textfile0.txt |
|
||||
| file_target | /textfile0 (2).txt |
|
||||
| share_with | user2 |
|
||||
| share_with_displayname | user2 |
|
||||
|
||||
@@ -887,7 +887,7 @@ Feature: sharing
|
||||
| share_type | 0 |
|
||||
| share_with | user2 |
|
||||
| file_source | A_NUMBER |
|
||||
| file_target | /textfile0.txt |
|
||||
| file_target | /textfile0 (2).txt |
|
||||
| path | /textfile0 (2).txt |
|
||||
| permissions | 19 |
|
||||
| stime | A_NUMBER |
|
||||
|
||||
@@ -559,6 +559,8 @@ Feature: sharing
|
||||
Scenario: getting all shares of a user using that user
|
||||
Given user "user0" exists
|
||||
And user "user1" exists
|
||||
When User "user1" deletes file "/textfile0.txt"
|
||||
And the HTTP status code should be "204"
|
||||
And file "textfile0.txt" of user "user0" is shared with user "user1"
|
||||
And As an "user0"
|
||||
When sending "GET" to "/apps/files_sharing/api/v1/shares"
|
||||
|
||||
@@ -1663,12 +1663,6 @@
|
||||
</MoreSpecificImplementedParamType>
|
||||
</file>
|
||||
<file src="apps/files_sharing/lib/SharedMount.php">
|
||||
<InternalMethod>
|
||||
<code><![CDATA[file_exists]]></code>
|
||||
<code><![CDATA[getAbsolutePath]]></code>
|
||||
<code><![CDATA[getAbsolutePath]]></code>
|
||||
<code><![CDATA[is_dir]]></code>
|
||||
</InternalMethod>
|
||||
<InvalidReturnType>
|
||||
<code><![CDATA[bool]]></code>
|
||||
</InvalidReturnType>
|
||||
|
||||
@@ -555,4 +555,13 @@ class UserMountCache implements IUserMountCache {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the internal in-memory caches
|
||||
*/
|
||||
public function flush(): void {
|
||||
$this->cacheInfoCache = new CappedMemoryCache();
|
||||
$this->internalPathCache = new CappedMemoryCache();
|
||||
$this->mountsForUsers = new CappedMemoryCache();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ use OC\Command\QueueBus;
|
||||
use OC\Files\AppData\Factory;
|
||||
use OC\Files\Cache\Storage;
|
||||
use OC\Files\Config\MountProviderCollection;
|
||||
use OC\Files\Config\UserMountCache;
|
||||
use OC\Files\Filesystem;
|
||||
use OC\Files\Mount\CacheMountProvider;
|
||||
use OC\Files\Mount\LocalHomeMountProvider;
|
||||
@@ -180,6 +181,8 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
|
||||
Storage::getGlobalCache()->clearCache();
|
||||
}
|
||||
|
||||
Server::get(UserMountCache::class)->flush();
|
||||
|
||||
// tearDown the traits
|
||||
$traits = $this->getTestTraits();
|
||||
foreach ($traits as $trait) {
|
||||
|
||||
Reference in New Issue
Block a user