diff options
author | Thomas Citharel <tcit@tcit.fr> | 2021-09-04 20:52:14 +0200 |
---|---|---|
committer | Thomas Citharel <tcit@tcit.fr> | 2021-09-04 20:55:12 +0200 |
commit | 45d5a797e7d305db9907d4ef9d6be5649e4b24cd (patch) | |
tree | 30bcd71d7fe754ce190d24cdf7e54ca82bac849e /apps/dav/lib | |
parent | 113da79c8f41075cca9db2d480fc21a12530339b (diff) | |
download | nextcloud-server-45d5a797e7d305db9907d4ef9d6be5649e4b24cd.tar.gz nextcloud-server-45d5a797e7d305db9907d4ef9d6be5649e4b24cd.zip |
Add repair job to delete calendar subscriptions that were orphaned when
deleteding an user
Follow-up to https://github.com/nextcloud/server/pull/28419
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/apps/dav/lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php b/apps/dav/lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php new file mode 100644 index 00000000000..50becf81e78 --- /dev/null +++ b/apps/dav/lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php @@ -0,0 +1,144 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2021 Thomas Citharel <nextcloud@tcit.fr> + * + * @author Thomas Citharel <nextcloud@tcit.fr> + * + * @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 OCA\DAV\Migration; + +use OCP\DB\Exception; +use OCP\IDBConnection; +use OCP\IUserManager; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class RemoveDeletedUsersCalendarSubscriptions implements IRepairStep { + /** @var IDBConnection */ + private $connection; + + /** @var IUserManager */ + private $userManager; + + /** @var int */ + private $progress = 0; + + private $orphanSubscriptions = []; + + private const SUBSCRIPTIONS_CHUNK_SIZE = 1000; + + public function __construct(IDBConnection $connection, IUserManager $userManager) { + $this->connection = $connection; + $this->userManager = $userManager; + } + + /** + * @inheritdoc + */ + public function getName(): string { + return 'Clean up old calendar subscriptions from deleted users that were not cleaned-up'; + } + + /** + * @inheritdoc + */ + public function run(IOutput $output) { + $nbSubscriptions = $this->countSubscriptions(); + + $output->startProgress($nbSubscriptions); + + while ($this->progress < $nbSubscriptions) { + $this->checkSubscriptions(); + + $this->progress += self::SUBSCRIPTIONS_CHUNK_SIZE; + $output->advance(min(self::SUBSCRIPTIONS_CHUNK_SIZE, $nbSubscriptions)); + } + $output->finishProgress(); + $this->deleteOrphanSubscriptions(); + + $output->info(sprintf('%d calendar subscriptions without an user have been cleaned up', count($this->orphanSubscriptions))); + } + + /** + * @throws Exception + */ + private function countSubscriptions(): int { + $qb = $this->connection->getQueryBuilder(); + $query = $qb->select($qb->func()->count('*')) + ->from('calendarsubscriptions'); + + $result = $query->execute(); + $count = $result->fetchOne(); + $result->closeCursor(); + + if ($count !== false) { + $count = (int)$count; + } else { + $count = 0; + } + + return $count; + } + + /** + * @throws Exception + */ + private function checkSubscriptions(): void { + $qb = $this->connection->getQueryBuilder(); + $query = $qb->selectDistinct(['id', 'principaluri']) + ->from('calendarsubscriptions') + ->setMaxResults(self::SUBSCRIPTIONS_CHUNK_SIZE) + ->setFirstResult($this->progress); + + $result = $query->execute(); + while ($row = $result->fetch()) { + $username = $this->getPrincipal($row['principaluri']); + if (!$this->userManager->userExists($username)) { + $this->orphanSubscriptions[] = $row['id']; + } + } + $result->closeCursor(); + } + + /** + * @throws Exception + */ + private function deleteOrphanSubscriptions(): void { + foreach ($this->orphanSubscriptions as $orphanSubscriptionID) { + $this->deleteOrphanSubscription($orphanSubscriptionID); + } + } + + /** + * @throws Exception + */ + private function deleteOrphanSubscription(int $orphanSubscriptionID): void { + $qb = $this->connection->getQueryBuilder(); + $qb->delete('calendarsubscriptions') + ->where($qb->expr()->eq('id', $qb->createNamedParameter($orphanSubscriptionID))) + ->executeStatement(); + } + + private function getPrincipal(string $principalUri): string { + $uri = explode('/', $principalUri); + return array_pop($uri); + } +} |