Skip to content

Commit 8124485

Browse files
kesselbhamza221
authored andcommitted
fix(carddav): return correct sync token for non-truncated requests
Signed-off-by: Daniel Kesselberg <[email protected]>
1 parent b54c539 commit 8124485

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

apps/dav/lib/CardDAV/CardDavBackend.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -921,18 +921,20 @@ public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel,
921921

922922
// Fetching all changes
923923
$stmt = $qb->executeQuery();
924+
$rowCount = $stmt->rowCount();
924925

925926
$changes = [];
927+
$highestSyncToken = 0;
926928

927929
// This loop ensures that any duplicates are overwritten, only the
928930
// last change on a node is relevant.
929931
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
930932
$changes[$row['uri']] = $row['operation'];
931-
// get the last synctoken, needed in case a limit was set
932-
$result['syncToken'] = $row['synctoken'];
933+
$highestSyncToken = $row['synctoken'];
933934
}
935+
934936
$stmt->closeCursor();
935-
937+
936938
// No changes found, use current token
937939
if (empty($changes)) {
938940
$result['syncToken'] = $currentToken;
@@ -951,6 +953,20 @@ public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel,
951953
break;
952954
}
953955
}
956+
957+
/*
958+
* The synctoken in oc_addressbooks is always the highest synctoken in oc_addressbookchanges for a given addressbook plus one (see addChange).
959+
*
960+
* For truncated results, it is expected that we return the highest token from the response, so the client can continue from the latest change.
961+
*
962+
* For non-truncated results, it is expected to return the currentToken. If we return the highest token, as with truncated results, the client will always think it is one change behind.
963+
*
964+
* Therefore, we differentiate between truncated and non-truncated results when returning the synctoken.
965+
*/
966+
if ($rowCount === $limit && $highestSyncToken < $currentToken) {
967+
$result['syncToken'] = $highestSyncToken;
968+
$result['result_truncated'] = true;
969+
}
954970
} else {
955971
$qb = $this->db->getQueryBuilder();
956972
$qb->select('id', 'uri')

apps/dav/tests/unit/CardDAV/SyncServiceTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public function testEmptySync(): void {
108108
'1',
109109
'principals/system/system',
110110
[]
111-
)['token'];
111+
)[0];
112112

113113
$this->assertEquals('http://sabre.io/ns/sync/1', $token);
114114
}
@@ -179,7 +179,7 @@ public function testSyncWithNewElement(): void {
179179
'1',
180180
'principals/system/system',
181181
[]
182-
)['token'];
182+
)[0];
183183

184184
$this->assertEquals('http://sabre.io/ns/sync/2', $token);
185185
}
@@ -250,7 +250,7 @@ public function testSyncWithUpdatedElement(): void {
250250
'1',
251251
'principals/system/system',
252252
[]
253-
)['token'];
253+
)[0];
254254

255255
$this->assertEquals('http://sabre.io/ns/sync/3', $token);
256256
}
@@ -291,7 +291,7 @@ public function testSyncWithDeletedElement(): void {
291291
'1',
292292
'principals/system/system',
293293
[]
294-
)['token'];
294+
)[0];
295295

296296
$this->assertEquals('http://sabre.io/ns/sync/4', $token);
297297
}
@@ -422,7 +422,7 @@ public function testDeleteAddressbookWhenAccessRevoked(): void {
422422
'1',
423423
'principals/system/system',
424424
[]
425-
)['token'];
425+
);
426426
}
427427

428428
#[\PHPUnit\Framework\Attributes\DataProvider('providerUseAbsoluteUriReport')]
@@ -462,7 +462,7 @@ public function testUseAbsoluteUriReport(string $host, string $expected): void {
462462
'1',
463463
'principals/system/system',
464464
[]
465-
)['token'];
465+
);
466466
}
467467

468468
public static function providerUseAbsoluteUriReport(): array {

apps/federation/tests/SyncFederationAddressbooksTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function testSync(): void {
4545
->with('https://cloud.example.org', 1, '1');
4646
$syncService = $this->createMock(SyncService::class);
4747
$syncService->expects($this->once())->method('syncRemoteAddressBook')
48-
->willReturn('1');
48+
->willReturn(['1', false]);
4949

5050
/** @var SyncService $syncService */
5151
$s = new SyncFederationAddressBooks($dbHandler, $syncService, $this->discoveryService, $this->logger);
@@ -96,7 +96,7 @@ public function testSuccessfulSyncWithoutChangesAfterFailure(): void {
9696
->with('https://cloud.example.org', 1);
9797
$syncService = $this->createMock(SyncService::class);
9898
$syncService->expects($this->once())->method('syncRemoteAddressBook')
99-
->willReturn('0');
99+
->willReturn(['0', false]);
100100

101101
/** @var SyncService $syncService */
102102
$s = new SyncFederationAddressBooks($dbHandler, $syncService, $this->discoveryService, $this->logger);

0 commit comments

Comments
 (0)