From ed228bb807db59a17b2250c92a20af7083c028fb Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Tue, 24 Oct 2023 19:57:06 +0200 Subject: [PATCH] fix(provisioning): Clean up orphaned accounts Signed-off-by: Christoph Wurst --- lib/Db/MailAccount.php | 2 +- lib/Db/MailAccountMapper.php | 18 ++++++++++++++++++ lib/Service/CleanupService.php | 9 ++++++++- tests/Integration/Db/MailAccountMapperTest.php | 13 +++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/Db/MailAccount.php b/lib/Db/MailAccount.php index 3fd86b4e14..be011943a5 100644 --- a/lib/Db/MailAccount.php +++ b/lib/Db/MailAccount.php @@ -65,7 +65,7 @@ * @method string getEditorMode() * @method void setEditorMode(string $editorMode) * @method int|null getProvisioningId() - * @method void setProvisioningId(int $provisioningId) + * @method void setProvisioningId(int|null $provisioningId) * @method int getOrder() * @method void setOrder(int $order) * @method bool|null getShowSubscribedOnly() diff --git a/lib/Db/MailAccountMapper.php b/lib/Db/MailAccountMapper.php index 2edc4052c3..24d59c6a19 100644 --- a/lib/Db/MailAccountMapper.php +++ b/lib/Db/MailAccountMapper.php @@ -151,6 +151,24 @@ public function deleteProvisionedAccountsByUid(string $uid): void { $delete->executeStatement(); } + public function deleteProvisionedOrphanAccounts(): void { + $inner = $this->db->getQueryBuilder() + ->select('id') + ->from('mail_provisionings'); + + $delete = $this->db->getQueryBuilder(); + $delete->delete($this->getTableName()) + ->where( + $delete->expr()->isNotNull('provisioning_id'), + $delete->expr()->notIn( + 'provisioning_id', + $delete->createFunction($inner->getSQL()), + IQueryBuilder::PARAM_INT_ARRAY + )); + + $delete->executeStatement(); + } + /** * @return MailAccount[] */ diff --git a/lib/Service/CleanupService.php b/lib/Service/CleanupService.php index 36d21ed72f..d3cba051e9 100644 --- a/lib/Service/CleanupService.php +++ b/lib/Service/CleanupService.php @@ -27,6 +27,7 @@ use OCA\Mail\Db\AliasMapper; use OCA\Mail\Db\CollectedAddressMapper; +use OCA\Mail\Db\MailAccountMapper; use OCA\Mail\Db\MailboxMapper; use OCA\Mail\Db\MessageMapper; use OCA\Mail\Db\MessageRetentionMapper; @@ -38,6 +39,8 @@ use Psr\Log\LoggerInterface; class CleanupService { + private MailAccountMapper $mailAccountMapper; + /** @var AliasMapper */ private $aliasMapper; @@ -60,7 +63,8 @@ class CleanupService { private PersistenceService $classifierPersistenceService; private ITimeFactory $timeFactory; - public function __construct(AliasMapper $aliasMapper, + public function __construct(MailAccountMapper $mailAccountMapper, + AliasMapper $aliasMapper, MailboxMapper $mailboxMapper, MessageMapper $messageMapper, CollectedAddressMapper $collectedAddressMapper, @@ -77,6 +81,7 @@ public function __construct(AliasMapper $aliasMapper, $this->messageRetentionMapper = $messageRetentionMapper; $this->messageSnoozeMapper = $messageSnoozeMapper; $this->classifierPersistenceService = $classifierPersistenceService; + $this->mailAccountMapper = $mailAccountMapper; $this->timeFactory = $timeFactory; } @@ -85,6 +90,8 @@ public function cleanUp(LoggerInterface $logger): void { $this->timeFactory, $logger ))->start('clean up'); + $this->mailAccountMapper->deleteProvisionedOrphanAccounts(); + $task->step('delete orphan provisioned accounts'); $this->aliasMapper->deleteOrphans(); $task->step('delete orphan aliases'); $this->mailboxMapper->deleteOrphans(); diff --git a/tests/Integration/Db/MailAccountMapperTest.php b/tests/Integration/Db/MailAccountMapperTest.php index ab78297db8..322432b0c0 100644 --- a/tests/Integration/Db/MailAccountMapperTest.php +++ b/tests/Integration/Db/MailAccountMapperTest.php @@ -28,10 +28,13 @@ use OC; use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailAccountMapper; +use OCP\AppFramework\Db\DoesNotExistException; use OCP\IDBConnection; +use function random_int; /** * @group DB + * @covers \OCA\Mail\Db\MailAccountMapper */ class MailAccountMapperTest extends TestCase { use DatabaseTransaction; @@ -106,4 +109,14 @@ public function testSave() { $this->assertNotNull($b->getId()); $this->assertEquals($b->getId(), $c->getId()); } + + public function testDeleteProvisionedOrphans(): void { + $this->account->setProvisioningId(random_int(1, 10000)); + $this->mapper->insert($this->account); + + $this->mapper->deleteProvisionedOrphanAccounts(); + + $this->expectException(DoesNotExistException::class); + $this->mapper->findById($this->account->getId()); + } }