diff options
author | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2023-07-12 19:50:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-12 19:50:40 +0200 |
commit | 592aeec17e766e41ce94846675530e23ebe8cc96 (patch) | |
tree | 1128f6e095c44fc21015ef5571cac2e713bac6ca /apps/dav | |
parent | e9b582164e008a2648bd2e99078145d3e3b114c5 (diff) | |
parent | f2e90444940d71f075214dcca8c0e69066dce7f4 (diff) | |
download | nextcloud-server-592aeec17e766e41ce94846675530e23ebe8cc96.tar.gz nextcloud-server-592aeec17e766e41ce94846675530e23ebe8cc96.zip |
Merge pull request #38919 from nextcloud/backport/38639/stable27
[stable27] pruneOutdatedSyncTokens deletes all entries
Diffstat (limited to 'apps/dav')
-rw-r--r-- | apps/dav/lib/CalDAV/CalDavBackend.php | 15 | ||||
-rw-r--r-- | apps/dav/lib/CardDAV/CardDavBackend.php | 15 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/CalDavBackendTest.php | 74 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/CardDavBackendTest.php | 41 |
4 files changed, 139 insertions, 6 deletions
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 1cdb705ac92..b872823d76d 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -3134,10 +3134,21 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription if ($keep < 0) { throw new \InvalidArgumentException(); } + + $query = $this->db->getQueryBuilder(); + $query->select($query->func()->max('id')) + ->from('calendarchanges'); + + $result = $query->executeQuery(); + $maxId = (int) $result->fetchOne(); + $result->closeCursor(); + if (!$maxId || $maxId < $keep) { + return 0; + } + $query = $this->db->getQueryBuilder(); $query->delete('calendarchanges') - ->orderBy('id', 'DESC') - ->setFirstResult($keep); + ->where($query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); return $query->executeStatement(); } diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 4e4d64f6f72..045ad4d1385 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -1399,10 +1399,21 @@ class CardDavBackend implements BackendInterface, SyncSupport { if ($keep < 0) { throw new \InvalidArgumentException(); } + + $query = $this->db->getQueryBuilder(); + $query->select($query->func()->max('id')) + ->from('addressbookchanges'); + + $result = $query->executeQuery(); + $maxId = (int) $result->fetchOne(); + $result->closeCursor(); + if (!$maxId || $maxId < $keep) { + return 0; + } + $query = $this->db->getQueryBuilder(); $query->delete('addressbookchanges') - ->orderBy('id', 'DESC') - ->setFirstResult($keep); + ->where($query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); return $query->executeStatement(); } diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index 69096d0cfbb..0fdd617943b 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -1291,6 +1291,8 @@ EOD; */ public function testPruneOutdatedSyncTokens(): void { $calendarId = $this->createTestCalendar(); + $changes = $this->backend->getChangesForCalendar($calendarId, '', 1); + $syncToken = $changes['syncToken']; $uri = static::getUniqueID('calobj'); $calData = <<<EOD @@ -1333,9 +1335,79 @@ EOD; $deleted = $this->backend->pruneOutdatedSyncTokens(0); // At least one from the object creation and one from the object update $this->assertGreaterThanOrEqual(2, $deleted); - $changes = $this->backend->getChangesForCalendar($calendarId, '5', 1); + $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1); $this->assertEmpty($changes['added']); $this->assertEmpty($changes['modified']); $this->assertEmpty($changes['deleted']); + + // Test that objects remain + + // Currently changes are empty + $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100); + $this->assertEquals(0, count($changes['added'] + $changes['modified'] + $changes['deleted'])); + + // Create card + $uri = static::getUniqueID('calobj'); +$calData = <<<EOD +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:Nextcloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20230910T125139Z +UID:47d15e3ec9 +LAST-MODIFIED;VALUE=DATE-TIME:20230910T125139Z +DTSTAMP;VALUE=DATE-TIME:20230910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20230912T130000Z +DTEND;VALUE=DATE-TIME:20230912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + $this->backend->createCalendarObject($calendarId, $uri, $calData); + + // We now have one add + $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100); + $this->assertEquals(1, count($changes['added'])); + $this->assertEmpty($changes['modified']); + $this->assertEmpty($changes['deleted']); + + // update the card + $calData = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:Nextcloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20230910T125139Z +UID:47d15e3ec9 +LAST-MODIFIED;VALUE=DATE-TIME:20230910T125139Z +DTSTAMP;VALUE=DATE-TIME:20230910T125139Z +SUMMARY:123 Event 🙈 +DTSTART;VALUE=DATE-TIME:20230912T130000Z +DTEND;VALUE=DATE-TIME:20230912T140000Z +ATTENDEE;CN=test:mailto:foo@bar.com +END:VEVENT +END:VCALENDAR +EOD; + $this->backend->updateCalendarObject($calendarId, $uri, $calData); + + // One add, one modify, but shortened to modify + $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100); + $this->assertEmpty($changes['added']); + $this->assertEquals(1, count($changes['modified'])); + $this->assertEmpty($changes['deleted']); + + // Delete all but last change + $deleted = $this->backend->pruneOutdatedSyncTokens(1); + $this->assertEquals(1, $deleted); // We had two changes before, now one + + // Only update should remain + $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100); + $this->assertEmpty($changes['added']); + $this->assertEquals(1, count($changes['modified'])); + $this->assertEmpty($changes['deleted']); + + // Check that no crash occurs when prune is called without current changes + $deleted = $this->backend->pruneOutdatedSyncTokens(1); } } diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index adf64ef82b0..425e7c44ba7 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -853,15 +853,54 @@ class CardDavBackendTest extends TestCase { */ public function testPruneOutdatedSyncTokens(): void { $addressBookId = $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $changes = $this->backend->getChangesForAddressBook($addressBookId, '', 1); + $syncToken = $changes['syncToken']; + $uri = $this->getUniqueID('card'); $this->backend->createCard($addressBookId, $uri, $this->vcardTest0); $this->backend->updateCard($addressBookId, $uri, $this->vcardTest1); $deleted = $this->backend->pruneOutdatedSyncTokens(0); // At least one from the object creation and one from the object update $this->assertGreaterThanOrEqual(2, $deleted); - $changes = $this->backend->getChangesForAddressBook($addressBookId, '5', 1); + $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 1); $this->assertEmpty($changes['added']); $this->assertEmpty($changes['modified']); $this->assertEmpty($changes['deleted']); + + // Test that objects remain + + // Currently changes are empty + $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100); + $this->assertEquals(0, count($changes['added'] + $changes['modified'] + $changes['deleted'])); + + // Create card + $uri = $this->getUniqueID('card'); + $this->backend->createCard($addressBookId, $uri, $this->vcardTest0); + // We now have one add + $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100); + $this->assertEquals(1, count($changes['added'])); + $this->assertEmpty($changes['modified']); + $this->assertEmpty($changes['deleted']); + + // Update card + $this->backend->updateCard($addressBookId, $uri, $this->vcardTest1); + // One add, one modify, but shortened to modify + $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100); + $this->assertEmpty($changes['added']); + $this->assertEquals(1, count($changes['modified'])); + $this->assertEmpty($changes['deleted']); + + // Delete all but last change + $deleted = $this->backend->pruneOutdatedSyncTokens(1); + $this->assertEquals(1, $deleted); // We had two changes before, now one + + // Only update should remain + $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100); + $this->assertEmpty($changes['added']); + $this->assertEquals(1, count($changes['modified'])); + $this->assertEmpty($changes['deleted']); + + // Check that no crash occurs when prune is called without current changes + $deleted = $this->backend->pruneOutdatedSyncTokens(1); } } |