diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php index f993a8104294e..69d9f3e6b9f4a 100644 --- a/apps/dav/appinfo/v1/publicwebdav.php +++ b/apps/dav/appinfo/v1/publicwebdav.php @@ -20,6 +20,7 @@ use OCP\Constants; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\Mount\IMountManager; use OCP\Files\Storage\IStorage; use OCP\IConfig; @@ -56,6 +57,7 @@ Server::get(ISession::class), Server::get(IRequest::class), Server::get(IConfig::class), + Server::get(ISetupManager::class), allowOcmAccessToken: true, ); $authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend); diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php index 5453c0a8bfb05..9ae8f55d45b11 100644 --- a/apps/dav/appinfo/v1/webdav.php +++ b/apps/dav/appinfo/v1/webdav.php @@ -11,6 +11,7 @@ use OCA\DAV\Connector\Sabre\ServerFactory; use OCA\DAV\Events\SabrePluginAddEvent; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\ISetupManager; use OCP\Files\Mount\IMountManager; use OCP\IConfig; use OCP\IDBConnection; @@ -66,6 +67,7 @@ Server::get(ISession::class), Server::get(IRequest::class), Server::get(IConfig::class), + Server::get(ISetupManager::class), ); $authPlugin->addBackend($bearerAuthPlugin); diff --git a/apps/dav/appinfo/v2/publicremote.php b/apps/dav/appinfo/v2/publicremote.php index 6fb5cafe6cbef..e077699f77eeb 100644 --- a/apps/dav/appinfo/v2/publicremote.php +++ b/apps/dav/appinfo/v2/publicremote.php @@ -25,6 +25,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IHomeStorage; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\Mount\IMountManager; use OCP\Files\Storage\IStorage; use OCP\ICacheFactory; @@ -74,6 +75,7 @@ $session, $request, Server::get(IConfig::class), + Server::get(ISetupManager::class), allowOcmAccessToken: true, ); $authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend); diff --git a/apps/dav/lib/Connector/Sabre/BearerAuth.php b/apps/dav/lib/Connector/Sabre/BearerAuth.php index 4d1530cf980e1..3156022b6c326 100644 --- a/apps/dav/lib/Connector/Sabre/BearerAuth.php +++ b/apps/dav/lib/Connector/Sabre/BearerAuth.php @@ -9,9 +9,11 @@ use OCP\AppFramework\Http; use OCP\Defaults; +use OCP\Files\ISetupManager; use OCP\IConfig; use OCP\IRequest; use OCP\ISession; +use OCP\IUser; use OCP\IUserSession; use OCP\Server; use OCP\Share\IManager; @@ -26,6 +28,7 @@ public function __construct( private ISession $session, private IRequest $request, private IConfig $config, + private ISetupManager $setupManager, private string $principalPrefix = 'principals/users/', private string $token = '', private bool $allowOcmAccessToken = false, @@ -35,10 +38,10 @@ public function __construct( $this->realm = $defaults->getName() ?: 'Nextcloud'; } - private function setupUserFs($userId) { - \OC_Util::setupFS($userId); + private function setupUserFs(IUser $user) { + $this->setupManager->setupForUser($user); $this->session->close(); - return $this->principalPrefix . $userId; + return $this->principalPrefix . $user->getUID(); } /** @@ -46,7 +49,7 @@ private function setupUserFs($userId) { */ #[\Override] public function validateBearerToken($bearerToken) { - \OC_Util::setupFS(); + $this->setupManager->setupRoot(); $this->token = $bearerToken; // public.php sets incognito mode for anonymous share access, which makes @@ -61,7 +64,7 @@ public function validateBearerToken($bearerToken) { $this->userSession->tryTokenLogin($this->request, $this->allowOcmAccessToken); } if ($this->userSession->isLoggedIn()) { - return $this->setupUserFs($this->userSession->getUser()->getUID()); + return $this->setupUserFs($this->userSession->getUser()); } return false; diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 68068dcfb6302..3f74d3e2ac5c8 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -83,6 +83,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IFilenameValidator; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\FilesMetadata\IFilesMetadataManager; use OCP\IAppConfig; use OCP\ICacheFactory; @@ -174,6 +175,7 @@ public function __construct( \OCP\Server::get(ISession::class), \OCP\Server::get(IRequest::class), \OCP\Server::get(IConfig::class), + \OCP\Server::get(ISetupManager::class), ); $authPlugin->addBackend($bearerAuthBackend); // because we are throwing exceptions this plugin has to be the last one diff --git a/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php b/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php index f72869015fc3a..fa10292b40738 100644 --- a/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php +++ b/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php @@ -10,9 +10,12 @@ namespace OCA\DAV\Tests\unit\Connector; use OCA\DAV\Connector\LegacyPublicAuth; +use OCP\Files\ISetupManager; use OCP\IRequest; use OCP\ISession; +use OCP\IUserManager; use OCP\Security\Bruteforce\IThrottler; +use OCP\Server; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; use OCP\Share\IShare; @@ -54,7 +57,10 @@ protected function tearDown(): void { // Set old user \OC_User::setUserId($this->oldUser ?: null); if ($this->oldUser !== false) { - \OC_Util::setupFS($this->oldUser); + $userObj = Server::get(IUserManager::class)->get($this->oldUser); + if ($userObj !== null) { + Server::get(ISetupManager::class)->setupForUser($userObj); + } } parent::tearDown(); diff --git a/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php b/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php index cf12927cc97cd..fe59876c537e0 100644 --- a/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php @@ -10,6 +10,7 @@ use OC\User\Session; use OCA\DAV\Connector\Sabre\BearerAuth; +use OCP\Files\ISetupManager; use OCP\IConfig; use OCP\IRequest; use OCP\ISession; @@ -26,6 +27,7 @@ class BearerAuthTest extends TestCase { private ISession&MockObject $session; private IRequest&MockObject $request; private BearerAuth $bearerAuth; + private ISetupManager&MockObject $setupManager; private IConfig&MockObject $config; @@ -36,12 +38,14 @@ protected function setUp(): void { $this->session = $this->createMock(ISession::class); $this->request = $this->createMock(IRequest::class); $this->config = $this->createMock(IConfig::class); + $this->setupManager = $this->createMock(ISetupManager::class); $this->bearerAuth = new BearerAuth( $this->userSession, $this->session, $this->request, $this->config, + $this->setupManager, ); } @@ -88,6 +92,7 @@ public function testValidateBearerTokenPassesOcmFlagWhenAllowed(): void { $this->session, $this->request, $this->config, + $this->setupManager, allowOcmAccessToken: true, ); $this->userSession @@ -105,9 +110,7 @@ public function testValidateBearerTokenPassesOcmFlagWhenAllowed(): void { } public function testChallenge(): void { - /** @var RequestInterface&MockObject $request */ $request = $this->createMock(RequestInterface::class); - /** @var ResponseInterface&MockObject $response */ $response = $this->createMock(ResponseInterface::class); $this->bearerAuth->challenge($request, $response); $this->assertTrue(true); diff --git a/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php b/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php index b853358569c7e..33e8c674d51fa 100644 --- a/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php @@ -10,10 +10,13 @@ namespace OCA\DAV\Tests\unit\Connector; use OCA\DAV\Connector\Sabre\PublicAuth; +use OCP\Files\ISetupManager; use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; +use OCP\IUserManager; use OCP\Security\Bruteforce\IThrottler; +use OCP\Server; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; use OCP\Share\IShare; @@ -66,9 +69,12 @@ protected function tearDown(): void { \OC_User::setIncognitoMode(false); // Set old user - \OC_User::setUserId($this->oldUser); + \OC_User::setUserId($this->oldUser ?: null); if ($this->oldUser !== false) { - \OC_Util::setupFS($this->oldUser); + $userObj = Server::get(IUserManager::class)->get($this->oldUser); + if ($userObj !== null) { + Server::get(ISetupManager::class)->setupForUser($userObj); + } } parent::tearDown(); diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php index 2fd5617254904..0beefa6d60449 100644 --- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php +++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php @@ -9,6 +9,7 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest; +use OCP\Files\ISetupManager; use OCP\IUserSession; use OCP\Server; use Sabre\DAV\Auth\Backend\BackendInterface; @@ -61,8 +62,9 @@ public function check(RequestInterface $request, ResponseInterface $response) { $result = $userSession->login($this->user, $this->password); if ($result) { //we need to pass the user name, which may differ from login name - $user = $userSession->getUser()->getUID(); - \OC_Util::setupFS($user); + $userObj = $userSession->getUser(); + $user = $userObj->getUID(); + Server::get(ISetupManager::class)->setupForUser($userObj); //trigger creation of user home and /files folder \OC::$server->getUserFolder($user); return [true, "principals/$user"]; diff --git a/apps/federatedfilesharing/tests/TestCase.php b/apps/federatedfilesharing/tests/TestCase.php index ade1eb1facb88..33f524e34481c 100644 --- a/apps/federatedfilesharing/tests/TestCase.php +++ b/apps/federatedfilesharing/tests/TestCase.php @@ -12,6 +12,7 @@ use OC\Files\Filesystem; use OC\Group\Database; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IGroupManager; use OCP\IUserManager; use OCP\IUserSession; @@ -57,7 +58,6 @@ public static function tearDownAfterClass(): void { $user->delete(); } - \OC_Util::tearDownFS(); \OC_User::setUserId(''); Filesystem::tearDown(); @@ -87,12 +87,15 @@ protected static function loginHelper(string $user, bool $create = false, bool $ } } - \OC_Util::tearDownFS(); + Server::get(ISetupManager::class)->tearDown(); Server::get(IUserSession::class)->setUser(null); Filesystem::tearDown(); Server::get(IUserSession::class)->login($user, $password); Server::get(IRootFolder::class)->getUserFolder($user); - \OC_Util::setupFS($user); + $userObj = Server::get(IUserManager::class)->get($user); + if ($userObj !== null) { + Server::get(ISetupManager::class)->setupForUser($userObj); + } } } diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php index 61b772b4ea44e..a546cd431bc48 100644 --- a/apps/files/lib/Service/OwnershipTransferService.php +++ b/apps/files/lib/Service/OwnershipTransferService.php @@ -21,10 +21,10 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IHomeMountProvider; use OCP\Files\Config\IUserMountCache; -use OCP\Files\File; use OCP\Files\FileInfo; use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\Mount\IMountManager; use OCP\Files\NotFoundException; use OCP\IUser; @@ -48,14 +48,15 @@ class OwnershipTransferService { public function __construct( - private IEncryptionManager $encryptionManager, - private IShareManager $shareManager, - private IMountManager $mountManager, - private IUserMountCache $userMountCache, - private IUserManager $userManager, - private IFactory $l10nFactory, - private IRootFolder $rootFolder, - private IEventDispatcher $eventDispatcher, + private readonly IEncryptionManager $encryptionManager, + private readonly IShareManager $shareManager, + private readonly IMountManager $mountManager, + private readonly IUserMountCache $userMountCache, + private readonly IUserManager $userManager, + private readonly IFactory $l10nFactory, + private readonly IRootFolder $rootFolder, + private readonly IEventDispatcher $eventDispatcher, + private readonly ISetupManager $setupManager, ) { } @@ -94,8 +95,8 @@ public function transfer( // Requesting the user folder will set it up if the user hasn't logged in before // We need a setupFS for the full filesystem setup before as otherwise we will just return // a lazy root folder which does not create the destination users folder - \OC_Util::setupFS($sourceUser->getUID()); - \OC_Util::setupFS($destinationUser->getUID()); + $this->setupManager->setupForUser($sourceUser); + $this->setupManager->setupForUser($destinationUser); $this->rootFolder->getUserFolder($sourceUser->getUID()); $this->rootFolder->getUserFolder($destinationUser->getUID()); Filesystem::initMountPoints($sourceUid); @@ -132,7 +133,7 @@ public function transfer( if ($move && !$view->is_dir($finalTarget)) { // Initialize storage - \OC_Util::setupFS($destinationUser->getUID()); + $this->setupManager->setupForUser($destinationUser); } if ($move && !$firstLogin && count($view->getDirectoryContent($finalTarget)) > 0) { diff --git a/apps/files/tests/Service/TagServiceTest.php b/apps/files/tests/Service/TagServiceTest.php index 6b88c999d486f..597999de0ffa2 100644 --- a/apps/files/tests/Service/TagServiceTest.php +++ b/apps/files/tests/Service/TagServiceTest.php @@ -13,6 +13,7 @@ use OCP\Activity\IManager; use OCP\Files\Folder; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\NotFoundException; use OCP\ITagManager; use OCP\ITags; @@ -43,7 +44,10 @@ protected function setUp(): void { $this->activityManager = $this->createMock(IManager::class); Server::get(IUserManager::class)->createUser($this->user, 'test'); \OC_User::setUserId($this->user); - \OC_Util::setupFS($this->user); + $userObj = Server::get(IUserManager::class)->get($this->user); + if ($userObj !== null) { + Server::get(ISetupManager::class)->setupForUser($userObj); + } $user = $this->createMock(IUser::class); $user->expects($this->any()) ->method('getUID') diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index a4d1b71e42605..c8393fcd30806 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -24,6 +24,7 @@ use OCP\Constants; use OCP\Files\Folder; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IAppConfig; use OCP\IConfig; use OCP\IDateTimeZone; @@ -1437,7 +1438,7 @@ public function testInvisibleSharesGroup(): void { $ocs->acceptShare($topId); $ocs->cleanup(); - \OC_Util::tearDownFS(); + Server::get(ISetupManager::class)->tearDown(); $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2); $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK); diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php index 8bec64ef42143..333cc6b9de032 100644 --- a/apps/files_sharing/tests/Controller/ShareControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php @@ -8,7 +8,6 @@ namespace OCA\Files_Sharing\Tests\Controllers; -use OC\Files\Filesystem; use OC\Files\Node\Folder; use OC\Share20\Manager; use OCA\FederatedFileSharing\FederatedShareProvider; @@ -32,6 +31,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\NotFoundException; use OCP\Files\Template\ITemplateManager; use OCP\IAppConfig; @@ -153,14 +153,14 @@ protected function setUp(): void { $this->user = Server::get(ISecureRandom::class)->generate(12, ISecureRandom::CHAR_LOWER); $this->createUser($this->user, $this->user); - \OC_Util::tearDownFS(); + Server::get(ISetupManager::class)->tearDown(); $this->loginAsUser($this->user); } protected function tearDown(): void { - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - Filesystem::tearDown(); + Server::get(ISetupManager::class)->tearDown(); + Server::get(ISession::class)->set('user_id', ''); + Server::get(ISetupManager::class)->tearDown(); $user = Server::get(IUserManager::class)->get($this->user); if ($user !== null) { $user->delete(); @@ -171,7 +171,9 @@ protected function tearDown(): void { // Set old user \OC_User::setUserId($this->oldUser); - \OC_Util::setupFS($this->oldUser); + if ($this->oldUser) { + Server::get(ISetupManager::class)->setupForUser(Server::get(IUserManager::class)->get($this->oldUser)); + } parent::tearDown(); } diff --git a/apps/files_trashbin/tests/TrashbinTest.php b/apps/files_trashbin/tests/TrashbinTest.php index d12cacd8f559f..d279298661b2e 100644 --- a/apps/files_trashbin/tests/TrashbinTest.php +++ b/apps/files_trashbin/tests/TrashbinTest.php @@ -27,6 +27,7 @@ use OCP\Files\File; use OCP\Files\FileInfo; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IConfig; use OCP\IDBConnection; use OCP\IUserManager; @@ -699,11 +700,14 @@ public static function loginHelper($user, $create = false) { } } - \OC_Util::tearDownFS(); + Server::get(ISetupManager::class)->tearDown(); \OC_User::setUserId(''); Filesystem::tearDown(); \OC_User::setUserId($user); - \OC_Util::setupFS($user); + $userObj = Server::get(IUserManager::class)->get($user); + if ($userObj !== null) { + Server::get(ISetupManager::class)->setupForUser($userObj); + } Server::get(IRootFolder::class)->getUserFolder($user); } } diff --git a/apps/files_versions/lib/BackgroundJob/ExpireVersions.php b/apps/files_versions/lib/BackgroundJob/ExpireVersions.php index 946dcc51f6c53..b79908e58b735 100644 --- a/apps/files_versions/lib/BackgroundJob/ExpireVersions.php +++ b/apps/files_versions/lib/BackgroundJob/ExpireVersions.php @@ -8,23 +8,25 @@ namespace OCA\Files_Versions\BackgroundJob; -use OC\Files\View; use OCA\Files_Versions\Expiration; use OCA\Files_Versions\Storage; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; +use OCP\Files\NotFoundException; use OCP\IConfig; use OCP\IUser; use OCP\IUserManager; class ExpireVersions extends TimedJob { - public const ITEMS_PER_SESSION = 1000; - public function __construct( - private IConfig $config, - private IUserManager $userManager, - private Expiration $expiration, + private readonly IConfig $config, + private readonly IUserManager $userManager, + private readonly Expiration $expiration, ITimeFactory $time, + private readonly ISetupManager $setupManager, + private readonly IRootFolder $rootFolder, ) { parent::__construct($time); // Run once per 30 minutes @@ -45,7 +47,7 @@ public function run($argument) { $this->userManager->callForSeenUsers(function (IUser $user): void { $uid = $user->getUID(); - if (!$this->setupFS($uid)) { + if (!$this->setupFS($user)) { return; } Storage::expireOlderThanMaxForUser($uid); @@ -55,16 +57,16 @@ public function run($argument) { /** * Act on behalf on trash item owner */ - protected function setupFS(string $user): bool { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($user); + protected function setupFS(IUser $user): bool { + $this->setupManager->tearDown(); + $this->setupManager->setupForUser($user); - // Check if this user has a versions directory - $view = new View('/' . $user); - if (!$view->is_dir('/files_versions')) { + // Check if this user has a version directory + try { + $this->rootFolder->get('/' . $user->getUID() . '/files_versions'); + return true; + } catch (NotFoundException) { return false; } - - return true; } } diff --git a/apps/files_versions/lib/Command/CleanUp.php b/apps/files_versions/lib/Command/CleanUp.php index 47a946b536361..32054b75deff8 100644 --- a/apps/files_versions/lib/Command/CleanUp.php +++ b/apps/files_versions/lib/Command/CleanUp.php @@ -10,7 +10,8 @@ use OCA\Files_Versions\Db\VersionsMapper; use OCP\Files\IRootFolder; -use OCP\IUserBackend; +use OCP\Files\ISetupManager; +use OCP\IUser; use OCP\IUserManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -20,9 +21,10 @@ class CleanUp extends Command { public function __construct( - protected IRootFolder $rootFolder, - protected IUserManager $userManager, - protected VersionsMapper $versionMapper, + private readonly IRootFolder $rootFolder, + private readonly IUserManager $userManager, + private readonly VersionsMapper $versionMapper, + private readonly ISetupManager $setupManager, ) { parent::__construct(); } @@ -62,38 +64,23 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (!empty($users)) { foreach ($users as $user) { - if (!$this->userManager->userExists($user)) { + $userObject = $this->userManager->get($user); + if ($userObject === null) { $output->writeln("Unknown user $user"); return self::FAILURE; } $output->writeln("Delete versions of $user"); - $this->deleteVersions($user, $path); + $this->deleteVersions($userObject, $path); } return self::SUCCESS; } $output->writeln('Delete all versions'); - foreach ($this->userManager->getBackends() as $backend) { - $name = get_class($backend); - - if ($backend instanceof IUserBackend) { - $name = $backend->getBackendName(); - } - - $output->writeln("Delete versions for users on backend $name"); - - $limit = 500; - $offset = 0; - do { - $users = $backend->getUsers('', $limit, $offset); - foreach ($users as $user) { - $output->writeln(" $user"); - $this->deleteVersions($user); - } - $offset += $limit; - } while (count($users) >= $limit); - } + $this->userManager->callForAllUsers(function (IUser $user) use ($output) { + $output->writeln(' ' . $user->getUID() . ''); + $this->deleteVersions($user); + }); return self::SUCCESS; } @@ -101,14 +88,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int /** * delete versions for the given user */ - protected function deleteVersions(string $user, ?string $path = null): void { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($user); + protected function deleteVersions(IUser $user, ?string $path = null): void { + $this->setupManager->tearDown(); + $this->setupManager->setupForUser($user); - $userHomeStorageId = $this->rootFolder->getUserFolder($user)->getStorage()->getCache()->getNumericStorageId(); + $userHomeStorageId = $this->rootFolder->getUserFolder($user->getUID())->getStorage()->getCache()->getNumericStorageId(); $this->versionMapper->deleteAllVersionsForUser($userHomeStorageId, $path); - $fullPath = '/' . $user . '/files_versions' . ($path ? '/' . $path : ''); + $fullPath = '/' . $user->getUID() . '/files_versions' . ($path ? '/' . $path : ''); if ($this->rootFolder->nodeExists($fullPath)) { $this->rootFolder->get($fullPath)->delete(); } diff --git a/apps/files_versions/lib/Command/ExpireVersions.php b/apps/files_versions/lib/Command/ExpireVersions.php index 4c3c065e7c2ab..d3037a3924e33 100644 --- a/apps/files_versions/lib/Command/ExpireVersions.php +++ b/apps/files_versions/lib/Command/ExpireVersions.php @@ -8,9 +8,11 @@ namespace OCA\Files_Versions\Command; -use OC\Files\View; use OCA\Files_Versions\Expiration; use OCA\Files_Versions\Storage; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; +use OCP\Files\NotFoundException; use OCP\IUser; use OCP\IUserManager; use Symfony\Component\Console\Command\Command; @@ -21,8 +23,10 @@ class ExpireVersions extends Command { public function __construct( - private IUserManager $userManager, - private Expiration $expiration, + private readonly IUserManager $userManager, + private readonly Expiration $expiration, + private readonly ISetupManager $setupManager, + private readonly IRootFolder $rootFolder, ) { parent::__construct(); } @@ -75,7 +79,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int public function expireVersionsForUser(IUser $user): void { $uid = $user->getUID(); - if (!$this->setupFS($uid)) { + if (!$this->setupFS($user)) { return; } Storage::expireOlderThanMaxForUser($uid); @@ -84,16 +88,16 @@ public function expireVersionsForUser(IUser $user): void { /** * Act on behalf on versions item owner */ - protected function setupFS(string $user): bool { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($user); + protected function setupFS(IUser $user): bool { + $this->setupManager->tearDown(); + $this->setupManager->setupForUser($user); // Check if this user has a version directory - $view = new View('/' . $user); - if (!$view->is_dir('/files_versions')) { + try { + $this->rootFolder->get('/' . $user->getUID() . '/files_versions'); + return true; + } catch (NotFoundException) { return false; } - - return true; } } diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index bd21c4f92b35e..94784cf7cdcbb 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -30,6 +30,7 @@ use OCP\Files\Folder; use OCP\Files\IMimeTypeDetector; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; @@ -861,7 +862,7 @@ public static function expire($filename, $uid) { throw new NoUserException('Backends provided no user object for ' . $uid); } - \OC_Util::setupFS($uid); + Server::get(ISetupManager::class)->setupForUser($user); try { if (!Filesystem::file_exists($filename)) { diff --git a/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php b/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php index 21e88e86f9054..1a5806c881a0b 100644 --- a/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php +++ b/apps/files_versions/tests/BackgroundJob/ExpireVersionsTest.php @@ -12,6 +12,8 @@ use OCA\Files_Versions\Expiration; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IConfig; use OCP\IUserManager; use PHPUnit\Framework\MockObject\MockObject; @@ -22,6 +24,8 @@ class ExpireVersionsTest extends TestCase { private IUserManager&MockObject $userManager; private Expiration&MockObject $expiration; private IJobList&MockObject $jobList; + private ISetupManager&MockObject $setupManager; + private IRootFolder&MockObject $rootFolder; protected function setUp(): void { parent::setUp(); @@ -30,6 +34,8 @@ protected function setUp(): void { $this->userManager = $this->createMock(IUserManager::class); $this->expiration = $this->createMock(Expiration::class); $this->jobList = $this->createMock(IJobList::class); + $this->setupManager = $this->createMock(ISetupManager::class); + $this->rootFolder = $this->createMock(IRootFolder::class); $this->jobList->expects($this->once()) ->method('setLastRun'); @@ -49,7 +55,7 @@ public function testBackgroundJobDeactivated(): void { ->with() ->willReturn(999999999); - $job = new ExpireVersions($this->config, $this->userManager, $this->expiration, $timeFactory); + $job = new ExpireVersions($this->config, $this->userManager, $this->expiration, $timeFactory, $this->setupManager, $this->rootFolder); $job->start($this->jobList); } } diff --git a/apps/files_versions/tests/Command/CleanupTest.php b/apps/files_versions/tests/Command/CleanupTest.php index d671b49cc6bc3..46a1e5a072eab 100644 --- a/apps/files_versions/tests/Command/CleanupTest.php +++ b/apps/files_versions/tests/Command/CleanupTest.php @@ -15,8 +15,9 @@ use OCP\Files\Cache\ICache; use OCP\Files\Folder; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\Storage\IStorage; -use OCP\UserInterface; +use OCP\IUser; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -32,6 +33,7 @@ class CleanupTest extends TestCase { protected IRootFolder&MockObject $rootFolder; protected VersionsMapper&MockObject $versionMapper; protected CleanUp $cleanup; + private ISetupManager&MockObject $setupManager; protected function setUp(): void { parent::setUp(); @@ -39,15 +41,19 @@ protected function setUp(): void { $this->rootFolder = $this->createMock(IRootFolder::class); $this->userManager = $this->createMock(Manager::class); $this->versionMapper = $this->createMock(VersionsMapper::class); + $this->setupManager = $this->createMock(ISetupManager::class); - $this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->versionMapper); + $this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->versionMapper, $this->setupManager); } - /** - * @param boolean $nodeExists - */ #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestDeleteVersions')] public function testDeleteVersions(bool $nodeExists): void { + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('testUser'); + + $this->setupManager->expects($this->once())->method('tearDown'); + $this->setupManager->expects($this->once())->method('setupForUser')->with($user); + $this->rootFolder->expects($this->once()) ->method('nodeExists') ->with('/testUser/files_versions') @@ -83,7 +89,7 @@ public function testDeleteVersions(bool $nodeExists): void { ->method('delete'); } - $this->invokePrivate($this->cleanup, 'deleteVersions', ['testUser']); + $this->invokePrivate($this->cleanup, 'deleteVersions', [$user]); } public static function dataTestDeleteVersions(): array { @@ -101,16 +107,27 @@ public function testExecuteDeleteListOfUsers(): void { $instance = $this->getMockBuilder(CleanUp::class) ->onlyMethods(['deleteVersions']) - ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper]) + ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper, $this->setupManager]) ->getMock(); + + $users = array_map(function (string $uid): IUser { + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn($uid); + return $user; + }, $userIds); + $instance->expects($this->exactly(count($userIds))) ->method('deleteVersions') - ->willReturnCallback(function ($user) use ($userIds): void { - $this->assertTrue(in_array($user, $userIds)); + ->willReturnCallback(function (IUser $user) use ($userIds): void { + $this->assertContains($user->getUID(), $userIds); }); $this->userManager->expects($this->exactly(count($userIds))) - ->method('userExists')->willReturn(true); + ->method('get') + ->willReturnCallback(function (string $uid) use ($users, $userIds): ?IUser { + $index = array_search($uid, $userIds); + return $index !== false ? $users[$index] : null; + }); $inputInterface = $this->createMock(\Symfony\Component\Console\Input\InputInterface::class); $inputInterface->expects($this->once())->method('getArgument') @@ -127,23 +144,23 @@ public function testExecuteDeleteListOfUsers(): void { */ public function testExecuteAllUsers(): void { $userIds = []; - $backendUsers = ['user1', 'user2']; + $backendUserIds = ['user1', 'user2']; $instance = $this->getMockBuilder(CleanUp::class) ->onlyMethods(['deleteVersions']) - ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper]) + ->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper, $this->setupManager]) ->getMock(); - $backend = $this->getMockBuilder(UserInterface::class) - ->disableOriginalConstructor()->getMock(); - $backend->expects($this->once())->method('getUsers') - ->with('', 500, 0) - ->willReturn($backendUsers); + $backendUsers = array_map(function (string $uid): IUser { + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn($uid); + return $user; + }, $backendUserIds); - $instance->expects($this->exactly(count($backendUsers))) + $instance->expects($this->exactly(count($backendUserIds))) ->method('deleteVersions') - ->willReturnCallback(function ($user) use ($backendUsers): void { - $this->assertTrue(in_array($user, $backendUsers)); + ->willReturnCallback(function (IUser $user) use ($backendUserIds): void { + $this->assertContains($user->getUID(), $backendUserIds); }); $inputInterface = $this->createMock(\Symfony\Component\Console\Input\InputInterface::class); @@ -154,8 +171,12 @@ public function testExecuteAllUsers(): void { $outputInterface = $this->createMock(\Symfony\Component\Console\Output\OutputInterface::class); $this->userManager->expects($this->once()) - ->method('getBackends') - ->willReturn([$backend]); + ->method('callForAllUsers') + ->willReturnCallback(function (callable $callback) use ($backendUsers): void { + foreach ($backendUsers as $user) { + $callback($user); + } + }); $this->invokePrivate($instance, 'execute', [$inputInterface, $outputInterface]); } diff --git a/apps/files_versions/tests/VersioningTest.php b/apps/files_versions/tests/VersioningTest.php index e0e738bf81237..6cf47de872036 100644 --- a/apps/files_versions/tests/VersioningTest.php +++ b/apps/files_versions/tests/VersioningTest.php @@ -24,9 +24,13 @@ use OCP\Constants; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IMimeTypeLoader; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IConfig; +use OCP\ISession; use OCP\IUser; use OCP\IUserManager; +use OCP\IUserSession; use OCP\Server; use OCP\Share\IShare; use OCP\User\Exceptions\UserNotFoundException; @@ -628,7 +632,8 @@ public function testGetVersionsEmptyFile(): void { public function testExpireNonexistingFile(): void { $this->logout(); // needed to have a FS setup (the background job does this) - \OC_Util::setupFS(self::TEST_VERSIONS_USER); + $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER); + Server::get(ISetupManager::class)->setupForUser($user); $this->assertFalse(Storage::expire('/void/unexist.txt', self::TEST_VERSIONS_USER)); } @@ -638,7 +643,8 @@ public function testExpireNonexistingUser(): void { $this->logout(); // needed to have a FS setup (the background job does this) - \OC_Util::setupFS(self::TEST_VERSIONS_USER); + $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER); + Server::get(ISetupManager::class)->setupForUser($user); Filesystem::file_put_contents('test.txt', 'test file'); $this->assertFalse(Storage::expire('test.txt', 'unexist')); @@ -932,7 +938,8 @@ public function testStoreVersionAsAnonymous(): void { // note: public link upload does this, // needed to make the hooks fire - \OC_Util::setupFS(self::TEST_VERSIONS_USER); + $user = Server::get(IUserManager::class)->get(self::TEST_VERSIONS_USER); + Server::get(ISetupManager::class)->setupForUser($user); $userView = new View('/' . self::TEST_VERSIONS_USER . '/files'); $this->createAndCheckVersions( @@ -963,19 +970,21 @@ private function createAndCheckVersions(View $view, string $path): array { return $versions; } - public static function loginHelper(string $user, bool $create = false) { + public static function loginHelper(string $uid, bool $create = false): void { if ($create) { $backend = new \Test\Util\User\Dummy(); - $backend->createUser($user, $user); + $backend->createUser($uid, $uid); Server::get(IUserManager::class)->registerBackend($backend); } - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - Filesystem::tearDown(); - \OC_User::setUserId($user); - \OC_Util::setupFS($user); - \OC::$server->getUserFolder($user); + $user = Server::get(IUserManager::class)->get($uid); + + Server::get(ISession::class)->set('user_id', ''); + Server::get(ISetupManager::class)->tearDown(); + + Server::get(IUserSession::class)->setUser($user); + Server::get(ISetupManager::class)->setupForUser($user); + Server::get(IRootFolder::class)->getUserFolder($uid); } } diff --git a/apps/provisioning_api/lib/Controller/AUserDataOCSController.php b/apps/provisioning_api/lib/Controller/AUserDataOCSController.php index 50a883caef18a..cd130e4e48753 100644 --- a/apps/provisioning_api/lib/Controller/AUserDataOCSController.php +++ b/apps/provisioning_api/lib/Controller/AUserDataOCSController.php @@ -21,6 +21,7 @@ use OCP\AppFramework\OCSController; use OCP\Files\FileInfo; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\NotFoundException; use OCP\Group\ISubAdmin; use OCP\IConfig; @@ -65,6 +66,7 @@ public function __construct( protected IFactory $l10nFactory, protected IRootFolder $rootFolder, private GroupDisplayNameCache $groupDisplayNameCache, + private readonly ISetupManager $setupManager, ) { parent::__construct($appName, $request); } @@ -306,8 +308,8 @@ protected function fillStorageInfo(IUser $user): array { try { if ($includeExternal) { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($user->getUID()); + $this->setupManager->tearDown(); + $this->setupManager->setupForUser($user); $storage = \OC_Helper::getStorageInfo('/', null, true, false); $data = [ 'free' => $storage['free'], diff --git a/apps/provisioning_api/lib/Controller/GroupsController.php b/apps/provisioning_api/lib/Controller/GroupsController.php index bcae81099c381..8907be359a52e 100644 --- a/apps/provisioning_api/lib/Controller/GroupsController.php +++ b/apps/provisioning_api/lib/Controller/GroupsController.php @@ -24,6 +24,7 @@ use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Group\ISubAdmin; use OCP\IConfig; use OCP\IGroup; @@ -55,6 +56,7 @@ public function __construct( IRootFolder $rootFolder, private LoggerInterface $logger, GroupDisplayNameCache $groupDisplayNameCache, + ISetupManager $setupManager, ) { parent::__construct($appName, $request, @@ -67,6 +69,7 @@ public function __construct( $l10nFactory, $rootFolder, $groupDisplayNameCache, + $setupManager, ); } diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 543892d673884..9869b0a9d3c33 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -35,6 +35,7 @@ use OCP\AppFramework\OCSController; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Group\ISubAdmin; use OCP\HintException; use OCP\IAppConfig; @@ -86,6 +87,7 @@ public function __construct( private IAppManager $appManager, private IAppConfig $appConfig, GroupDisplayNameCache $groupDisplayNameCache, + ISetupManager $setupManager, ) { parent::__construct( $appName, @@ -99,6 +101,7 @@ public function __construct( $l10nFactory, $rootFolder, $groupDisplayNameCache, + $setupManager, ); $this->l10n = $l10nFactory->get($appName); diff --git a/apps/provisioning_api/tests/Controller/GroupsControllerTest.php b/apps/provisioning_api/tests/Controller/GroupsControllerTest.php index 983fddb3352e3..319280f60fdfc 100644 --- a/apps/provisioning_api/tests/Controller/GroupsControllerTest.php +++ b/apps/provisioning_api/tests/Controller/GroupsControllerTest.php @@ -14,6 +14,7 @@ use OCP\Accounts\IAccountManager; use OCP\AppFramework\OCS\OCSException; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Group\ISubAdmin; use OCP\IConfig; use OCP\IGroup; @@ -39,6 +40,7 @@ class GroupsControllerTest extends \Test\TestCase { protected LoggerInterface&MockObject $logger; protected GroupsController&MockObject $api; private GroupDisplayNameCache&MockObject $groupDisplayNameCache; + private ISetupManager&MockObject $setupManager; private IRootFolder $rootFolder; @@ -56,6 +58,7 @@ protected function setUp(): void { $this->logger = $this->createMock(LoggerInterface::class); $this->rootFolder = $this->createMock(IRootFolder::class); $this->groupDisplayNameCache = $this->createMock(GroupDisplayNameCache::class); + $this->setupManager = $this->createMock(ISetupManager::class); $this->groupManager ->method('getSubAdmin') @@ -75,6 +78,7 @@ protected function setUp(): void { $this->rootFolder, $this->logger, $this->groupDisplayNameCache, + $this->setupManager, ]) ->onlyMethods(['fillStorageInfo']) ->getMock(); diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index b1ba3c2cf4e8d..3c28f907f69c4 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -29,6 +29,7 @@ use OCP\AppFramework\OCSController; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Group\ISubAdmin; use OCP\IAppConfig; use OCP\IConfig; @@ -72,6 +73,7 @@ class UsersControllerTest extends TestCase { private IAppManager $appManager; private IAppConfig&MockObject $appConfig; private GroupDisplayNameCache&MockObject $groupDisplayNameCache; + private ISetupManager&MockObject $setupManager; protected function setUp(): void { parent::setUp(); @@ -96,6 +98,7 @@ protected function setUp(): void { $this->appConfig = $this->createMock(IAppConfig::class); $this->rootFolder = $this->createMock(IRootFolder::class); $this->groupDisplayNameCache = $this->createMock(GroupDisplayNameCache::class); + $this->setupManager = $this->createMock(ISetupManager::class); $l10n = $this->createMock(IL10N::class); $l10n->method('t')->willReturnCallback(fn (string $txt, array $replacement = []) => sprintf($txt, ...$replacement)); @@ -124,6 +127,7 @@ protected function setUp(): void { $this->appManager, $this->appConfig, $this->groupDisplayNameCache, + $this->setupManager, ]) ->onlyMethods(['fillStorageInfo']) ->getMock(); @@ -278,6 +282,7 @@ public function testGetUsersDetailsReturnsEmptyGroupsList(): void { $this->appManager, $this->appConfig, $this->groupDisplayNameCache, + $this->setupManager, ]) ->onlyMethods(['getUserData']) ->getMock(); @@ -592,6 +597,7 @@ public function testAddUserSuccessfulWithDisplayName(): void { $this->appManager, $this->appConfig, $this->groupDisplayNameCache, + $this->setupManager, ]) ->onlyMethods(['editUser']) ->getMock(); @@ -4193,6 +4199,7 @@ public function testGetCurrentUserLoggedIn(): void { $this->appManager, $this->appConfig, $this->groupDisplayNameCache, + $this->setupManager, ]) ->onlyMethods(['getUserData']) ->getMock(); @@ -4287,6 +4294,7 @@ public function testGetUser(): void { $this->appManager, $this->appConfig, $this->groupDisplayNameCache, + $this->setupManager, ]) ->onlyMethods(['getUserData']) ->getMock(); diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php index 0aa70be16ab4b..457dc918dabe8 100644 --- a/apps/settings/lib/Settings/Personal/PersonalInfo.php +++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php @@ -19,12 +19,13 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\Files\FileInfo; +use OCP\Files\ISetupManager; use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; use OCP\IL10N; use OCP\IUser; -use OCP\IUserManager; +use OCP\IUserSession; use OCP\L10N\IFactory; use OCP\Notification\IManager; use OCP\Server; @@ -36,17 +37,18 @@ class PersonalInfo implements ISettings { public function __construct( - private IConfig $config, - private IUserManager $userManager, - private IGroupManager $groupManager, - private ITeamManager $teamManager, - private IAccountManager $accountManager, - private ProfileManager $profileManager, - private IAppManager $appManager, - private IFactory $l10nFactory, - private IL10N $l, - private IInitialState $initialStateService, - private IManager $manager, + private readonly IConfig $config, + private readonly IGroupManager $groupManager, + private readonly ITeamManager $teamManager, + private readonly IAccountManager $accountManager, + private readonly ProfileManager $profileManager, + private readonly IAppManager $appManager, + private readonly IFactory $l10nFactory, + private readonly IL10N $l, + private readonly IInitialState $initialStateService, + private readonly IManager $manager, + private readonly IUserSession $userSession, + private readonly ISetupManager $setupManager, ) { } @@ -61,12 +63,11 @@ public function getForm(): TemplateResponse { $lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled(); } - $uid = \OC_User::getUser(); - $user = $this->userManager->get($uid); + $user = $this->userSession->getUser(); $account = $this->accountManager->getAccount($user); // make sure FS is setup before querying storage related stuff... - \OC_Util::setupFS($user->getUID()); + $this->setupManager->setupForUser($user); $storageInfo = \OC_Helper::getStorageInfo('/'); if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) { @@ -84,7 +85,7 @@ public function getForm(): TemplateResponse { ] + $messageParameters; $personalInfoParameters = [ - 'userId' => $uid, + 'userId' => $user->getUID(), 'avatar' => $this->getProperty($account, IAccountManager::PROPERTY_AVATAR), 'groups' => $this->getGroups($user), 'teams' => $this->getTeamMemberships($user), @@ -110,8 +111,8 @@ public function getForm(): TemplateResponse { 'headline' => $this->getProperty($account, IAccountManager::PROPERTY_HEADLINE), 'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY), 'birthdate' => $this->getProperty($account, IAccountManager::PROPERTY_BIRTHDATE), - 'firstDayOfWeek' => $this->config->getUserValue($uid, 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK), - 'timezone' => $this->config->getUserValue($uid, 'core', 'timezone', ''), + 'firstDayOfWeek' => $this->config->getUserValue($user->getUID(), 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK), + 'timezone' => $this->config->getUserValue($user->getUID(), 'core', 'timezone', ''), 'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS), ]; diff --git a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php index 040bab095a1fa..9d434b9682674 100644 --- a/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php +++ b/apps/user_ldap/tests/Integration/Lib/User/IntegrationTestUserAvatar.php @@ -16,6 +16,7 @@ use OCA\User_LDAP\User\User; use OCA\User_LDAP\User_LDAP; use OCA\User_LDAP\UserPluginManager; +use OCP\Files\ISetupManager; use OCP\IAvatarManager; use OCP\IConfig; use OCP\IDBConnection; @@ -60,8 +61,11 @@ private function execFetchTest($dn, $username, $image) { // initialize home folder and make sure that the user will update // also remove an possibly existing avatar - \OC_Util::tearDownFS(); - \OC_Util::setupFS($username); + Server::get(ISetupManager::class)->tearDown(); + $userObj = Server::get(IUserManager::class)->get($username); + if ($userObj !== null) { + Server::get(ISetupManager::class)->setupForUser($userObj); + } \OC::$server->getUserFolder($username); Server::get(IConfig::class)->deleteUserValue($username, 'user_ldap', User::USER_PREFKEY_LASTREFRESH); if (Server::get(IAvatarManager::class)->getAvatar($username)->exists()) { diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 33204e7699da1..873983e742523 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -665,10 +665,6 @@ - - - - @@ -1493,11 +1489,6 @@ - - getUID())]]> - getUID())]]> - getUID())]]> - @@ -2059,52 +2050,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2144,9 +2098,6 @@ - - - @@ -2267,16 +2218,11 @@ - - getUID())]]> - - - @@ -2429,9 +2375,6 @@ - - getUID())]]> - @@ -2925,14 +2868,7 @@ - - - - - - - @@ -2997,24 +2933,6 @@ - - - - - - - - - - - - - - - - - - @@ -3186,11 +3104,6 @@ - - - getUserId())]]> - - diff --git a/core/BackgroundJobs/CheckForUserCertificates.php b/core/BackgroundJobs/CheckForUserCertificates.php index 439a591e89f20..c21fe80cc3f1b 100644 --- a/core/BackgroundJobs/CheckForUserCertificates.php +++ b/core/BackgroundJobs/CheckForUserCertificates.php @@ -13,6 +13,7 @@ use OCP\BackgroundJob\QueuedJob; use OCP\Files\Folder; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\NotFoundException; use OCP\IConfig; use OCP\IUser; @@ -20,9 +21,10 @@ class CheckForUserCertificates extends QueuedJob { public function __construct( - protected IConfig $config, - private IUserManager $userManager, - private IRootFolder $rootFolder, + private readonly IConfig $config, + private readonly IUserManager $userManager, + private readonly IRootFolder $rootFolder, + private readonly ISetupManager $setupManager, ITimeFactory $time, ) { parent::__construct($time); @@ -37,10 +39,10 @@ public function run($argument): void { $this->userManager->callForSeenUsers(function (IUser $user) use (&$uploadList): void { $userId = $user->getUID(); try { - \OC_Util::setupFS($userId); + $this->setupManager->setupForUser($user); $filesExternalUploadsFolder = $this->rootFolder->get($userId . '/files_external/uploads'); } catch (NotFoundException $e) { - \OC_Util::tearDownFS(); + $this->setupManager->tearDown(); return; } if ($filesExternalUploadsFolder instanceof Folder) { @@ -50,7 +52,7 @@ public function run($argument): void { $uploadList[] = "$userId/files_external/uploads/$filename"; } } - \OC_Util::tearDownFS(); + $this->setupManager->tearDown(); }); if (empty($uploadList)) { diff --git a/core/Command/Encryption/ChangeKeyStorageRoot.php b/core/Command/Encryption/ChangeKeyStorageRoot.php index b75b728b2f330..6b0246fa1cdad 100644 --- a/core/Command/Encryption/ChangeKeyStorageRoot.php +++ b/core/Command/Encryption/ChangeKeyStorageRoot.php @@ -11,8 +11,12 @@ use OC\Encryption\Keys\Storage; use OC\Encryption\Util; use OC\Files\Filesystem; -use OC\Files\View; -use OCP\IConfig; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; +use OCP\Files\NotFoundException; +use OCP\IUser; use OCP\IUserManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; @@ -24,17 +28,17 @@ class ChangeKeyStorageRoot extends Command { public function __construct( - protected View $rootView, - protected IUserManager $userManager, - protected IConfig $config, - protected Util $util, - protected QuestionHelper $questionHelper, + private readonly IUserManager $userManager, + private readonly Util $util, + private readonly QuestionHelper $questionHelper, + private readonly ISetupManager $setupManager, + private readonly IRootFolder $rootFolder, ) { parent::__construct(); } #[\Override] - protected function configure() { + protected function configure(): void { parent::configure(); $this ->setName('encryption:change-key-storage-root') @@ -73,25 +77,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int } /** - * move keys to new key storage root + * Move keys to new key storage root. * - * @param string $oldRoot - * @param string $newRoot - * @param OutputInterface $output - * @return bool * @throws \Exception */ - protected function moveAllKeys($oldRoot, $newRoot, OutputInterface $output) { + protected function moveAllKeys(string $oldRoot, string $newRoot, OutputInterface $output): bool { $output->writeln('Start to move keys:'); - if ($this->rootView->is_dir($oldRoot) === false) { + try { + $oldRootFolder = $this->rootFolder->get($oldRoot); + } catch (NotFoundException) { $output->writeln('No old keys found: Nothing needs to be moved'); return false; } + if (!$oldRootFolder instanceof Folder) { + $output->writeln('Old root is not a folder'); + return false; + } + $this->prepareNewRoot($newRoot); - $this->moveSystemKeys($oldRoot, $newRoot); - $this->moveUserKeys($oldRoot, $newRoot, $output); + $this->moveSystemKeys($oldRootFolder, $newRoot); + $this->moveUserKeys($oldRootFolder, $newRoot, $output); return true; } @@ -99,95 +106,76 @@ protected function moveAllKeys($oldRoot, $newRoot, OutputInterface $output) { /** * prepare new key storage * - * @param string $newRoot * @throws \Exception */ - protected function prepareNewRoot($newRoot) { - if ($this->rootView->is_dir($newRoot) === false) { + protected function prepareNewRoot(string $newRoot): void { + if (!$this->rootFolder->nodeExists($newRoot)) { throw new \Exception("New root folder doesn't exist. Please create the folder or check the permissions and try again."); } - $result = $this->rootView->file_put_contents( - $newRoot . '/' . Storage::KEY_STORAGE_MARKER, - 'Nextcloud will detect this folder as key storage root only if this file exists' - ); - - if (!$result) { - throw new \Exception("Can't access the new root folder. Please check the permissions and make sure that the folder is in your data folder"); + /** @var File $node */ + $node = $this->rootFolder->get($newRoot . '/' . Storage::KEY_STORAGE_MARKER); + try { + $node->putContent('Nextcloud will detect this folder as key storage root only if this file exists'); + } catch (\Exception $e) { + throw new \Exception("Can't access the new root folder. Please check the permissions and make sure that the folder is in your data folder", previous: $e); } } /** - * move system key folder - * - * @param string $oldRoot - * @param string $newRoot + * Move system key folder */ - protected function moveSystemKeys($oldRoot, $newRoot) { - if ( - $this->rootView->is_dir($oldRoot . '/files_encryption') - && $this->targetExists($newRoot . '/files_encryption') === false - ) { - $this->rootView->rename($oldRoot . '/files_encryption', $newRoot . '/files_encryption'); + protected function moveSystemKeys(Folder $oldRoot, string $newRoot): void { + try { + $fileEncryptionFolder = $oldRoot->get('files_encryption'); + } catch (NotFoundException) { + return; + } + + if (!$this->targetExists($newRoot . '/files_encryption')) { + $fileEncryptionFolder->move($newRoot . '/files_encryption'); } } /** * setup file system for the given user - * - * @param string $uid */ - protected function setupUserFS($uid) { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($uid); + protected function setupUserFS(IUser $user): void { + $this->setupManager->tearDown(); + $this->setupManager->setupForUser($user); } /** * iterate over each user and move the keys to the new storage - * - * @param string $oldRoot - * @param string $newRoot - * @param OutputInterface $output */ - protected function moveUserKeys($oldRoot, $newRoot, OutputInterface $output) { + protected function moveUserKeys(Folder $oldRootFolder, string $newRoot, OutputInterface $output): void { $progress = new ProgressBar($output); $progress->start(); - foreach ($this->userManager->getBackends() as $backend) { - $limit = 500; - $offset = 0; - do { - $users = $backend->getUsers('', $limit, $offset); - foreach ($users as $user) { - $progress->advance(); - $this->setupUserFS($user); - $this->moveUserEncryptionFolder($user, $oldRoot, $newRoot); - } - $offset += $limit; - } while (count($users) >= $limit); - } + $this->userManager->callForAllUsers(function (IUser $user) use ($progress, $oldRootFolder, $newRoot, $output) { + $progress->advance(); + $this->setupUserFS($user); + $this->moveUserEncryptionFolder($user, $oldRootFolder, $newRoot); + }); $progress->finish(); } /** * move user encryption folder to new root folder * - * @param string $user - * @param string $oldRoot - * @param string $newRoot * @throws \Exception */ - protected function moveUserEncryptionFolder($user, $oldRoot, $newRoot) { - if ($this->userManager->userExists($user)) { - $source = $oldRoot . '/' . $user . '/files_encryption'; - $target = $newRoot . '/' . $user . '/files_encryption'; - if ( - $this->rootView->is_dir($source) - && $this->targetExists($target) === false - ) { - $this->prepareParentFolder($newRoot . '/' . $user); - $this->rootView->rename($source, $target); - } + protected function moveUserEncryptionFolder(IUser $user, Folder $oldRootFolder, string $newRoot): void { + try { + $fileEncryptionFolder = $oldRootFolder->get($user->getUID() . '/files_encryption'); + } catch (NotFoundException) { + return; + } + + $target = $newRoot . '/' . $user->getUID() . '/files_encryption'; + if (!$this->targetExists($target)) { + $this->prepareParentFolder($newRoot . '/' . $user->getUID()); + $fileEncryptionFolder->move($target); } } @@ -196,33 +184,32 @@ protected function moveUserEncryptionFolder($user, $oldRoot, $newRoot) { * * @param string $path relative to data/ */ - protected function prepareParentFolder($path) { + protected function prepareParentFolder(string $path): void { $path = Filesystem::normalizePath($path); // If the file resides within a subdirectory, create it - if ($this->rootView->file_exists($path) === false) { + if ($this->rootFolder->nodeExists($path) === false) { $sub_dirs = explode('/', ltrim($path, '/')); $dir = ''; foreach ($sub_dirs as $sub_dir) { $dir .= '/' . $sub_dir; - if ($this->rootView->file_exists($dir) === false) { - $this->rootView->mkdir($dir); + if ($this->rootFolder->nodeExists($dir) === false) { + $this->rootFolder->newFolder($dir); } } } } /** - * check if target already exists + * Check if target already exists * - * @param $path - * @return bool * @throws \Exception */ - protected function targetExists($path) { - if ($this->rootView->file_exists($path)) { + protected function targetExists(string $path): bool { + try { + $this->rootFolder->get($path); throw new \Exception("new folder '$path' already exists"); + } catch (NotFoundException) { + return false; } - - return false; } } diff --git a/core/Command/Encryption/MigrateKeyStorage.php b/core/Command/Encryption/MigrateKeyStorage.php index 2867f7343290e..ff0a9d6ec879c 100644 --- a/core/Command/Encryption/MigrateKeyStorage.php +++ b/core/Command/Encryption/MigrateKeyStorage.php @@ -11,8 +11,13 @@ use OC\Encryption\Keys\Storage; use OC\Encryption\Util; -use OC\Files\View; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; +use OCP\Files\NotFoundException; use OCP\IConfig; +use OCP\IUser; use OCP\IUserManager; use OCP\Security\ICrypto; use Symfony\Component\Console\Command\Command; @@ -22,11 +27,12 @@ class MigrateKeyStorage extends Command { public function __construct( - protected View $rootView, - protected IUserManager $userManager, - protected IConfig $config, - protected Util $util, - private ICrypto $crypto, + private readonly IUserManager $userManager, + private readonly IConfig $config, + private readonly Util $util, + private readonly ICrypto $crypto, + private readonly ISetupManager $setupManager, + private readonly IRootFolder $rootFolder, ) { parent::__construct(); } @@ -68,31 +74,34 @@ protected function updateKeys(string $root, OutputInterface $output): bool { * Move system key folder */ protected function updateSystemKeys(string $root, OutputInterface $output): void { - if (!$this->rootView->is_dir($root . '/files_encryption')) { - return; + try { + $folder = $this->rootFolder->get($root . '/files_encryption'); + } catch (NotFoundException $e) { + $folder = null; } - $this->traverseKeys($root . '/files_encryption', null, $output); + if ($folder instanceof Folder) { + $this->traverseKeys($folder, null, $output); + } } - private function traverseKeys(string $folder, ?string $uid, OutputInterface $output): void { - $listing = $this->rootView->getDirectoryContent($folder); + private function traverseKeys(Folder $folder, ?Iuser $user, OutputInterface $output): void { + $listing = $folder->getDirectoryListing(); foreach ($listing as $node) { - if ($node['mimetype'] === 'httpd/unix-directory') { + if (!$node instanceof File) { continue; } - if ($node['name'] === 'fileKey' - || str_ends_with($node['name'], '.privateKey') - || str_ends_with($node['name'], '.publicKey') - || str_ends_with($node['name'], '.shareKey')) { - $path = $folder . '/' . $node['name']; - - $content = $this->rootView->file_get_contents($path); + if ($node->getName() === 'fileKey' + || str_ends_with($node->getName(), '.privateKey') + || str_ends_with($node->getName(), '.publicKey') + || str_ends_with($node->getName(), '.shareKey')) { - if ($content === false) { - $output->writeln("Failed to open path $path"); + try { + $content = $node->getContent(); + } catch (\Exception) { + $output->writeln('Failed to open path ' . $node->getPath() . ''); continue; } @@ -105,41 +114,31 @@ private function traverseKeys(string $folder, ?string $uid, OutputInterface $out $data = [ 'key' => base64_encode($content), - 'uid' => $uid, + 'uid' => $user?->getUID() ?? null, ]; $enc = $this->crypto->encrypt(json_encode($data)); - $this->rootView->file_put_contents($path, $enc); + $node->putContent($enc); } } } - private function traverseFileKeys(string $folder, OutputInterface $output): void { - $listing = $this->rootView->getDirectoryContent($folder); + private function traverseFileKeys(Folder $folder, OutputInterface $output): void { + $listing = $folder->getDirectoryListing(); foreach ($listing as $node) { - if ($node['mimetype'] === 'httpd/unix-directory') { - $this->traverseFileKeys($folder . '/' . $node['name'], $output); - } else { - $endsWith = function (string $haystack, string $needle): bool { - $length = strlen($needle); - if ($length === 0) { - return true; - } - - return (substr($haystack, -$length) === $needle); - }; - - if ($node['name'] === 'fileKey' - || $endsWith($node['name'], '.privateKey') - || $endsWith($node['name'], '.publicKey') - || $endsWith($node['name'], '.shareKey')) { - $path = $folder . '/' . $node['name']; + if ($node instanceof Folder) { + $this->traverseFileKeys($node, $output); + } elseif ($node instanceof File) { + if ($node->getName() === 'fileKey' + || str_ends_with($node->getName(), '.privateKey') + || str_ends_with($node->getName(), '.publicKey') + || str_ends_with($node->getName(), '.shareKey')) { - $content = $this->rootView->file_get_contents($path); - - if ($content === false) { - $output->writeln("Failed to open path $path"); + try { + $content = $node->getContent(); + } catch (\Exception) { + $output->writeln('Failed to open path ' . $node->getPath() . ''); continue; } @@ -155,20 +154,12 @@ private function traverseFileKeys(string $folder, OutputInterface $output): void ]; $enc = $this->crypto->encrypt(json_encode($data)); - $this->rootView->file_put_contents($path, $enc); + $node->putContent($enc); } } } } - /** - * setup file system for the given user - */ - protected function setupUserFS(string $uid): void { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($uid); - } - /** * iterate over each user and move the keys to the new storage */ @@ -176,19 +167,12 @@ protected function updateUsersKeys(string $root, OutputInterface $output): void $progress = new ProgressBar($output); $progress->start(); - foreach ($this->userManager->getBackends() as $backend) { - $limit = 500; - $offset = 0; - do { - $users = $backend->getUsers('', $limit, $offset); - foreach ($users as $user) { - $progress->advance(); - $this->setupUserFS($user); - $this->updateUserKeys($root, $user, $output); - } - $offset += $limit; - } while (count($users) >= $limit); - } + $this->userManager->callForAllUsers(function (IUser $user) use ($progress, $root, $output): void { + $progress->advance(); + $this->setupManager->tearDown(); + $this->setupManager->setupForUser($user); + $this->updateUserKeys($root, $user, $output); + }); $progress->finish(); } @@ -197,17 +181,28 @@ protected function updateUsersKeys(string $root, OutputInterface $output): void * * @throws \Exception */ - protected function updateUserKeys(string $root, string $user, OutputInterface $output): void { - if ($this->userManager->userExists($user)) { - $source = $root . '/' . $user . '/files_encryption/OC_DEFAULT_MODULE'; - if ($this->rootView->is_dir($source)) { - $this->traverseKeys($source, $user, $output); - } + protected function updateUserKeys(string $root, IUser $user, OutputInterface $output): void { + $source = $root . '/' . $user->getUID() . '/files_encryption/OC_DEFAULT_MODULE'; + try { + $folder = $this->rootFolder->get($source); + } catch (NotFoundException) { + $folder = null; + } - $source = $root . '/' . $user . '/files_encryption/keys'; - if ($this->rootView->is_dir($source)) { - $this->traverseFileKeys($source, $output); - } + if ($folder instanceof Folder) { + $this->traverseKeys($folder, $user, $output); + } + + $source = $root . '/' . $user->getUID() . '/files_encryption/keys'; + + try { + $folder = $this->rootFolder->get($source); + } catch (NotFoundException) { + $folder = null; + } + + if ($folder instanceof Folder) { + $this->traverseFileKeys($folder, $output); } } } diff --git a/core/Controller/TaskProcessingApiController.php b/core/Controller/TaskProcessingApiController.php index 72811eb044cdf..1aca2be6661b0 100644 --- a/core/Controller/TaskProcessingApiController.php +++ b/core/Controller/TaskProcessingApiController.php @@ -24,9 +24,11 @@ use OCP\Files\IAppData; use OCP\Files\IMimeTypeDetector; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\NotPermittedException; use OCP\IL10N; use OCP\IRequest; +use OCP\IUserManager; use OCP\Lock\LockedException; use OCP\TaskProcessing\Exception\Exception; use OCP\TaskProcessing\Exception\NotFoundException; @@ -53,6 +55,8 @@ public function __construct( private IRootFolder $rootFolder, private IAppData $appData, private IMimeTypeDetector $mimeTypeDetector, + private IUserManager $userManager, + private ISetupManager $setupManager, ) { parent::__construct($appName, $request); } @@ -556,7 +560,10 @@ private function getFileContentsInternal(Task $task, int $fileId): StreamRespons return new DataResponse(['message' => $this->l->t('Not found')], Http::STATUS_NOT_FOUND); } if ($task->getUserId() !== null) { - \OC_Util::setupFS($task->getUserId()); + $user = $this->userManager->get($task->getUserId()); + if ($user !== null) { + $this->setupManager->setupForUser($user); + } } $node = $this->rootFolder->getFirstNodeById($fileId); if ($node === null) { diff --git a/lib/composer/composer/LICENSE b/lib/composer/composer/LICENSE index f27399a042d95..62ecfd8d0046b 100644 --- a/lib/composer/composer/LICENSE +++ b/lib/composer/composer/LICENSE @@ -1,4 +1,3 @@ - Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy @@ -18,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/lib/composer/composer/installed.json b/lib/composer/composer/installed.json index f20a6c47c6d4f..d8ad3e7828fca 100644 --- a/lib/composer/composer/installed.json +++ b/lib/composer/composer/installed.json @@ -1,5 +1,68 @@ { - "packages": [], - "dev": false, - "dev-package-names": [] + "packages": [ + { + "name": "bamarni/composer-bin-plugin", + "version": "1.9.1", + "version_normalized": "1.9.1.0", + "source": { + "type": "git", + "url": "https://github.com/bamarni/composer-bin-plugin.git", + "reference": "641d0663f5ac270b1aeec4337b7856f76204df47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/641d0663f5ac270b1aeec4337b7856f76204df47", + "reference": "641d0663f5ac270b1aeec4337b7856f76204df47", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2.2.26", + "ext-json": "*", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8 || ^2.0", + "phpstan/phpstan-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.0", + "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" + }, + "time": "2026-02-04T10:18:12+00:00", + "type": "composer-plugin", + "extra": { + "class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Bamarni\\Composer\\Bin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "No conflicts for your bin dependencies", + "keywords": [ + "composer", + "conflict", + "dependency", + "executable", + "isolation", + "tool" + ], + "support": { + "issues": "https://github.com/bamarni/composer-bin-plugin/issues", + "source": "https://github.com/bamarni/composer-bin-plugin/tree/1.9.1" + }, + "install-path": "../bamarni/composer-bin-plugin" + } + ], + "dev": true, + "dev-package-names": [ + "bamarni/composer-bin-plugin" + ] } diff --git a/lib/composer/composer/installed.php b/lib/composer/composer/installed.php index 87357f5e32faa..0349aad269547 100644 --- a/lib/composer/composer/installed.php +++ b/lib/composer/composer/installed.php @@ -3,21 +3,30 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '671cec33f134e670bb21c5e3c49c685bd78fc339', + 'reference' => '21fbfa12a01282fa0234cb809c35b8f595b69b53', 'type' => 'library', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), - 'dev' => false, + 'dev' => true, ), 'versions' => array( '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '671cec33f134e670bb21c5e3c49c685bd78fc339', + 'reference' => '21fbfa12a01282fa0234cb809c35b8f595b69b53', 'type' => 'library', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), 'dev_requirement' => false, ), + 'bamarni/composer-bin-plugin' => array( + 'pretty_version' => '1.9.1', + 'version' => '1.9.1.0', + 'reference' => '641d0663f5ac270b1aeec4337b7856f76204df47', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../bamarni/composer-bin-plugin', + 'aliases' => array(), + 'dev_requirement' => true, + ), ), ); diff --git a/lib/private/Command/FileAccess.php b/lib/private/Command/FileAccess.php index a8deeac359e83..55bcc67105691 100644 --- a/lib/private/Command/FileAccess.php +++ b/lib/private/Command/FileAccess.php @@ -8,15 +8,18 @@ namespace OC\Command; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IUser; +use OCP\Server; trait FileAccess { - protected function setupFS(IUser $user) { - \OC_Util::setupFS($user->getUID()); + protected function setupFS(IUser $user): void { + Server::get(ISetupManager::class)->setupForUser($user); } - protected function getUserFolder(IUser $user) { + protected function getUserFolder(IUser $user): void { $this->setupFS($user); - return \OC::$server->getUserFolder($user->getUID()); + Server::get(IRootFolder::class)->getUserFolder($user->getUID()); } } diff --git a/lib/private/Encryption/DecryptAll.php b/lib/private/Encryption/DecryptAll.php index 59d0eb03d28e1..099b4ec87ba30 100644 --- a/lib/private/Encryption/DecryptAll.php +++ b/lib/private/Encryption/DecryptAll.php @@ -14,6 +14,7 @@ use OC\Files\View; use OCP\Encryption\IEncryptionModule; use OCP\Encryption\IManager; +use OCP\Files\ISetupManager; use OCP\IUserManager; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; @@ -27,6 +28,7 @@ public function __construct( protected IManager $encryptionManager, protected IUserManager $userManager, protected View $rootView, + protected ISetupManager $setupManager, ) { } @@ -228,7 +230,10 @@ protected function getTimestamp(): int { * setup user file system */ protected function setupUserFS(string $uid): void { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($uid); + $this->setupManager->tearDown(); + $user = $this->userManager->get($uid); + if ($user !== null) { + $this->setupManager->setupForUser($user); + } } } diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 022467e754877..12cdf5197aaae 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -15,6 +15,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Events\Node\FilesystemTornDownEvent; use OCP\Files\InvalidPathException; +use OCP\Files\ISetupManager; use OCP\Files\Mount\IMountManager; use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; @@ -240,7 +241,7 @@ public static function getMountManager(): Mount\Manager { */ public static function getMountPoint($path) { if (!self::$mounts) { - \OC_Util::setupFS(); + Server::get(ISetupManager::class)->setupRoot(); } $mount = self::$mounts->find($path); return $mount->getMountPoint(); @@ -254,7 +255,7 @@ public static function getMountPoint($path) { */ public static function getMountPoints($path) { if (!self::$mounts) { - \OC_Util::setupFS(); + Server::get(ISetupManager::class)->setupRoot(); } $result = []; $mounts = self::$mounts->findIn($path); @@ -351,8 +352,7 @@ public static function initMountPoints(string|IUser|null $user = ''): void { $userObject = ($user instanceof IUser) ? $user : $userManager->get($user); if ($userObject) { - /** @var SetupManager $setupManager */ - $setupManager = Server::get(SetupManager::class); + $setupManager = Server::get(ISetupManager::class); $setupManager->setupForUser($userObject); } else { throw new NoUserException(); @@ -378,8 +378,8 @@ public static function getView(): ?View { /** * tear down the filesystem, removing all storage providers */ - public static function tearDown() { - \OC_Util::tearDownFS(); + public static function tearDown(): void { + Server::get(ISetupManager::class)->tearDown(); } /** @@ -405,7 +405,7 @@ public static function getRoot() { */ public static function mount($class, $arguments, $mountpoint) { if (!self::$mounts) { - \OC_Util::setupFS(); + Server::get(ISetupManager::class)->setupRoot(); } $mount = new MountPoint($class, $mountpoint, $arguments, self::getLoader()); self::$mounts->addMount($mount); diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php index 304de7f788f6c..12d15f4098e49 100644 --- a/lib/private/Files/SetupManager.php +++ b/lib/private/Files/SetupManager.php @@ -424,9 +424,7 @@ private function setupForUserWith(IUser $user, callable $mountCallback): void { $this->eventLogger->end('fs:setup:user:setup-hook'); } - /** - * Set up the root filesystem - */ + #[Override] public function setupRoot(): void { //setting up the filesystem twice can only lead to trouble if ($this->rootSetup) { diff --git a/lib/private/SpeechToText/TranscriptionJob.php b/lib/private/SpeechToText/TranscriptionJob.php index 75feef20b3f9a..e4d99b2d68aae 100644 --- a/lib/private/SpeechToText/TranscriptionJob.php +++ b/lib/private/SpeechToText/TranscriptionJob.php @@ -14,8 +14,10 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\IUserManager; use OCP\PreConditionNotMetException; use OCP\SpeechToText\Events\TranscriptionFailedEvent; use OCP\SpeechToText\Events\TranscriptionSuccessfulEvent; @@ -30,6 +32,8 @@ public function __construct( private IEventDispatcher $eventDispatcher, private IRootFolder $rootFolder, private LoggerInterface $logger, + private IUserManager $userManager, + private ISetupManager $setupManager, ) { parent::__construct($timeFactory); $this->setAllowParallelRuns(false); @@ -46,7 +50,10 @@ protected function run($argument) { $appId = $argument['appId']; $file = null; try { - \OC_Util::setupFS($owner); + $user = $this->userManager->get($owner); + if ($user !== null) { + $this->setupManager->setupForUser($user); + } $userFolder = $this->rootFolder->getUserFolder($owner); $file = $userFolder->getFirstNodeById($fileId); if (!($file instanceof File)) { diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php index 608856fd27017..625a7b00c477f 100644 --- a/lib/private/TaskProcessing/Manager.php +++ b/lib/private/TaskProcessing/Manager.php @@ -30,6 +30,7 @@ use OCP\Files\IAppData; use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Files\Node; use OCP\Files\NotPermittedException; use OCP\Files\SimpleFS\ISimpleFile; @@ -163,6 +164,7 @@ public function __construct( ICacheFactory $cacheFactory, private IFactory $l10nFactory, private ITimeFactory $timeFactory, + private ISetupManager $setupManager, ) { $this->appData = $appDataFactory->get('core'); $this->distributedCache = $cacheFactory->createDistributed('task_processing::'); @@ -1484,7 +1486,10 @@ public function claimNextScheduledTask(array $taskTypeIds = []): ?Task { */ public function fillInputFileData(?string $userId, array $input, ...$specs): array { if ($userId !== null) { - \OC_Util::setupFS($userId); + $user = $this->userManager->get($userId); + if ($user !== null) { + $this->setupManager->setupForUser($user); + } } $newInputOutput = []; $spec = array_reduce($specs, fn ($carry, $spec) => $carry + $spec, []); diff --git a/lib/private/legacy/OC_User.php b/lib/private/legacy/OC_User.php index 1cc3b343832b1..67e6a51b7e083 100644 --- a/lib/private/legacy/OC_User.php +++ b/lib/private/legacy/OC_User.php @@ -18,6 +18,8 @@ use OCP\Authentication\IProvideUserSecretBackend; use OCP\Authentication\Token\IToken; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IGroupManager; use OCP\IRequest; use OCP\ISession; @@ -193,7 +195,11 @@ public static function loginWithApache(IApacheBackend $backend): bool { } // setup the filesystem - OC_Util::setupFS($uid); + $user = Server::get(IUserManager::class)->get($uid); + if ($user) { + Server::get(ISetupManager::class)->setupForUser($user); + } + // first call the post_login hooks, the login-process needs to be // completed before we can safely create the users folder. // For example encryption needs to initialize the users keys first @@ -208,14 +214,14 @@ public static function loginWithApache(IApacheBackend $backend): bool { ] ); $dispatcher->dispatchTyped(new UserLoggedInEvent( - Server::get(IUserManager::class)->get($uid), + $user, $uid, null, false) ); - //trigger creation of user home and /files folder - \OC::$server->getUserFolder($uid); + // trigger creation of user home and /files folder + Server::get(IRootFolder::class)->getUserFolder($uid); } return true; } diff --git a/lib/public/Files/ISetupManager.php b/lib/public/Files/ISetupManager.php index 1519b2709d89c..40735b9bf2a51 100644 --- a/lib/public/Files/ISetupManager.php +++ b/lib/public/Files/ISetupManager.php @@ -57,4 +57,11 @@ public function setupForPath(string $path, bool $includeChildren = false): void; * @since 34.0.0 */ public function isSetupComplete(IUser $user): bool; + + /** + * Set up the root filesystem (without any user-specific mounts). + * + * @since 35.0.0 + */ + public function setupRoot(): void; } diff --git a/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php b/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php index f831a6e181fa0..596dcb9d11377 100644 --- a/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php +++ b/tests/Core/Command/Encryption/ChangeKeyStorageRootTest.php @@ -11,10 +11,13 @@ use OC\Core\Command\Encryption\ChangeKeyStorageRoot; use OC\Encryption\Keys\Storage; use OC\Encryption\Util; -use OC\Files\View; -use OCP\IConfig; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; +use OCP\Files\NotFoundException; +use OCP\IUser; use OCP\IUserManager; -use OCP\UserInterface; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; @@ -22,23 +25,17 @@ use Test\TestCase; class ChangeKeyStorageRootTest extends TestCase { - /** @var ChangeKeyStorageRoot */ - protected $changeKeyStorageRoot; + protected ChangeKeyStorageRoot $changeKeyStorageRoot; - /** @var View | \PHPUnit\Framework\MockObject\MockObject */ - protected $view; + protected IUserManager&\PHPUnit\Framework\MockObject\MockObject $userManager; - /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */ - protected $userManager; + protected Util&\PHPUnit\Framework\MockObject\MockObject $util; - /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */ - protected $config; + protected QuestionHelper&\PHPUnit\Framework\MockObject\MockObject $questionHelper; - /** @var Util | \PHPUnit\Framework\MockObject\MockObject */ - protected $util; + protected ISetupManager&\PHPUnit\Framework\MockObject\MockObject $setupManager; - /** @var QuestionHelper | \PHPUnit\Framework\MockObject\MockObject */ - protected $questionHelper; + protected IRootFolder&\PHPUnit\Framework\MockObject\MockObject $rootFolder; /** @var InputInterface | \PHPUnit\Framework\MockObject\MockObject */ protected $inputInterface; @@ -46,21 +43,17 @@ class ChangeKeyStorageRootTest extends TestCase { /** @var OutputInterface | \PHPUnit\Framework\MockObject\MockObject */ protected $outputInterface; - /** @var UserInterface|\PHPUnit\Framework\MockObject\MockObject */ - protected $userInterface; - #[\Override] protected function setUp(): void { parent::setUp(); - $this->view = $this->getMockBuilder(View::class)->getMock(); $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock(); - $this->config = $this->getMockBuilder(IConfig::class)->getMock(); $this->util = $this->getMockBuilder('OC\Encryption\Util')->disableOriginalConstructor()->getMock(); $this->questionHelper = $this->getMockBuilder(QuestionHelper::class)->getMock(); + $this->setupManager = $this->getMockBuilder(ISetupManager::class)->getMock(); + $this->rootFolder = $this->getMockBuilder(IRootFolder::class)->getMock(); $this->inputInterface = $this->getMockBuilder(InputInterface::class)->getMock(); $this->outputInterface = $this->getMockBuilder(OutputInterface::class)->getMock(); - $this->userInterface = $this->getMockBuilder(UserInterface::class)->getMock(); /* We need format method to return a string */ $outputFormatter = $this->createMock(OutputFormatterInterface::class); @@ -71,11 +64,11 @@ protected function setUp(): void { ->willReturn($outputFormatter); $this->changeKeyStorageRoot = new ChangeKeyStorageRoot( - $this->view, $this->userManager, - $this->config, $this->util, - $this->questionHelper + $this->questionHelper, + $this->setupManager, + $this->rootFolder, ); } @@ -84,11 +77,11 @@ public function testExecute($newRoot, $answer, $successMoveKey): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ - $this->view, $this->userManager, - $this->config, $this->util, - $this->questionHelper + $this->questionHelper, + $this->setupManager, + $this->rootFolder, ] )->onlyMethods(['moveAllKeys'])->getMock(); @@ -138,96 +131,111 @@ public function testMoveAllKeys(): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ - $this->view, $this->userManager, - $this->config, $this->util, - $this->questionHelper + $this->questionHelper, + $this->setupManager, + $this->rootFolder, ] )->onlyMethods(['prepareNewRoot', 'moveSystemKeys', 'moveUserKeys'])->getMock(); + $oldRootFolder = $this->createMock(Folder::class); + $this->rootFolder->expects($this->once())->method('get') + ->with('oldRoot') + ->willReturn($oldRootFolder); + $changeKeyStorageRoot->expects($this->once())->method('prepareNewRoot')->with('newRoot'); - $changeKeyStorageRoot->expects($this->once())->method('moveSystemKeys')->with('oldRoot', 'newRoot'); - $changeKeyStorageRoot->expects($this->once())->method('moveUserKeys')->with('oldRoot', 'newRoot', $this->outputInterface); + $changeKeyStorageRoot->expects($this->once())->method('moveSystemKeys')->with($oldRootFolder, 'newRoot'); + $changeKeyStorageRoot->expects($this->once())->method('moveUserKeys')->with($oldRootFolder, 'newRoot', $this->outputInterface); $this->invokePrivate($changeKeyStorageRoot, 'moveAllKeys', ['oldRoot', 'newRoot', $this->outputInterface]); } public function testPrepareNewRoot(): void { - $this->view->expects($this->once())->method('is_dir')->with('newRoot') + $this->rootFolder->expects($this->once())->method('nodeExists')->with('newRoot') ->willReturn(true); - $this->view->expects($this->once())->method('file_put_contents') - ->with('newRoot/' . Storage::KEY_STORAGE_MARKER, - 'Nextcloud will detect this folder as key storage root only if this file exists')->willReturn(true); + $file = $this->createMock(File::class); + $this->rootFolder->expects($this->once())->method('get') + ->with('newRoot/' . Storage::KEY_STORAGE_MARKER) + ->willReturn($file); + $file->expects($this->once())->method('putContent') + ->with('Nextcloud will detect this folder as key storage root only if this file exists'); $this->invokePrivate($this->changeKeyStorageRoot, 'prepareNewRoot', ['newRoot']); } - /** - * - * @param bool $dirExists - * @param bool $couldCreateFile - */ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestPrepareNewRootException')] - public function testPrepareNewRootException($dirExists, $couldCreateFile): void { + public function testPrepareNewRootException(bool $dirExists, bool $putContentFails): void { $this->expectException(\Exception::class); - $this->view->expects($this->once())->method('is_dir')->with('newRoot') - ->willReturn($dirExists); - $this->view->expects($this->any())->method('file_put_contents')->willReturn($couldCreateFile); + $this->rootFolder->method('nodeExists')->with('newRoot')->willReturn($dirExists); + + if ($dirExists) { + $file = $this->createMock(File::class); + $this->rootFolder->method('get')->willReturn($file); + if ($putContentFails) { + $file->method('putContent')->willThrowException(new \Exception('write error')); + } + } $this->invokePrivate($this->changeKeyStorageRoot, 'prepareNewRoot', ['newRoot']); } public static function dataTestPrepareNewRootException(): array { return [ - [true, false], - [true, null], - [false, true] + [false, false], + [true, true], ]; } /** * - * @param bool $dirExists + * @param bool $folderExists * @param bool $targetExists - * @param bool $executeRename + * @param bool $executeMove */ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestMoveSystemKeys')] - public function testMoveSystemKeys($dirExists, $targetExists, $executeRename): void { + public function testMoveSystemKeys(bool $folderExists, bool $targetExists, bool $executeMove): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ - $this->view, $this->userManager, - $this->config, $this->util, - $this->questionHelper + $this->questionHelper, + $this->setupManager, + $this->rootFolder, ] )->onlyMethods(['targetExists'])->getMock(); - $this->view->expects($this->once())->method('is_dir') - ->with('oldRoot/files_encryption')->willReturn($dirExists); - $changeKeyStorageRoot->expects($this->any())->method('targetExists') - ->with('newRoot/files_encryption')->willReturn($targetExists); + $oldRoot = $this->createMock(Folder::class); + $fileEncryptionNode = $this->createMock(Folder::class); + + if ($folderExists) { + $oldRoot->method('get')->with('files_encryption')->willReturn($fileEncryptionNode); + } else { + $oldRoot->method('get')->willThrowException(new NotFoundException()); + } + + $changeKeyStorageRoot->method('targetExists') + ->with('newRoot/files_encryption') + ->willReturn($targetExists); - if ($executeRename) { - $this->view->expects($this->once())->method('rename') - ->with('oldRoot/files_encryption', 'newRoot/files_encryption'); + if ($executeMove) { + $fileEncryptionNode->expects($this->once())->method('move') + ->with('newRoot/files_encryption'); } else { - $this->view->expects($this->never())->method('rename'); + $fileEncryptionNode->expects($this->never())->method('move'); } - $this->invokePrivate($changeKeyStorageRoot, 'moveSystemKeys', ['oldRoot', 'newRoot']); + $this->invokePrivate($changeKeyStorageRoot, 'moveSystemKeys', [$oldRoot, 'newRoot']); } public static function dataTestMoveSystemKeys(): array { return [ [true, false, true], - [false, true, false], [true, true, false], - [false, false, false] + [false, false, false], ]; } @@ -235,82 +243,93 @@ public function testMoveUserKeys(): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ - $this->view, $this->userManager, - $this->config, $this->util, - $this->questionHelper + $this->questionHelper, + $this->setupManager, + $this->rootFolder, ] )->onlyMethods(['setupUserFS', 'moveUserEncryptionFolder'])->getMock(); - $this->userManager->expects($this->once())->method('getBackends') - ->willReturn([$this->userInterface]); - $this->userInterface->expects($this->once())->method('getUsers') - ->willReturn(['user1', 'user2']); + $oldRootFolder = $this->createMock(Folder::class); + + $user1 = $this->createMock(IUser::class); + $user2 = $this->createMock(IUser::class); + + $this->userManager->expects($this->once())->method('callForAllUsers') + ->willReturnCallback(function (callable $callback) use ($user1, $user2): void { + $callback($user1); + $callback($user2); + }); + $changeKeyStorageRoot->expects($this->exactly(2))->method('setupUserFS'); $changeKeyStorageRoot->expects($this->exactly(2))->method('moveUserEncryptionFolder'); - $this->invokePrivate($changeKeyStorageRoot, 'moveUserKeys', ['oldRoot', 'newRoot', $this->outputInterface]); + $this->invokePrivate($changeKeyStorageRoot, 'moveUserKeys', [$oldRootFolder, 'newRoot', $this->outputInterface]); } /** * - * @param bool $userExists - * @param bool $isDir + * @param bool $folderExists * @param bool $targetExists - * @param bool $shouldRename + * @param bool $shouldMove */ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestMoveUserEncryptionFolder')] - public function testMoveUserEncryptionFolder($userExists, $isDir, $targetExists, $shouldRename): void { + public function testMoveUserEncryptionFolder(bool $folderExists, bool $targetExists, bool $shouldMove): void { $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot') ->setConstructorArgs( [ - $this->view, $this->userManager, - $this->config, $this->util, - $this->questionHelper + $this->questionHelper, + $this->setupManager, + $this->rootFolder, ] )->onlyMethods(['targetExists', 'prepareParentFolder'])->getMock(); - $this->userManager->expects($this->once())->method('userExists') - ->willReturn($userExists); - $this->view->expects($this->any())->method('is_dir') - ->willReturn($isDir); - $changeKeyStorageRoot->expects($this->any())->method('targetExists') - ->willReturn($targetExists); + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('user1'); + + $oldRootFolder = $this->createMock(Folder::class); + $fileEncryptionFolder = $this->createMock(Folder::class); + + if ($folderExists) { + $oldRootFolder->method('get') + ->with('user1/files_encryption') + ->willReturn($fileEncryptionFolder); + } else { + $oldRootFolder->method('get')->willThrowException(new NotFoundException()); + } + + $changeKeyStorageRoot->method('targetExists')->willReturn($targetExists); - if ($shouldRename) { + if ($shouldMove) { $changeKeyStorageRoot->expects($this->once())->method('prepareParentFolder') ->with('newRoot/user1'); - $this->view->expects($this->once())->method('rename') - ->with('oldRoot/user1/files_encryption', 'newRoot/user1/files_encryption'); + $fileEncryptionFolder->expects($this->once())->method('move') + ->with('newRoot/user1/files_encryption'); } else { $changeKeyStorageRoot->expects($this->never())->method('prepareParentFolder'); - $this->view->expects($this->never())->method('rename'); + $fileEncryptionFolder->expects($this->never())->method('move'); } - $this->invokePrivate($changeKeyStorageRoot, 'moveUserEncryptionFolder', ['user1', 'oldRoot', 'newRoot']); + $this->invokePrivate($changeKeyStorageRoot, 'moveUserEncryptionFolder', [$user, $oldRootFolder, 'newRoot']); } public static function dataTestMoveUserEncryptionFolder(): array { return [ - [true, true, false, true], - [true, false, true, false], - [false, true, true, false], - [false, false, true, false], - [false, true, false, false], - [false, true, true, false], - [false, false, false, false] + [true, false, true], + [true, true, false], + [false, false, false], ]; } #[\PHPUnit\Framework\Attributes\DataProvider('dataTestPrepareParentFolder')] public function testPrepareParentFolder($path, $pathExists): void { - $this->view->expects($this->any())->method('file_exists') + $this->rootFolder->expects($this->any())->method('nodeExists') ->willReturnCallback( - function ($fileExistsPath) use ($path, $pathExists) { - if ($path === $fileExistsPath) { + function (string $nodeExistsPath) use ($path, $pathExists): bool { + if ($path === $nodeExistsPath) { return $pathExists; } return false; @@ -319,9 +338,9 @@ function ($fileExistsPath) use ($path, $pathExists) { if ($pathExists === false) { $subDirs = explode('/', ltrim($path, '/')); - $this->view->expects($this->exactly(count($subDirs)))->method('mkdir'); + $this->rootFolder->expects($this->exactly(count($subDirs)))->method('newFolder'); } else { - $this->view->expects($this->never())->method('mkdir'); + $this->rootFolder->expects($this->never())->method('newFolder'); } $this->invokePrivate( @@ -339,8 +358,8 @@ public static function dataTestPrepareParentFolder(): array { } public function testTargetExists(): void { - $this->view->expects($this->once())->method('file_exists')->with('path') - ->willReturn(false); + $this->rootFolder->expects($this->once())->method('get')->with('path') + ->willThrowException(new NotFoundException()); $this->assertFalse( $this->invokePrivate($this->changeKeyStorageRoot, 'targetExists', ['path']) @@ -350,8 +369,9 @@ public function testTargetExists(): void { public function testTargetExistsException(): void { $this->expectException(\Exception::class); - $this->view->expects($this->once())->method('file_exists')->with('path') - ->willReturn(true); + $node = $this->createMock(\OCP\Files\Node::class); + $this->rootFolder->expects($this->once())->method('get')->with('path') + ->willReturn($node); $this->invokePrivate($this->changeKeyStorageRoot, 'targetExists', ['path']); } diff --git a/tests/lib/Command/AsyncBusTestCase.php b/tests/lib/Command/AsyncBusTestCase.php index 7682a27abea8c..c945c2bd777b1 100644 --- a/tests/lib/Command/AsyncBusTestCase.php +++ b/tests/lib/Command/AsyncBusTestCase.php @@ -15,7 +15,7 @@ class SimpleCommand implements ICommand { #[\Override] - public function handle() { + public function handle(): void { AsyncBusTestCase::$lastCommand = 'SimpleCommand'; } } @@ -27,7 +27,7 @@ public function __construct( } #[\Override] - public function handle() { + public function handle(): void { AsyncBusTestCase::$lastCommand = $this->state; } } @@ -36,7 +36,7 @@ class FilesystemCommand implements ICommand { use FileAccess; #[\Override] - public function handle() { + public function handle(): void { AsyncBusTestCase::$lastCommand = 'FileAccess'; } } diff --git a/tests/lib/Encryption/DecryptAllTest.php b/tests/lib/Encryption/DecryptAllTest.php index 27b13b7da3b5c..c7de76bc87522 100644 --- a/tests/lib/Encryption/DecryptAllTest.php +++ b/tests/lib/Encryption/DecryptAllTest.php @@ -15,6 +15,7 @@ use OC\Encryption\Manager; use OC\Files\FileInfo; use OC\Files\View; +use OCP\Files\ISetupManager; use OCP\Files\Storage\IStorage; use OCP\IUserManager; use OCP\UserInterface; @@ -36,6 +37,7 @@ class DecryptAllTest extends TestCase { private IUserManager&MockObject $userManager; private Manager&MockObject $encryptionManager; private View&MockObject $view; + private ISetupManager&MockObject $setupManager; private InputInterface&MockObject $inputInterface; private OutputInterface&MockObject $outputInterface; private UserInterface&MockObject $userInterface; @@ -52,6 +54,7 @@ protected function setUp(): void { ->disableOriginalConstructor()->getMock(); $this->view = $this->getMockBuilder(View::class) ->disableOriginalConstructor()->getMock(); + $this->setupManager = $this->createMock(ISetupManager::class); $this->inputInterface = $this->getMockBuilder(InputInterface::class) ->disableOriginalConstructor()->getMock(); $this->outputInterface = $this->getMockBuilder(OutputInterface::class) @@ -69,7 +72,7 @@ protected function setUp(): void { $this->outputInterface->expects($this->any())->method('getFormatter') ->willReturn($outputFormatter); - $this->instance = new DecryptAll($this->encryptionManager, $this->userManager, $this->view); + $this->instance = new DecryptAll($this->encryptionManager, $this->userManager, $this->view, $this->setupManager); $this->invokePrivate($this->instance, 'input', [$this->inputInterface]); $this->invokePrivate($this->instance, 'output', [$this->outputInterface]); @@ -98,7 +101,8 @@ public function testDecryptAll(bool $prepareResult, string $user, bool $userExis [ $this->encryptionManager, $this->userManager, - $this->view + $this->view, + $this->setupManager, ] ) ->onlyMethods(['prepareEncryptionModules', 'decryptAllUsersFiles']) @@ -181,7 +185,8 @@ public function testDecryptAllUsersFiles($user): void { [ $this->encryptionManager, $this->userManager, - $this->view + $this->view, + $this->setupManager, ] ) ->onlyMethods(['decryptUsersFiles']) @@ -227,7 +232,8 @@ public function testDecryptUsersFiles(): void { [ $this->encryptionManager, $this->userManager, - $this->view + $this->view, + $this->setupManager, ] ) ->onlyMethods(['decryptFile']) @@ -309,7 +315,8 @@ public function testDecryptFile($isEncrypted): void { [ $this->encryptionManager, $this->userManager, - $this->view + $this->view, + $this->setupManager, ] ) ->onlyMethods(['getTimestamp']) @@ -349,7 +356,8 @@ public function testDecryptFileFailure(): void { [ $this->encryptionManager, $this->userManager, - $this->view + $this->view, + $this->setupManager, ] ) ->onlyMethods(['getTimestamp']) diff --git a/tests/lib/Files/Node/HookConnectorTest.php b/tests/lib/Files/Node/HookConnectorTest.php index 425c94fc9d740..522cfec64df4c 100644 --- a/tests/lib/Files/Node/HookConnectorTest.php +++ b/tests/lib/Files/Node/HookConnectorTest.php @@ -31,6 +31,7 @@ use OCP\Files\Events\Node\NodeRenamedEvent; use OCP\Files\Events\Node\NodeTouchedEvent; use OCP\Files\Events\Node\NodeWrittenEvent; +use OCP\Files\ISetupManager; use OCP\Files\Node; use OCP\IAppConfig; use OCP\ICacheFactory; @@ -100,7 +101,7 @@ protected function setUp(): void { protected function tearDown(): void { parent::tearDown(); \OC_Hook::clear('OC_Filesystem'); - \OC_Util::tearDownFS(); + Server::get(ISetupManager::class)->tearDown(); } public static function viewToNodeProvider(): array { diff --git a/tests/lib/Lockdown/Filesystem/NoFSTest.php b/tests/lib/Lockdown/Filesystem/NoFSTest.php index b4ec22cf4cab3..ac2f04741ff73 100644 --- a/tests/lib/Lockdown/Filesystem/NoFSTest.php +++ b/tests/lib/Lockdown/Filesystem/NoFSTest.php @@ -11,6 +11,7 @@ use OC\Files\Filesystem; use OC\Lockdown\Filesystem\NullStorage; use OCP\Authentication\Token\IToken; +use OCP\Files\ISetupManager; use OCP\Lockdown\ILockdownManager; use OCP\Server; use Test\Traits\UserTrait; @@ -38,12 +39,12 @@ protected function setUp(): void { ]); Server::get(ILockdownManager::class)->setToken($token); - $this->createUser('foo', 'var'); } public function testSetupFS(): void { - \OC_Util::tearDownFS(); - \OC_Util::setupFS('foo'); + $user = $this->createUser('foo', 'var'); + Server::get(ISetupManager::class)->tearDown(); + Server::get(ISetupManager::class)->setupForUser($user); $this->assertInstanceOf(NullStorage::class, Filesystem::getStorage('/foo/files')); } diff --git a/tests/lib/Security/CertificateManagerTest.php b/tests/lib/Security/CertificateManagerTest.php index 61a14e2351e1a..8202233b6dd9d 100644 --- a/tests/lib/Security/CertificateManagerTest.php +++ b/tests/lib/Security/CertificateManagerTest.php @@ -10,14 +10,15 @@ namespace Test\Security; -use OC\Files\Filesystem; use OC\Files\Storage\Temporary; use OC\Files\View; use OC\Security\Certificate; use OC\Security\CertificateManager; use OCP\Files\InvalidPathException; +use OCP\Files\ISetupManager; use OCP\IConfig; use OCP\IUserManager; +use OCP\IUserSession; use OCP\Security\ISecureRandom; use OCP\Server; use PHPUnit\Framework\MockObject\MockObject; @@ -45,10 +46,10 @@ protected function setUp(): void { $storage = new Temporary(); $this->registerMount($this->username, $storage, '/' . $this->username . '/'); - \OC_Util::tearDownFS(); - \OC_User::setUserId($this->username); - Filesystem::tearDown(); - \OC_Util::setupFS($this->username); + Server::get(ISetupManager::class)->tearDown(); + $user = Server::get(IUserManager::class)->get($this->username); + Server::get(IUserSession::class)->setUser($user); + Server::get(ISetupManager::class)->setupForUser($user); $config = $this->createMock(IConfig::class); $config->expects($this->any())->method('getSystemValueBool') diff --git a/tests/lib/TaskProcessing/TaskProcessingTest.php b/tests/lib/TaskProcessing/TaskProcessingTest.php index 8dc361dd20fb4..4f9c2a096f317 100644 --- a/tests/lib/TaskProcessing/TaskProcessingTest.php +++ b/tests/lib/TaskProcessing/TaskProcessingTest.php @@ -23,6 +23,7 @@ use OCP\Files\Config\IUserMountCache; use OCP\Files\File; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\Http\Client\IClientService; use OCP\IAppConfig; use OCP\ICacheFactory; @@ -856,6 +857,7 @@ protected function setUp(): void { Server::get(ICacheFactory::class), Server::get(IFactory::class), Server::get(ITimeFactory::class), + Server::get(ISetupManager::class), ); } diff --git a/tests/lib/TestCase.php b/tests/lib/TestCase.php index aa091b98113ef..1955d8d8c1ab8 100644 --- a/tests/lib/TestCase.php +++ b/tests/lib/TestCase.php @@ -27,6 +27,7 @@ use OCP\Command\IBus; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\IRootFolder; +use OCP\Files\ISetupManager; use OCP\IAppConfig; use OCP\IConfig; use OCP\IDBConnection; @@ -259,12 +260,8 @@ protected static function invokePrivate($object, $methodName, array $parameters /** * Returns a unique identifier as uniqid() is not reliable sometimes - * - * @param string $prefix - * @param int $length - * @return string */ - protected static function getUniqueID($prefix = '', $length = 13) { + protected static function getUniqueID(string $prefix = '', int $length = 13): string { return $prefix . Server::get(ISecureRandom::class)->generate( $length, // Do not use dots and slashes as we use the value for file names @@ -332,8 +329,7 @@ public static function tearDownAfterClass(): void { /** @psalm-suppress DeprecatedMethod */ unset(\OC::$server[Updater::class]); - /** @var SetupManager $setupManager */ - $setupManager = Server::get(SetupManager::class); + $setupManager = Server::get(ISetupManager::class); $setupManager->tearDown(); /** @var MountProviderCollection $mountProviderCollection */ @@ -347,6 +343,7 @@ public static function tearDownAfterClass(): void { $objectStoreConfig = Server::get(PrimaryObjectStoreConfig::class); $mountProviderCollection->registerRootProvider(new RootMountProvider($objectStoreConfig, $config)); + /** @var SetupManager $setupManager */ $setupManager->setupRoot(); parent::tearDownAfterClass(); @@ -447,10 +444,10 @@ protected static function tearDownAfterClassCleanStrayLocks(): void { */ protected static function loginAsUser(string $user = ''): void { self::logout(); - Filesystem::tearDown(); + $setupManager = Server::get(ISetupManager::class); + $setupManager->tearDown(); \OC_User::setUserId($user); $userManager = Server::get(IUserManager::class); - $setupManager = Server::get(SetupManager::class); $userObject = $userManager->get($user); if (!is_null($userObject)) { $userObject->updateLastLoginTimestamp(); diff --git a/tests/lib/Traits/EncryptionTrait.php b/tests/lib/Traits/EncryptionTrait.php index 7b3c016d52276..585355a7a8587 100644 --- a/tests/lib/Traits/EncryptionTrait.php +++ b/tests/lib/Traits/EncryptionTrait.php @@ -17,6 +17,7 @@ use OCA\Encryption\Users\Setup; use OCP\App\IAppManager; use OCP\Encryption\IManager; +use OCP\Files\IRootFolder; use OCP\Files\ISetupManager; use OCP\IAppConfig; use OCP\IConfig; @@ -42,21 +43,11 @@ abstract protected static function assertTrue($condition, string $message = ''): private IUserManager $userManagerEncTrait; private ISetupManager $setupManagerEncTrait; - - /** - * @var IConfig - */ - private $config; - + private ?IConfig $config = null; private IAppConfig $appConfig; - - /** - * @var Application - */ - private $encryptionApp; + private Application $encryptionApp; protected function loginWithEncryption($user = '') { - \OC_Util::tearDownFS(); \OC_User::setUserId(''); // needed for fully logout Server::get(IUserSession::class)->setUser(null); @@ -65,29 +56,29 @@ protected function loginWithEncryption($user = '') { \OC_User::setUserId($user); $this->postLogin(); - \OC_Util::setupFS($user); + $this->setupManagerEncTrait->setupForUser($this->userManagerEncTrait->get($user)); if ($this->userManagerEncTrait->userExists($user)) { - \OC::$server->getUserFolder($user); + Server::get(IRootFolder::class)->getUserFolder($user); } } - protected function setupForUser($name, $password) { + protected function setupForUser(string $name, string $password): void { $this->setupManagerEncTrait->tearDown(); $this->setupManagerEncTrait->setupForUser($this->userManagerEncTrait->get($name)); $container = $this->encryptionApp->getContainer(); /** @var KeyManager $keyManager */ - $keyManager = $container->query(KeyManager::class); + $keyManager = $container->get(KeyManager::class); /** @var Setup $userSetup */ - $userSetup = $container->query(Setup::class); + $userSetup = $container->get(Setup::class); $userSetup->setupUser($name, $password); - $encryptionManager = $container->query(IManager::class); + $encryptionManager = $container->get(IManager::class); $this->encryptionApp->setUp($encryptionManager); $keyManager->init($name, $password); $this->invokePrivate($keyManager, 'keyUid', [$name]); } - protected function postLogin() { + protected function postLogin(): void { $encryptionWrapper = new EncryptionWrapper( new ArrayCache(), Server::get(\OCP\Encryption\IManager::class), @@ -97,7 +88,7 @@ protected function postLogin() { $this->registerStorageWrapper('oc_encryption', [$encryptionWrapper, 'wrapStorage']); } - protected function setUpEncryptionTrait() { + protected function setUpEncryptionTrait(): void { $isReady = Server::get(\OCP\Encryption\IManager::class)->isReady(); if (!$isReady) { $this->markTestSkipped('Encryption not ready'); @@ -108,18 +99,18 @@ protected function setUpEncryptionTrait() { Server::get(IAppManager::class)->loadApp('encryption'); - $this->encryptionApp = new Application([], $isReady); + $this->encryptionApp = new Application([]); $this->config = Server::get(IConfig::class); $this->appConfig = Server::get(IAppConfig::class); $this->encryptionWasEnabled = $this->appConfig->getValueBool('core', 'encryption_enabled'); - $this->originalEncryptionModule = $this->config->getAppValue('core', 'default_encryption_module'); + $this->originalEncryptionModule = $this->appConfig->getValueString('core', 'default_encryption_module'); $this->config->setAppValue('core', 'default_encryption_module', Encryption::ID); $this->appConfig->setValueBool('core', 'encryption_enabled', true); $this->assertTrue(Server::get(\OCP\Encryption\IManager::class)->isEnabled()); } - protected function tearDownEncryptionTrait() { + protected function tearDownEncryptionTrait(): void { if ($this->config) { $this->appConfig->setValueBool('core', 'encryption_enabled', $this->encryptionWasEnabled); $this->config->setAppValue('core', 'default_encryption_module', $this->originalEncryptionModule);