Skip to content

Commit ec7c823

Browse files
Merge pull request #51539 from nextcloud/backport/51380/stable31
[stable31] fix(cardav): only show users from enabled addressBooks in contacts menu
2 parents 806a3d1 + 7e6801a commit ec7c823

10 files changed

+166
-34
lines changed

apps/dav/lib/AppInfo/Application.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,11 @@ private function setupContactsProvider(IContactsManager $contactsManager,
263263
$cm->setupContactsProvider($contactsManager, $userID, $urlGenerator);
264264
}
265265

266-
private function setupSystemContactsProvider(IContactsManager $contactsManager,
267-
IAppContainer $container): void {
266+
private function setupSystemContactsProvider(IContactsManager $contactsManager, IAppContainer $container): void {
268267
/** @var ContactsManager $cm */
269268
$cm = $container->query(ContactsManager::class);
270269
$urlGenerator = $container->getServer()->getURLGenerator();
271-
$cm->setupSystemContactsProvider($contactsManager, $urlGenerator);
270+
$cm->setupSystemContactsProvider($contactsManager, null, $urlGenerator);
272271
}
273272

274273
public function registerCalendarManager(ICalendarManager $calendarManager,

apps/dav/lib/CardDAV/AddressBookImpl.php

+26-2
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
*/
88
namespace OCA\DAV\CardDAV;
99

10+
use OCA\DAV\Db\PropertyMapper;
1011
use OCP\Constants;
11-
use OCP\IAddressBook;
12+
use OCP\IAddressBookEnabled;
1213
use OCP\IURLGenerator;
1314
use Sabre\VObject\Component\VCard;
1415
use Sabre\VObject\Property;
1516
use Sabre\VObject\Reader;
1617
use Sabre\VObject\UUIDUtil;
1718

18-
class AddressBookImpl implements IAddressBook {
19+
class AddressBookImpl implements IAddressBookEnabled {
1920

2021
/**
2122
* AddressBookImpl constructor.
@@ -30,6 +31,8 @@ public function __construct(
3031
private array $addressBookInfo,
3132
private CardDavBackend $backend,
3233
private IURLGenerator $urlGenerator,
34+
private PropertyMapper $propertyMapper,
35+
private ?string $userId,
3336
) {
3437
}
3538

@@ -308,4 +311,25 @@ public function isSystemAddressBook(): bool {
308311
$this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl()
309312
);
310313
}
314+
315+
public function isEnabled(): bool {
316+
if (!$this->userId) {
317+
return true;
318+
}
319+
320+
if ($this->isSystemAddressBook()) {
321+
$user = $this->userId ;
322+
$uri = 'z-server-generated--system';
323+
} else {
324+
$user = str_replace('principals/users/', '', $this->addressBookInfo['principaluri']);
325+
$uri = $this->addressBookInfo['uri'];
326+
}
327+
328+
$path = 'addressbooks/users/' . $user . '/' . $uri;
329+
$properties = $this->propertyMapper->findPropertyByPathAndName($user, $path, '{http://owncloud.org/ns}enabled');
330+
if (count($properties) > 0) {
331+
return (bool)$properties[0]->getPropertyvalue();
332+
}
333+
return true;
334+
}
311335
}

apps/dav/lib/CardDAV/ContactsManager.php

+12-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
namespace OCA\DAV\CardDAV;
99

10+
use OCA\DAV\Db\PropertyMapper;
1011
use OCP\Contacts\IManager;
1112
use OCP\IL10N;
1213
use OCP\IURLGenerator;
@@ -21,6 +22,7 @@ class ContactsManager {
2122
public function __construct(
2223
private CardDavBackend $backend,
2324
private IL10N $l10n,
25+
private PropertyMapper $propertyMapper,
2426
) {
2527
}
2628

@@ -31,33 +33,37 @@ public function __construct(
3133
*/
3234
public function setupContactsProvider(IManager $cm, $userId, IURLGenerator $urlGenerator) {
3335
$addressBooks = $this->backend->getAddressBooksForUser("principals/users/$userId");
34-
$this->register($cm, $addressBooks, $urlGenerator);
35-
$this->setupSystemContactsProvider($cm, $urlGenerator);
36+
$this->register($cm, $addressBooks, $urlGenerator, $userId);
37+
$this->setupSystemContactsProvider($cm, $userId, $urlGenerator);
3638
}
3739

3840
/**
3941
* @param IManager $cm
42+
* @param ?string $userId
4043
* @param IURLGenerator $urlGenerator
4144
*/
42-
public function setupSystemContactsProvider(IManager $cm, IURLGenerator $urlGenerator) {
45+
public function setupSystemContactsProvider(IManager $cm, ?string $userId, IURLGenerator $urlGenerator) {
4346
$addressBooks = $this->backend->getAddressBooksForUser('principals/system/system');
44-
$this->register($cm, $addressBooks, $urlGenerator);
47+
$this->register($cm, $addressBooks, $urlGenerator, $userId);
4548
}
4649

4750
/**
4851
* @param IManager $cm
4952
* @param $addressBooks
5053
* @param IURLGenerator $urlGenerator
54+
* @param ?string $userId
5155
*/
52-
private function register(IManager $cm, $addressBooks, $urlGenerator) {
56+
private function register(IManager $cm, $addressBooks, $urlGenerator, ?string $userId) {
5357
foreach ($addressBooks as $addressBookInfo) {
5458
$addressBook = new AddressBook($this->backend, $addressBookInfo, $this->l10n);
5559
$cm->registerAddressBook(
5660
new AddressBookImpl(
5761
$addressBook,
5862
$addressBookInfo,
5963
$this->backend,
60-
$urlGenerator
64+
$urlGenerator,
65+
$this->propertyMapper,
66+
$userId,
6167
)
6268
);
6369
}

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

+27-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use OCA\DAV\CardDAV\AddressBook;
1111
use OCA\DAV\CardDAV\AddressBookImpl;
1212
use OCA\DAV\CardDAV\CardDavBackend;
13+
use OCA\DAV\Db\PropertyMapper;
1314
use OCP\IURLGenerator;
1415
use Sabre\VObject\Component\VCard;
1516
use Sabre\VObject\Property\Text;
@@ -32,6 +33,9 @@ class AddressBookImplTest extends TestCase {
3233
/** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject */
3334
private $backend;
3435

36+
/** @var PropertyMapper | \PHPUnit\Framework\MockObject\MockObject */
37+
private $propertyMapper;
38+
3539
/** @var VCard | \PHPUnit\Framework\MockObject\MockObject */
3640
private $vCard;
3741

@@ -50,12 +54,15 @@ protected function setUp(): void {
5054
->disableOriginalConstructor()->getMock();
5155
$this->vCard = $this->createMock(VCard::class);
5256
$this->urlGenerator = $this->createMock(IURLGenerator::class);
57+
$this->propertyMapper = $this->createMock(PropertyMapper::class);
5358

5459
$this->addressBookImpl = new AddressBookImpl(
5560
$this->addressBook,
5661
$this->addressBookInfo,
5762
$this->backend,
58-
$this->urlGenerator
63+
$this->urlGenerator,
64+
$this->propertyMapper,
65+
null
5966
);
6067
}
6168

@@ -78,6 +85,8 @@ public function testSearch(): void {
7885
$this->addressBookInfo,
7986
$this->backend,
8087
$this->urlGenerator,
88+
$this->propertyMapper,
89+
null
8190
]
8291
)
8392
->setMethods(['vCard2Array', 'readCard'])
@@ -124,6 +133,8 @@ public function testCreate($properties): void {
124133
$this->addressBookInfo,
125134
$this->backend,
126135
$this->urlGenerator,
136+
$this->propertyMapper,
137+
null
127138
]
128139
)
129140
->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard'])
@@ -174,6 +185,8 @@ public function testUpdate(): void {
174185
$this->addressBookInfo,
175186
$this->backend,
176187
$this->urlGenerator,
188+
$this->propertyMapper,
189+
null
177190
]
178191
)
179192
->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
@@ -211,6 +224,8 @@ public function testUpdateWithTypes(): void {
211224
$this->addressBookInfo,
212225
$this->backend,
213226
$this->urlGenerator,
227+
$this->propertyMapper,
228+
null
214229
]
215230
)
216231
->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
@@ -292,6 +307,8 @@ public function testCreateUid(): void {
292307
$this->addressBookInfo,
293308
$this->backend,
294309
$this->urlGenerator,
310+
$this->propertyMapper,
311+
null
295312
]
296313
)
297314
->setMethods(['getUid'])
@@ -488,7 +505,9 @@ public function testIsSystemAddressBook(): void {
488505
$this->addressBook,
489506
$addressBookInfo,
490507
$this->backend,
491-
$this->urlGenerator
508+
$this->urlGenerator,
509+
$this->propertyMapper,
510+
null
492511
);
493512

494513
$this->assertTrue($addressBookImpl->isSystemAddressBook());
@@ -507,7 +526,9 @@ public function testIsShared(): void {
507526
$this->addressBook,
508527
$addressBookInfo,
509528
$this->backend,
510-
$this->urlGenerator
529+
$this->urlGenerator,
530+
$this->propertyMapper,
531+
'user2'
511532
);
512533

513534
$this->assertFalse($addressBookImpl->isSystemAddressBook());
@@ -527,7 +548,9 @@ public function testIsNotShared(): void {
527548
$this->addressBook,
528549
$addressBookInfo,
529550
$this->backend,
530-
$this->urlGenerator
551+
$this->urlGenerator,
552+
$this->propertyMapper,
553+
'user2'
531554
);
532555

533556
$this->assertFalse($addressBookImpl->isSystemAddressBook());

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use OCA\DAV\CardDAV\CardDavBackend;
1111
use OCA\DAV\CardDAV\ContactsManager;
12+
use OCA\DAV\Db\PropertyMapper;
1213
use OCP\Contacts\IManager;
1314
use OCP\IL10N;
1415
use OCP\IURLGenerator;
@@ -25,9 +26,10 @@ public function test(): void {
2526
$backEnd->method('getAddressBooksForUser')->willReturn([
2627
['{DAV:}displayname' => 'Test address book', 'uri' => 'default'],
2728
]);
29+
$propertyMapper = $this->createMock(PropertyMapper::class);
2830

2931
$l = $this->createMock(IL10N::class);
30-
$app = new ContactsManager($backEnd, $l);
32+
$app = new ContactsManager($backEnd, $l, $propertyMapper);
3133
$app->setupContactsProvider($cm, 'user01', $urlGenerator);
3234
}
3335
}

lib/composer/composer/autoload_classmap.php

+1
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@
551551
'OCP\\Http\\WellKnown\\IResponse' => $baseDir . '/lib/public/Http/WellKnown/IResponse.php',
552552
'OCP\\Http\\WellKnown\\JrdResponse' => $baseDir . '/lib/public/Http/WellKnown/JrdResponse.php',
553553
'OCP\\IAddressBook' => $baseDir . '/lib/public/IAddressBook.php',
554+
'OCP\\IAddressBookEnabled' => $baseDir . '/lib/public/IAddressBookEnabled.php',
554555
'OCP\\IAppConfig' => $baseDir . '/lib/public/IAppConfig.php',
555556
'OCP\\IAvatar' => $baseDir . '/lib/public/IAvatar.php',
556557
'OCP\\IAvatarManager' => $baseDir . '/lib/public/IAvatarManager.php',

lib/composer/composer/autoload_static.php

+1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
600600
'OCP\\Http\\WellKnown\\IResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/IResponse.php',
601601
'OCP\\Http\\WellKnown\\JrdResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/JrdResponse.php',
602602
'OCP\\IAddressBook' => __DIR__ . '/../../..' . '/lib/public/IAddressBook.php',
603+
'OCP\\IAddressBookEnabled' => __DIR__ . '/../../..' . '/lib/public/IAddressBookEnabled.php',
603604
'OCP\\IAppConfig' => __DIR__ . '/../../..' . '/lib/public/IAppConfig.php',
604605
'OCP\\IAvatar' => __DIR__ . '/../../..' . '/lib/public/IAvatar.php',
605606
'OCP\\IAvatarManager' => __DIR__ . '/../../..' . '/lib/public/IAvatarManager.php',

lib/private/ContactsManager.php

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use OCP\Constants;
1111
use OCP\Contacts\IManager;
1212
use OCP\IAddressBook;
13+
use OCP\IAddressBookEnabled;
1314

1415
class ContactsManager implements IManager {
1516
/**
@@ -34,6 +35,9 @@ public function search($pattern, $searchProperties = [], $options = []) {
3435
$this->loadAddressBooks();
3536
$result = [];
3637
foreach ($this->addressBooks as $addressBook) {
38+
if ($addressBook instanceof IAddressBookEnabled && !$addressBook->isEnabled()) {
39+
continue;
40+
}
3741
$searchOptions = $options;
3842
$strictSearch = array_key_exists('strict_search', $options) && $options['strict_search'] === true;
3943

lib/public/IAddressBookEnabled.php

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors"
7+
* SPDX-License-Identifier: AGPL-3.0-only
8+
*/
9+
// use OCP namespace for all classes that are considered public.
10+
// This means that they should be used by apps instead of the internal Nextcloud classes
11+
12+
namespace OCP;
13+
14+
/**
15+
* IAddressBook Interface extension for checking if the address book is enabled
16+
*
17+
* @since 32.0.0
18+
*/
19+
interface IAddressBookEnabled extends IAddressBook {
20+
/**
21+
* Check if the address book is enabled
22+
* @return bool
23+
* @since 32.0.0
24+
*/
25+
public function isEnabled(): bool;
26+
}

0 commit comments

Comments
 (0)