Skip to content

Commit 8ce5adc

Browse files
Merge pull request #6903 from nextcloud/feature/679/remove_valarms_from_read_only_shared_calendars
remove reminders from read-only shared calendars
2 parents 299ef9a + 1855204 commit 8ce5adc

2 files changed

Lines changed: 221 additions & 11 deletions

File tree

apps/dav/lib/CalDAV/CalendarObject.php

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,24 @@ class CalendarObject extends \Sabre\CalDAV\CalendarObject {
3737
*/
3838
function get() {
3939
$data = parent::get();
40-
if ($this->isShared() && $this->objectData['classification'] === CalDavBackend::CLASSIFICATION_CONFIDENTIAL) {
41-
return $this->createConfidentialObject($data);
40+
41+
if (!$this->isShared()) {
42+
return $data;
43+
}
44+
45+
$vObject = Reader::read($data);
46+
47+
// remove VAlarms if calendar is shared read-only
48+
if (!$this->canWrite()) {
49+
$this->removeVAlarms($vObject);
50+
}
51+
52+
// shows as busy if event is declared confidential
53+
if ($this->objectData['classification'] === CalDavBackend::CLASSIFICATION_CONFIDENTIAL) {
54+
$this->createConfidentialObject($vObject);
4255
}
43-
return $data;
56+
57+
return $vObject->serialize();
4458
}
4559

4660
protected function isShared() {
@@ -52,13 +66,10 @@ protected function isShared() {
5266
}
5367

5468
/**
55-
* @param string $calData
56-
* @return string
69+
* @param Component\VCalendar $vObject
70+
* @return void
5771
*/
58-
private static function createConfidentialObject($calData) {
59-
60-
$vObject = Reader::read($calData);
61-
72+
private static function createConfidentialObject(Component\VCalendar $vObject) {
6273
/** @var Component $vElement */
6374
$vElement = null;
6475
if(isset($vObject->VEVENT)) {
@@ -92,8 +103,27 @@ private static function createConfidentialObject($calData) {
92103
}
93104
}
94105
}
95-
96-
return $vObject->serialize();
97106
}
98107

108+
/**
109+
* @param Component\VCalendar $vObject
110+
* @return void
111+
*/
112+
private function removeVAlarms(Component\VCalendar $vObject) {
113+
$subcomponents = $vObject->getComponents();
114+
115+
foreach($subcomponents as $subcomponent) {
116+
unset($subcomponent->VALARM);
117+
}
118+
}
119+
120+
/**
121+
* @return bool
122+
*/
123+
private function canWrite() {
124+
if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
125+
return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
126+
}
127+
return true;
128+
}
99129
}

apps/dav/tests/unit/CalDAV/CalendarTest.php

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,184 @@ public function providesConfidentialClassificationData() {
381381
[2, true]
382382
];
383383
}
384+
385+
public function testRemoveVAlarms() {
386+
$publicObjectData = <<<EOD
387+
BEGIN:VCALENDAR
388+
VERSION:2.0
389+
PRODID:-//Nextcloud calendar v1.5.6
390+
CALSCALE:GREGORIAN
391+
BEGIN:VEVENT
392+
CREATED:20171022T125130
393+
DTSTAMP:20171022T125130
394+
LAST-MODIFIED:20171022T125130
395+
UID:PPL24TH8UGOWE94XET87ER
396+
SUMMARY:Foo bar blub
397+
CLASS:PUBLIC
398+
STATUS:CONFIRMED
399+
DTSTART;VALUE=DATE:20171024
400+
DTEND;VALUE=DATE:20171025
401+
BEGIN:VALARM
402+
ACTION:AUDIO
403+
TRIGGER:-PT15M
404+
END:VALARM
405+
END:VEVENT
406+
END:VCALENDAR
407+
408+
EOD;
409+
410+
$confidentialObjectData = <<<EOD
411+
BEGIN:VCALENDAR
412+
VERSION:2.0
413+
PRODID:-//Nextcloud calendar v1.5.6
414+
CALSCALE:GREGORIAN
415+
BEGIN:VEVENT
416+
CREATED:20171022T125130
417+
DTSTAMP:20171022T125130
418+
LAST-MODIFIED:20171022T125130
419+
UID:PPL24TH8UGOWE94XET87ER
420+
SUMMARY:Foo bar blub
421+
CLASS:CONFIDENTIAL
422+
STATUS:CONFIRMED
423+
DTSTART;VALUE=DATE:20171024
424+
DTEND;VALUE=DATE:20171025
425+
BEGIN:VALARM
426+
ACTION:AUDIO
427+
TRIGGER:-PT15M
428+
END:VALARM
429+
END:VEVENT
430+
END:VCALENDAR
431+
432+
EOD;
433+
434+
$publicObjectDataWithoutVAlarm = <<<EOD
435+
BEGIN:VCALENDAR
436+
VERSION:2.0
437+
PRODID:-//Nextcloud calendar v1.5.6
438+
CALSCALE:GREGORIAN
439+
BEGIN:VEVENT
440+
CREATED:20171022T125130
441+
DTSTAMP:20171022T125130
442+
LAST-MODIFIED:20171022T125130
443+
UID:PPL24TH8UGOWE94XET87ER
444+
SUMMARY:Foo bar blub
445+
CLASS:PUBLIC
446+
STATUS:CONFIRMED
447+
DTSTART;VALUE=DATE:20171024
448+
DTEND;VALUE=DATE:20171025
449+
END:VEVENT
450+
END:VCALENDAR
451+
452+
EOD;
453+
454+
$confidentialObjectCleaned = <<<EOD
455+
BEGIN:VCALENDAR
456+
VERSION:2.0
457+
PRODID:-//Nextcloud calendar v1.5.6
458+
CALSCALE:GREGORIAN
459+
BEGIN:VEVENT
460+
CREATED:20171022T125130
461+
UID:PPL24TH8UGOWE94XET87ER
462+
SUMMARY:Busy
463+
CLASS:CONFIDENTIAL
464+
DTSTART;VALUE=DATE:20171024
465+
DTEND;VALUE=DATE:20171025
466+
END:VEVENT
467+
END:VCALENDAR
468+
469+
EOD;
470+
471+
472+
473+
$publicObject = ['uri' => 'event-0',
474+
'classification' => CalDavBackend::CLASSIFICATION_PUBLIC,
475+
'calendardata' => $publicObjectData];
476+
477+
$confidentialObject = ['uri' => 'event-1',
478+
'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL,
479+
'calendardata' => $confidentialObjectData];
480+
481+
/** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */
482+
$backend = $this->createMock(CalDavBackend::class);
483+
$backend->expects($this->any())
484+
->method('getCalendarObjects')
485+
->willReturn([$publicObject, $confidentialObject]);
486+
487+
$backend->expects($this->any())
488+
->method('getMultipleCalendarObjects')
489+
->with(666, ['event-0', 'event-1'])
490+
->willReturn([$publicObject, $confidentialObject]);
491+
492+
$backend->expects($this->any())
493+
->method('getCalendarObject')
494+
->will($this->returnCallback(function($cId, $uri) use($publicObject, $confidentialObject) {
495+
switch($uri) {
496+
case 'event-0':
497+
return $publicObject;
498+
499+
case 'event-1':
500+
return $confidentialObject;
501+
502+
default:
503+
throw new \Exception('unexpected uri');
504+
}
505+
}));
506+
507+
$backend->expects($this->any())
508+
->method('applyShareAcl')
509+
->willReturnArgument(1);
510+
511+
$calendarInfoOwner = [
512+
'{http://owncloud.org/ns}owner-principal' => 'user1',
513+
'principaluri' => 'user1',
514+
'id' => 666,
515+
'uri' => 'cal',
516+
];
517+
$calendarInfoSharedRW = [
518+
'{http://owncloud.org/ns}owner-principal' => 'user1',
519+
'principaluri' => 'user2',
520+
'id' => 666,
521+
'uri' => 'cal',
522+
];
523+
$calendarInfoSharedRO = [
524+
'{http://owncloud.org/ns}owner-principal' => 'user1',
525+
'{http://owncloud.org/ns}read-only' => true,
526+
'principaluri' => 'user2',
527+
'id' => 666,
528+
'uri' => 'cal',
529+
];
530+
531+
$ownerCalendar = new Calendar($backend, $calendarInfoOwner, $this->l10n);
532+
$rwCalendar = new Calendar($backend, $calendarInfoSharedRW, $this->l10n);
533+
$roCalendar = new Calendar($backend, $calendarInfoSharedRO, $this->l10n);
534+
535+
$this->assertEquals(count($ownerCalendar->getChildren()), 2);
536+
$this->assertEquals(count($rwCalendar->getChildren()), 2);
537+
$this->assertEquals(count($roCalendar->getChildren()), 2);
538+
539+
// calendar data shall not be altered for the owner
540+
$this->assertEquals($ownerCalendar->getChild('event-0')->get(), $publicObjectData);
541+
$this->assertEquals($ownerCalendar->getChild('event-1')->get(), $confidentialObjectData);
542+
543+
// valarms shall not be removed for read-write shares
544+
$this->assertEquals(
545+
$this->fixLinebreak($rwCalendar->getChild('event-0')->get()),
546+
$this->fixLinebreak($publicObjectData));
547+
$this->assertEquals(
548+
$this->fixLinebreak($rwCalendar->getChild('event-1')->get()),
549+
$this->fixLinebreak($confidentialObjectCleaned));
550+
551+
// valarms shall be removed for read-only shares
552+
$this->assertEquals(
553+
$this->fixLinebreak($roCalendar->getChild('event-0')->get()),
554+
$this->fixLinebreak($publicObjectDataWithoutVAlarm));
555+
$this->assertEquals(
556+
$this->fixLinebreak($roCalendar->getChild('event-1')->get()),
557+
$this->fixLinebreak($confidentialObjectCleaned));
558+
559+
}
560+
561+
private function fixLinebreak($str) {
562+
return preg_replace('~(*BSR_ANYCRLF)\R~', "\r\n", $str);
563+
}
384564
}

0 commit comments

Comments
 (0)