diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 13667900..42f4c447 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -17,6 +17,7 @@ use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorage; use OCP\Util; use OCP\WorkflowEngine\Events\RegisterOperationsEvent; @@ -40,13 +41,14 @@ public function addStorageWrapper(): void { * @param IStorage $storage * @return StorageWrapper|IStorage */ - public function addStorageWrapperCallback($mountPoint, IStorage $storage) { + public function addStorageWrapperCallback($mountPoint, IStorage $storage, IMountPoint $mount) { if (!OC::$CLI && $mountPoint !== '/') { /** @var Operation $operation */ $operation = $this->getContainer()->get(Operation::class); return new StorageWrapper([ 'storage' => $storage, 'mountPoint' => $mountPoint, + 'mount' => $mount, 'operation' => $operation, ]); } diff --git a/lib/Operation.php b/lib/Operation.php index 9711ba71..dc085ef0 100644 --- a/lib/Operation.php +++ b/lib/Operation.php @@ -274,10 +274,17 @@ public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatch * @param array|ICacheEntry|null $cacheEntry */ private function getNode(IStorage $storage, string $path, $cacheEntry = null): ?Node { - /** @var IMountPoint|false $mountPoint */ - $mountPoint = current($this->mountManager->findByStorageId($storage->getId())); - if (!$mountPoint) { - return null; + if ($storage->instanceOfStorage(StorageWrapper::class)) { + /** @var StorageWrapper $storage */ + $mountPoint = $storage->getMount(); + } else { + // fairly sure this branch is never taken, but not 100% + + /** @var IMountPoint|false $mountPoint */ + $mountPoint = current($this->mountManager->findByStorageId($storage->getId())); + if (!$mountPoint) { + return null; + } } $fullPath = $mountPoint->getMountPoint() . $path; diff --git a/lib/StorageWrapper.php b/lib/StorageWrapper.php index 9bb95a0e..e5a2f9ea 100644 --- a/lib/StorageWrapper.php +++ b/lib/StorageWrapper.php @@ -8,12 +8,12 @@ namespace OCA\FilesAccessControl; -use OC\Files\Cache\Cache; use OC\Files\Storage\Storage; use OC\Files\Storage\Wrapper\Wrapper; use OCP\Constants; use OCP\Files\Cache\ICache; use OCP\Files\ForbiddenException; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorage; use OCP\Files\Storage\IWriteStreamStorage; @@ -21,6 +21,7 @@ class StorageWrapper extends Wrapper implements IWriteStreamStorage { protected readonly Operation $operation; public readonly string $mountPoint; protected readonly int $mask; + private readonly IMountPoint $mount; /** * @param array $parameters @@ -29,6 +30,7 @@ public function __construct($parameters) { parent::__construct($parameters); $this->operation = $parameters['operation']; $this->mountPoint = $parameters['mountPoint']; + $this->mount = $parameters['mount']; $this->mask = Constants::PERMISSION_ALL & ~Constants::PERMISSION_READ @@ -152,7 +154,7 @@ public function getPermissions($path): int { * see http://php.net/manual/en/function.file_get_contents.php * * @param string $path - * @return string + * @return string|false * @throws ForbiddenException */ #[\Override] @@ -165,12 +167,12 @@ public function file_get_contents($path): string|false { * see http://php.net/manual/en/function.file_put_contents.php * * @param string $path - * @param string $data - * @return bool + * @param mixed $data + * @return int|float|false * @throws ForbiddenException */ #[\Override] - public function file_put_contents($path, $data): int|float|false { + public function file_put_contents(string $path, mixed $data): int|float|false { $this->checkFileAccess($path, false); return $this->storage->file_put_contents($path, $data); } @@ -225,7 +227,7 @@ public function copy($source, $target): bool { * * @param string $path * @param string $mode - * @return resource + * @return resource|false * @throws ForbiddenException */ #[\Override] @@ -254,7 +256,7 @@ public function touch($path, $mtime = null): bool { * * @param string $path * @param Storage (optional) the storage to pass to the cache - * @return Cache + * @return ICache */ #[\Override] public function getCache($path = '', $storage = null): ICache { @@ -271,7 +273,7 @@ public function getCache($path = '', $storage = null): ICache { * For now the returned array can hold the parameter url - in future more attributes might follow. * * @param string $path - * @return array + * @return array|false * @throws ForbiddenException */ #[\Override] @@ -323,7 +325,7 @@ public function writeStream(string $path, $stream, ?int $size = null): int { $this->checkFileAccess($path, false); } - $result = $this->storage->writeStream($path, $stream, $size); + $result = parent::writeStream($path, $stream, $size); if (!$this->isPartFile($path)) { return $result; } @@ -343,4 +345,8 @@ private function isPartFile(string $path): bool { $extension = pathinfo($path, PATHINFO_EXTENSION); return $extension === 'part'; } + + public function getMount(): IMountPoint { + return $this->mount; + } } diff --git a/psalm.xml b/psalm.xml index 4e5bf0bb..5e7c69ec 100644 --- a/psalm.xml +++ b/psalm.xml @@ -26,6 +26,9 @@ + + + diff --git a/tests/Unit/StorageWrapperTest.php b/tests/Unit/StorageWrapperTest.php index 204232d5..723e5d59 100644 --- a/tests/Unit/StorageWrapperTest.php +++ b/tests/Unit/StorageWrapperTest.php @@ -11,6 +11,7 @@ use OCA\FilesAccessControl\Operation; use OCA\FilesAccessControl\StorageWrapper; use OCP\Files\ForbiddenException; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorage; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -27,12 +28,16 @@ protected function setUp(): void { } protected function getInstance(array $methods = []): StorageWrapper&MockObject { + $mount = $this->createMock(IMountPoint::class); + $mount->method('getMountPoint') + ->willReturn('mountPoint'); return $this->getMockBuilder(StorageWrapper::class) ->setConstructorArgs([ [ 'storage' => $this->storage, 'mountPoint' => 'mountPoint', 'operation' => $this->operation, + 'mount' => $mount, ] ]) ->onlyMethods($methods) diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index b17e249b..62960cba 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -6,18 +6,10 @@ - - - - - fileEntity]]> - - - @@ -31,12 +23,4 @@ - - - - - - - - diff --git a/tests/stubs/oc_files_cache_cache.php b/tests/stubs/oc_files_cache_cache.php new file mode 100644 index 00000000..2a6c7a08 --- /dev/null +++ b/tests/stubs/oc_files_cache_cache.php @@ -0,0 +1,77 @@ +cache = $cache; + } + public function getNumericStorageId() { + } + public function getIncomplete() { + } + public function getPathById($id) { + } + public function getAll() { + } + public function get($file) { + } + public function getFolderContents($folder) { + } + public function getFolderContentsById($fileId) { + } + public function put($file, array $data) { + } + public function insert($file, array $data) { + } + public function update($id, array $data) { + } + public function getId($file) { + } + public function getParentId($file) { + } + public function inCache($file) { + } + public function remove($file) { + } + public function move($source, $target) { + } + public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { + } + public function clear() { + } + public function getStatus($file) { + } + public function search($pattern) { + } + public function searchByMime($mimetype) { + } + public function searchQuery(ISearchQuery $query) { + } + public function correctFolderSize($path, $data = null, $isBackgroundScan = false) { + } + public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, string $targetPath): int { + } + public function normalize($path) { + } + public function getQueryFilterForStorage(): ISearchOperator { + } + public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry { + } + public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader) { + } + } +} diff --git a/tests/stubs/oc_files_cache_wrapper_cachewrapper.php b/tests/stubs/oc_files_cache_wrapper_cachewrapper.php new file mode 100644 index 00000000..2d99ba2e --- /dev/null +++ b/tests/stubs/oc_files_cache_wrapper_cachewrapper.php @@ -0,0 +1,21 @@ + $class + * @psalm-return T|null + */ + public function getInstanceOfStorage(string $class): ?IStorage { + } + + /** + * Pass any methods custom to specific storage implementations to the wrapped storage + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) { + } + + public function getDirectDownload($path): array|false { + } + + public function getAvailability(): array { + } + + public function setAvailability($isAvailable): void { + } + + public function verifyPath($path, $fileName): void { + } + + public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + } + + public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath): bool { + } + + public function getMetaData($path): ?array { + } + + public function acquireLock($path, $type, ILockingProvider $provider): void { + } + + public function releaseLock($path, $type, ILockingProvider $provider): void { + } + + public function changeLock($path, $type, ILockingProvider $provider): void { + } + + public function needsPartFile(): bool { + } + + public function writeStream(string $path, $stream, ?int $size = null): int { + } + + public function getDirectoryContent($directory): \Traversable { + } + + public function isWrapperOf(IStorage $storage): bool { + } + + public function setOwner(?string $user): void { + } + } +}