]> source.dussan.org Git - nextcloud-server.git/commitdiff
move share owner repair to occ command
authorRobin Appelman <robin@icewind.nl>
Thu, 29 Sep 2022 11:40:04 +0000 (13:40 +0200)
committerRobin Appelman <robin@icewind.nl>
Tue, 8 Nov 2022 16:13:33 +0000 (17:13 +0100)
Signed-off-by: Robin Appelman <robin@icewind.nl>
core/Command/Maintenance/RepairShareOwnership.php [new file with mode: 0644]
core/register_command.php
lib/private/Repair.php
lib/private/Repair/RepairShareOwnership.php [deleted file]
lib/private/Share20/Manager.php

diff --git a/core/Command/Maintenance/RepairShareOwnership.php b/core/Command/Maintenance/RepairShareOwnership.php
new file mode 100644 (file)
index 0000000..351f2b9
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Core\Command\Maintenance;
+
+use Symfony\Component\Console\Command\Command;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Share\IManager;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class RepairShareOwnership extends Command {
+       private IDBConnection $dbConnection;
+       private IManager $shareManager;
+       private IUserManager $userManager;
+
+       public function __construct(
+               IDBConnection $dbConnection,
+               IManager $shareManager,
+               IUserManager $userManager
+       ) {
+               $this->dbConnection = $dbConnection;
+               $this->shareManager = $shareManager;
+               $this->userManager = $userManager;
+               parent::__construct();
+       }
+
+       protected function configure() {
+               $this
+                       ->setName('maintenance:repair-share-owner')
+                       ->setDescription('repair invalid share-owner entries in the database')
+                       ->addOption('dry-run', null, InputOption::VALUE_NONE, "List detected issues without fixing them")
+                       ->addArgument('user', InputArgument::OPTIONAL, "User to fix incoming shares for, if omitted all users will be fixed");
+       }
+
+       protected function execute(InputInterface $input, OutputInterface $output): int {
+               $dryRun = $input->getOption('dry-run');
+               $userId = $input->getArgument('user');
+               if ($userId) {
+                       $user = $this->userManager->get($userId);
+                       if (!$user) {
+                               $output->writeln("<error>user $userId not found</error>");
+                               return 1;
+                       }
+                       $found = $this->repairWrongShareOwnershipForUser($user, $dryRun);
+               } else {
+                       $found = [];
+                       $userCount = $this->userManager->countSeenUsers();
+                       $progress = new ProgressBar($output, $userCount);
+                       $this->userManager->callForSeenUsers(function (IUser $user) use ($dryRun, &$found, $progress) {
+                               $progress->advance();
+                               $found = array_merge($found, $this->repairWrongShareOwnershipForUser($user, $dryRun));
+                       });
+                       $progress->finish();
+                       $output->writeln("");
+               }
+               foreach ($found as $item) {
+                       $output->writeln($item);
+               }
+               return 0;
+       }
+
+       protected function repairWrongShareOwnershipForUser(IUser $user, bool $dryRun = true): array {
+               $qb = $this->dbConnection->getQueryBuilder();
+               $brokenShare = $qb
+                       ->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with', 's.share_type')
+                       ->from('share', 's')
+                       ->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', $qb->expr()->castColumn('f.fileid', IQueryBuilder::PARAM_STR)))
+                       ->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
+                       ->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
+                       ->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
+                       ->andWhere($qb->expr()->eq('s.share_with', $qb->createNamedParameter($user->getUID())))
+                       ->executeQuery()
+                       ->fetchAll();
+
+               $found = [];
+
+               foreach ($brokenShare as $queryResult) {
+                       $shareId = (int) $queryResult['id'];
+                       $shareType = (int) $queryResult['share_type'];
+                       $initiator = $queryResult['uid_initiator'];
+                       $receiver = $queryResult['share_with'];
+                       $owner = $queryResult['uid_owner'];
+                       $mountOwner = $queryResult['user_id'];
+
+                       $found[] = "Found share from $initiator to $receiver, owned by $owner, that should be owned by $mountOwner";
+
+                       if ($dryRun) {
+                               continue;
+                       }
+
+                       $provider = $this->shareManager->getProviderForType($shareType);
+                       $share = $provider->getShareById($shareId);
+
+                       if ($share->getShareOwner() === $share->getSharedBy()) {
+                               $share->setSharedBy($mountOwner);
+                       }
+                       $share->setShareOwner($mountOwner);
+
+                       $this->shareManager->updateShare($share);
+               }
+
+               return $found;
+       }
+}
index 943180da706b1d3a85aa18ced86cd2fd31a91774..b6da0a6d44d0138579cc3fa5e146886b6adddb3f 100644 (file)
@@ -173,6 +173,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
                \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class),
                \OC::$server->getAppManager()
        ));
+       $application->add(\OC::$server->query(OC\Core\Command\Maintenance\RepairShareOwnership::class));
 
        $application->add(\OC::$server->query(\OC\Core\Command\Preview\Repair::class));
        $application->add(\OC::$server->query(\OC\Core\Command\Preview\ResetRenderedTexts::class));
index b8875f199451bde692f50175fdaee8a9bc1747c6..d8476338486932feb425efde76ed676c513c6503 100644 (file)
@@ -210,7 +210,6 @@ class Repair implements IOutput {
                        \OCP\Server::get(LookupServerSendCheck::class),
                        \OCP\Server::get(AddTokenCleanupJob::class),
                        \OCP\Server::get(CleanUpAbandonedApps::class),
-                       \OCP\Server::get(RepairShareOwnership::class),
                ];
        }
 
diff --git a/lib/private/Repair/RepairShareOwnership.php b/lib/private/Repair/RepairShareOwnership.php
deleted file mode 100644 (file)
index b7ff476..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-namespace OC\Repair;
-
-use OCP\IDBConnection;
-use OCP\Share\IManager;
-use OCP\Migration\IOutput;
-use OCP\Migration\IRepairStep;
-
-class RepairShareOwnership implements IRepairStep {
-       private IDBConnection $dbConnection;
-       private IManager $shareManager;
-
-       public function __construct(
-               IDBConnection $dbConnection,
-               IManager $shareManager
-       ) {
-               $this->dbConnection = $dbConnection;
-               $this->shareManager = $shareManager;
-       }
-
-       /**
-        * @inheritDoc
-        */
-       public function getName() {
-               return 'Repair shares ownership';
-       }
-
-       protected function repairWrongShareOwnership(IOutput $output, bool $dryRun = true) {
-               $qb = $this->dbConnection->getQueryBuilder();
-               $brokenShare = $qb
-                       ->select('s.id', 'm.user_id', 's.uid_owner', 's.uid_initiator', 's.share_with')
-                       ->from('share', 's')
-                       ->join('s', 'filecache', 'f', $qb->expr()->eq('s.item_source', 'f.fileid'))
-                       ->join('s', 'mounts', 'm', $qb->expr()->eq('f.storage', 'm.storage_id'))
-                       ->where($qb->expr()->neq('m.user_id', 's.uid_owner'))
-                       ->andWhere($qb->expr()->eq($qb->func()->concat($qb->expr()->literal('/'), 'm.user_id', $qb->expr()->literal('/')), 'm.mount_point'))
-                       ->executeQuery()
-                       ->fetchAll();
-
-               foreach ($brokenShare as $queryResult) {
-                       $shareId = $queryResult['id'];
-                       $initiator = $queryResult['uid_initiator'];
-                       $receiver = $queryResult['share_with'];
-                       $owner = $queryResult['uid_owner'];
-                       $mountOwner = $queryResult['user_id'];
-
-                       $output->info("Found share from $initiator to $receiver, owned by $owner, that should be owned by $mountOwner");
-
-                       if ($dryRun) {
-                               continue;
-                       }
-
-                       $share = $this->shareManager->getShareById($shareId);
-
-                       if ($share->getShareOwner() === $share->getSharedBy()) {
-                               $share->setSharedBy($mountOwner);
-                       }
-                       $share->setShareOwner($mountOwner);
-
-                       $this->shareManager->updateShare($share);
-               }
-       }
-
-       /**
-        * @inheritDoc
-        */
-       public function run(IOutput $output) {
-               $this->repairWrongShareOwnership($output);
-       }
-}
index ffd779707dff00d8fa44285e6124d8e313f91967..9e6a867cf1b41ab9a0e324cc30f7e7167a48d7e1 100644 (file)
@@ -2088,4 +2088,8 @@ class Manager implements IManager {
                        yield from $provider->getAllShares();
                }
        }
+
+       public function getProviderForType(int $shareType): IShareProvider {
+               return $this->factory->getProviderForType($shareType);
+       }
 }