123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- <?php
- declare(strict_types=1);
- /*
- * @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @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\Tests\unit\CardDAV;
- use OC\AppFramework\Http\Request;
- use OCA\DAV\CardDAV\SyncService;
- use OCA\DAV\CardDAV\SystemAddressbook;
- use OCA\Federation\TrustedServers;
- use OCP\Accounts\IAccountManager;
- use OCP\IConfig;
- use OCP\IGroup;
- use OCP\IGroupManager;
- use OCP\IL10N;
- use OCP\IRequest;
- use OCP\IUser;
- use OCP\IUserSession;
- use PHPUnit\Framework\MockObject\MockObject;
- use Sabre\CardDAV\Backend\BackendInterface;
- use Sabre\DAV\Exception\Forbidden;
- use Sabre\DAV\Exception\NotFound;
- use Sabre\VObject\Component\VCard;
- use Sabre\VObject\Reader;
- use Test\TestCase;
- class SystemAddressBookTest extends TestCase {
- private MockObject|BackendInterface $cardDavBackend;
- private array $addressBookInfo;
- private IL10N|MockObject $l10n;
- private IConfig|MockObject $config;
- private IUserSession $userSession;
- private IRequest|MockObject $request;
- private array $server;
- private TrustedServers|MockObject $trustedServers;
- private IGroupManager|MockObject $groupManager;
- private SystemAddressbook $addressBook;
- protected function setUp(): void {
- parent::setUp();
- $this->cardDavBackend = $this->createMock(BackendInterface::class);
- $this->addressBookInfo = [
- 'id' => 123,
- '{DAV:}displayname' => 'Accounts',
- 'principaluri' => 'principals/system/system',
- ];
- $this->l10n = $this->createMock(IL10N::class);
- $this->config = $this->createMock(IConfig::class);
- $this->userSession = $this->createMock(IUserSession::class);
- $this->request = $this->createMock(Request::class);
- $this->server = [
- 'PHP_AUTH_USER' => 'system',
- 'PHP_AUTH_PW' => 'shared123',
- ];
- $this->request->method('__get')->with('server')->willReturn($this->server);
- $this->trustedServers = $this->createMock(TrustedServers::class);
- $this->groupManager = $this->createMock(IGroupManager::class);
- $this->addressBook = new SystemAddressbook(
- $this->cardDavBackend,
- $this->addressBookInfo,
- $this->l10n,
- $this->config,
- $this->userSession,
- $this->request,
- $this->trustedServers,
- $this->groupManager,
- );
- }
- public function testGetChildrenAsGuest(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getUID')->willReturn('user');
- $user->method('getBackendClassName')->willReturn('Guests');
- $this->userSession->expects(self::once())
- ->method('getUser')
- ->willReturn($user);
- $vcfWithScopes = <<<VCF
- BEGIN:VCARD
- VERSION:3.0
- PRODID:-//Sabre//Sabre VObject 4.4.2//EN
- UID:admin
- FN;X-NC-SCOPE=v2-federated:admin
- N;X-NC-SCOPE=v2-federated:admin;;;;
- ADR;TYPE=OTHER;X-NC-SCOPE=v2-local:Testing test test test;;;;;;
- EMAIL;TYPE=OTHER;X-NC-SCOPE=v2-federated:miau_lalala@gmx.net
- TEL;TYPE=OTHER;X-NC-SCOPE=v2-local:+435454454544
- CLOUD:admin@http://localhost
- END:VCARD
- VCF;
- $originalCard = [
- 'carddata' => $vcfWithScopes,
- ];
- $this->cardDavBackend->expects(self::once())
- ->method('getCard')
- ->with(123, 'Guests:user.vcf')
- ->willReturn($originalCard);
- $children = $this->addressBook->getChildren();
- self::assertCount(1, $children);
- }
- public function testGetFilteredChildForFederation(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $this->trustedServers->expects(self::once())
- ->method('getServers')
- ->willReturn([
- [
- 'shared_secret' => 'shared123',
- ],
- ]);
- $vcfWithScopes = <<<VCF
- BEGIN:VCARD
- VERSION:3.0
- PRODID:-//Sabre//Sabre VObject 4.4.2//EN
- UID:admin
- FN;X-NC-SCOPE=v2-federated:admin
- N;X-NC-SCOPE=v2-federated:admin;;;;
- ADR;TYPE=OTHER;X-NC-SCOPE=v2-local:Testing test test test;;;;;;
- EMAIL;TYPE=OTHER;X-NC-SCOPE=v2-federated:miau_lalala@gmx.net
- TEL;TYPE=OTHER;X-NC-SCOPE=v2-local:+435454454544
- CLOUD:admin@http://localhost
- END:VCARD
- VCF;
- $originalCard = [
- 'carddata' => $vcfWithScopes,
- ];
- $this->cardDavBackend->expects(self::once())
- ->method('getCard')
- ->with(123, 'user.vcf')
- ->willReturn($originalCard);
- $card = $this->addressBook->getChild("user.vcf");
- /** @var VCard $vCard */
- $vCard = Reader::read($card->get());
- foreach ($vCard->children() as $child) {
- $scope = $child->offsetGet('X-NC-SCOPE');
- if ($scope !== null) {
- self::assertNotEquals(IAccountManager::SCOPE_PRIVATE, $scope->getValue());
- self::assertNotEquals(IAccountManager::SCOPE_LOCAL, $scope->getValue());
- }
- }
- }
- public function testGetChildNotFound(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $this->trustedServers->expects(self::once())
- ->method('getServers')
- ->willReturn([
- [
- 'shared_secret' => 'shared123',
- ],
- ]);
- $this->expectException(NotFound::class);
- $this->addressBook->getChild("LDAP:user.vcf");
- }
- public function testGetChildWithoutEnumeration(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $this->expectException(Forbidden::class);
- $this->addressBook->getChild("LDAP:user.vcf");
- }
- public function testGetChildAsGuest(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getBackendClassName')->willReturn('Guests');
- $this->userSession->expects(self::once())
- ->method('getUser')
- ->willReturn($user);
- $this->expectException(Forbidden::class);
- $this->addressBook->getChild("LDAP:user.vcf");
- }
- public function testGetChildWithGroupEnumerationRestriction(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getBackendClassName')->willReturn('LDAP');
- $this->userSession->expects(self::once())
- ->method('getUser')
- ->willReturn($user);
- $otherUser = $this->createMock(IUser::class);
- $user->method('getBackendClassName')->willReturn('LDAP');
- $otherUser->method('getUID')->willReturn('other');
- $group = $this->createMock(IGroup::class);
- $group->expects(self::once())
- ->method('getUsers')
- ->willReturn([$otherUser]);
- $this->groupManager->expects(self::once())
- ->method('getUserGroups')
- ->with($user)
- ->willReturn([$group]);
- $cardData = <<<VCF
- BEGIN:VCARD
- VERSION:3.0
- PRODID:-//Sabre//Sabre VObject 4.4.2//EN
- UID:admin
- FN;X-NC-SCOPE=v2-federated:other
- END:VCARD
- VCF;
- $this->cardDavBackend->expects(self::once())
- ->method('getCard')
- ->with($this->addressBookInfo['id'], "{$otherUser->getBackendClassName()}:{$otherUser->getUID()}.vcf")
- ->willReturn([
- 'id' => 123,
- 'carddata' => $cardData,
- ]);
- $this->addressBook->getChild("{$otherUser->getBackendClassName()}:{$otherUser->getUID()}.vcf");
- }
- public function testGetChildWithPhoneNumberEnumerationRestriction(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getBackendClassName')->willReturn('LDAP');
- $this->userSession->expects(self::once())
- ->method('getUser')
- ->willReturn($user);
- $this->expectException(Forbidden::class);
- $this->addressBook->getChild("LDAP:user.vcf");
- }
- public function testGetOwnChildWithPhoneNumberEnumerationRestriction(): void {
- $this->config->expects(self::exactly(3))
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getBackendClassName')->willReturn('LDAP');
- $user->method('getUID')->willReturn('user');
- $this->userSession->expects(self::once())
- ->method('getUser')
- ->willReturn($user);
- $cardData = <<<VCF
- BEGIN:VCARD
- VERSION:3.0
- PRODID:-//Sabre//Sabre VObject 4.4.2//EN
- UID:admin
- FN;X-NC-SCOPE=v2-federated:user
- END:VCARD
- VCF;
- $this->cardDavBackend->expects(self::once())
- ->method('getCard')
- ->with($this->addressBookInfo['id'], 'LDAP:user.vcf')
- ->willReturn([
- 'id' => 123,
- 'carddata' => $cardData,
- ]);
- $this->addressBook->getChild("LDAP:user.vcf");
- }
- public function testGetMultipleChildrenWithGroupEnumerationRestriction(): void {
- $this->config
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getUID')->willReturn('user');
- $user->method('getBackendClassName')->willReturn('LDAP');
- $other1 = $this->createMock(IUser::class);
- $other1->method('getUID')->willReturn('other1');
- $other1->method('getBackendClassName')->willReturn('LDAP');
- $other2 = $this->createMock(IUser::class);
- $other2->method('getUID')->willReturn('other2');
- $other2->method('getBackendClassName')->willReturn('LDAP');
- $other3 = $this->createMock(IUser::class);
- $other3->method('getUID')->willReturn('other3');
- $other3->method('getBackendClassName')->willReturn('LDAP');
- $this->userSession
- ->method('getUser')
- ->willReturn($user);
- $group1 = $this->createMock(IGroup::class);
- $group1
- ->method('getUsers')
- ->willReturn([$user, $other1]);
- $group2 = $this->createMock(IGroup::class);
- $group2
- ->method('getUsers')
- ->willReturn([$other1, $other2, $user]);
- $this->groupManager
- ->method('getUserGroups')
- ->with($user)
- ->willReturn([$group1]);
- $this->cardDavBackend->expects(self::once())
- ->method('getMultipleCards')
- ->with($this->addressBookInfo['id'], [
- SyncService::getCardUri($user),
- SyncService::getCardUri($other1),
- ])
- ->willReturn([
- [],
- [],
- ]);
- $cards = $this->addressBook->getMultipleChildren([
- SyncService::getCardUri($user),
- SyncService::getCardUri($other1),
- // SyncService::getCardUri($other2), // Omitted to test that it's not returned as stray
- SyncService::getCardUri($other3), // No overlapping group with this one
- ]);
- self::assertCount(2, $cards);
- }
- public function testGetMultipleChildrenAsGuest(): void {
- $this->config
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $user = $this->createMock(IUser::class);
- $user->method('getUID')->willReturn('user');
- $user->method('getBackendClassName')->willReturn('Guests');
- $this->userSession->expects(self::once())
- ->method('getUser')
- ->willReturn($user);
- $cards = $this->addressBook->getMultipleChildren(['Database:user1.vcf', 'LDAP:user2.vcf']);
- self::assertEmpty($cards);
- }
- public function testGetMultipleChildren(): void {
- $this->config
- ->method('getAppValue')
- ->willReturnMap([
- ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
- ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
- ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
- ]);
- $this->trustedServers
- ->method('getServers')
- ->willReturn([
- [
- 'shared_secret' => 'shared123',
- ],
- ]);
- $cardData = <<<VCF
- BEGIN:VCARD
- VERSION:3.0
- PRODID:-//Sabre//Sabre VObject 4.4.2//EN
- UID:admin
- FN;X-NC-SCOPE=v2-federated:user
- END:VCARD
- VCF;
- $this->cardDavBackend->expects(self::once())
- ->method('getMultipleCards')
- ->with($this->addressBookInfo['id'], ['Database:user1.vcf', 'LDAP:user2.vcf'])
- ->willReturn([
- [
- 'id' => 123,
- 'carddata' => $cardData,
- ],
- [
- 'id' => 321,
- 'carddata' => $cardData,
- ],
- ]);
- $cards = $this->addressBook->getMultipleChildren(['Database:user1.vcf', 'LDAP:user2.vcf']);
- self::assertCount(2, $cards);
- }
- }
|