Skip to content
Open
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
14 changes: 10 additions & 4 deletions apps/files_sharing/lib/ShareTargetValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function verifyMountPoint(
$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();

Expand All @@ -79,9 +79,15 @@ public function verifyMountPoint(
$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(
Expand Down
59 changes: 57 additions & 2 deletions apps/files_sharing/tests/ShareTargetValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,25 @@

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;
Expand All @@ -40,7 +49,17 @@ protected function setUp(): void {
$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);
Expand Down Expand Up @@ -138,4 +157,40 @@ public function testShareMountOverShare(): void {
$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);
}
}
50 changes: 37 additions & 13 deletions lib/public/Share/Events/VerifyMountPointEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,25 @@

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;
}

/**
Expand All @@ -45,12 +40,15 @@ public function getShare(): IShare {

/**
* @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 {
Expand All @@ -63,4 +61,30 @@ public function getParent(): string {
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;
}
}
Loading