diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php index ca23b9f0830af..532663fe9620a 100644 --- a/apps/files/lib/AppInfo/Application.php +++ b/apps/files/lib/AppInfo/Application.php @@ -125,6 +125,7 @@ public function register(IRegistrationContext $context): void { $context->registerNotifierService(Notifier::class); $context->registerDashboardWidget(FavoriteWidget::class); + } public function boot(IBootContext $context): void { diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml index bc2786cc3b485..3e80dda221f52 100644 --- a/apps/files_external/appinfo/info.xml +++ b/apps/files_external/appinfo/info.xml @@ -14,7 +14,7 @@ This application enables administrators to configure connections to external sto External storage can be configured using the GUI or at the command line. This second option provides the administration with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation. - 1.23.0 + 1.23.1 agpl Robin Appelman Michael Gapczynski diff --git a/apps/files_external/composer/composer/autoload_classmap.php b/apps/files_external/composer/composer/autoload_classmap.php index 589b70a078b05..d884d2213985d 100644 --- a/apps/files_external/composer/composer/autoload_classmap.php +++ b/apps/files_external/composer/composer/autoload_classmap.php @@ -107,6 +107,7 @@ 'OCA\\Files_External\\Migration\\Version1011Date20200630192246' => $baseDir . '/../lib/Migration/Version1011Date20200630192246.php', 'OCA\\Files_External\\Migration\\Version1015Date20211104103506' => $baseDir . '/../lib/Migration/Version1015Date20211104103506.php', 'OCA\\Files_External\\Migration\\Version1016Date20220324154536' => $baseDir . '/../lib/Migration/Version1016Date20220324154536.php', + 'OCA\\Files_External\\Migration\\Version1025Date20250228162604' => $baseDir . '/../lib/Migration/Version1025Date20250228162604.php', 'OCA\\Files_External\\Migration\\Version22000Date20210216084416' => $baseDir . '/../lib/Migration/Version22000Date20210216084416.php', 'OCA\\Files_External\\MountConfig' => $baseDir . '/../lib/MountConfig.php', 'OCA\\Files_External\\NotFoundException' => $baseDir . '/../lib/NotFoundException.php', diff --git a/apps/files_external/composer/composer/autoload_static.php b/apps/files_external/composer/composer/autoload_static.php index 0399f47685c8a..72a889fcc02fa 100644 --- a/apps/files_external/composer/composer/autoload_static.php +++ b/apps/files_external/composer/composer/autoload_static.php @@ -122,6 +122,7 @@ class ComposerStaticInitFiles_External 'OCA\\Files_External\\Migration\\Version1011Date20200630192246' => __DIR__ . '/..' . '/../lib/Migration/Version1011Date20200630192246.php', 'OCA\\Files_External\\Migration\\Version1015Date20211104103506' => __DIR__ . '/..' . '/../lib/Migration/Version1015Date20211104103506.php', 'OCA\\Files_External\\Migration\\Version1016Date20220324154536' => __DIR__ . '/..' . '/../lib/Migration/Version1016Date20220324154536.php', + 'OCA\\Files_External\\Migration\\Version1025Date20250228162604' => __DIR__ . '/..' . '/../lib/Migration/Version1025Date20250228162604.php', 'OCA\\Files_External\\Migration\\Version22000Date20210216084416' => __DIR__ . '/..' . '/../lib/Migration/Version22000Date20210216084416.php', 'OCA\\Files_External\\MountConfig' => __DIR__ . '/..' . '/../lib/MountConfig.php', 'OCA\\Files_External\\NotFoundException' => __DIR__ . '/..' . '/../lib/NotFoundException.php', diff --git a/apps/files_external/lib/Migration/Version1025Date20250228162604.php b/apps/files_external/lib/Migration/Version1025Date20250228162604.php new file mode 100644 index 0000000000000..f3d76ed7baa4e --- /dev/null +++ b/apps/files_external/lib/Migration/Version1025Date20250228162604.php @@ -0,0 +1,35 @@ +globalStoragesServices->updateOverwriteHomeFolders(); + } +} diff --git a/apps/files_external/lib/Service/DBConfigService.php b/apps/files_external/lib/Service/DBConfigService.php index 3820f6b0d96a2..18e301b4a7b81 100644 --- a/apps/files_external/lib/Service/DBConfigService.php +++ b/apps/files_external/lib/Service/DBConfigService.php @@ -4,6 +4,7 @@ * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OCA\Files_External\Service; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; @@ -63,16 +64,16 @@ public function getMountsForUser($userId, $groupIds) { ->where($builder->expr()->orX( $builder->expr()->andX( // global mounts $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)), - $builder->expr()->isNull('a.value') + $builder->expr()->isNull('a.value'), ), $builder->expr()->andX( // mounts for user $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)), - $builder->expr()->eq('a.value', $builder->createNamedParameter($userId)) + $builder->expr()->eq('a.value', $builder->createNamedParameter($userId)), ), $builder->expr()->andX( // mounts for group $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)), - $builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)) - ) + $builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)), + ), )); return $this->getMountsFromQuery($query); @@ -93,8 +94,8 @@ protected function modifyMountsOnDelete(string $applicableId, int $applicableTyp ->leftJoin('a', 'external_applicable', 'b', $builder->expr()->eq('a.mount_id', 'b.mount_id')) ->where($builder->expr()->andX( $builder->expr()->eq('b.type', $builder->createNamedParameter($applicableType, IQueryBuilder::PARAM_INT)), - $builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)) - ) + $builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)), + ), ) ->groupBy(['a.mount_id']); $stmt = $query->executeQuery(); @@ -226,7 +227,7 @@ public function addMount($mountPoint, $storageBackend, $authBackend, $priority, 'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR), 'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR), 'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT), - 'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT) + 'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT), ]); $query->executeStatement(); return $query->getLastInsertId(); @@ -497,4 +498,17 @@ private function decryptValue($value) { return $value; } } + + /** + * Check if any mountpoint is configured that overwrite the home folder + */ + public function hasHomeFolderOverwriteMount(): bool { + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select('mount_id') + ->from('external_mounts') + ->where($builder->expr()->eq('mount_point', $builder->createNamedParameter('/'))) + ->setMaxResults(1); + $result = $query->executeQuery(); + return count($result->fetchAll()) > 0; + } } diff --git a/apps/files_external/lib/Service/StoragesService.php b/apps/files_external/lib/Service/StoragesService.php index 67de6e8b6b8c1..c2bdcc145697d 100644 --- a/apps/files_external/lib/Service/StoragesService.php +++ b/apps/files_external/lib/Service/StoragesService.php @@ -8,6 +8,8 @@ use OC\Files\Cache\Storage; use OC\Files\Filesystem; +use OCA\Files\AppInfo\Application as FilesApplication; +use OCA\Files_External\AppInfo\Application; use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\Auth\InvalidAuth; use OCA\Files_External\Lib\Backend\Backend; @@ -19,6 +21,7 @@ use OCP\Files\Config\IUserMountCache; use OCP\Files\Events\InvalidateMountCacheEvent; use OCP\Files\StorageNotAvailableException; +use OCP\IAppConfig; use OCP\Util; use Psr\Log\LoggerInterface; @@ -38,6 +41,7 @@ public function __construct( protected DBConfigService $dbConfig, protected IUserMountCache $userMountCache, protected IEventDispatcher $eventDispatcher, + protected IAppConfig $appConfig, ) { } @@ -240,6 +244,9 @@ public function addStorage(StorageConfig $newStorage) { $this->triggerHooks($newStorage, Filesystem::signal_create_mount); $newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS); + + $this->updateOverwriteHomeFolders(); + return $newStorage; } @@ -423,6 +430,8 @@ public function updateStorage(StorageConfig $updatedStorage) { } } + $this->updateOverwriteHomeFolders(); + return $this->getStorage($id); } @@ -447,6 +456,8 @@ public function removeStorage(int $id) { // delete oc_storages entries and oc_filecache Storage::cleanByMountId($id); + + $this->updateOverwriteHomeFolders(); } /** @@ -471,4 +482,20 @@ private function getStorageId(StorageConfig $storageConfig) { return -1; } } + + public function updateOverwriteHomeFolders(): void { + $appIdsList = $this->appConfig->getValueArray(FilesApplication::APP_ID, 'overwrites_home_folders'); + + if ($this->dbConfig->hasHomeFolderOverwriteMount()) { + if (!in_array(Application::APP_ID, $appIdsList)) { + $appIdsList[] = Application::APP_ID; + $this->appConfig->setValueArray(FilesApplication::APP_ID, 'overwrites_home_folders', $appIdsList); + } + } else { + if (in_array(Application::APP_ID, $appIdsList)) { + $appIdsList = array_values(array_filter($appIdsList, fn ($v) => $v !== Application::APP_ID)); + $this->appConfig->setValueArray(FilesApplication::APP_ID, 'overwrites_home_folders', $appIdsList); + } + } + } } diff --git a/apps/files_external/lib/Service/UserGlobalStoragesService.php b/apps/files_external/lib/Service/UserGlobalStoragesService.php index 01bc91ef3ff51..3f9a394744512 100644 --- a/apps/files_external/lib/Service/UserGlobalStoragesService.php +++ b/apps/files_external/lib/Service/UserGlobalStoragesService.php @@ -9,6 +9,7 @@ use OCA\Files_External\Lib\StorageConfig; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IUserMountCache; +use OCP\IAppConfig; use OCP\IGroupManager; use OCP\IUser; use OCP\IUserSession; @@ -20,14 +21,6 @@ class UserGlobalStoragesService extends GlobalStoragesService { use UserTrait; - /** - * @param BackendService $backendService - * @param DBConfigService $dbConfig - * @param IUserSession $userSession - * @param IGroupManager $groupManager - * @param IUserMountCache $userMountCache - * @param IEventDispatcher $eventDispatcher - */ public function __construct( BackendService $backendService, DBConfigService $dbConfig, @@ -35,8 +28,9 @@ public function __construct( protected IGroupManager $groupManager, IUserMountCache $userMountCache, IEventDispatcher $eventDispatcher, + IAppConfig $appConfig, ) { - parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher); + parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig); $this->userSession = $userSession; } diff --git a/apps/files_external/lib/Service/UserStoragesService.php b/apps/files_external/lib/Service/UserStoragesService.php index defa97451cd87..5b3dbd57ffcda 100644 --- a/apps/files_external/lib/Service/UserStoragesService.php +++ b/apps/files_external/lib/Service/UserStoragesService.php @@ -12,6 +12,7 @@ use OCA\Files_External\NotFoundException; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IUserMountCache; +use OCP\IAppConfig; use OCP\IUserSession; /** @@ -23,12 +24,6 @@ class UserStoragesService extends StoragesService { /** * Create a user storages service - * - * @param BackendService $backendService - * @param DBConfigService $dbConfig - * @param IUserSession $userSession user session - * @param IUserMountCache $userMountCache - * @param IEventDispatcher $eventDispatcher */ public function __construct( BackendService $backendService, @@ -36,9 +31,10 @@ public function __construct( IUserSession $userSession, IUserMountCache $userMountCache, IEventDispatcher $eventDispatcher, + IAppConfig $appConfig, ) { $this->userSession = $userSession; - parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher); + parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig); } protected function readDBConfig() { diff --git a/apps/files_external/tests/Service/GlobalStoragesServiceTest.php b/apps/files_external/tests/Service/GlobalStoragesServiceTest.php index b4907f7f00f8e..4e0daa7d69155 100644 --- a/apps/files_external/tests/Service/GlobalStoragesServiceTest.php +++ b/apps/files_external/tests/Service/GlobalStoragesServiceTest.php @@ -17,7 +17,7 @@ class GlobalStoragesServiceTest extends StoragesServiceTest { protected function setUp(): void { parent::setUp(); - $this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher); + $this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher, $this->appConfig); } protected function tearDown(): void { diff --git a/apps/files_external/tests/Service/StoragesServiceTest.php b/apps/files_external/tests/Service/StoragesServiceTest.php index 797d4382ae90f..1f028cd8bb93d 100644 --- a/apps/files_external/tests/Service/StoragesServiceTest.php +++ b/apps/files_external/tests/Service/StoragesServiceTest.php @@ -25,10 +25,12 @@ use OCP\Files\Config\IUserMountCache; use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorage; +use OCP\IAppConfig; use OCP\IDBConnection; use OCP\IUser; use OCP\Server; use OCP\Util; +use PHPUnit\Framework\MockObject\MockObject; class CleaningDBConfig extends DBConfigService { private $mountIds = []; @@ -50,40 +52,15 @@ public function clean() { * @group DB */ abstract class StoragesServiceTest extends \Test\TestCase { - /** - * @var StoragesService - */ + /** @var StoragesService $service */ protected $service; - - /** @var BackendService */ - protected $backendService; - - /** - * Data directory - * - * @var string - */ - protected $dataDir; - - /** @var CleaningDBConfig */ - protected $dbConfig; - - /** - * Hook calls - * - * @var array - */ - protected static $hookCalls; - - /** - * @var \PHPUnit\Framework\MockObject\MockObject|IUserMountCache - */ - protected $mountCache; - - /** - * @var \PHPUnit\Framework\MockObject\MockObject|IEventDispatcher - */ - protected IEventDispatcher $eventDispatcher; + protected BackendService&MockObject $backendService; + protected string $dataDir; + protected CleaningDBConfig $dbConfig; + protected static array $hookCalls; + protected IUserMountCache&MockObject $mountCache; + protected IEventDispatcher&MockObject $eventDispatcher; + protected IAppConfig&MockObject $appConfig; protected function setUp(): void { parent::setUp(); @@ -98,6 +75,7 @@ protected function setUp(): void { $this->mountCache = $this->createMock(IUserMountCache::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->appConfig = $this->createMock(IAppConfig::class); // prepare BackendService mock $this->backendService = diff --git a/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php b/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php index 571664b32c8f0..5ada2dd5fd277 100644 --- a/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php +++ b/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php @@ -83,6 +83,7 @@ protected function setUp(): void { $this->groupManager, $this->mountCache, $this->eventDispatcher, + $this->appConfig, ); } diff --git a/apps/files_external/tests/Service/UserStoragesServiceTest.php b/apps/files_external/tests/Service/UserStoragesServiceTest.php index 7bf101ebfc4b3..388fcf84bed23 100644 --- a/apps/files_external/tests/Service/UserStoragesServiceTest.php +++ b/apps/files_external/tests/Service/UserStoragesServiceTest.php @@ -35,7 +35,7 @@ class UserStoragesServiceTest extends StoragesServiceTest { protected function setUp(): void { parent::setUp(); - $this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher); + $this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher, $this->appConfig); $this->userId = $this->getUniqueID('user_'); $this->createUser($this->userId, $this->userId); @@ -48,7 +48,7 @@ protected function setUp(): void { ->method('getUser') ->willReturn($this->user); - $this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache, $this->eventDispatcher); + $this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache, $this->eventDispatcher, $this->appConfig); } private function makeTestStorageData() { diff --git a/cypress/e2e/files_external/StorageUtils.ts b/cypress/e2e/files_external/StorageUtils.ts index 0f7fec65edfb7..33402feac1f43 100644 --- a/cypress/e2e/files_external/StorageUtils.ts +++ b/cypress/e2e/files_external/StorageUtils.ts @@ -9,10 +9,15 @@ export type StorageConfig = { [key: string]: string } +export type StorageMountOption = { + readonly: boolean +} + export enum StorageBackend { DAV = 'dav', SMB = 'smb', SFTP = 'sftp', + LOCAL = 'local', } export enum AuthBackend { @@ -22,6 +27,7 @@ export enum AuthBackend { SessionCredentials = 'password::sessioncredentials', UserGlobalAuth = 'password::global::user', UserProvided = 'password::userprovided', + Null = 'null::null', } /** @@ -35,4 +41,20 @@ export function createStorageWithConfig(mountPoint: string, storageBackend: Stor cy.log(`Creating storage with command: ${command}`) return cy.runOccCommand(command) + .then(({ stdout }) => { + return stdout.replace('Storage created with id ', '') + }) +} + +export function setStorageMountOptions(mountId: string, options: StorageMountOption) { + for (const [key, value] of Object.entries(options)) { + cy.runOccCommand(`files_external:option ${mountId} ${key} ${value}`) + } +} + +export function deleteAllExternalStorages() { + cy.runOccCommand('files_external:list --all --output=json').then(({ stdout }) => { + const list = JSON.parse(stdout) + list.forEach((storage) => cy.runOccCommand(`files_external:delete --yes ${storage.mount_id}`), { failOnNonZeroExit: false }) + }) } diff --git a/cypress/e2e/files_external/home-folder-root-mount-permissions.cy.ts b/cypress/e2e/files_external/home-folder-root-mount-permissions.cy.ts new file mode 100644 index 0000000000000..b2938e3106bc0 --- /dev/null +++ b/cypress/e2e/files_external/home-folder-root-mount-permissions.cy.ts @@ -0,0 +1,46 @@ +/** + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { User } from '@nextcloud/cypress' +import { AuthBackend, createStorageWithConfig, deleteAllExternalStorages, setStorageMountOptions, StorageBackend } from './StorageUtils' + +describe('Home folder root mount permissions', { testIsolation: true }, () => { + let user1: User + + before(() => { + cy.runOccCommand('app:enable files_external') + cy.createRandomUser().then((user) => { user1 = user }) + }) + + after(() => { + deleteAllExternalStorages() + cy.runOccCommand('app:disable files_external') + }) + + it('Does not show write actions on read-only storage mounted at the root of the user\'s home folder', () => { + cy.login(user1) + cy.visit('/apps/files/') + cy.runOccCommand('config:app:get files overwrites_home_folders --default-value=[]') + .then(({ stdout }) => assert.equal(stdout.trim(), '[]')) + + cy.get('[data-cy-upload-picker=""]').should('exist') + + createStorageWithConfig('/', StorageBackend.LOCAL, AuthBackend.Null, { datadir: '/tmp' }) + .then((id) => setStorageMountOptions(id, { readonly: true })) + // HACK: somehow, we need to create an external folder targeting a subpath for the previous one to show. + createStorageWithConfig('/a', StorageBackend.LOCAL, AuthBackend.Null, { datadir: '/tmp' }) + cy.visit('/apps/files/') + cy.visit('/apps/files/') + cy.runOccCommand('config:app:get files overwrites_home_folders') + .then(({ stdout }) => assert.equal(stdout.trim(), '["files_external"]')) + cy.get('[data-cy-upload-picker=""]').should('not.exist') + + deleteAllExternalStorages() + cy.visit('/apps/files/') + cy.runOccCommand('config:app:get files overwrites_home_folders') + .then(({ stdout }) => assert.equal(stdout.trim(), '[]')) + cy.get('[data-cy-upload-picker=""]').should('exist') + }) +}) diff --git a/lib/private/Files/Node/LazyUserFolder.php b/lib/private/Files/Node/LazyUserFolder.php index 77479c2fa5e06..d7afb199b913f 100644 --- a/lib/private/Files/Node/LazyUserFolder.php +++ b/lib/private/Files/Node/LazyUserFolder.php @@ -19,38 +19,50 @@ use Psr\Log\LoggerInterface; class LazyUserFolder extends LazyFolder { - private IUser $user; private string $path; - private IMountManager $mountManager; - public function __construct(IRootFolder $rootFolder, IUser $user, IMountManager $mountManager) { - $this->user = $user; - $this->mountManager = $mountManager; + public function __construct( + IRootFolder $rootFolder, + private IUser $user, + private IMountManager $mountManager, + bool $useDefaultHomeFoldersPermissions = true, + ) { $this->path = '/' . $user->getUID() . '/files'; - parent::__construct($rootFolder, function () use ($user): Folder { - try { - $node = $this->getRootFolder()->get($this->path); - if ($node instanceof File) { - $e = new \RuntimeException(); - \OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: ' . $this->path, [ - 'exception' => $e, - ]); - throw $e; - } - return $node; - } catch (NotFoundException $e) { - if (!$this->getRootFolder()->nodeExists('/' . $user->getUID())) { - $this->getRootFolder()->newFolder('/' . $user->getUID()); - } - return $this->getRootFolder()->newFolder($this->path); - } - }, [ + $data = [ 'path' => $this->path, - // Sharing user root folder is not allowed - 'permissions' => Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE, 'type' => FileInfo::TYPE_FOLDER, 'mimetype' => FileInfo::MIMETYPE_FOLDER, - ]); + ]; + + // By default, we assume the permissions for the users' home folders. + // If a mount point is mounted on a user's home folder, the permissions cannot be assumed. + if ($useDefaultHomeFoldersPermissions) { + // Sharing user root folder is not allowed + $data['permissions'] = Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE; + } + + parent::__construct( + $rootFolder, + function () use ($user): Folder { + try { + $node = $this->getRootFolder()->get($this->path); + if ($node instanceof File) { + $e = new \RuntimeException(); + \OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: ' . $this->path, [ + 'exception' => $e, + ]); + throw $e; + } + return $node; + } catch (NotFoundException $e) { + if (!$this->getRootFolder()->nodeExists('/' . $user->getUID())) { + $this->getRootFolder()->newFolder('/' . $user->getUID()); + } + return $this->getRootFolder()->newFolder($this->path); + } + }, + $data, + ); } public function getMountPoint() { diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index 88aa46ce33617..6ea5a04e00c84 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -14,6 +14,7 @@ use OC\Files\View; use OC\Hooks\PublicEmitter; use OC\User\NoUserException; +use OCA\Files\AppInfo\Application; use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICacheEntry; @@ -24,6 +25,7 @@ use OCP\Files\Node as INode; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\IAppConfig; use OCP\ICache; use OCP\ICacheFactory; use OCP\IUser; @@ -51,43 +53,30 @@ * @package OC\Files\Node */ class Root extends Folder implements IRootFolder { - private Manager $mountManager; private PublicEmitter $emitter; - private ?IUser $user; private CappedMemoryCache $userFolderCache; - private IUserMountCache $userMountCache; - private LoggerInterface $logger; - private IUserManager $userManager; - private IEventDispatcher $eventDispatcher; private ICache $pathByIdCache; + private bool $useDefaultHomeFoldersPermissions = true; - /** - * @param Manager $manager - * @param View $view - * @param IUser|null $user - */ public function __construct( - $manager, - $view, - $user, - IUserMountCache $userMountCache, - LoggerInterface $logger, - IUserManager $userManager, + private Manager $mountManager, + View $view, + private ?IUser $user, + private IUserMountCache $userMountCache, + private LoggerInterface $logger, + private IUserManager $userManager, IEventDispatcher $eventDispatcher, ICacheFactory $cacheFactory, + IAppConfig $appConfig, ) { parent::__construct($this, $view, ''); - $this->mountManager = $manager; - $this->user = $user; $this->emitter = new PublicEmitter(); $this->userFolderCache = new CappedMemoryCache(); - $this->userMountCache = $userMountCache; - $this->logger = $logger; - $this->userManager = $userManager; $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () { $this->userFolderCache = new CappedMemoryCache(); }); $this->pathByIdCache = $cacheFactory->createLocal('path-by-id'); + $this->useDefaultHomeFoldersPermissions = count($appConfig->getValueArray(Application::APP_ID, 'overwrites_home_folders')) === 0; } /** @@ -367,7 +356,7 @@ public function getUserFolder($userId) { $folder = $this->newFolder('/' . $userId . '/files'); } } else { - $folder = new LazyUserFolder($this, $userObject, $this->mountManager); + $folder = new LazyUserFolder($this, $userObject, $this->mountManager, $this->useDefaultHomeFoldersPermissions); } $this->userFolderCache->set($userId, $folder); diff --git a/lib/private/Server.php b/lib/private/Server.php index 6464901ebaba4..ebcebe88f6a4f 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -408,6 +408,7 @@ public function __construct($webRoot, \OC\Config $config) { $this->get(IUserManager::class), $this->get(IEventDispatcher::class), $this->get(ICacheFactory::class), + $this->get(IAppConfig::class), ); $previewConnector = new \OC\Preview\WatcherConnector( diff --git a/tests/lib/Files/Node/FileTest.php b/tests/lib/Files/Node/FileTest.php index a67c94336630f..fc4968d436cc2 100644 --- a/tests/lib/Files/Node/FileTest.php +++ b/tests/lib/Files/Node/FileTest.php @@ -38,7 +38,7 @@ protected function getViewDeleteMethod() { public function testGetContent(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ $root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $hook = function ($file) { @@ -68,7 +68,7 @@ public function testGetContentNotPermitted(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ $root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) @@ -87,7 +87,7 @@ public function testGetContentNotPermitted(): void { public function testPutContent(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ $root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) @@ -114,7 +114,7 @@ public function testPutContentNotPermitted(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ $root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $this->view->expects($this->once()) @@ -129,7 +129,7 @@ public function testPutContentNotPermitted(): void { public function testGetMimeType(): void { /** @var \OC\Files\Node\Root|\PHPUnit\Framework\MockObject\MockObject $root */ $root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $this->view->expects($this->once()) @@ -155,6 +155,7 @@ public function testFOpenRead(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $hook = function ($file) { @@ -192,6 +193,7 @@ public function testFOpenWrite(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $hooksCalled = 0; $hook = function ($file) use (&$hooksCalled) { @@ -233,6 +235,7 @@ public function testFOpenReadNotPermitted(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $hook = function ($file) { throw new \Exception('Hooks are not supposed to be called'); @@ -260,6 +263,7 @@ public function testFOpenReadWriteNoReadPermissions(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $hook = function () { throw new \Exception('Hooks are not supposed to be called'); @@ -287,6 +291,7 @@ public function testFOpenReadWriteNoWritePermissions(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $hook = function () { throw new \Exception('Hooks are not supposed to be called'); diff --git a/tests/lib/Files/Node/FolderTest.php b/tests/lib/Files/Node/FolderTest.php index e3edf202f8eef..12ab85904cc78 100644 --- a/tests/lib/Files/Node/FolderTest.php +++ b/tests/lib/Files/Node/FolderTest.php @@ -70,7 +70,7 @@ public function testGetDirectoryContent(): void { * @var \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject $view */ $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -103,7 +103,7 @@ public function testGet(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -122,7 +122,7 @@ public function testNodeExists(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -142,7 +142,7 @@ public function testNodeExistsNotExists(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -160,7 +160,7 @@ public function testNewFolder(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -184,7 +184,7 @@ public function testNewFolderDeepParent(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -211,7 +211,7 @@ public function testNewFolderNotPermitted(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->method('getUser') ->willReturn($this->user); @@ -228,7 +228,7 @@ public function testNewFile(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -255,7 +255,7 @@ public function testNewFileNotPermitted(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->method('getUser') ->willReturn($this->user); @@ -272,7 +272,7 @@ public function testGetFreeSpace(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->method('getUser') ->willReturn($this->user); @@ -289,7 +289,7 @@ public function testSearch(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->method('getUser') ->willReturn($this->user); @@ -338,7 +338,7 @@ public function testSearchInRoot(): void { $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) ->setMethods(['getUser', 'getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -381,7 +381,7 @@ public function testSearchInStorageRoot(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->method('getUser') ->willReturn($this->user); @@ -424,7 +424,7 @@ public function testSearchSubStorages(): void { $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') @@ -500,7 +500,7 @@ public function testGetById(): void { $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) ->setMethods(['getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $storage = $this->createMock(\OC\Files\Storage\Storage::class); $mount = new MountPoint($storage, '/bar'); @@ -549,7 +549,7 @@ public function testGetByIdMountRoot(): void { $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) ->setMethods(['getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $storage = $this->createMock(\OC\Files\Storage\Storage::class); $mount = new MountPoint($storage, '/bar'); @@ -594,7 +594,7 @@ public function testGetByIdOutsideFolder(): void { $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) ->setMethods(['getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $storage = $this->createMock(\OC\Files\Storage\Storage::class); $mount = new MountPoint($storage, '/bar'); @@ -638,7 +638,7 @@ public function testGetByIdMultipleStorages(): void { $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) ->setMethods(['getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $storage = $this->createMock(\OC\Files\Storage\Storage::class); $mount1 = new MountPoint($storage, '/bar'); @@ -699,7 +699,7 @@ public function testGetUniqueName($name, $existingFiles, $expected): void { $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) ->setMethods(['getUser', 'getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $view->expects($this->any()) @@ -724,7 +724,7 @@ public function testRecent(): void { /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */ $root = $this->getMockBuilder(Root::class) ->setMethods(['getUser', 'getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */ $folderInfo = $this->getMockBuilder(FileInfo::class) @@ -793,7 +793,7 @@ public function testRecentFolder(): void { /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */ $root = $this->getMockBuilder(Root::class) ->setMethods(['getUser', 'getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */ $folderInfo = $this->getMockBuilder(FileInfo::class) @@ -860,7 +860,7 @@ public function testRecentJail(): void { /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */ $root = $this->getMockBuilder(Root::class) ->setMethods(['getUser', 'getMountsIn', 'getMount']) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */ $folderInfo = $this->getMockBuilder(FileInfo::class) @@ -947,7 +947,7 @@ public function testSearchSubStoragesLimitOffset(int $offset, int $limit, array $manager = $this->createMock(Manager::class); $view = $this->getRootViewMock(); $root = $this->getMockBuilder(Root::class) - ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); $root->expects($this->any()) ->method('getUser') diff --git a/tests/lib/Files/Node/HookConnectorTest.php b/tests/lib/Files/Node/HookConnectorTest.php index 1a3337b9ddcee..64bc4d8f5bae1 100644 --- a/tests/lib/Files/Node/HookConnectorTest.php +++ b/tests/lib/Files/Node/HookConnectorTest.php @@ -30,6 +30,7 @@ use OCP\Files\Events\Node\NodeTouchedEvent; use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\Files\Node; +use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\IUserManager; use Psr\Log\LoggerInterface; @@ -85,6 +86,7 @@ protected function setUp(): void { $this->createMock(IUserManager::class), $this->createMock(IEventDispatcher::class), $cacheFactory, + $this->createMock(IAppConfig::class), ); $this->eventDispatcher = \OC::$server->query(IEventDispatcher::class); $this->logger = \OC::$server->query(LoggerInterface::class); diff --git a/tests/lib/Files/Node/IntegrationTest.php b/tests/lib/Files/Node/IntegrationTest.php index c90a6115f2aba..65194c58ee164 100644 --- a/tests/lib/Files/Node/IntegrationTest.php +++ b/tests/lib/Files/Node/IntegrationTest.php @@ -14,6 +14,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IUserMountCache; use OCP\Files\Mount\IMountManager; +use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\IUserManager; use Psr\Log\LoggerInterface; @@ -69,6 +70,7 @@ protected function setUp(): void { $this->createMock(IUserManager::class), $this->createMock(IEventDispatcher::class), $cacheFactory, + $this->createMock(IAppConfig::class), ); $storage = new Temporary([]); $subStorage = new Temporary([]); diff --git a/tests/lib/Files/Node/NodeTest.php b/tests/lib/Files/Node/NodeTest.php index db87aa925d3b3..5c26a5386a04c 100644 --- a/tests/lib/Files/Node/NodeTest.php +++ b/tests/lib/Files/Node/NodeTest.php @@ -17,6 +17,7 @@ use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\Files\Storage\IStorage; +use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\IUser; use OCP\IUserManager; @@ -46,6 +47,8 @@ abstract class NodeTest extends \Test\TestCase { protected $eventDispatcher; /** @var ICacheFactory|\PHPUnit\Framework\MockObject\MockObject */ protected $cacheFactory; + /** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */ + protected $appConfig; protected function setUp(): void { parent::setUp(); @@ -71,8 +74,10 @@ protected function setUp(): void { ->willReturnCallback(function () { return new ArrayCache(); }); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->getMock(); } @@ -184,6 +189,7 @@ public function testDeleteHooks(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->createMock(IAppConfig::class), ); $root->listen('\OC\Files', 'preDelete', $preListener); @@ -433,6 +439,7 @@ public function testTouchHooks(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->createMock(IAppConfig::class), ); $root->listen('\OC\Files', 'preTouch', $preListener); $root->listen('\OC\Files', 'postTouch', $postListener); @@ -609,7 +616,7 @@ public function moveOrCopyProvider() { public function testMoveCopyHooks($operationMethod, $viewMethod, $preHookName, $postHookName): void { /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject $root */ $root = $this->getMockBuilder('\OC\Files\Node\Root') - ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory]) + ->setConstructorArgs([$this->manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory, $this->appConfig]) ->setMethods(['get']) ->getMock(); diff --git a/tests/lib/Files/Node/RootTest.php b/tests/lib/Files/Node/RootTest.php index f2ef1a0e3ee04..6837e59280d82 100644 --- a/tests/lib/Files/Node/RootTest.php +++ b/tests/lib/Files/Node/RootTest.php @@ -14,9 +14,12 @@ use OC\Memcache\ArrayCache; use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; +use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\IUser; use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; /** @@ -25,20 +28,14 @@ * @package Test\Files\Node */ class RootTest extends \Test\TestCase { - /** @var \OC\User\User */ - private $user; - /** @var \OC\Files\Mount\Manager */ - private $manager; - /** @var \OCP\Files\Config\IUserMountCache|\PHPUnit\Framework\MockObject\MockObject */ - private $userMountCache; - /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ - private $logger; - /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */ - private $userManager; - /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ - private $eventDispatcher; - /** @var ICacheFactory|\PHPUnit\Framework\MockObject\MockObject */ - protected $cacheFactory; + private IUser&MockObject $user; + private Manager&MockObject $manager; + private IUserMountCache&MockObject $userMountCache; + private LoggerInterface&MockObject $logger; + private IUserManager&MockObject $userManager; + private IEventDispatcher&MockObject $eventDispatcher; + protected ICacheFactory&MockObject $cacheFactory; + protected IAppConfig&MockObject $appConfig; protected function setUp(): void { parent::setUp(); @@ -58,10 +55,11 @@ protected function setUp(): void { ->willReturnCallback(function () { return new ArrayCache(); }); + $this->appConfig = $this->createMock(IAppConfig::class); } /** - * @return \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject $view + * @return \OC\Files\View &MockObject $view */ protected function getRootViewMock() { $view = $this->createMock(View::class); @@ -92,6 +90,7 @@ public function testGet(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $view->expects($this->once()) @@ -125,6 +124,7 @@ public function testGetNotFound(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $view->expects($this->once()) @@ -150,6 +150,7 @@ public function testGetInvalidPath(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $root->get('/../foo'); @@ -169,6 +170,7 @@ public function testGetNoStorages(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $root->get('/bar/foo'); @@ -184,6 +186,7 @@ public function testGetUserFolder(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $user = $this->createMock(IUser::class); $user @@ -195,7 +198,7 @@ public function testGetUserFolder(): void { ->method('get') ->with('MyUserId') ->willReturn($user); - /** @var CappedMemoryCache|\PHPUnit\Framework\MockObject\MockObject $cappedMemoryCache */ + /** @var CappedMemoryCache&MockObject $cappedMemoryCache */ $cappedMemoryCache = $this->createMock(CappedMemoryCache::class); $cappedMemoryCache ->expects($this->once()) @@ -226,6 +229,7 @@ public function testGetUserFolderWithNoUserObj(): void { $this->userManager, $this->eventDispatcher, $this->cacheFactory, + $this->appConfig, ); $this->userManager ->expects($this->once())