diff --git a/apps/dav/lib/CardDAV/Converter.php b/apps/dav/lib/CardDAV/Converter.php index e19b52b478362..a24c0462f7619 100644 --- a/apps/dav/lib/CardDAV/Converter.php +++ b/apps/dav/lib/CardDAV/Converter.php @@ -28,7 +28,11 @@ namespace OCA\DAV\CardDAV; use Exception; +use OCA\DAV\AppInfo\Application; use OCP\Accounts\IAccountManager; +use OCP\IConfig; +use OCP\IGroup; +use OCP\IGroupManager; use OCP\IURLGenerator; use OCP\IImage; use OCP\IUser; @@ -42,12 +46,16 @@ class Converter { /** @var IAccountManager */ private $accountManager; private IUserManager $userManager; + private IGroupManager $groupManager; + private IConfig $config; public function __construct(IAccountManager $accountManager, - IUserManager $userManager, IURLGenerator $urlGenerator) { + IUserManager $userManager, IGroupManager $groupManager, IURLGenerator $urlGenerator, IConfig $config) { $this->accountManager = $accountManager; $this->userManager = $userManager; + $this->groupManager = $groupManager; $this->urlGenerator = $urlGenerator; + $this->config = $config; } public function createCardFromUser(IUser $user): ?VCard { @@ -151,6 +159,17 @@ public function createCardFromUser(IUser $user): ?VCard { } } + if ($this->config->getAppValue(Application::APP_ID, 'system_addressbook_expose_groups', 'yes') === 'yes') { + $groupsToIgnore = explode(',', $this->config->getAppValue(Application::APP_ID, 'system_addressbook_groups_to_ignore', '')); + $groupNames = array_reduce($this->groupManager->getUserGroups($user), function ($groupNames, IGroup $group) use ($groupsToIgnore) { + if (!in_array($group->getGID(), $groupsToIgnore, true)) { + $groupNames[] = $group->getDisplayName(); + } + return $groupNames; + }, []); + $vCard->add(new Text($vCard, 'CATEGORIES', implode(',', $groupNames))); + } + if ($publish && !empty($cloudId)) { $vCard->add(new Text($vCard, 'CLOUD', $cloudId)); $vCard->validate(); diff --git a/apps/dav/tests/unit/CardDAV/ConverterTest.php b/apps/dav/tests/unit/CardDAV/ConverterTest.php index 7205cf5665444..405c900a1c690 100644 --- a/apps/dav/tests/unit/CardDAV/ConverterTest.php +++ b/apps/dav/tests/unit/CardDAV/ConverterTest.php @@ -30,39 +30,45 @@ */ namespace OCA\DAV\Tests\unit\CardDAV; +use OCA\DAV\AppInfo\Application; use OCA\DAV\CardDAV\Converter; use OCP\Accounts\IAccount; use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountProperty; +use OCP\IConfig; +use OCP\IGroup; +use OCP\IGroupManager; use OCP\IURLGenerator; use OCP\IImage; use OCP\IUser; use OCP\IUserManager; use PHPUnit\Framework\MockObject\MockObject; +use Sabre\VObject\Component\VCard; +use Sabre\VObject\Reader; use Test\TestCase; class ConverterTest extends TestCase { - - /** @var IAccountManager|\PHPUnit\Framework\MockObject\MockObject */ - private $accountManager; - /** @var IUserManager|(IUserManager&MockObject)|MockObject */ + private IAccountManager|MockObject $accountManager; private IUserManager|MockObject $userManager; + private IGroupManager|MockObject $groupManager; + private IURLGenerator|MockObject $urlGenerator; - /** @var IURLGenerator */ - private $urlGenerator; + private IConfig|MockObject $config; protected function setUp(): void { parent::setUp(); $this->accountManager = $this->createMock(IAccountManager::class); $this->userManager = $this->createMock(IUserManager::class); + $this->groupManager = $this->createMock(IGroupManager::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->config = $this->createMock(IConfig::class); } /** * @return IAccountProperty|MockObject */ - protected function getAccountPropertyMock(string $name, ?string $value, string $scope) { + protected function getAccountPropertyMock(string $name, ?string $value, string $scope): IAccountProperty|MockObject { $property = $this->createMock(IAccountProperty::class); $property->expects($this->any()) ->method('getName') @@ -108,10 +114,10 @@ public function testCreation($expectedVCard, $displayName = null, $eMailAddress $user = $this->getUserMock((string)$displayName, $eMailAddress, $cloudId); $accountManager = $this->getAccountManager($user); - $converter = new Converter($accountManager, $this->userManager, $this->urlGenerator); + $converter = new Converter($accountManager, $this->userManager, $this->groupManager, $this->urlGenerator, $this->config); $vCard = $converter->createCardFromUser($user); if ($expectedVCard !== null) { - $this->assertInstanceOf('Sabre\VObject\Component\VCard', $vCard); + $this->assertInstanceOf(VCard::class, $vCard); $cardData = $vCard->jsonSerialize(); $this->compareData($expectedVCard, $cardData); } else { @@ -129,7 +135,7 @@ public function testManagerProp(): void { ->willReturn('Manager'); $accountManager = $this->getAccountManager($user); - $converter = new Converter($accountManager, $this->userManager, $this->urlGenerator); + $converter = new Converter($accountManager, $this->userManager, $this->groupManager, $this->urlGenerator, $this->config); $vCard = $converter->createCardFromUser($user); $this->compareData( @@ -142,7 +148,7 @@ public function testManagerProp(): void { ); } - protected function compareData($expected, $data) { + protected function compareData($expected, $data): void { foreach ($expected as $key => $value) { $found = false; foreach ($data[1] as $d) { @@ -152,12 +158,12 @@ protected function compareData($expected, $data) { } } if (!$found) { - $this->assertTrue(false, 'Expected data: ' . $key . ' not found.'); + $this->fail('Expected data: ' . $key . ' not found.'); } } } - public function providesNewUsers() { + public function providesNewUsers(): array { return [ [ null @@ -213,17 +219,15 @@ public function providesNewUsers() { /** * @dataProvider providesNames - * @param $expected - * @param $fullName */ - public function testNameSplitter($expected, $fullName): void { - $converter = new Converter($this->accountManager, $this->userManager, $this->urlGenerator); + public function testNameSplitter(string $expected, string $fullName): void { + $converter = new Converter($this->accountManager, $this->userManager, $this->groupManager, $this->urlGenerator, $this->config); $r = $converter->splitFullName($fullName); $r = implode(';', $r); $this->assertEquals($expected, $r); } - public function providesNames() { + public function providesNames(): array { return [ ['Sauron;;;;', 'Sauron'], ['Baggins;Bilbo;;;', 'Bilbo Baggins'], @@ -231,13 +235,7 @@ public function providesNames() { ]; } - /** - * @param $displayName - * @param $eMailAddress - * @param $cloudId - * @return IUser | \PHPUnit\Framework\MockObject\MockObject - */ - protected function getUserMock(string $displayName, ?string $eMailAddress, ?string $cloudId) { + protected function getUserMock(string $displayName, ?string $eMailAddress, ?string $cloudId): IUser|MockObject { $image0 = $this->getMockBuilder(IImage::class)->disableOriginalConstructor()->getMock(); $image0->method('mimeType')->willReturn('image/jpeg'); $image0->method('data')->willReturn('123456789'); @@ -249,4 +247,45 @@ protected function getUserMock(string $displayName, ?string $eMailAddress, ?stri $user->method('getAvatarImage')->willReturn($image0); return $user; } + + /** + * @dataProvider dataForTestExposeGroups + */ + public function testExposeGroups(bool $exposeGroups, array $groups, string $groupsToIgnore, ?string $result): void { + $user = $this->getUserMock("user", "user@domain.tld", "user@cloud.domain.tld"); + $this->config->expects($exposeGroups ? $this->exactly(2) :$this->once())->method('getAppValue')->withConsecutive( + [Application::APP_ID, 'system_addressbook_expose_groups', 'yes'], + [Application::APP_ID, 'system_addressbook_groups_to_ignore', ''] + )->willReturnOnConsecutiveCalls( + $exposeGroups ? 'yes' : 'no', + $groupsToIgnore + ); + + $ignoredGroups = explode(',', $groupsToIgnore); + + $this->groupManager->expects($exposeGroups ? $this->once() : $this->never())->method('getUserGroups')->with($user)->willReturn(array_map(function ($groupName) use ($groups, $exposeGroups, $ignoredGroups) { + $group = $this->createMock(IGroup::class); + $group->expects($exposeGroups ? $this->once() : $this->never())->method('getGID')->willReturn($groupName); + $group->expects($exposeGroups && !in_array($groupName, $ignoredGroups, true) ? $this->once() : $this->never())->method('getDisplayName')->willReturn($groupName); + return $group; + }, $groups)); + $accountManager = $this->getAccountManager($user); + + $converter = new Converter($accountManager, $this->userManager, $this->groupManager, $this->urlGenerator, $this->config); + $vCard = $converter->createCardFromUser($user); + + $parsed = Reader::read($vCard->serialize(), Reader::OPTION_FORGIVING); + + $this->assertEquals((string) $parsed->CATEGORIES, $result); + } + + public function dataForTestExposeGroups(): array { + return [ + [false, ['myGroup1'], '', null], + [true, ['myGroup1'], '', 'myGroup1'], + [true, ['myGroup1', 'myGroup2'], '', 'myGroup1,myGroup2'], + [true, ['myGroup1', 'myGroup2', 'myGroup3', 'myGroup4'], 'myGroup2,myGroup3', 'myGroup1,myGroup4'], + [true, ['myGroup1', 'myGroup2'], 'myGroup2,myGroup3', 'myGroup1'] + ]; + } }