diff options
Diffstat (limited to 'apps/files/lib')
-rw-r--r-- | apps/files/lib/AppInfo/Application.php | 8 | ||||
-rw-r--r-- | apps/files/lib/Command/Copy.php | 7 | ||||
-rw-r--r-- | apps/files/lib/Command/Move.php | 7 | ||||
-rw-r--r-- | apps/files/lib/Command/TransferOwnership.php | 46 | ||||
-rw-r--r-- | apps/files/lib/Service/OwnershipTransferService.php | 79 | ||||
-rw-r--r-- | apps/files/lib/Service/UserConfig.php | 6 |
6 files changed, 120 insertions, 33 deletions
diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php index 4b3948d43b5..32c072ef0f4 100644 --- a/apps/files/lib/AppInfo/Application.php +++ b/apps/files/lib/AppInfo/Application.php @@ -132,7 +132,6 @@ class Application extends App implements IBootstrap { public function boot(IBootContext $context): void { $context->injectFn(Closure::fromCallable([$this, 'registerCollaboration'])); $context->injectFn([Listener::class, 'register']); - $this->registerTemplates(); $this->registerHooks(); } @@ -140,13 +139,6 @@ class Application extends App implements IBootstrap { $providerManager->registerResourceProvider(ResourceProvider::class); } - private function registerTemplates(): void { - $templateManager = \OC_Helper::getFileTemplateManager(); - $templateManager->registerTemplate('application/vnd.oasis.opendocument.presentation', 'core/templates/filetemplates/template.odp'); - $templateManager->registerTemplate('application/vnd.oasis.opendocument.text', 'core/templates/filetemplates/template.odt'); - $templateManager->registerTemplate('application/vnd.oasis.opendocument.spreadsheet', 'core/templates/filetemplates/template.ods'); - } - private function registerHooks(): void { Util::connectHook('\OCP\Config', 'js', '\OCA\Files\App', 'extendJsConfig'); } diff --git a/apps/files/lib/Command/Copy.php b/apps/files/lib/Command/Copy.php index e51a1689907..ad0dfa90de1 100644 --- a/apps/files/lib/Command/Copy.php +++ b/apps/files/lib/Command/Copy.php @@ -19,10 +19,9 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; class Copy extends Command { - private FileUtils $fileUtils; - - public function __construct(FileUtils $fileUtils) { - $this->fileUtils = $fileUtils; + public function __construct( + private FileUtils $fileUtils, + ) { parent::__construct(); } diff --git a/apps/files/lib/Command/Move.php b/apps/files/lib/Command/Move.php index cd9e56f8e29..29dd8860b2a 100644 --- a/apps/files/lib/Command/Move.php +++ b/apps/files/lib/Command/Move.php @@ -20,10 +20,9 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; class Move extends Command { - private FileUtils $fileUtils; - - public function __construct(FileUtils $fileUtils) { - $this->fileUtils = $fileUtils; + public function __construct( + private FileUtils $fileUtils, + ) { parent::__construct(); } diff --git a/apps/files/lib/Command/TransferOwnership.php b/apps/files/lib/Command/TransferOwnership.php index edc73e62c38..104a8fb4985 100644 --- a/apps/files/lib/Command/TransferOwnership.php +++ b/apps/files/lib/Command/TransferOwnership.php @@ -11,20 +11,26 @@ namespace OCA\Files\Command; use OCA\Files\Exception\TransferOwnershipException; use OCA\Files\Service\OwnershipTransferService; +use OCA\Files_External\Config\ConfigAdapter; +use OCP\Files\Mount\IMountManager; +use OCP\Files\Mount\IMountPoint; use OCP\IConfig; use OCP\IUser; use OCP\IUserManager; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; class TransferOwnership extends Command { public function __construct( private IUserManager $userManager, private OwnershipTransferService $transferService, private IConfig $config, + private IMountManager $mountManager, ) { parent::__construct(); } @@ -60,6 +66,16 @@ class TransferOwnership extends Command { InputOption::VALUE_OPTIONAL, 'transfer incoming user file shares to destination user. Usage: --transfer-incoming-shares=1 (value required)', '2' + )->addOption( + 'include-external-storage', + null, + InputOption::VALUE_NONE, + 'include files on external storages, this will _not_ setup an external storage for the target user, but instead moves all the files from the external storages into the target users home directory', + )->addOption( + 'force-include-external-storage', + null, + InputOption::VALUE_NONE, + 'don\'t ask for confirmation for transferring external storages', ); } @@ -87,6 +103,31 @@ class TransferOwnership extends Command { return self::FAILURE; } + $path = ltrim($input->getOption('path'), '/'); + $includeExternalStorage = $input->getOption('include-external-storage'); + if ($includeExternalStorage) { + $mounts = $this->mountManager->findIn('/' . rtrim($sourceUserObject->getUID() . '/files/' . $path, '/')); + /** @var IMountPoint[] $mounts */ + $mounts = array_filter($mounts, fn ($mount) => $mount->getMountProvider() === ConfigAdapter::class); + if (count($mounts) > 0) { + $output->writeln(count($mounts) . ' external storages will be transferred:'); + foreach ($mounts as $mount) { + $output->writeln(' - <info>' . $mount->getMountPoint() . '</info>'); + } + $output->writeln(''); + $output->writeln('<comment>Any other users with access to these external storages will lose access to the files.</comment>'); + $output->writeln(''); + if (!$input->getOption('force-include-external-storage')) { + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + $question = new ConfirmationQuestion('Are you sure you want to transfer external storages? (y/N) ', false); + if (!$helper->ask($input, $output, $question)) { + return self::FAILURE; + } + } + } + } + try { $includeIncomingArgument = $input->getOption('transfer-incoming-shares'); @@ -112,11 +153,12 @@ class TransferOwnership extends Command { $this->transferService->transfer( $sourceUserObject, $destinationUserObject, - ltrim($input->getOption('path'), '/'), + $path, $output, $input->getOption('move') === true, false, - $includeIncoming + $includeIncoming, + $includeExternalStorage, ); } catch (TransferOwnershipException $e) { $output->writeln('<error>' . $e->getMessage() . '</error>'); diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php index 7f6681a9b89..b3a36ee13e5 100644 --- a/apps/files/lib/Service/OwnershipTransferService.php +++ b/apps/files/lib/Service/OwnershipTransferService.php @@ -15,10 +15,11 @@ use OC\Files\View; use OC\User\NoUserException; use OCA\Encryption\Util; use OCA\Files\Exception\TransferOwnershipException; +use OCA\Files_External\Config\ConfigAdapter; use OCP\Encryption\IManager as IEncryptionManager; +use OCP\Files\Config\IHomeMountProvider; use OCP\Files\Config\IUserMountCache; use OCP\Files\FileInfo; -use OCP\Files\IHomeStorage; use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountManager; @@ -70,6 +71,7 @@ class OwnershipTransferService { bool $move = false, bool $firstLogin = false, bool $transferIncomingShares = false, + bool $includeExternalStorage = false, ): void { $output = $output ?? new NullOutput(); $sourceUid = $sourceUser->getUID(); @@ -149,7 +151,8 @@ class OwnershipTransferService { $sourcePath, $finalTarget, $view, - $output + $output, + $includeExternalStorage, ); $sizeDifference = $sourceSize - $view->getFileInfo($finalTarget)->getSize(); @@ -215,11 +218,14 @@ class OwnershipTransferService { * * @throws TransferOwnershipException */ - protected function analyse(string $sourceUid, + protected function analyse( + string $sourceUid, string $destinationUid, string $sourcePath, View $view, - OutputInterface $output): void { + OutputInterface $output, + bool $includeExternalStorage = false, + ): void { $output->writeln('Validating quota'); $sourceFileInfo = $view->getFileInfo($sourcePath, false); if ($sourceFileInfo === false) { @@ -247,17 +253,22 @@ class OwnershipTransferService { $encryptedFiles[] = $sourceFileInfo; } else { $this->walkFiles($view, $sourcePath, - function (FileInfo $fileInfo) use ($progress, $masterKeyEnabled, &$encryptedFiles) { + function (FileInfo $fileInfo) use ($progress, $masterKeyEnabled, &$encryptedFiles, $includeExternalStorage) { if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) { + $mount = $fileInfo->getMountPoint(); // only analyze into folders from main storage, - if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) { + if ( + $mount->getMountProvider() instanceof IHomeMountProvider || + ($includeExternalStorage && $mount->getMountProvider() instanceof ConfigAdapter) + ) { + if ($fileInfo->isEncrypted()) { + /* Encrypted folder means e2ee encrypted, we cannot transfer it */ + $encryptedFiles[] = $fileInfo; + } + return true; + } else { return false; } - if ($fileInfo->isEncrypted()) { - /* Encrypted folder means e2ee encrypted, we cannot transfer it */ - $encryptedFiles[] = $fileInfo; - } - return true; } $progress->advance(); if ($fileInfo->isEncrypted() && !$masterKeyEnabled) { @@ -399,11 +410,14 @@ class OwnershipTransferService { /** * @throws TransferOwnershipException */ - protected function transferFiles(string $sourceUid, + protected function transferFiles( + string $sourceUid, string $sourcePath, string $finalTarget, View $view, - OutputInterface $output): void { + OutputInterface $output, + bool $includeExternalStorage, + ): void { $output->writeln("Transferring files to $finalTarget ..."); // This change will help user to transfer the folder specified using --path option. @@ -412,15 +426,50 @@ class OwnershipTransferService { $view->mkdir($finalTarget); $finalTarget = $finalTarget . '/' . basename($sourcePath); } - if ($view->rename($sourcePath, $finalTarget, ['checkSubMounts' => false]) === false) { - throw new TransferOwnershipException('Could not transfer files.', 1); + $sourceInfo = $view->getFileInfo($sourcePath); + + /// handle the external storages mounted at the root, or the admin specifying an external storage with --path + if ($sourceInfo->getInternalPath() === '' && $includeExternalStorage) { + $this->moveMountContents($view, $sourcePath, $finalTarget); + } else { + if ($view->rename($sourcePath, $finalTarget, ['checkSubMounts' => false]) === false) { + throw new TransferOwnershipException('Could not transfer files.', 1); + } + } + + if ($includeExternalStorage) { + $nestedMounts = $this->mountManager->findIn($sourcePath); + foreach ($nestedMounts as $mount) { + if ($mount->getMountProvider() === ConfigAdapter::class) { + $relativePath = substr(trim($mount->getMountPoint(), '/'), strlen($sourcePath)); + $this->moveMountContents($view, $mount->getMountPoint(), $finalTarget . $relativePath); + } + } } + if (!is_dir("$sourceUid/files")) { // because the files folder is moved away we need to recreate it $view->mkdir("$sourceUid/files"); } } + private function moveMountContents(View $rootView, string $source, string $target) { + if ($rootView->copy($source, $target)) { + // just doing `rmdir` on the mountpoint would cause it to try and unmount the storage + // we need to empty the contents instead + $content = $rootView->getDirectoryContent($source); + foreach ($content as $item) { + if ($item->getType() === FileInfo::TYPE_FOLDER) { + $rootView->rmdir($item->getPath()); + } else { + $rootView->unlink($item->getPath()); + } + } + } else { + throw new TransferOwnershipException("Could not transfer $source to $target"); + } + } + /** * @param string $targetLocation New location of the transfered node * @param array<array{share: IShare, suffix: string}> $shares previously collected share information diff --git a/apps/files/lib/Service/UserConfig.php b/apps/files/lib/Service/UserConfig.php index b01caf9f960..a2f2f1c1d14 100644 --- a/apps/files/lib/Service/UserConfig.php +++ b/apps/files/lib/Service/UserConfig.php @@ -54,6 +54,12 @@ class UserConfig { 'default' => true, 'allowed' => [true, false], ], + [ + // Whether to show the mime column or not + 'key' => 'show_mime_column', + 'default' => false, + 'allowed' => [true, false], + ] ]; protected ?IUser $user = null; |