From 8b22bfea4f1609605c3cebd40a50ed7a77929d3f Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Fri, 20 Oct 2017 13:29:59 +0200
Subject: [PATCH 1/9] Add admin checkbox to disable birthday calendars
Signed-off-by: Georg Ehrke
---
apps/dav/appinfo/routes.php | 29 +++++++
apps/dav/js/settings-admin-caldav.js | 10 +++
.../Controller/BirthdayCalendarController.php | 81 +++++++++++++++++++
apps/dav/lib/Settings/CalDAVSettings.php | 1 +
apps/dav/templates/settings-admin-caldav.php | 8 ++
.../BirthdayCalendarControllerTest.php | 75 +++++++++++++++++
6 files changed, 204 insertions(+)
create mode 100644 apps/dav/appinfo/routes.php
create mode 100644 apps/dav/lib/Controller/BirthdayCalendarController.php
create mode 100644 apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
diff --git a/apps/dav/appinfo/routes.php b/apps/dav/appinfo/routes.php
new file mode 100644
index 0000000000..e6785bfd4e
--- /dev/null
+++ b/apps/dav/appinfo/routes.php
@@ -0,0 +1,29 @@
+
+ *
+ * @author Georg Ehrke
+ *
+ * @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 .
+ *
+ */
+
+return [
+ 'routes' => [
+ ['name' => 'birthday_calendar#enable', 'url' => '/enableBirthdayCalendar', 'verb' => 'POST'],
+ ['name' => 'birthday_calendar#disable', 'url' => '/disableBirthdayCalendar', 'verb' => 'POST'],
+ ]
+];
diff --git a/apps/dav/js/settings-admin-caldav.js b/apps/dav/js/settings-admin-caldav.js
index 10eb89ab61..cf1a2006f6 100644
--- a/apps/dav/js/settings-admin-caldav.js
+++ b/apps/dav/js/settings-admin-caldav.js
@@ -26,3 +26,13 @@ $('#caldavSendInvitations').change(function() {
OCP.AppConfig.setValue('dav', 'sendInvitations', val ? 'yes' : 'no');
});
+
+$('#caldavGenerateBirthdayCalendar').change(function() {
+ var val = $(this)[0].checked;
+
+ if (val) {
+ $.post(OC.generateUrl(OC.linkTo("dav", "enableBirthdayCalendar")));
+ } else {
+ $.post(OC.generateUrl(OC.linkTo("dav", "disableBirthdayCalendar")));
+ }
+});
diff --git a/apps/dav/lib/Controller/BirthdayCalendarController.php b/apps/dav/lib/Controller/BirthdayCalendarController.php
new file mode 100644
index 0000000000..c7172c2905
--- /dev/null
+++ b/apps/dav/lib/Controller/BirthdayCalendarController.php
@@ -0,0 +1,81 @@
+
+ *
+ * @author Georg Ehrke
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\DAV\Controller;
+
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\Response;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IRequest;
+
+class BirthdayCalendarController extends Controller {
+
+ /**
+ * @var IDBConnection
+ */
+ protected $db;
+
+ /**
+ * @var IConfig
+ */
+ protected $config;
+
+ /**
+ * BirthdayCalendar constructor.
+ *
+ * @param string $appName
+ * @param IRequest $request
+ * @param IDBConnection $db
+ * @param IConfig $config
+ */
+ public function __construct($appName, IRequest $request,
+ IDBConnection $db, IConfig $config){
+ parent::__construct($appName, $request);
+ $this->db = $db;
+ $this->config = $config;
+ }
+
+ /**
+ * @return Response
+ */
+ public function enable() {
+ $this->config->setAppValue($this->appName, 'generateBirthdayCalendar', 'yes');
+
+ // TODO schedule background job to regenerate
+
+ return new JSONResponse([]);
+ }
+
+ /**
+ * @return Response
+ */
+ public function disable() {
+ $this->config->setAppValue($this->appName, 'generateBirthdayCalendar', 'no');
+
+ // TODO delete all birthday calendars
+
+ return new JSONResponse([]);
+ }
+}
diff --git a/apps/dav/lib/Settings/CalDAVSettings.php b/apps/dav/lib/Settings/CalDAVSettings.php
index 1c85d19432..a419afa1c5 100644
--- a/apps/dav/lib/Settings/CalDAVSettings.php
+++ b/apps/dav/lib/Settings/CalDAVSettings.php
@@ -47,6 +47,7 @@ class CalDAVSettings implements ISettings {
public function getForm() {
$parameters = [
'send_invitations' => $this->config->getAppValue('dav', 'sendInvitations', 'yes'),
+ 'generate_birthday_calendar' => $this->config->getAppValue('dav', 'generateBirthdayCalendar', 'yes'),
];
return new TemplateResponse('dav', 'settings-admin-caldav', $parameters);
diff --git a/apps/dav/templates/settings-admin-caldav.php b/apps/dav/templates/settings-admin-caldav.php
index 8dbe5b3841..a3e3188fb4 100644
--- a/apps/dav/templates/settings-admin-caldav.php
+++ b/apps/dav/templates/settings-admin-caldav.php
@@ -37,4 +37,12 @@ script('dav', [
t('Please make sure to properly set up the email settings above.')); ?>
+
+ />
+
+
+ t('Birthday calendars will be generated by a background job.')); ?>
+ t('Hence they will not be available immediately after enabling but will show up after some time.')); ?>
+
diff --git a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
new file mode 100644
index 0000000000..8963546ffe
--- /dev/null
+++ b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
@@ -0,0 +1,75 @@
+
+ *
+ * @author Georg Ehrke
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\DAV\Tests\Unit\DAV\Controller;
+
+use OCA\DAV\Controller\BirthdayCalendarController;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IRequest;
+use Test\TestCase;
+
+class BirthdayCalendarControllerTest extends TestCase {
+
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
+ private $request;
+
+ /** @var IDBConnection|\PHPUnit_Framework_MockObject_MockObject */
+ private $db;
+
+ /** @var BirthdayCalendarController|\PHPUnit_Framework_MockObject_MockObject */
+ private $controller;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->db = $this->createMock(IDBConnection::class);
+
+ $this->controller = new BirthdayCalendarController('dav',
+ $this->request, $this->db, $this->config);
+ }
+
+ public function testEnable() {
+ $this->config->expects($this->once())
+ ->method('setAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes');
+
+ $response = $this->controller->enable();
+ $this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
+ }
+
+ public function testDisable() {
+ $this->config->expects($this->once())
+ ->method('setAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'no');
+
+ $response = $this->controller->disable();
+ $this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
+ }
+
+}
From dc346220083443376642a14c01c5da5af5d56e81 Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Fri, 20 Oct 2017 15:09:52 +0200
Subject: [PATCH 2/9] remember when a user deleted their contact birthdays
calendar
Signed-off-by: Georg Ehrke
---
apps/dav/lib/CalDAV/Calendar.php | 18 ++++++-
apps/dav/lib/CalDAV/CalendarHome.php | 8 +++-
apps/dav/lib/CalDAV/PublicCalendarRoot.php | 21 ++++++--
apps/dav/lib/RootCollection.php | 3 +-
.../tests/unit/CalDAV/CalDavBackendTest.php | 10 ++--
apps/dav/tests/unit/CalDAV/CalendarTest.php | 48 +++++++++++++++----
.../unit/CalDAV/PublicCalendarRootTest.php | 14 ++++--
.../tests/unit/CalDAV/PublicCalendarTest.php | 9 +++-
8 files changed, 104 insertions(+), 27 deletions(-)
diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php
index ac3bcec617..02808ab566 100644
--- a/apps/dav/lib/CalDAV/Calendar.php
+++ b/apps/dav/lib/CalDAV/Calendar.php
@@ -27,6 +27,7 @@
namespace OCA\DAV\CalDAV;
use OCA\DAV\DAV\Sharing\IShareable;
+use OCP\IConfig;
use OCP\IL10N;
use Sabre\CalDAV\Backend\BackendInterface;
use Sabre\DAV\Exception\Forbidden;
@@ -41,7 +42,10 @@ use Sabre\DAV\PropPatch;
*/
class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
- public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n) {
+ /** @var IConfig */
+ private $config;
+
+ public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n, IConfig $config) {
parent::__construct($caldavBackend, $calendarInfo);
if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
@@ -51,6 +55,8 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
$this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Personal');
}
+
+ $this->config = $config;
}
/**
@@ -201,6 +207,16 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
]);
return;
}
+
+ // Remember when a user deleted their birthday calendar
+ // in order to not regenerate it on the next contacts change
+ if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
+ $principalURI = $this->getPrincipalURI();
+ $userId = substr($principalURI, 17);
+
+ $this->config->setUserValue($userId, 'dav', 'generateBirthdayCalendar', 'no');
+ }
+
parent::delete();
}
diff --git a/apps/dav/lib/CalDAV/CalendarHome.php b/apps/dav/lib/CalDAV/CalendarHome.php
index 3429c24705..c1988c7493 100644
--- a/apps/dav/lib/CalDAV/CalendarHome.php
+++ b/apps/dav/lib/CalDAV/CalendarHome.php
@@ -38,9 +38,13 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
/** @var \OCP\IL10N */
private $l10n;
+ /** @var \OCP\IConfig */
+ private $config;
+
public function __construct(BackendInterface $caldavBackend, $principalInfo) {
parent::__construct($caldavBackend, $principalInfo);
$this->l10n = \OC::$server->getL10N('dav');
+ $this->config = \OC::$server->getConfig();
}
/**
@@ -57,7 +61,7 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
$calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
$objects = [];
foreach ($calendars as $calendar) {
- $objects[] = new Calendar($this->caldavBackend, $calendar, $this->l10n);
+ $objects[] = new Calendar($this->caldavBackend, $calendar, $this->l10n, $this->config);
}
if ($this->caldavBackend instanceof SchedulingSupport) {
@@ -98,7 +102,7 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
// Calendars
foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) {
if ($calendar['uri'] === $name) {
- return new Calendar($this->caldavBackend, $calendar, $this->l10n);
+ return new Calendar($this->caldavBackend, $calendar, $this->l10n, $this->config);
}
}
diff --git a/apps/dav/lib/CalDAV/PublicCalendarRoot.php b/apps/dav/lib/CalDAV/PublicCalendarRoot.php
index 55f969e216..9385f487bd 100644
--- a/apps/dav/lib/CalDAV/PublicCalendarRoot.php
+++ b/apps/dav/lib/CalDAV/PublicCalendarRoot.php
@@ -24,6 +24,8 @@
*/
namespace OCA\DAV\CalDAV;
+use OCP\IConfig;
+use OCP\IL10N;
use Sabre\DAV\Collection;
class PublicCalendarRoot extends Collection {
@@ -34,9 +36,22 @@ class PublicCalendarRoot extends Collection {
/** @var \OCP\IL10N */
protected $l10n;
- function __construct(CalDavBackend $caldavBackend) {
+ /** @var \OCP\IConfig */
+ protected $config;
+
+ /**
+ * PublicCalendarRoot constructor.
+ *
+ * @param CalDavBackend $caldavBackend
+ * @param IL10N $l10n
+ * @param IConfig $config
+ */
+ function __construct(CalDavBackend $caldavBackend, IL10N $l10n,
+ IConfig $config) {
$this->caldavBackend = $caldavBackend;
- $this->l10n = \OC::$server->getL10N('dav');
+ $this->l10n = $l10n;
+ $this->config = $config;
+
}
/**
@@ -51,7 +66,7 @@ class PublicCalendarRoot extends Collection {
*/
function getChild($name) {
$calendar = $this->caldavBackend->getPublicCalendar($name);
- return new PublicCalendar($this->caldavBackend, $calendar, $this->l10n);
+ return new PublicCalendar($this->caldavBackend, $calendar, $this->l10n, $this->config);
}
/**
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index e4ba1f2c02..a382f77cfd 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -39,6 +39,7 @@ class RootCollection extends SimpleCollection {
public function __construct() {
$config = \OC::$server->getConfig();
+ $l10n = \OC::$server->getL10N('dav');
$random = \OC::$server->getSecureRandom();
$userManager = \OC::$server->getUserManager();
$groupManager = \OC::$server->getGroupManager();
@@ -64,7 +65,7 @@ class RootCollection extends SimpleCollection {
$caldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $random, $dispatcher);
$calendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users');
$calendarRoot->disableListing = $disableListing;
- $publicCalendarRoot = new PublicCalendarRoot($caldavBackend);
+ $publicCalendarRoot = new PublicCalendarRoot($caldavBackend, $l10n, $config);
$publicCalendarRoot->disableListing = $disableListing;
$systemTagCollection = new SystemTag\SystemTagsByIdCollection(
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index fae2156a6b..74820792c3 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -31,6 +31,7 @@ use DateTime;
use DateTimeZone;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
+use OCP\IConfig;
use OCP\IL10N;
use Sabre\DAV\PropPatch;
use Sabre\DAV\Xml\Property\Href;
@@ -131,6 +132,8 @@ class CalDavBackendTest extends AbstractCalDavBackend {
return vsprintf($text, $parameters);
}));
+ $config = $this->createMock(IConfig::class);
+
$this->userManager->expects($this->any())
->method('userExists')
->willReturn(true);
@@ -142,14 +145,14 @@ class CalDavBackendTest extends AbstractCalDavBackend {
$calendarId = $this->createTestCalendar();
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertCount(1, $calendars);
- $calendar = new Calendar($this->backend, $calendars[0], $l10n);
+ $calendar = new Calendar($this->backend, $calendars[0], $l10n, $config);
$this->dispatcher->expects($this->at(0))
->method('dispatch')
->with('\OCA\DAV\CalDAV\CalDavBackend::updateShares');
$this->backend->updateShares($calendar, $add, []);
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1);
$this->assertCount(1, $calendars);
- $calendar = new Calendar($this->backend, $calendars[0], $l10n);
+ $calendar = new Calendar($this->backend, $calendars[0], $l10n, $config);
$acl = $calendar->getACL();
$this->assertAcl(self::UNIT_TEST_USER, '{DAV:}read', $acl);
$this->assertAcl(self::UNIT_TEST_USER, '{DAV:}write', $acl);
@@ -505,8 +508,9 @@ EOD;
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject $l10n */
$l10n = $this->createMock(IL10N::class);
+ $config = $this->createMock(IConfig::class);
- $calendar = new Calendar($this->backend, $calendarInfo, $l10n);
+ $calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config);
$calendar->setPublishStatus(true);
$this->assertNotEquals(false, $calendar->getPublishStatus());
diff --git a/apps/dav/tests/unit/CalDAV/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php
index 99ad640c44..dbdbf0dbaf 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php
@@ -29,6 +29,7 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
+use OCP\IConfig;
use OCP\IL10N;
use Sabre\DAV\PropPatch;
use Sabre\VObject\Reader;
@@ -39,10 +40,14 @@ class CalendarTest extends TestCase {
/** @var IL10N */
protected $l10n;
+ /** @var IConfig */
+ protected $config;
+
public function setUp() {
parent::setUp();
$this->l10n = $this->getMockBuilder(IL10N::class)
->disableOriginalConstructor()->getMock();
+ $this->config = $this->createMock(IConfig::class);
$this->l10n
->expects($this->any())
->method('t')
@@ -64,7 +69,7 @@ class CalendarTest extends TestCase {
'id' => 666,
'uri' => 'cal',
];
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$c->delete();
}
@@ -84,7 +89,7 @@ class CalendarTest extends TestCase {
'id' => 666,
'uri' => 'cal',
];
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$c->delete();
}
@@ -94,6 +99,8 @@ class CalendarTest extends TestCase {
$backend->expects($this->never())->method('updateShares');
$backend->expects($this->never())->method('getShares');
+ $this->config->expects($this->never())->method('setUserValue');
+
$backend->expects($this->once())->method('deleteCalendar')
->with(666);
@@ -103,7 +110,28 @@ class CalendarTest extends TestCase {
'id' => 666,
'uri' => 'cal',
];
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
+ $c->delete();
+ }
+
+ public function testDeleteBirthdayCalendar() {
+ /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
+ $backend = $this->createMock(CalDavBackend::class);
+ $backend->expects($this->once())->method('deleteCalendar')
+ ->with(666);
+
+ $this->config->expects($this->once())
+ ->method('setUserValue')
+ ->with('user1', 'dav', 'generateBirthdayCalendar', 'no');
+
+ $calendarInfo = [
+ '{http://owncloud.org/ns}owner-principal' => 'principals/users/user1',
+ 'principaluri' => 'principals/users/user1',
+ 'id' => 666,
+ 'uri' => 'contact_birthdays',
+ ];
+
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$c->delete();
}
@@ -146,7 +174,7 @@ class CalendarTest extends TestCase {
'id' => 666,
'uri' => 'default'
];
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$propPatch = new PropPatch($mutations);
if (!$shared) {
@@ -176,7 +204,7 @@ class CalendarTest extends TestCase {
if ($hasOwnerSet) {
$calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1';
}
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$acl = $c->getACL();
$childAcl = $c->getChildACL();
@@ -271,7 +299,7 @@ class CalendarTest extends TestCase {
$calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1';
}
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$children = $c->getChildren();
$this->assertEquals($expectedChildren, count($children));
$children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2']);
@@ -355,7 +383,7 @@ EOD;
'id' => 666,
'uri' => 'cal',
];
- $c = new Calendar($backend, $calendarInfo, $this->l10n);
+ $c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config);
$this->assertEquals(count($c->getChildren()), $expectedChildren);
@@ -531,9 +559,9 @@ EOD;
'uri' => 'cal',
];
- $ownerCalendar = new Calendar($backend, $calendarInfoOwner, $this->l10n);
- $rwCalendar = new Calendar($backend, $calendarInfoSharedRW, $this->l10n);
- $roCalendar = new Calendar($backend, $calendarInfoSharedRO, $this->l10n);
+ $ownerCalendar = new Calendar($backend, $calendarInfoOwner, $this->l10n, $this->config);
+ $rwCalendar = new Calendar($backend, $calendarInfoSharedRW, $this->l10n, $this->config);
+ $roCalendar = new Calendar($backend, $calendarInfoSharedRO, $this->l10n, $this->config);
$this->assertEquals(count($ownerCalendar->getChildren()), 2);
$this->assertEquals(count($rwCalendar->getChildren()), 2);
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
index 82f4161c20..fef8507418 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
@@ -30,6 +30,7 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\PublicCalendar;
use OCA\DAV\Connector\Sabre\Principal;
+use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IL10N;
use OCA\DAV\CalDAV\CalDavBackend;
@@ -61,6 +62,8 @@ class PublicCalendarRootTest extends TestCase {
protected $userManager;
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
protected $groupManager;
+ /** @var IConfig */
+ protected $config;
/** @var ISecureRandom */
private $random;
@@ -87,11 +90,12 @@ class PublicCalendarRootTest extends TestCase {
$this->random,
$dispatcher
);
-
- $this->publicCalendarRoot = new PublicCalendarRoot($this->backend);
-
$this->l10n = $this->getMockBuilder(IL10N::class)
->disableOriginalConstructor()->getMock();
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->publicCalendarRoot = new PublicCalendarRoot($this->backend,
+ $this->l10n, $this->config);
}
public function tearDown() {
@@ -141,11 +145,11 @@ class PublicCalendarRootTest extends TestCase {
$this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
$calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
- $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n);
+ $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config);
$publicUri = $calendar->setPublishStatus(true);
$calendarInfo = $this->backend->getPublicCalendar($publicUri);
- $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n);
+ $calendar = new PublicCalendar($this->backend, $calendarInfo, $this->l10n, $this->config);
return $calendar;
}
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
index 9783d1a626..98dd330f42 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
@@ -26,6 +26,7 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\PublicCalendar;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCP\IConfig;
use Sabre\VObject\Reader;
class PublicCalendarTest extends CalendarTest {
@@ -61,8 +62,10 @@ class PublicCalendarTest extends CalendarTest {
'id' => 666,
'uri' => 'cal',
];
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IConfig $config */
+ $config = $this->createMock(IConfig::class);
- $c = new PublicCalendar($backend, $calendarInfo, $this->l10n);
+ $c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config);
$children = $c->getChildren();
$this->assertEquals(2, count($children));
$children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2']);
@@ -146,7 +149,9 @@ EOD;
'id' => 666,
'uri' => 'cal',
];
- $c = new PublicCalendar($backend, $calendarInfo, $this->l10n);
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IConfig $config */
+ $config = $this->createMock(IConfig::class);
+ $c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config);
$this->assertEquals(count($c->getChildren()), 2);
From 5068d56fb09f709c9e711399ac67e892bcd5f577 Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Fri, 20 Oct 2017 16:53:02 +0200
Subject: [PATCH 3/9] add CalDAV interface that allows users to re-enable their
birthday calendar
Signed-off-by: Georg Ehrke
---
.../CalDAV/BirthdayCalendar/EnablePlugin.php | 130 +++++++++++++
apps/dav/lib/Server.php | 3 +
.../BirthdayCalendar/EnablePluginTest.php | 171 ++++++++++++++++++
3 files changed, 304 insertions(+)
create mode 100644 apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
create mode 100644 apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
diff --git a/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php b/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
new file mode 100644
index 0000000000..9f9b24e205
--- /dev/null
+++ b/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
@@ -0,0 +1,130 @@
+
+ *
+ * @author Georg Ehrke
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\DAV\CalDAV\BirthdayCalendar;
+
+use OCA\DAV\CalDAV\CalendarHome;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use OCP\IConfig;
+
+/**
+ * Class EnablePlugin
+ * allows users to re-enable the birthday calendar via CalDAV
+ *
+ * @package OCA\DAV\CalDAV\BirthdayCalendar
+ */
+class EnablePlugin extends ServerPlugin {
+ const NS_Nextcloud = 'http://nextcloud.com/ns';
+
+ /**
+ * @var IConfig
+ */
+ protected $config;
+
+ /**
+ * @var Server
+ */
+ protected $server;
+
+ /**
+ * PublishPlugin constructor.
+ *
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * This method should return a list of server-features.
+ *
+ * This is for example 'versioning' and is added to the DAV: header
+ * in an OPTIONS response.
+ *
+ * @return string[]
+ */
+ public function getFeatures() {
+ return ['nc-enable-birthday-calendar'];
+ }
+
+ /**
+ * Returns a plugin name.
+ *
+ * Using this name other plugins will be able to access other plugins
+ * using Sabre\DAV\Server::getPlugin
+ *
+ * @return string
+ */
+ public function getPluginName() {
+ return 'nc-enable-birthday-calendar';
+ }
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre\DAV\Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the required event subscriptions.
+ *
+ * @param Server $server
+ */
+ public function initialize(Server $server) {
+ $this->server = $server;
+
+ $this->server->on('method:POST', [$this, 'httpPost']);
+ }
+
+ /**
+ * We intercept this to handle POST requests on calendar homes.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ *
+ * @return bool|void
+ */
+ public function httpPost(RequestInterface $request, ResponseInterface $response) {
+ $node = $this->server->tree->getNodeForPath($this->server->getRequestUri());
+ if (!($node instanceof CalendarHome)) {
+ return;
+ }
+
+ $requestBody = $request->getBodyAsString();
+ $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
+ if ($documentType !== '{'.self::NS_Nextcloud.'}enable-birthday-calendar') {
+ return;
+ }
+
+ $principalUri = $node->getOwner();
+ $userId = substr($principalUri, 17);
+
+ $this->config->setUserValue($userId, 'dav', 'generateBirthdayCalendar', 'yes');
+
+ $this->server->httpResponse->setStatus(204);
+
+ return false;
+ }
+}
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 14f6f4e49e..ab20d14cab 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -259,6 +259,9 @@ class Server {
$view
)));
}
+ $this->server->addPlugin(new \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin(
+ \OC::$server->getConfig()
+ ));
}
// register plugins from apps
diff --git a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
new file mode 100644
index 0000000000..6e7965ea61
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
@@ -0,0 +1,171 @@
+
+ *
+ * @copyright Copyright (c) 2017 Georg Ehrke
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV\BirthdayCalendar;
+
+use OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin;
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\CalDAV\CalendarHome;
+use OCP\IConfig;
+use Test\TestCase;
+
+class EnablePluginTest extends TestCase {
+
+ /** @var \Sabre\DAV\Server|\PHPUnit_Framework_MockObject_MockObject */
+ protected $server;
+
+ /** @var \OCP\IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
+ /** @var \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin $plugin */
+ protected $plugin;
+
+ protected $request;
+
+ protected $response;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->server = $this->createMock(\Sabre\DAV\Server::class);
+ $this->server->tree = $this->createMock(\Sabre\DAV\Tree::class);
+ $this->server->httpResponse = $this->createMock(\Sabre\HTTP\Response::class);
+ $this->server->xml = $this->createMock(\Sabre\DAV\Xml\Service::class);
+
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->plugin = new EnablePlugin($this->config);
+ $this->plugin->initialize($this->server);
+
+ $this->request = $this->createMock(\Sabre\HTTP\RequestInterface::class);
+ $this->response = $this->createMock(\Sabre\HTTP\ResponseInterface::class);
+ }
+
+ public function testGetFeatures() {
+ $this->assertEquals(['nc-enable-birthday-calendar'], $this->plugin->getFeatures());
+ }
+
+ public function testGetName() {
+ $this->assertEquals('nc-enable-birthday-calendar', $this->plugin->getPluginName());
+ }
+
+ public function testInitialize() {
+ $server = $this->createMock(\Sabre\DAV\Server::class);
+
+ $plugin = new EnablePlugin($this->config);
+
+ $server->expects($this->at(0))
+ ->method('on')
+ ->with('method:POST', [$plugin, 'httpPost']);
+
+ $plugin->initialize($server);
+ }
+
+ public function testHttpPostNoCalendarHome() {
+ $calendar = $this->createMock(Calendar::class);
+
+ $this->server->expects($this->once())
+ ->method('getRequestUri')
+ ->will($this->returnValue('/bar/foo'));
+ $this->server->tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with('/bar/foo')
+ ->will($this->returnValue($calendar));
+
+ $this->config->expects($this->never())
+ ->method('setUserValue');
+
+ $this->plugin->httpPost($this->request, $this->response);
+ }
+
+ public function testHttpPostWrongRequest() {
+ $calendarHome = $this->createMock(CalendarHome::class);
+
+ $this->server->expects($this->once())
+ ->method('getRequestUri')
+ ->will($this->returnValue('/bar/foo'));
+ $this->server->tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with('/bar/foo')
+ ->will($this->returnValue($calendarHome));
+
+ $this->request->expects($this->at(0))
+ ->method('getBodyAsString')
+ ->will($this->returnValue(''));
+
+ $this->request->expects($this->at(1))
+ ->method('getUrl')
+ ->will($this->returnValue('url_abc'));
+
+ $this->server->xml->expects($this->once())
+ ->method('parse')
+ ->will($this->returnCallback(function($requestBody, $url, &$documentType) {
+ $documentType = '{http://nextcloud.com/ns}disable-birthday-calendar';
+ }));
+
+ $this->config->expects($this->never())
+ ->method('setUserValue');
+
+ $this->plugin->httpPost($this->request, $this->response);
+ }
+
+ public function testHttpPost() {
+ $calendarHome = $this->createMock(CalendarHome::class);
+
+ $this->server->expects($this->once())
+ ->method('getRequestUri')
+ ->will($this->returnValue('/bar/foo'));
+ $this->server->tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with('/bar/foo')
+ ->will($this->returnValue($calendarHome));
+
+ $calendarHome->expects($this->once())
+ ->method('getOwner')
+ ->will($this->returnValue('principals/users/BlaBlub'));
+
+ $this->request->expects($this->at(0))
+ ->method('getBodyAsString')
+ ->will($this->returnValue(''));
+
+ $this->request->expects($this->at(1))
+ ->method('getUrl')
+ ->will($this->returnValue('url_abc'));
+
+ $this->server->xml->expects($this->once())
+ ->method('parse')
+ ->will($this->returnCallback(function($requestBody, $url, &$documentType) {
+ $documentType = '{http://nextcloud.com/ns}enable-birthday-calendar';
+ }));
+
+ $this->config->expects($this->once())
+ ->method('setUserValue')
+ ->with('BlaBlub', 'dav', 'generateBirthdayCalendar', 'yes');
+
+ $this->server->httpResponse->expects($this->once())
+ ->method('setStatus')
+ ->with(204);
+
+ $result = $this->plugin->httpPost($this->request, $this->response);
+
+ $this->assertEquals(false, $result);
+ }
+}
From 1c106a66b1b287eec177204b71c40ed00a450268 Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Sat, 21 Oct 2017 11:04:09 +0200
Subject: [PATCH 4/9] adapt occ 'dav:sync-birthday-calendar command
Signed-off-by: Georg Ehrke
---
apps/dav/lib/Command/SyncBirthdayCalendar.php | 34 ++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/apps/dav/lib/Command/SyncBirthdayCalendar.php b/apps/dav/lib/Command/SyncBirthdayCalendar.php
index a99e2ea4b8..88f85a9881 100644
--- a/apps/dav/lib/Command/SyncBirthdayCalendar.php
+++ b/apps/dav/lib/Command/SyncBirthdayCalendar.php
@@ -23,6 +23,7 @@
namespace OCA\DAV\Command;
use OCA\DAV\CalDAV\BirthdayService;
+use OCP\IConfig;
use OCP\IUser;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
@@ -36,16 +37,22 @@ class SyncBirthdayCalendar extends Command {
/** @var BirthdayService */
private $birthdayService;
+ /** @var IConfig */
+ private $config;
+
/** @var IUserManager */
private $userManager;
/**
* @param IUserManager $userManager
+ * @param IConfig $config
* @param BirthdayService $birthdayService
*/
- function __construct(IUserManager $userManager, BirthdayService $birthdayService) {
+ function __construct(IUserManager $userManager, IConfig $config,
+ BirthdayService $birthdayService) {
parent::__construct();
$this->birthdayService = $birthdayService;
+ $this->config = $config;
$this->userManager = $userManager;
}
@@ -63,11 +70,21 @@ class SyncBirthdayCalendar extends Command {
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output) {
+ $this->verifyEnabled();
+
$user = $input->getArgument('user');
if (!is_null($user)) {
if (!$this->userManager->userExists($user)) {
throw new \InvalidArgumentException("User <$user> in unknown.");
}
+
+ // re-enable the birthday calendar in case it's called directly with a user name
+ $isEnabled = $this->config->getUserValue($user, 'dav', 'generateBirthdayCalendar', 'yes');
+ if ($isEnabled !== 'yes') {
+ $this->config->setUserValue($user, 'dav', 'generateBirthdayCalendar', 'yes');
+ $output->writeln("Re-enabling birthday calendar for $user");
+ }
+
$output->writeln("Start birthday calendar sync for $user");
$this->birthdayService->syncUser($user);
return;
@@ -77,6 +94,13 @@ class SyncBirthdayCalendar extends Command {
$p->start();
$this->userManager->callForAllUsers(function($user) use ($p) {
$p->advance();
+
+ $userId = $user->getUID();
+ $isEnabled = $this->config->getUserValue($userId, 'dav', 'generateBirthdayCalendar', 'yes');
+ if ($isEnabled !== 'yes') {
+ return;
+ }
+
/** @var IUser $user */
$this->birthdayService->syncUser($user->getUID());
});
@@ -84,4 +108,12 @@ class SyncBirthdayCalendar extends Command {
$p->finish();
$output->writeln('');
}
+
+ protected function verifyEnabled () {
+ $isEnabled = $this->config->getAppValue('dav', 'generateBirthdayCalendar', 'yes');
+
+ if ($isEnabled !== 'yes') {
+ throw new \InvalidArgumentException('Birthday calendars are disabled');
+ }
+ }
}
From d59b3392abf021d0289b5b2ea1a67bc99e8d89da Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Sat, 21 Oct 2017 11:19:01 +0200
Subject: [PATCH 5/9] disallow users to create calendars with reserved names
Signed-off-by: Georg Ehrke
---
apps/dav/lib/CalDAV/CalendarHome.php | 15 ++++
.../tests/unit/CalDAV/CalendarHomeTest.php | 81 +++++++++++++++++++
2 files changed, 96 insertions(+)
create mode 100644 apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
diff --git a/apps/dav/lib/CalDAV/CalendarHome.php b/apps/dav/lib/CalDAV/CalendarHome.php
index c1988c7493..3e645db459 100644
--- a/apps/dav/lib/CalDAV/CalendarHome.php
+++ b/apps/dav/lib/CalDAV/CalendarHome.php
@@ -32,6 +32,8 @@ use Sabre\CalDAV\Schedule\Inbox;
use Sabre\CalDAV\Schedule\Outbox;
use Sabre\CalDAV\Subscriptions\Subscription;
use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\Exception\MethodNotAllowed;
+use Sabre\DAV\MkCol;
class CalendarHome extends \Sabre\CalDAV\CalendarHome {
@@ -54,6 +56,19 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
return $this->caldavBackend;
}
+ /**
+ * @inheritdoc
+ */
+ function createExtendedCollection($name, MkCol $mkCol) {
+ $reservedNames = [BirthdayService::BIRTHDAY_CALENDAR_URI];
+
+ if (in_array($name, $reservedNames)) {
+ throw new MethodNotAllowed('The resource you tried to create has a reserved name');
+ }
+
+ parent::createExtendedCollection($name, $mkCol);
+ }
+
/**
* @inheritdoc
*/
diff --git a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
new file mode 100644
index 0000000000..a7981cfa15
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
@@ -0,0 +1,81 @@
+
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\CalendarHome;
+use Sabre\DAV\MkCol;
+use Test\TestCase;
+
+class CalendarHomeTest extends TestCase {
+
+ /** @var CalDavBackend | \PHPUnit_Framework_MockObject_MockObject */
+ private $backend;
+
+ /** @var array */
+ private $principalInfo = [];
+
+ /** @var CalendarHome */
+ private $calendarHome;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->backend = $this->createMock(CalDavBackend::class);
+ $this->principalInfo = [
+ 'uri' => 'user-principal-123',
+ ];
+
+ $this->calendarHome = new CalendarHome($this->backend,
+ $this->principalInfo);
+ }
+
+ public function testCreateCalendarValidName() {
+ /** @var MkCol | \PHPUnit_Framework_MockObject_MockObject $mkCol */
+ $mkCol = $this->createMock(MkCol::class);
+
+ $mkCol->method('getResourceType')
+ ->will($this->returnValue(['{DAV:}collection',
+ '{urn:ietf:params:xml:ns:caldav}calendar']));
+ $mkCol->method('getRemainingValues')
+ ->will($this->returnValue(['... properties ...']));
+
+ $this->backend->expects($this->once())
+ ->method('createCalendar')
+ ->with('user-principal-123', 'name123', ['... properties ...']);
+
+ $this->calendarHome->createExtendedCollection('name123', $mkCol);
+ }
+
+ /**
+ * @expectedException \Sabre\DAV\Exception\MethodNotAllowed
+ * @expectedExceptionMessage The resource you tried to create has a reserved name
+ */
+ public function testCreateCalendarReservedName() {
+ /** @var MkCol | \PHPUnit_Framework_MockObject_MockObject $mkCol */
+ $mkCol = $this->createMock(MkCol::class);
+
+ $this->calendarHome->createExtendedCollection('contact_birthdays', $mkCol);
+ }
+}
From ef6f41a16ce2043cab812887f6ccfe790045ad90 Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Sat, 11 Nov 2017 01:27:48 +0100
Subject: [PATCH 6/9] respect admin / user choice about birthday calendars in
corresponding hooks
Signed-off-by: Georg Ehrke
---
apps/dav/lib/CalDAV/BirthdayService.php | 52 +++++++-
.../unit/CardDAV/BirthdayServiceTest.php | 115 +++++++++++++++++-
2 files changed, 160 insertions(+), 7 deletions(-)
diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php
index aa902bacc5..62d218f0a2 100644
--- a/apps/dav/lib/CalDAV/BirthdayService.php
+++ b/apps/dav/lib/CalDAV/BirthdayService.php
@@ -31,6 +31,7 @@ namespace OCA\DAV\CalDAV;
use Exception;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\DAV\GroupPrincipalBackend;
+use OCP\IConfig;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\DateTimeParser;
@@ -52,17 +53,22 @@ class BirthdayService {
/** @var CardDavBackend */
private $cardDavBackEnd;
+ /** @var IConfig */
+ private $config;
+
/**
* BirthdayService constructor.
*
* @param CalDavBackend $calDavBackEnd
* @param CardDavBackend $cardDavBackEnd
* @param GroupPrincipalBackend $principalBackend
+ * @param IConfig $config;
*/
- public function __construct(CalDavBackend $calDavBackEnd, CardDavBackend $cardDavBackEnd, GroupPrincipalBackend $principalBackend) {
+ public function __construct(CalDavBackend $calDavBackEnd, CardDavBackend $cardDavBackEnd, GroupPrincipalBackend $principalBackend, IConfig $config) {
$this->calDavBackEnd = $calDavBackEnd;
$this->cardDavBackEnd = $cardDavBackEnd;
$this->principalBackend = $principalBackend;
+ $this->config = $config;
}
/**
@@ -71,8 +77,11 @@ class BirthdayService {
* @param string $cardData
*/
public function onCardChanged($addressBookId, $cardUri, $cardData) {
+ if (!$this->isGloballyEnabled()) {
+ return;
+ }
+
$targetPrincipals = $this->getAllAffectedPrincipals($addressBookId);
-
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
$targetPrincipals[] = $book['principaluri'];
$datesToSync = [
@@ -81,6 +90,10 @@ class BirthdayService {
['postfix' => '-anniversary', 'field' => 'ANNIVERSARY', 'symbol' => "⚭"],
];
foreach ($targetPrincipals as $principalUri) {
+ if (!$this->isUserEnabled($principalUri)) {
+ continue;
+ }
+
$calendar = $this->ensureCalendarExists($principalUri);
foreach ($datesToSync as $type) {
$this->updateCalendar($cardUri, $cardData, $book, $calendar['id'], $type);
@@ -93,10 +106,18 @@ class BirthdayService {
* @param string $cardUri
*/
public function onCardDeleted($addressBookId, $cardUri) {
+ if (!$this->isGloballyEnabled()) {
+ return;
+ }
+
$targetPrincipals = $this->getAllAffectedPrincipals($addressBookId);
$book = $this->cardDavBackEnd->getAddressBookById($addressBookId);
$targetPrincipals[] = $book['principaluri'];
foreach ($targetPrincipals as $principalUri) {
+ if (!$this->isUserEnabled($principalUri)) {
+ continue;
+ }
+
$calendar = $this->ensureCalendarExists($principalUri);
foreach (['', '-death', '-anniversary'] as $tag) {
$objectUri = $book['uri'] . '-' . $cardUri . $tag .'.ics';
@@ -293,4 +314,31 @@ class BirthdayService {
}
}
+ /**
+ * checks if the admin opted-out of birthday calendars
+ *
+ * @return bool
+ */
+ private function isGloballyEnabled() {
+ $isGloballyEnabled = $this->config->getAppValue('dav', 'generateBirthdayCalendar', 'yes');
+ return $isGloballyEnabled === 'yes';
+ }
+
+ /**
+ * checks if the user opted-out of birthday calendars
+ *
+ * @param $userPrincipal
+ * @return bool
+ */
+ private function isUserEnabled($userPrincipal) {
+ if (strpos($userPrincipal, 'principals/users/') === 0) {
+ $userId = substr($userPrincipal, 17);
+ $isEnabled = $this->config->getUserValue($userId, 'dav', 'generateBirthdayCalendar', 'yes');
+ return $isEnabled === 'yes';
+ }
+
+ // not sure how we got here, just be on the safe side and return true
+ return true;
+ }
+
}
diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
index 72b3c57bea..867168033a 100644
--- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
@@ -28,6 +28,7 @@ use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\DAV\GroupPrincipalBackend;
+use OCP\IConfig;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Reader;
use Test\TestCase;
@@ -42,15 +43,19 @@ class BirthdayServiceTest extends TestCase {
private $cardDav;
/** @var GroupPrincipalBackend | \PHPUnit_Framework_MockObject_MockObject */
private $groupPrincipalBackend;
+ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
+ private $config;
public function setUp() {
parent::setUp();
- $this->calDav = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
- $this->cardDav = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
- $this->groupPrincipalBackend = $this->getMockBuilder(GroupPrincipalBackend::class)->disableOriginalConstructor()->getMock();
+ $this->calDav = $this->createMock(CalDavBackend::class);
+ $this->cardDav = $this->createMock(CardDavBackend::class);
+ $this->groupPrincipalBackend = $this->createMock(GroupPrincipalBackend::class);
+ $this->config = $this->createMock(IConfig::class);
- $this->service = new BirthdayService($this->calDav, $this->cardDav, $this->groupPrincipalBackend);
+ $this->service = new BirthdayService($this->calDav, $this->cardDav,
+ $this->groupPrincipalBackend, $this->config);
}
/**
@@ -71,7 +76,52 @@ class BirthdayServiceTest extends TestCase {
}
}
+ public function testOnCardDeleteGloballyDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->cardDav->expects($this->never())->method('getAddressBookById');
+
+ $this->service->onCardDeleted(666, 'gump.vcf');
+ }
+
+ public function testOnCardDeleteUserDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with('user01', 'dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->cardDav->expects($this->once())->method('getAddressBookById')
+ ->with(666)
+ ->willReturn([
+ 'principaluri' => 'principals/users/user01',
+ 'uri' => 'default'
+ ]);
+ $this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
+ $this->calDav->expects($this->never())->method('getCalendarByUri');
+ $this->calDav->expects($this->never())->method('deleteCalendarObject');
+
+ $this->service->onCardDeleted(666, 'gump.vcf');
+ }
+
public function testOnCardDeleted() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with('user01', 'dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
$this->cardDav->expects($this->once())->method('getAddressBookById')
->with(666)
->willReturn([
@@ -91,10 +141,65 @@ class BirthdayServiceTest extends TestCase {
$this->service->onCardDeleted(666, 'gump.vcf');
}
+ public function testOnCardChangedGloballyDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->cardDav->expects($this->never())->method('getAddressBookById');
+
+ $service = $this->getMockBuilder(BirthdayService::class)
+ ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config])
+ ->getMock();
+
+ $service->onCardChanged(666, 'gump.vcf', '');
+ }
+
+ public function testOnCardChangedUserDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with('user01', 'dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->cardDav->expects($this->once())->method('getAddressBookById')
+ ->with(666)
+ ->willReturn([
+ 'principaluri' => 'principals/users/user01',
+ 'uri' => 'default'
+ ]);
+ $this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
+ $this->calDav->expects($this->never())->method('getCalendarByUri');
+
+ /** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject $service */
+ $service = $this->getMockBuilder(BirthdayService::class)
+ ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config])
+ ->getMock();
+
+ $service->onCardChanged(666, 'gump.vcf', '');
+ }
+
/**
* @dataProvider providesCardChanges
*/
public function testOnCardChanged($expectedOp) {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with('user01', 'dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
$this->cardDav->expects($this->once())->method('getAddressBookById')
->with(666)
->willReturn([
@@ -111,7 +216,7 @@ class BirthdayServiceTest extends TestCase {
/** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject $service */
$service = $this->getMockBuilder(BirthdayService::class)
->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
- ->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend])
+ ->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config])
->getMock();
if ($expectedOp === 'delete') {
From 4d5ed1372a8a22f17b5da6673fcf151aab8ce801 Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Sat, 11 Nov 2017 01:28:52 +0100
Subject: [PATCH 7/9] update autoloaders
Signed-off-by: Georg Ehrke
---
apps/dav/composer/composer/autoload_classmap.php | 2 ++
apps/dav/composer/composer/autoload_static.php | 2 ++
2 files changed, 4 insertions(+)
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index f29e3a7b29..9a9daf3faf 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -21,6 +21,7 @@ return array(
'OCA\\DAV\\CalDAV\\Activity\\Setting\\Calendar' => $baseDir . '/../lib/CalDAV/Activity/Setting/Calendar.php',
'OCA\\DAV\\CalDAV\\Activity\\Setting\\Event' => $baseDir . '/../lib/CalDAV/Activity/Setting/Event.php',
'OCA\\DAV\\CalDAV\\Activity\\Setting\\Todo' => $baseDir . '/../lib/CalDAV/Activity/Setting/Todo.php',
+ 'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => $baseDir . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
'OCA\\DAV\\CalDAV\\BirthdayService' => $baseDir . '/../lib/CalDAV/BirthdayService.php',
'OCA\\DAV\\CalDAV\\CalDavBackend' => $baseDir . '/../lib/CalDAV/CalDavBackend.php',
'OCA\\DAV\\CalDAV\\Calendar' => $baseDir . '/../lib/CalDAV/Calendar.php',
@@ -103,6 +104,7 @@ return array(
'OCA\\DAV\\Connector\\Sabre\\SharesPlugin' => $baseDir . '/../lib/Connector/Sabre/SharesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\TagList' => $baseDir . '/../lib/Connector/Sabre/TagList.php',
'OCA\\DAV\\Connector\\Sabre\\TagsPlugin' => $baseDir . '/../lib/Connector/Sabre/TagsPlugin.php',
+ 'OCA\\DAV\\Controller\\BirthdayCalendarController' => $baseDir . '/../lib/Controller/BirthdayCalendarController.php',
'OCA\\DAV\\DAV\\CustomPropertiesBackend' => $baseDir . '/../lib/DAV/CustomPropertiesBackend.php',
'OCA\\DAV\\DAV\\GroupPrincipalBackend' => $baseDir . '/../lib/DAV/GroupPrincipalBackend.php',
'OCA\\DAV\\DAV\\PublicAuth' => $baseDir . '/../lib/DAV/PublicAuth.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 412666a8aa..a940da7971 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -36,6 +36,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CalDAV\\Activity\\Setting\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Setting/Calendar.php',
'OCA\\DAV\\CalDAV\\Activity\\Setting\\Event' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Setting/Event.php',
'OCA\\DAV\\CalDAV\\Activity\\Setting\\Todo' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Setting/Todo.php',
+ 'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
'OCA\\DAV\\CalDAV\\BirthdayService' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayService.php',
'OCA\\DAV\\CalDAV\\CalDavBackend' => __DIR__ . '/..' . '/../lib/CalDAV/CalDavBackend.php',
'OCA\\DAV\\CalDAV\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Calendar.php',
@@ -118,6 +119,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Connector\\Sabre\\SharesPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/SharesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\TagList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagList.php',
'OCA\\DAV\\Connector\\Sabre\\TagsPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagsPlugin.php',
+ 'OCA\\DAV\\Controller\\BirthdayCalendarController' => __DIR__ . '/..' . '/../lib/Controller/BirthdayCalendarController.php',
'OCA\\DAV\\DAV\\CustomPropertiesBackend' => __DIR__ . '/..' . '/../lib/DAV/CustomPropertiesBackend.php',
'OCA\\DAV\\DAV\\GroupPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/GroupPrincipalBackend.php',
'OCA\\DAV\\DAV\\PublicAuth' => __DIR__ . '/..' . '/../lib/DAV/PublicAuth.php',
From a87d9860418948a72fbe3d29a2cc5d589be147ec Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Sat, 11 Nov 2017 02:02:17 +0100
Subject: [PATCH 8/9] create a user's birthday calendar right after they
requested it
Signed-off-by: Georg Ehrke
---
.../CalDAV/BirthdayCalendar/EnablePlugin.php | 11 ++++++++++-
apps/dav/lib/Server.php | 4 +++-
.../BirthdayCalendar/EnablePluginTest.php | 19 +++++++++++++++++--
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php b/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
index 9f9b24e205..497d7112b3 100644
--- a/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
+++ b/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
@@ -23,6 +23,7 @@
namespace OCA\DAV\CalDAV\BirthdayCalendar;
+use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalendarHome;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
@@ -44,6 +45,11 @@ class EnablePlugin extends ServerPlugin {
*/
protected $config;
+ /**
+ * @var BirthdayService
+ */
+ protected $birthdayService;
+
/**
* @var Server
*/
@@ -53,9 +59,11 @@ class EnablePlugin extends ServerPlugin {
* PublishPlugin constructor.
*
* @param IConfig $config
+ * @param BirthdayService $birthdayService
*/
- public function __construct(IConfig $config) {
+ public function __construct(IConfig $config, BirthdayService $birthdayService) {
$this->config = $config;
+ $this->birthdayService = $birthdayService;
}
/**
@@ -122,6 +130,7 @@ class EnablePlugin extends ServerPlugin {
$userId = substr($principalUri, 17);
$this->config->setUserValue($userId, 'dav', 'generateBirthdayCalendar', 'yes');
+ $this->birthdayService->syncUser($userId);
$this->server->httpResponse->setStatus(204);
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index ab20d14cab..afa52530b0 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -33,6 +33,7 @@
namespace OCA\DAV;
use OC\AppFramework\Utility\TimeFactory;
+use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\Schedule\IMipPlugin;
use OCA\DAV\CardDAV\ImageExportPlugin;
use OCA\DAV\CardDAV\PhotoCache;
@@ -260,7 +261,8 @@ class Server {
)));
}
$this->server->addPlugin(new \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin(
- \OC::$server->getConfig()
+ \OC::$server->getConfig(),
+ \OC::$server->query(BirthdayService::class)
));
}
diff --git a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
index 6e7965ea61..44bf9237b2 100644
--- a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
@@ -22,6 +22,7 @@
namespace OCA\DAV\Tests\unit\CalDAV\BirthdayCalendar;
use OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin;
+use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCP\IConfig;
@@ -35,6 +36,9 @@ class EnablePluginTest extends TestCase {
/** @var \OCP\IConfig|\PHPUnit_Framework_MockObject_MockObject */
protected $config;
+ /** @var BirthdayService |\PHPUnit_Framework_MockObject_MockObject */
+ protected $birthdayService;
+
/** @var \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin $plugin */
protected $plugin;
@@ -51,8 +55,9 @@ class EnablePluginTest extends TestCase {
$this->server->xml = $this->createMock(\Sabre\DAV\Xml\Service::class);
$this->config = $this->createMock(IConfig::class);
+ $this->birthdayService = $this->createMock(BirthdayService::class);
- $this->plugin = new EnablePlugin($this->config);
+ $this->plugin = new EnablePlugin($this->config, $this->birthdayService);
$this->plugin->initialize($this->server);
$this->request = $this->createMock(\Sabre\HTTP\RequestInterface::class);
@@ -70,7 +75,7 @@ class EnablePluginTest extends TestCase {
public function testInitialize() {
$server = $this->createMock(\Sabre\DAV\Server::class);
- $plugin = new EnablePlugin($this->config);
+ $plugin = new EnablePlugin($this->config, $this->birthdayService);
$server->expects($this->at(0))
->method('on')
@@ -93,6 +98,9 @@ class EnablePluginTest extends TestCase {
$this->config->expects($this->never())
->method('setUserValue');
+ $this->birthdayService->expects($this->never())
+ ->method('syncUser');
+
$this->plugin->httpPost($this->request, $this->response);
}
@@ -124,6 +132,9 @@ class EnablePluginTest extends TestCase {
$this->config->expects($this->never())
->method('setUserValue');
+ $this->birthdayService->expects($this->never())
+ ->method('syncUser');
+
$this->plugin->httpPost($this->request, $this->response);
}
@@ -160,6 +171,10 @@ class EnablePluginTest extends TestCase {
->method('setUserValue')
->with('BlaBlub', 'dav', 'generateBirthdayCalendar', 'yes');
+ $this->birthdayService->expects($this->once())
+ ->method('syncUser')
+ ->with('BlaBlub');
+
$this->server->httpResponse->expects($this->once())
->method('setStatus')
->with(204);
From 2b51d84b98a5a44c2a42a8498164a35b6822e760 Mon Sep 17 00:00:00 2001
From: Georg Ehrke
Date: Sat, 11 Nov 2017 11:25:40 +0100
Subject: [PATCH 9/9] generate birthday calendars in a background job after
admin enabled them
Signed-off-by: Georg Ehrke
---
.../composer/composer/autoload_classmap.php | 1 +
.../dav/composer/composer/autoload_static.php | 1 +
.../GenerateBirthdayCalendarBackgroundJob.php | 69 ++++++++++++
apps/dav/lib/CalDAV/CalDavBackend.php | 16 +++
.../Controller/BirthdayCalendarController.php | 41 ++++++-
...erateBirthdayCalendarBackgroundJobTest.php | 103 ++++++++++++++++++
.../BirthdayCalendarControllerTest.php | 50 ++++++++-
7 files changed, 277 insertions(+), 4 deletions(-)
create mode 100644 apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php
create mode 100644 apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 9a9daf3faf..7ef9989594 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -11,6 +11,7 @@ return array(
'OCA\\DAV\\Avatars\\AvatarHome' => $baseDir . '/../lib/Avatars/AvatarHome.php',
'OCA\\DAV\\Avatars\\AvatarNode' => $baseDir . '/../lib/Avatars/AvatarNode.php',
'OCA\\DAV\\Avatars\\RootCollection' => $baseDir . '/../lib/Avatars/RootCollection.php',
+ 'OCA\\DAV\\BackgroundJob\\GenerateBirthdayCalendarBackgroundJob' => $baseDir . '/../lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php',
'OCA\\DAV\\CalDAV\\Activity\\Backend' => $baseDir . '/../lib/CalDAV/Activity/Backend.php',
'OCA\\DAV\\CalDAV\\Activity\\Filter\\Calendar' => $baseDir . '/../lib/CalDAV/Activity/Filter/Calendar.php',
'OCA\\DAV\\CalDAV\\Activity\\Filter\\Todo' => $baseDir . '/../lib/CalDAV/Activity/Filter/Todo.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index a940da7971..388e1f0130 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -26,6 +26,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Avatars\\AvatarHome' => __DIR__ . '/..' . '/../lib/Avatars/AvatarHome.php',
'OCA\\DAV\\Avatars\\AvatarNode' => __DIR__ . '/..' . '/../lib/Avatars/AvatarNode.php',
'OCA\\DAV\\Avatars\\RootCollection' => __DIR__ . '/..' . '/../lib/Avatars/RootCollection.php',
+ 'OCA\\DAV\\BackgroundJob\\GenerateBirthdayCalendarBackgroundJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php',
'OCA\\DAV\\CalDAV\\Activity\\Backend' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Backend.php',
'OCA\\DAV\\CalDAV\\Activity\\Filter\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Filter/Calendar.php',
'OCA\\DAV\\CalDAV\\Activity\\Filter\\Todo' => __DIR__ . '/..' . '/../lib/CalDAV/Activity/Filter/Todo.php',
diff --git a/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php b/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php
new file mode 100644
index 0000000000..c4279c5108
--- /dev/null
+++ b/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php
@@ -0,0 +1,69 @@
+
+ *
+ * @author Georg Ehrke
+ *
+ * @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 .
+ *
+ */
+namespace OCA\DAV\BackgroundJob;
+
+use OC\BackgroundJob\QueuedJob;
+use OCA\DAV\CalDAV\BirthdayService;
+use OCP\IConfig;
+
+class GenerateBirthdayCalendarBackgroundJob extends QueuedJob {
+
+ /** @var BirthdayService */
+ private $birthdayService;
+
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * GenerateAllBirthdayCalendarsBackgroundJob constructor.
+ *
+ * @param BirthdayService $birthdayService
+ * @param IConfig $config
+ */
+ public function __construct(BirthdayService $birthdayService,
+ IConfig $config) {
+ $this->birthdayService = $birthdayService;
+ $this->config = $config;
+ }
+
+ /**
+ * @param array $arguments
+ */
+ public function run($arguments) {
+ $userId = $arguments['userId'];
+
+ // make sure admin didn't change his mind
+ $isGloballyEnabled = $this->config->getAppValue('dav', 'generateBirthdayCalendar', 'yes');
+ if ($isGloballyEnabled !== 'yes') {
+ return;
+ }
+
+ // did the user opt out?
+ $isUserEnabled = $this->config->getUserValue($userId, 'dav', 'generateBirthdayCalendar', 'yes');
+ if ($isUserEnabled !== 'yes') {
+ return;
+ }
+
+ $this->birthdayService->syncUser($userId);
+ }
+}
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 9505a00ea5..73f0a287fa 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -2076,6 +2076,22 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
}
+ /**
+ * deletes all birthday calendars
+ */
+ public function deleteAllBirthdayCalendars() {
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select(['id'])->from('calendars')
+ ->where($query->expr()->eq('uri',
+ $query->createNamedParameter(BirthdayService::BIRTHDAY_CALENDAR_URI)))
+ ->execute();
+
+ $ids = $result->fetchAll();
+ foreach($ids as $id) {
+ $this->deleteCalendar($id['id']);
+ }
+ }
+
/**
* read VCalendar data into a VCalendar object
*
diff --git a/apps/dav/lib/Controller/BirthdayCalendarController.php b/apps/dav/lib/Controller/BirthdayCalendarController.php
index c7172c2905..244111e3ae 100644
--- a/apps/dav/lib/Controller/BirthdayCalendarController.php
+++ b/apps/dav/lib/Controller/BirthdayCalendarController.php
@@ -23,12 +23,17 @@
namespace OCA\DAV\Controller;
+use OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob;
+use OCA\DAV\CalDAV\CalDavBackend;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\Response;
+use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserManager;
class BirthdayCalendarController extends Controller {
@@ -42,6 +47,21 @@ class BirthdayCalendarController extends Controller {
*/
protected $config;
+ /**
+ * @var IUserManager
+ */
+ protected $userManager;
+
+ /**
+ * @var CalDavBackend
+ */
+ protected $caldavBackend;
+
+ /**
+ * @var IJobList
+ */
+ protected $jobList;
+
/**
* BirthdayCalendar constructor.
*
@@ -49,12 +69,21 @@ class BirthdayCalendarController extends Controller {
* @param IRequest $request
* @param IDBConnection $db
* @param IConfig $config
+ * @param IJobList $jobList
+ * @param IUserManager $userManager
+ * @param CalDavBackend $calDavBackend
*/
public function __construct($appName, IRequest $request,
- IDBConnection $db, IConfig $config){
+ IDBConnection $db, IConfig $config,
+ IJobList $jobList,
+ IUserManager $userManager,
+ CalDavBackend $calDavBackend){
parent::__construct($appName, $request);
$this->db = $db;
$this->config = $config;
+ $this->userManager = $userManager;
+ $this->jobList = $jobList;
+ $this->caldavBackend = $calDavBackend;
}
/**
@@ -63,7 +92,12 @@ class BirthdayCalendarController extends Controller {
public function enable() {
$this->config->setAppValue($this->appName, 'generateBirthdayCalendar', 'yes');
- // TODO schedule background job to regenerate
+ // add background job for each user
+ $this->userManager->callForAllUsers(function(IUser $user) {
+ $this->jobList->add(GenerateBirthdayCalendarBackgroundJob::class, [
+ 'userId' => $user->getUID(),
+ ]);
+ });
return new JSONResponse([]);
}
@@ -74,7 +108,8 @@ class BirthdayCalendarController extends Controller {
public function disable() {
$this->config->setAppValue($this->appName, 'generateBirthdayCalendar', 'no');
- // TODO delete all birthday calendars
+ $this->jobList->remove(GenerateBirthdayCalendarBackgroundJob::class);
+ $this->caldavBackend->deleteAllBirthdayCalendars();
return new JSONResponse([]);
}
diff --git a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
new file mode 100644
index 0000000000..010289a745
--- /dev/null
+++ b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
@@ -0,0 +1,103 @@
+
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\BackgroundJob;
+
+use OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob;
+use OCA\DAV\CalDAV\BirthdayService;
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\CalendarHome;
+use OCP\IConfig;
+use Sabre\DAV\MkCol;
+use Test\TestCase;
+
+class GenerateBirthdayCalendarBackgroundJobTest extends TestCase {
+
+ /** @var BirthdayService | \PHPUnit_Framework_MockObject_MockObject */
+ private $birthdayService;
+
+ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+
+ /** @var \OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob */
+ private $backgroundJob;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->birthdayService = $this->createMock(BirthdayService::class);
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->backgroundJob = new GenerateBirthdayCalendarBackgroundJob(
+ $this->birthdayService, $this->config);
+ }
+
+ public function testRun() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with('user123', 'dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->birthdayService->expects($this->once())
+ ->method('syncUser')
+ ->with('user123');
+
+ $this->backgroundJob->run(['userId' => 'user123']);
+ }
+
+ public function testRunGloballyDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->config->expects($this->never())
+ ->method('getUserValue');
+
+ $this->birthdayService->expects($this->never())
+ ->method('syncUser');
+
+ $this->backgroundJob->run(['userId' => 'user123']);
+ }
+
+ public function testRunUserDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('yes'));
+
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with('user123', 'dav', 'generateBirthdayCalendar', 'yes')
+ ->will($this->returnValue('no'));
+
+ $this->birthdayService->expects($this->never())
+ ->method('syncUser');
+
+ $this->backgroundJob->run(['userId' => 'user123']);
+ }
+}
diff --git a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
index 8963546ffe..46ed58df4f 100644
--- a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
+++ b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
@@ -23,10 +23,15 @@
namespace OCA\DAV\Tests\Unit\DAV\Controller;
+use OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob;
+use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Controller\BirthdayCalendarController;
+use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserManager;
use Test\TestCase;
class BirthdayCalendarControllerTest extends TestCase {
@@ -40,6 +45,15 @@ class BirthdayCalendarControllerTest extends TestCase {
/** @var IDBConnection|\PHPUnit_Framework_MockObject_MockObject */
private $db;
+ /** @var IJobList|\PHPUnit_Framework_MockObject_MockObject */
+ private $jobList;
+
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $userManager;
+
+ /** @var CalDavBackend|\PHPUnit_Framework_MockObject_MockObject */
+ private $caldav;
+
/** @var BirthdayCalendarController|\PHPUnit_Framework_MockObject_MockObject */
private $controller;
@@ -49,9 +63,13 @@ class BirthdayCalendarControllerTest extends TestCase {
$this->config = $this->createMock(IConfig::class);
$this->request = $this->createMock(IRequest::class);
$this->db = $this->createMock(IDBConnection::class);
+ $this->jobList = $this->createMock(IJobList::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->caldav = $this->createMock(CalDavBackend::class);
$this->controller = new BirthdayCalendarController('dav',
- $this->request, $this->db, $this->config);
+ $this->request, $this->db, $this->config, $this->jobList,
+ $this->userManager, $this->caldav);
}
public function testEnable() {
@@ -59,6 +77,31 @@ class BirthdayCalendarControllerTest extends TestCase {
->method('setAppValue')
->with('dav', 'generateBirthdayCalendar', 'yes');
+ $this->userManager->expects($this->once())
+ ->method('callForAllUsers')
+ ->will($this->returnCallback(function($closure) {
+ $user1 = $this->createMock(IUser::class);
+ $user1->method('getUID')->will($this->returnValue('uid1'));
+ $user2 = $this->createMock(IUser::class);
+ $user2->method('getUID')->will($this->returnValue('uid2'));
+ $user3 = $this->createMock(IUser::class);
+ $user3->method('getUID')->will($this->returnValue('uid3'));
+
+ $closure($user1);
+ $closure($user2);
+ $closure($user3);
+ }));
+
+ $this->jobList->expects($this->at(0))
+ ->method('add')
+ ->with(GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid1']);
+ $this->jobList->expects($this->at(1))
+ ->method('add')
+ ->with(GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid2']);
+ $this->jobList->expects($this->at(2))
+ ->method('add')
+ ->with(GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid3']);
+
$response = $this->controller->enable();
$this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
}
@@ -67,6 +110,11 @@ class BirthdayCalendarControllerTest extends TestCase {
$this->config->expects($this->once())
->method('setAppValue')
->with('dav', 'generateBirthdayCalendar', 'no');
+ $this->jobList->expects($this->once())
+ ->method('remove')
+ ->with(GenerateBirthdayCalendarBackgroundJob::class);
+ $this->caldav->expects($this->once())
+ ->method('deleteAllBirthdayCalendars');
$response = $this->controller->disable();
$this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);