feat: improve VerifyMountPointEvent event

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2026-02-09 18:33:22 +01:00
parent 9cd337bebe
commit a3cc9754f8
No known key found for this signature in database
GPG key ID: 42B69D8A64526EFB
3 changed files with 104 additions and 19 deletions

View file

@ -61,7 +61,7 @@ class ShareTargetValidator {
$parent = dirname($share->getTarget());
$recipientView = $this->getViewForUser($user);
$event = new VerifyMountPointEvent($share, $recipientView, $parent);
$event = new VerifyMountPointEvent($share, $recipientView, $parent, $user);
$this->eventDispatcher->dispatchTyped($event);
$parent = $event->getParent();
@ -79,9 +79,15 @@ class ShareTargetValidator {
$this->folderExistsCache->set($parent, $parentExists);
}
if (!$parentExists) {
$parent = Helper::getShareFolder($recipientView, $user->getUID());
/** @psalm-suppress InternalMethod */
$absoluteParent = $recipientView->getAbsolutePath($parent);
if ($event->createParent()) {
$internalPath = $parentMount->getInternalPath($absoluteParent);
$parentMount->getStorage()->mkdir($internalPath);
$parentMount->getStorage()->getUpdater()->update($internalPath);
} else {
$parent = Helper::getShareFolder($recipientView, $user->getUID());
/** @psalm-suppress InternalMethod */
$absoluteParent = $recipientView->getAbsolutePath($parent);
}
}
$newAbsoluteMountPoint = $this->generateUniqueTarget(

View file

@ -8,16 +8,25 @@ declare(strict_types=1);
namespace OCA\Files_Sharing\Tests;
use OC\EventDispatcher\EventDispatcher;
use OC\Files\SetupManager;
use OCA\Files_Sharing\ShareTargetValidator;
use OCP\Constants;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Folder;
use OCP\Files\Mount\IMountManager;
use OCP\IUser;
use OCP\Server;
use OCP\Share\Events\VerifyMountPointEvent;
use OCP\Share\IManager;
use OCP\Share\IShare;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher as SymfonyEventDispatcher;
#[\PHPUnit\Framework\Attributes\Group('DB')]
class ShareTargetValidatorTest extends TestCase {
private IEventDispatcher $eventDispatcher;
private ShareTargetValidator $targetValidator;
private IUser $user2;
@ -40,7 +49,17 @@ class ShareTargetValidatorTest extends TestCase {
$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->eventDispatcher = new EventDispatcher(
new SymfonyEventDispatcher(),
Server::get(ContainerInterface::class),
$this->createMock(LoggerInterface::class),
);
$this->targetValidator = new ShareTargetValidator(
Server::get(IManager::class),
$this->eventDispatcher,
Server::get(SetupManager::class),
Server::get(IMountManager::class),
);
$this->user2 = $this->createMock(IUser::class);
$this->user2->method('getUID')
->willReturn(self::TEST_FILES_SHARING_API_USER2);
@ -138,4 +157,40 @@ class ShareTargetValidatorTest extends TestCase {
$this->shareManager->deleteShare($share2);
$this->view->unlink($this->folder);
}
/**
* test if the parent folder is created if asked for
*/
public function testShareMountCreateParentFolder(): 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->eventDispatcher->addListener(VerifyMountPointEvent::class, function (VerifyMountPointEvent $event) {
$event->setCreateParent(true);
});
$this->targetValidator->verifyMountPoint($this->user2, $share, [], [$share]);
$share = $this->shareManager->getShareById($share->getFullId());
$this->assertSame('/foo/bar' . $this->folder, $share->getTarget());
$userFolder = $this->rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER2);
$this->assertTrue($userFolder->nodeExists('/foo/bar'));
//cleanup
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
$this->shareManager->deleteShare($share);
$this->view->unlink($this->folder);
}
}

View file

@ -10,30 +10,25 @@ namespace OCP\Share\Events;
use OC\Files\View;
use OCP\EventDispatcher\Event;
use OCP\IUser;
use OCP\Share\IShare;
/**
* @since 19.0.0
*/
class VerifyMountPointEvent extends Event {
/** @var IShare */
private $share;
/** @var View */
private $view;
/** @var string */
private $parent;
private bool $createParent = false;
/**
* @since 19.0.0
*/
public function __construct(IShare $share,
View $view,
string $parent) {
public function __construct(
private readonly IShare $share,
private readonly View $view,
private string $parent,
private readonly IUser $user,
) {
parent::__construct();
$this->share = $share;
$this->view = $view;
$this->parent = $parent;
}
/**
@ -45,12 +40,15 @@ class VerifyMountPointEvent extends Event {
/**
* @since 19.0.0
* @depecated 34.0.0 Get the user folder for `$this->getUser()` instead
*/
public function getView(): View {
return $this->view;
}
/**
* The parent folder where the share is placed, as relative path to the users home directory.
*
* @since 19.0.0
*/
public function getParent(): string {
@ -63,4 +61,30 @@ class VerifyMountPointEvent extends Event {
public function setParent(string $parent): void {
$this->parent = $parent;
}
/**
* @since 34.0.0
*/
public function setCreateParent(bool $create): void {
$this->createParent = $create;
}
/**
* Whether the parent folder should be created if missing.
*
* If set for `false` (the default), and the parent folder doesn't exist already,
* the share will be moved to the default share folder instead.
*
* @since 34.0.0
*/
public function createParent(): bool {
return $this->createParent;
}
/**
* @since 34.0.0
*/
public function getUser(): IUser {
return $this->user;
}
}