CalendarTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. * @author Thomas Müller <thomas.mueller@tmit.eu>
  7. *
  8. * @license AGPL-3.0
  9. *
  10. * This code is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License, version 3,
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License, version 3,
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>
  21. *
  22. */
  23. namespace OCA\DAV\Tests\unit\CalDAV;
  24. use OCA\DAV\CalDAV\BirthdayService;
  25. use OCA\DAV\CalDAV\CalDavBackend;
  26. use OCA\DAV\CalDAV\Calendar;
  27. use OCP\IL10N;
  28. use Sabre\DAV\PropPatch;
  29. use Sabre\VObject\Reader;
  30. use Test\TestCase;
  31. class CalendarTest extends TestCase {
  32. /** @var IL10N */
  33. private $l10n;
  34. public function setUp() {
  35. parent::setUp();
  36. $this->l10n = $this->getMockBuilder('\OCP\IL10N')
  37. ->disableOriginalConstructor()->getMock();
  38. $this->l10n
  39. ->expects($this->any())
  40. ->method('t')
  41. ->will($this->returnCallback(function ($text, $parameters = array()) {
  42. return vsprintf($text, $parameters);
  43. }));
  44. }
  45. public function testDelete() {
  46. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  47. $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
  48. $backend->expects($this->once())->method('updateShares');
  49. $backend->expects($this->any())->method('getShares')->willReturn([
  50. ['href' => 'principal:user2']
  51. ]);
  52. $calendarInfo = [
  53. '{http://owncloud.org/ns}owner-principal' => 'user1',
  54. 'principaluri' => 'user2',
  55. 'id' => 666,
  56. 'uri' => 'cal',
  57. ];
  58. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  59. $c->delete();
  60. }
  61. /**
  62. * @expectedException \Sabre\DAV\Exception\Forbidden
  63. */
  64. public function testDeleteFromGroup() {
  65. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  66. $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
  67. $backend->expects($this->never())->method('updateShares');
  68. $backend->expects($this->any())->method('getShares')->willReturn([
  69. ['href' => 'principal:group2']
  70. ]);
  71. $calendarInfo = [
  72. '{http://owncloud.org/ns}owner-principal' => 'user1',
  73. 'principaluri' => 'user2',
  74. 'id' => 666,
  75. 'uri' => 'cal',
  76. ];
  77. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  78. $c->delete();
  79. }
  80. public function testDeleteOwn() {
  81. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  82. $backend = $this->createMock(CalDavBackend::class);
  83. $backend->expects($this->never())->method('updateShares');
  84. $backend->expects($this->never())->method('getShares');
  85. $backend->expects($this->once())->method('deleteCalendar')
  86. ->with(666);
  87. $calendarInfo = [
  88. '{http://owncloud.org/ns}owner-principal' => 'user1',
  89. 'principaluri' => 'user1',
  90. 'id' => 666,
  91. 'uri' => 'cal',
  92. ];
  93. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  94. $c->delete();
  95. }
  96. public function dataPropPatch() {
  97. return [
  98. ['user1', 'user2', [], true],
  99. ['user1', 'user2', [
  100. '{http://owncloud.org/ns}calendar-enabled' => true,
  101. ], false],
  102. ['user1', 'user2', [
  103. '{DAV:}displayname' => true,
  104. ], true],
  105. ['user1', 'user2', [
  106. '{DAV:}displayname' => true,
  107. '{http://owncloud.org/ns}calendar-enabled' => true,
  108. ], true],
  109. ['user1', 'user1', [], false],
  110. ['user1', 'user1', [
  111. '{http://owncloud.org/ns}calendar-enabled' => true,
  112. ], false],
  113. ['user1', 'user1', [
  114. '{DAV:}displayname' => true,
  115. ], false],
  116. ['user1', 'user1', [
  117. '{DAV:}displayname' => true,
  118. '{http://owncloud.org/ns}calendar-enabled' => true,
  119. ], false],
  120. ];
  121. }
  122. /**
  123. * @dataProvider dataPropPatch
  124. */
  125. public function testPropPatch($ownerPrincipal, $principalUri, $mutations, $throws) {
  126. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  127. $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
  128. $calendarInfo = [
  129. '{http://owncloud.org/ns}owner-principal' => $ownerPrincipal,
  130. 'principaluri' => $principalUri,
  131. 'id' => 666,
  132. 'uri' => 'default'
  133. ];
  134. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  135. if ($throws) {
  136. $this->setExpectedException('\Sabre\DAV\Exception\Forbidden');
  137. }
  138. $c->propPatch(new PropPatch($mutations));
  139. if (!$throws) {
  140. $this->assertTrue(true);
  141. }
  142. }
  143. /**
  144. * @dataProvider providesReadOnlyInfo
  145. */
  146. public function testAcl($expectsWrite, $readOnlyValue, $hasOwnerSet, $uri = 'default') {
  147. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  148. $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
  149. $backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
  150. $calendarInfo = [
  151. 'principaluri' => 'user2',
  152. 'id' => 666,
  153. 'uri' => $uri
  154. ];
  155. if (!is_null($readOnlyValue)) {
  156. $calendarInfo['{http://owncloud.org/ns}read-only'] = $readOnlyValue;
  157. }
  158. if ($hasOwnerSet) {
  159. $calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1';
  160. }
  161. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  162. $acl = $c->getACL();
  163. $childAcl = $c->getChildACL();
  164. $expectedAcl = [[
  165. 'privilege' => '{DAV:}read',
  166. 'principal' => $hasOwnerSet ? 'user1' : 'user2',
  167. 'protected' => true
  168. ], [
  169. 'privilege' => '{DAV:}write',
  170. 'principal' => $hasOwnerSet ? 'user1' : 'user2',
  171. 'protected' => true
  172. ]];
  173. if ($uri === BirthdayService::BIRTHDAY_CALENDAR_URI) {
  174. $expectedAcl = [[
  175. 'privilege' => '{DAV:}read',
  176. 'principal' => $hasOwnerSet ? 'user1' : 'user2',
  177. 'protected' => true
  178. ]];
  179. }
  180. if ($hasOwnerSet) {
  181. $expectedAcl[] = [
  182. 'privilege' => '{DAV:}read',
  183. 'principal' => 'user2',
  184. 'protected' => true
  185. ];
  186. if ($expectsWrite) {
  187. $expectedAcl[] = [
  188. 'privilege' => '{DAV:}write',
  189. 'principal' => 'user2',
  190. 'protected' => true
  191. ];
  192. }
  193. }
  194. $this->assertEquals($expectedAcl, $acl);
  195. $this->assertEquals($expectedAcl, $childAcl);
  196. }
  197. public function providesReadOnlyInfo() {
  198. return [
  199. 'read-only property not set' => [true, null, true],
  200. 'read-only property is false' => [true, false, true],
  201. 'read-only property is true' => [false, true, true],
  202. 'read-only property not set and no owner' => [true, null, false],
  203. 'read-only property is false and no owner' => [true, false, false],
  204. 'read-only property is true and no owner' => [false, true, false],
  205. 'birthday calendar' => [false, false, false, BirthdayService::BIRTHDAY_CALENDAR_URI]
  206. ];
  207. }
  208. /**
  209. * @dataProvider providesConfidentialClassificationData
  210. * @param $expectedChildren
  211. * @param $isShared
  212. */
  213. public function testPrivateClassification($expectedChildren, $isShared) {
  214. $calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
  215. $calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
  216. $calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
  217. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  218. $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
  219. $backend->expects($this->any())->method('getCalendarObjects')->willReturn([
  220. $calObject0, $calObject1, $calObject2
  221. ]);
  222. $backend->expects($this->any())->method('getMultipleCalendarObjects')
  223. ->with(666, ['event-0', 'event-1', 'event-2'])
  224. ->willReturn([
  225. $calObject0, $calObject1, $calObject2
  226. ]);
  227. $backend->expects($this->any())->method('getCalendarObject')
  228. ->willReturn($calObject2)->with(666, 'event-2');
  229. $calendarInfo = [
  230. 'principaluri' => 'user2',
  231. 'id' => 666,
  232. 'uri' => 'cal',
  233. ];
  234. if ($isShared) {
  235. $calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1';
  236. }
  237. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  238. $children = $c->getChildren();
  239. $this->assertEquals($expectedChildren, count($children));
  240. $children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2']);
  241. $this->assertEquals($expectedChildren, count($children));
  242. $this->assertEquals(!$isShared, $c->childExists('event-2'));
  243. }
  244. /**
  245. * @dataProvider providesConfidentialClassificationData
  246. * @param $expectedChildren
  247. * @param $isShared
  248. */
  249. public function testConfidentialClassification($expectedChildren, $isShared) {
  250. $start = '20160609';
  251. $end = '20160610';
  252. $calData = <<<EOD
  253. BEGIN:VCALENDAR
  254. PRODID:-//ownCloud calendar v1.2.2
  255. BEGIN:VEVENT
  256. CREATED:20160602T133732
  257. DTSTAMP:20160602T133732
  258. LAST-MODIFIED:20160602T133732
  259. UID:wej2z68l9h
  260. SUMMARY:Test Event
  261. LOCATION:Somewhere ...
  262. ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;CN=de
  263. epdiver:MAILTO:thomas.mueller@tmit.eu
  264. ORGANIZER;CN=deepdiver:MAILTO:thomas.mueller@tmit.eu
  265. DESCRIPTION:maybe ....
  266. DTSTART;TZID=Europe/Berlin;VALUE=DATE:$start
  267. DTEND;TZID=Europe/Berlin;VALUE=DATE:$end
  268. RRULE:FREQ=DAILY
  269. BEGIN:VALARM
  270. ACTION:AUDIO
  271. TRIGGER:-PT15M
  272. END:VALARM
  273. END:VEVENT
  274. BEGIN:VTIMEZONE
  275. TZID:Europe/Berlin
  276. BEGIN:DAYLIGHT
  277. DTSTART:19810329T020000
  278. RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
  279. TZNAME:MESZ
  280. TZOFFSETFROM:+0100
  281. TZOFFSETTO:+0200
  282. END:DAYLIGHT
  283. BEGIN:STANDARD
  284. DTSTART:19961027T030000
  285. RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
  286. TZNAME:MEZ
  287. TZOFFSETFROM:+0200
  288. TZOFFSETTO:+0100
  289. END:STANDARD
  290. END:VTIMEZONE
  291. END:VCALENDAR
  292. EOD;
  293. $calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
  294. $calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
  295. $calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
  296. /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
  297. $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
  298. $backend->expects($this->any())->method('getCalendarObjects')->willReturn([
  299. $calObject0, $calObject1, $calObject2
  300. ]);
  301. $backend->expects($this->any())->method('getMultipleCalendarObjects')
  302. ->with(666, ['event-0', 'event-1', 'event-2'])
  303. ->willReturn([
  304. $calObject0, $calObject1, $calObject2
  305. ]);
  306. $backend->expects($this->any())->method('getCalendarObject')
  307. ->willReturn($calObject1)->with(666, 'event-1');
  308. $calendarInfo = [
  309. '{http://owncloud.org/ns}owner-principal' => $isShared ? 'user1' : 'user2',
  310. 'principaluri' => 'user2',
  311. 'id' => 666,
  312. 'uri' => 'cal',
  313. ];
  314. $c = new Calendar($backend, $calendarInfo, $this->l10n);
  315. $this->assertEquals(count($c->getChildren()), $expectedChildren);
  316. // test private event
  317. $privateEvent = $c->getChild('event-1');
  318. $calData = $privateEvent->get();
  319. $event = Reader::read($calData);
  320. $this->assertEquals($start, $event->VEVENT->DTSTART->getValue());
  321. $this->assertEquals($end, $event->VEVENT->DTEND->getValue());
  322. if ($isShared) {
  323. $this->assertEquals('Busy', $event->VEVENT->SUMMARY->getValue());
  324. $this->assertArrayNotHasKey('ATTENDEE', $event->VEVENT);
  325. $this->assertArrayNotHasKey('LOCATION', $event->VEVENT);
  326. $this->assertArrayNotHasKey('DESCRIPTION', $event->VEVENT);
  327. $this->assertArrayNotHasKey('ORGANIZER', $event->VEVENT);
  328. } else {
  329. $this->assertEquals('Test Event', $event->VEVENT->SUMMARY->getValue());
  330. }
  331. }
  332. public function providesConfidentialClassificationData() {
  333. return [
  334. [3, false],
  335. [2, true]
  336. ];
  337. }
  338. }