diff options
author | Lukas Reschke <lukas@owncloud.com> | 2016-06-21 11:18:22 +0200 |
---|---|---|
committer | Lukas Reschke <lukas@owncloud.com> | 2016-06-21 11:18:22 +0200 |
commit | 2b493e2f9dca674ba11f88a1d182d6872e04eaaa (patch) | |
tree | ef7fa75d1b4da812de80e93c3590dbb5404d7f06 /lib/private/Repair | |
parent | b4df57f3f02f65ed71d1072280751170379a53e8 (diff) | |
parent | 0e575c7eeadc6c8eb11b0be2ed1d39cdcf6cfcb8 (diff) | |
download | nextcloud-server-2b493e2f9dca674ba11f88a1d182d6872e04eaaa.tar.gz nextcloud-server-2b493e2f9dca674ba11f88a1d182d6872e04eaaa.zip |
Merge remote-tracking branch 'upstream/master' into master-sync-upstream
Diffstat (limited to 'lib/private/Repair')
-rw-r--r-- | lib/private/Repair/CleanTags.php | 57 | ||||
-rw-r--r-- | lib/private/Repair/RemoveRootShares.php | 157 |
2 files changed, 213 insertions, 1 deletions
diff --git a/lib/private/Repair/CleanTags.php b/lib/private/Repair/CleanTags.php index 60ddeff08f3..4241fa6da3a 100644 --- a/lib/private/Repair/CleanTags.php +++ b/lib/private/Repair/CleanTags.php @@ -25,6 +25,7 @@ namespace OC\Repair; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use OCP\IUserManager; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; @@ -38,11 +39,18 @@ class CleanTags implements IRepairStep { /** @var IDBConnection */ protected $connection; + /** @var IUserManager */ + protected $userManager; + + protected $deletedTags = 0; + /** * @param IDBConnection $connection + * @param IUserManager $userManager */ - public function __construct(IDBConnection $connection) { + public function __construct(IDBConnection $connection, IUserManager $userManager) { $this->connection = $connection; + $this->userManager = $userManager; } /** @@ -56,12 +64,59 @@ class CleanTags implements IRepairStep { * Updates the configuration after running an update */ public function run(IOutput $output) { + $this->deleteOrphanTags($output); $this->deleteOrphanFileEntries($output); $this->deleteOrphanTagEntries($output); $this->deleteOrphanCategoryEntries($output); } /** + * Delete tags for deleted users + */ + protected function deleteOrphanTags(IOutput $output) { + $offset = 0; + while ($this->checkTags($offset)) { + $offset += 50; + } + + $output->info(sprintf('%d tags of deleted users have been removed.', $this->deletedTags)); + } + + protected function checkTags($offset) { + $query = $this->connection->getQueryBuilder(); + $query->select('uid') + ->from('vcategory') + ->groupBy('uid') + ->orderBy('uid') + ->setMaxResults(50) + ->setFirstResult($offset); + $result = $query->execute(); + + $users = []; + $hadResults = false; + while ($row = $result->fetch()) { + $hadResults = true; + if (!$this->userManager->userExists($row['uid'])) { + $users[] = $row['uid']; + } + } + $result->closeCursor(); + + if (!$hadResults) { + // No more tags, stop looping + return false; + } + + if (!empty($users)) { + $query = $this->connection->getQueryBuilder(); + $query->delete('vcategory') + ->where($query->expr()->in('uid', $query->createNamedParameter($users, IQueryBuilder::PARAM_STR_ARRAY))); + $this->deletedTags += $query->execute(); + } + return true; + } + + /** * Delete tag entries for deleted files */ protected function deleteOrphanFileEntries(IOutput $output) { diff --git a/lib/private/Repair/RemoveRootShares.php b/lib/private/Repair/RemoveRootShares.php new file mode 100644 index 00000000000..89f797e3ef0 --- /dev/null +++ b/lib/private/Repair/RemoveRootShares.php @@ -0,0 +1,157 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ +namespace OC\Repair; + +use OCP\Files\IRootFolder; +use OCP\IDBConnection; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +/** + * Class RemoveRootShares + * + * @package OC\Repair + */ +class RemoveRootShares implements IRepairStep { + + /** @var IDBConnection */ + protected $connection; + + /** @var IUserManager */ + protected $userManager; + + /** @var IRootFolder */ + protected $rootFolder; + + /** + * RemoveRootShares constructor. + * + * @param IDBConnection $connection + * @param IUserManager $userManager + * @param IRootFolder $rootFolder + */ + public function __construct(IDBConnection $connection, + IUserManager $userManager, + IRootFolder $rootFolder) { + $this->connection = $connection; + $this->userManager = $userManager; + $this->rootFolder = $rootFolder; + } + + /** + * @return string + */ + public function getName() { + return 'Remove shares of a users root folder'; + } + + /** + * @param IOutput $output + */ + public function run(IOutput $output) { + if ($this->rootSharesExist()) { + $this->removeRootShares($output); + } + } + + /** + * @param IOutput $output + */ + private function removeRootShares(IOutput $output) { + $function = function(IUser $user) use ($output) { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $fileId = $userFolder->getId(); + + $qb = $this->connection->getQueryBuilder(); + $qb->delete('share') + ->where($qb->expr()->eq('file_source', $qb->createNamedParameter($fileId))) + ->andWhere($qb->expr()->orX( + $qb->expr()->eq('item_type', $qb->expr()->literal('file')), + $qb->expr()->eq('item_type', $qb->expr()->literal('folder')) + )); + + $qb->execute(); + + $output->advance(); + }; + + $userCount = $this->countUsers(); + $output->startProgress($userCount); + + $this->userManager->callForAllUsers($function); + + $output->finishProgress(); + } + + /** + * Count all the users + * + * @return int + */ + private function countUsers() { + $allCount = $this->userManager->countUsers(); + + $totalCount = 0; + foreach ($allCount as $backend => $count) { + $totalCount += $count; + } + + return $totalCount; + } + + /** + * Verify if this repair steps is required + * It *should* not be necessary in most cases and it can be very + * costly. + * + * @return bool + */ + private function rootSharesExist() { + $qb = $this->connection->getQueryBuilder(); + $qb2 = $this->connection->getQueryBuilder(); + + $qb->select('fileid') + ->from('filecache') + ->where($qb->expr()->eq('path', $qb->expr()->literal('files'))); + + $qb2->select('id') + ->from('share') + ->where($qb2->expr()->in('file_source', $qb2->createFunction($qb->getSQL()))) + ->andWhere($qb2->expr()->orX( + $qb2->expr()->eq('item_type', $qb->expr()->literal('file')), + $qb2->expr()->eq('item_type', $qb->expr()->literal('folder')) + )) + ->setMaxResults(1); + + $cursor = $qb2->execute(); + $data = $cursor->fetch(); + $cursor->closeCursor(); + + if ($data === false) { + return false; + } + + return true; + } +} + |