Merge pull request #23510 from owncloud/birthdays-on-shared-addressbooks
Propagate birthdays of shared addressbooks to the sharee's birthday c…
This commit is contained in:
commit
6f3eeeeb36
|
@ -27,6 +27,8 @@ use OCA\DAV\CardDAV\CardDavBackend;
|
||||||
use OCA\DAV\CardDAV\ContactsManager;
|
use OCA\DAV\CardDAV\ContactsManager;
|
||||||
use OCA\DAV\CardDAV\SyncJob;
|
use OCA\DAV\CardDAV\SyncJob;
|
||||||
use OCA\DAV\CardDAV\SyncService;
|
use OCA\DAV\CardDAV\SyncService;
|
||||||
|
use OCA\DAV\Connector\Sabre\Principal;
|
||||||
|
use OCA\DAV\DAV\GroupPrincipalBackend;
|
||||||
use OCA\DAV\HookManager;
|
use OCA\DAV\HookManager;
|
||||||
use OCA\Dav\Migration\AddressBookAdapter;
|
use OCA\Dav\Migration\AddressBookAdapter;
|
||||||
use OCA\Dav\Migration\CalendarAdapter;
|
use OCA\Dav\Migration\CalendarAdapter;
|
||||||
|
@ -79,7 +81,7 @@ class Application extends App {
|
||||||
/** @var IAppContainer $c */
|
/** @var IAppContainer $c */
|
||||||
$db = $c->getServer()->getDatabaseConnection();
|
$db = $c->getServer()->getDatabaseConnection();
|
||||||
$dispatcher = $c->getServer()->getEventDispatcher();
|
$dispatcher = $c->getServer()->getEventDispatcher();
|
||||||
$principal = new \OCA\DAV\Connector\Sabre\Principal(
|
$principal = new Principal(
|
||||||
$c->getServer()->getUserManager(),
|
$c->getServer()->getUserManager(),
|
||||||
$c->getServer()->getGroupManager()
|
$c->getServer()->getGroupManager()
|
||||||
);
|
);
|
||||||
|
@ -89,7 +91,7 @@ class Application extends App {
|
||||||
$container->registerService('CalDavBackend', function($c) {
|
$container->registerService('CalDavBackend', function($c) {
|
||||||
/** @var IAppContainer $c */
|
/** @var IAppContainer $c */
|
||||||
$db = $c->getServer()->getDatabaseConnection();
|
$db = $c->getServer()->getDatabaseConnection();
|
||||||
$principal = new \OCA\DAV\Connector\Sabre\Principal(
|
$principal = new Principal(
|
||||||
$c->getServer()->getUserManager(),
|
$c->getServer()->getUserManager(),
|
||||||
$c->getServer()->getGroupManager()
|
$c->getServer()->getGroupManager()
|
||||||
);
|
);
|
||||||
|
@ -122,11 +124,14 @@ class Application extends App {
|
||||||
|
|
||||||
$container->registerService('BirthdayService', function($c) {
|
$container->registerService('BirthdayService', function($c) {
|
||||||
/** @var IAppContainer $c */
|
/** @var IAppContainer $c */
|
||||||
|
$g = new GroupPrincipalBackend(
|
||||||
|
$c->getServer()->getGroupManager()
|
||||||
|
);
|
||||||
return new BirthdayService(
|
return new BirthdayService(
|
||||||
$c->query('CalDavBackend'),
|
$c->query('CalDavBackend'),
|
||||||
$c->query('CardDavBackend')
|
$c->query('CardDavBackend'),
|
||||||
|
$g
|
||||||
);
|
);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +152,7 @@ class Application extends App {
|
||||||
|
|
||||||
$listener = function($event) {
|
$listener = function($event) {
|
||||||
if ($event instanceof GenericEvent) {
|
if ($event instanceof GenericEvent) {
|
||||||
|
/** @var BirthdayService $b */
|
||||||
$b = $this->getContainer()->query('BirthdayService');
|
$b = $this->getContainer()->query('BirthdayService');
|
||||||
$b->onCardChanged(
|
$b->onCardChanged(
|
||||||
$event->getArgument('addressBookId'),
|
$event->getArgument('addressBookId'),
|
||||||
|
@ -161,6 +167,7 @@ class Application extends App {
|
||||||
$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $listener);
|
$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $listener);
|
||||||
$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function($event) {
|
$dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function($event) {
|
||||||
if ($event instanceof GenericEvent) {
|
if ($event instanceof GenericEvent) {
|
||||||
|
/** @var BirthdayService $b */
|
||||||
$b = $this->getContainer()->query('BirthdayService');
|
$b = $this->getContainer()->query('BirthdayService');
|
||||||
$b->onCardDeleted(
|
$b->onCardDeleted(
|
||||||
$event->getArgument('addressBookId'),
|
$event->getArgument('addressBookId'),
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace OCA\DAV\CalDAV;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use OCA\DAV\CardDAV\CardDavBackend;
|
use OCA\DAV\CardDAV\CardDavBackend;
|
||||||
|
use OCA\DAV\DAV\GroupPrincipalBackend;
|
||||||
use Sabre\VObject\Component\VCalendar;
|
use Sabre\VObject\Component\VCalendar;
|
||||||
use Sabre\VObject\Reader;
|
use Sabre\VObject\Reader;
|
||||||
|
|
||||||
|
@ -30,15 +31,20 @@ class BirthdayService {
|
||||||
|
|
||||||
const BIRTHDAY_CALENDAR_URI = 'contact_birthdays';
|
const BIRTHDAY_CALENDAR_URI = 'contact_birthdays';
|
||||||
|
|
||||||
|
/** @var GroupPrincipalBackend */
|
||||||
|
private $principalBackend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BirthdayService constructor.
|
* BirthdayService constructor.
|
||||||
*
|
*
|
||||||
* @param CalDavBackend $calDavBackEnd
|
* @param CalDavBackend $calDavBackEnd
|
||||||
* @param CardDavBackend $cardDavBackEnd
|
* @param CardDavBackend $cardDavBackEnd
|
||||||
|
* @param GroupPrincipalBackend $principalBackend
|
||||||
*/
|
*/
|
||||||
public function __construct($calDavBackEnd, $cardDavBackEnd) {
|
public function __construct($calDavBackEnd, $cardDavBackEnd, $principalBackend) {
|
||||||
$this->calDavBackEnd = $calDavBackEnd;
|
$this->calDavBackEnd = $calDavBackEnd;
|
||||||
$this->cardDavBackEnd = $cardDavBackEnd;
|
$this->cardDavBackEnd = $cardDavBackEnd;
|
||||||
|
$this->principalBackend = $principalBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,8 +54,11 @@ class BirthdayService {
|
||||||
*/
|
*/
|
||||||
public function onCardChanged($addressBookId, $cardUri, $cardData) {
|
public function onCardChanged($addressBookId, $cardUri, $cardData) {
|
||||||
|
|
||||||
|
$targetPrincipals = $this->getAllAffectedPrincipals($addressBookId);
|
||||||
|
|
||||||
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
|
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
|
||||||
$principalUri = $book['principaluri'];
|
$targetPrincipals[] = $book['principaluri'];
|
||||||
|
foreach ($targetPrincipals as $principalUri) {
|
||||||
$calendar = $this->ensureCalendarExists($principalUri);
|
$calendar = $this->ensureCalendarExists($principalUri);
|
||||||
$objectUri = $book['uri'] . '-' . $cardUri. '.ics';
|
$objectUri = $book['uri'] . '-' . $cardUri. '.ics';
|
||||||
$calendarData = $this->buildBirthdayFromContact($cardData);
|
$calendarData = $this->buildBirthdayFromContact($cardData);
|
||||||
|
@ -68,18 +77,22 @@ class BirthdayService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $addressBookId
|
* @param int $addressBookId
|
||||||
* @param string $cardUri
|
* @param string $cardUri
|
||||||
*/
|
*/
|
||||||
public function onCardDeleted($addressBookId, $cardUri) {
|
public function onCardDeleted($addressBookId, $cardUri) {
|
||||||
|
$targetPrincipals = $this->getAllAffectedPrincipals($addressBookId);
|
||||||
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
|
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
|
||||||
$principalUri = $book['principaluri'];
|
$targetPrincipals[] = $book['principaluri'];
|
||||||
|
foreach ($targetPrincipals as $principalUri) {
|
||||||
$calendar = $this->ensureCalendarExists($principalUri);
|
$calendar = $this->ensureCalendarExists($principalUri);
|
||||||
$objectUri = $book['uri'] . '-' . $cardUri. '.ics';
|
$objectUri = $book['uri'] . '-' . $cardUri . '.ics';
|
||||||
$this->calDavBackEnd->deleteCalendarObject($calendar['id'], $objectUri);
|
$this->calDavBackEnd->deleteCalendarObject($calendar['id'], $objectUri);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $principal
|
* @param string $principal
|
||||||
|
@ -190,4 +203,24 @@ class BirthdayService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $addressBookId
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function getAllAffectedPrincipals($addressBookId) {
|
||||||
|
$targetPrincipals = [];
|
||||||
|
$shares = $this->cardDavBackEnd->getShares($addressBookId);
|
||||||
|
foreach ($shares as $share) {
|
||||||
|
if ($share['{http://owncloud.org/ns}group-share']) {
|
||||||
|
$users = $this->principalBackend->getGroupMemberSet($share['{http://owncloud.org/ns}principal']);
|
||||||
|
foreach ($users as $user) {
|
||||||
|
$targetPrincipals[] = $user['uri'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$targetPrincipals[] = $share['{http://owncloud.org/ns}principal'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array_values(array_unique($targetPrincipals, SORT_STRING));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace OCA\DAV\DAV;
|
||||||
|
|
||||||
use OCP\IGroup;
|
use OCP\IGroup;
|
||||||
use OCP\IGroupManager;
|
use OCP\IGroupManager;
|
||||||
|
use OCP\IUser;
|
||||||
use Sabre\DAV\Exception;
|
use Sabre\DAV\Exception;
|
||||||
use \Sabre\DAV\PropPatch;
|
use \Sabre\DAV\PropPatch;
|
||||||
use Sabre\DAVACL\PrincipalBackend\BackendInterface;
|
use Sabre\DAVACL\PrincipalBackend\BackendInterface;
|
||||||
|
@ -82,10 +83,10 @@ class GroupPrincipalBackend implements BackendInterface {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$name = $elements[2];
|
$name = $elements[2];
|
||||||
$user = $this->groupManager->get($name);
|
$group = $this->groupManager->get($name);
|
||||||
|
|
||||||
if (!is_null($user)) {
|
if (!is_null($group)) {
|
||||||
return $this->groupToPrincipal($user);
|
return $this->groupToPrincipal($group);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -99,9 +100,24 @@ class GroupPrincipalBackend implements BackendInterface {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function getGroupMemberSet($principal) {
|
public function getGroupMemberSet($principal) {
|
||||||
// TODO: implement if we want that
|
$elements = explode('/', $principal);
|
||||||
|
if ($elements[0] !== 'principals') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
if ($elements[1] !== 'groups') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$name = $elements[2];
|
||||||
|
$group = $this->groupManager->get($name);
|
||||||
|
|
||||||
|
if (is_null($group)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_map(function($user) {
|
||||||
|
return $this->userToPrincipal($user);
|
||||||
|
}, $group->getUsers());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of groups a principal is a member of
|
* Returns the list of groups a principal is a member of
|
||||||
|
@ -168,4 +184,17 @@ class GroupPrincipalBackend implements BackendInterface {
|
||||||
|
|
||||||
return $principal;
|
return $principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param IUser $user
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function userToPrincipal($user) {
|
||||||
|
$principal = [
|
||||||
|
'uri' => 'principals/users/' . $user->getUID(),
|
||||||
|
'{DAV:}displayname' => $user->getDisplayName(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return $principal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,8 @@ class Backend {
|
||||||
'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
|
'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
|
||||||
'status' => 1,
|
'status' => 1,
|
||||||
'readOnly' => ($row['access'] == self::ACCESS_READ),
|
'readOnly' => ($row['access'] == self::ACCESS_READ),
|
||||||
'{'.\OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD.'}principal' => $row['principaluri']
|
'{http://owncloud.org/ns}principal' => $row['principaluri'],
|
||||||
|
'{http://owncloud.org/ns}group-share' => is_null($p)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace OCA\DAV\Tests\Unit\CardDAV;
|
||||||
use OCA\DAV\CalDAV\BirthdayService;
|
use OCA\DAV\CalDAV\BirthdayService;
|
||||||
use OCA\DAV\CalDAV\CalDavBackend;
|
use OCA\DAV\CalDAV\CalDavBackend;
|
||||||
use OCA\DAV\CardDAV\CardDavBackend;
|
use OCA\DAV\CardDAV\CardDavBackend;
|
||||||
|
use OCA\DAV\DAV\GroupPrincipalBackend;
|
||||||
use Sabre\VObject\Component\VCalendar;
|
use Sabre\VObject\Component\VCalendar;
|
||||||
use Sabre\VObject\Reader;
|
use Sabre\VObject\Reader;
|
||||||
use Test\TestCase;
|
use Test\TestCase;
|
||||||
|
@ -36,14 +37,17 @@ class BirthdayServiceTest extends TestCase {
|
||||||
private $calDav;
|
private $calDav;
|
||||||
/** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */
|
/** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $cardDav;
|
private $cardDav;
|
||||||
|
/** @var GroupPrincipalBackend | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $groupPrincialBackend;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->calDav = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock();
|
$this->calDav = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock();
|
||||||
$this->cardDav = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock();
|
$this->cardDav = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend')->disableOriginalConstructor()->getMock();
|
||||||
|
$this->groupPrincialBackend = $this->getMockBuilder('OCA\DAV\DAV\GroupPrincipalBackend')->disableOriginalConstructor()->getMock();
|
||||||
|
|
||||||
$this->service = new BirthdayService($this->calDav, $this->cardDav);
|
$this->service = new BirthdayService($this->calDav, $this->cardDav, $this->groupPrincialBackend);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,6 +81,7 @@ class BirthdayServiceTest extends TestCase {
|
||||||
'id' => 1234
|
'id' => 1234
|
||||||
]);
|
]);
|
||||||
$this->calDav->expects($this->once())->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics');
|
$this->calDav->expects($this->once())->method('deleteCalendarObject')->with(1234, 'default-gump.vcf.ics');
|
||||||
|
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
|
||||||
|
|
||||||
$this->service->onCardDeleted(666, 'gump.vcf');
|
$this->service->onCardDeleted(666, 'gump.vcf');
|
||||||
}
|
}
|
||||||
|
@ -96,10 +101,11 @@ class BirthdayServiceTest extends TestCase {
|
||||||
->willReturn([
|
->willReturn([
|
||||||
'id' => 1234
|
'id' => 1234
|
||||||
]);
|
]);
|
||||||
|
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
|
||||||
|
|
||||||
/** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject $service */
|
/** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject $service */
|
||||||
$service = $this->getMock('\OCA\DAV\CalDAV\BirthdayService',
|
$service = $this->getMock('\OCA\DAV\CalDAV\BirthdayService',
|
||||||
['buildBirthdayFromContact', 'birthdayEvenChanged'], [$this->calDav, $this->cardDav]);
|
['buildBirthdayFromContact', 'birthdayEvenChanged'], [$this->calDav, $this->cardDav, $this->groupPrincialBackend]);
|
||||||
|
|
||||||
if ($expectedOp === 'delete') {
|
if ($expectedOp === 'delete') {
|
||||||
$this->calDav->expects($this->once())->method('getCalendarObject')->willReturn('');
|
$this->calDav->expects($this->once())->method('getCalendarObject')->willReturn('');
|
||||||
|
@ -132,6 +138,45 @@ class BirthdayServiceTest extends TestCase {
|
||||||
$this->assertEquals($expected, $this->service->birthdayEvenChanged($old, $new));
|
$this->assertEquals($expected, $this->service->birthdayEvenChanged($old, $new));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetAllAffectedPrincipals() {
|
||||||
|
$this->cardDav->expects($this->once())->method('getShares')->willReturn([
|
||||||
|
[
|
||||||
|
'{http://owncloud.org/ns}group-share' => false,
|
||||||
|
'{http://owncloud.org/ns}principal' => 'principals/users/user01'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'{http://owncloud.org/ns}group-share' => false,
|
||||||
|
'{http://owncloud.org/ns}principal' => 'principals/users/user01'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'{http://owncloud.org/ns}group-share' => false,
|
||||||
|
'{http://owncloud.org/ns}principal' => 'principals/users/user02'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'{http://owncloud.org/ns}group-share' => true,
|
||||||
|
'{http://owncloud.org/ns}principal' => 'principals/groups/users'
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->groupPrincialBackend->expects($this->once())->method('getGroupMemberSet')
|
||||||
|
->willReturn([
|
||||||
|
[
|
||||||
|
'uri' => 'principals/users/user01',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'uri' => 'principals/users/user02',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'uri' => 'principals/users/user03',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$users = $this->invokePrivate($this->service, 'getAllAffectedPrincipals', [6666]);
|
||||||
|
$this->assertEquals([
|
||||||
|
'principals/users/user01',
|
||||||
|
'principals/users/user02',
|
||||||
|
'principals/users/user03'
|
||||||
|
], $users);
|
||||||
|
}
|
||||||
|
|
||||||
public function providesBirthday() {
|
public function providesBirthday() {
|
||||||
return [
|
return [
|
||||||
[true,
|
[true,
|
||||||
|
|
Loading…
Reference in New Issue