aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorRichard Steinmetz <richard@steinmetz.cloud>2024-06-11 09:42:03 +0200
committerRichard Steinmetz <richard@steinmetz.cloud>2024-06-11 20:08:57 +0200
commit3a975d0a89e4576f60d6b9628c3de902e683fdc0 (patch)
tree15f692f8b9e0c574c815f32ed0639e92cb1ab977 /apps
parent9fbf20885882b914bb689076443ba92c2f6da985 (diff)
downloadnextcloud-server-3a975d0a89e4576f60d6b9628c3de902e683fdc0.tar.gz
nextcloud-server-3a975d0a89e4576f60d6b9628c3de902e683fdc0.zip
fix(caldav): event links in shared calendar notifications
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Event.php28
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Todo.php12
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php39
3 files changed, 61 insertions, 18 deletions
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Event.php b/apps/dav/lib/CalDAV/Activity/Provider/Event.php
index 45354faae69..45d4f731e20 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Event.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Event.php
@@ -60,7 +60,7 @@ class Event extends Base {
* @param array $eventData
* @return array
*/
- protected function generateObjectParameter(array $eventData) {
+ protected function generateObjectParameter(array $eventData, string $affectedUser): array {
if (!isset($eventData['id']) || !isset($eventData['name'])) {
throw new \InvalidArgumentException();
}
@@ -76,7 +76,15 @@ class Event extends Base {
// The calendar app needs to be manually loaded for the routes to be loaded
OC_App::loadApp('calendar');
$linkData = $eventData['link'];
- $objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $linkData['owner'] . '/' . $linkData['calendar_uri'] . '/' . $linkData['object_uri']);
+ if ($affectedUser === $linkData['owner']) {
+ $objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $linkData['owner'] . '/' . $linkData['calendar_uri'] . '/' . $linkData['object_uri']);
+ } else {
+ // Can't use the "real" owner and calendar names here because we create a custom
+ // calendar for incoming shares with the name "<calendar>_shared_by_<sharer>".
+ // Hack: Fix the link by generating it for the incoming shared calendar instead,
+ // as seen from the affected user.
+ $objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $affectedUser . '/' . $linkData['calendar_uri'] . '_shared_by_' . $linkData['owner'] . '/' . $linkData['object_uri']);
+ }
$link = [
'view' => 'dayGridMonth',
'timeRange' => 'now',
@@ -168,7 +176,7 @@ class Event extends Base {
return [
'actor' => $this->generateUserParameter($parameters['actor']),
'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
- 'event' => $this->generateClassifiedObjectParameter($parameters['object']),
+ 'event' => $this->generateClassifiedObjectParameter($parameters['object'], $event->getAffectedUser()),
];
case self::SUBJECT_OBJECT_ADD . '_event_self':
case self::SUBJECT_OBJECT_DELETE . '_event_self':
@@ -177,7 +185,7 @@ class Event extends Base {
case self::SUBJECT_OBJECT_RESTORE . '_event_self':
return [
'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
- 'event' => $this->generateClassifiedObjectParameter($parameters['object']),
+ 'event' => $this->generateClassifiedObjectParameter($parameters['object'], $event->getAffectedUser()),
];
}
}
@@ -189,13 +197,13 @@ class Event extends Base {
'actor' => $this->generateUserParameter($parameters['actor']),
'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l),
'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l),
- 'event' => $this->generateClassifiedObjectParameter($parameters['object']),
+ 'event' => $this->generateClassifiedObjectParameter($parameters['object'], $event->getAffectedUser()),
];
case self::SUBJECT_OBJECT_MOVE . '_event_self':
return [
'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l),
'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l),
- 'event' => $this->generateClassifiedObjectParameter($parameters['object']),
+ 'event' => $this->generateClassifiedObjectParameter($parameters['object'], $event->getAffectedUser()),
];
}
}
@@ -212,22 +220,22 @@ class Event extends Base {
return [
'actor' => $this->generateUserParameter($parameters[0]),
'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
- 'event' => $this->generateObjectParameter($parameters[2]),
+ 'event' => $this->generateObjectParameter($parameters[2], $event->getAffectedUser()),
];
case self::SUBJECT_OBJECT_ADD . '_event_self':
case self::SUBJECT_OBJECT_DELETE . '_event_self':
case self::SUBJECT_OBJECT_UPDATE . '_event_self':
return [
'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
- 'event' => $this->generateObjectParameter($parameters[2]),
+ 'event' => $this->generateObjectParameter($parameters[2], $event->getAffectedUser()),
];
}
throw new \InvalidArgumentException();
}
- private function generateClassifiedObjectParameter(array $eventData) {
- $parameter = $this->generateObjectParameter($eventData);
+ private function generateClassifiedObjectParameter(array $eventData, string $affectedUser): array {
+ $parameter = $this->generateObjectParameter($eventData, $affectedUser);
if (!empty($eventData['classified'])) {
$parameter['name'] = $this->l->t('Busy');
}
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php
index 052370c7d3a..68a95341ff2 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php
@@ -85,7 +85,7 @@ class Todo extends Event {
return [
'actor' => $this->generateUserParameter($parameters['actor']),
'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
- 'todo' => $this->generateObjectParameter($parameters['object']),
+ 'todo' => $this->generateObjectParameter($parameters['object'], $event->getAffectedUser()),
];
case self::SUBJECT_OBJECT_ADD . '_todo_self':
case self::SUBJECT_OBJECT_DELETE . '_todo_self':
@@ -94,7 +94,7 @@ class Todo extends Event {
case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self':
return [
'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
- 'todo' => $this->generateObjectParameter($parameters['object']),
+ 'todo' => $this->generateObjectParameter($parameters['object'], $event->getAffectedUser()),
];
}
}
@@ -106,13 +106,13 @@ class Todo extends Event {
'actor' => $this->generateUserParameter($parameters['actor']),
'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l),
'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l),
- 'todo' => $this->generateObjectParameter($parameters['object']),
+ 'todo' => $this->generateObjectParameter($parameters['object'], $event->getAffectedUser()),
];
case self::SUBJECT_OBJECT_MOVE . '_todo_self':
return [
'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l),
'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l),
- 'todo' => $this->generateObjectParameter($parameters['object']),
+ 'todo' => $this->generateObjectParameter($parameters['object'], $event->getAffectedUser()),
];
}
}
@@ -131,7 +131,7 @@ class Todo extends Event {
return [
'actor' => $this->generateUserParameter($parameters[0]),
'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
- 'todo' => $this->generateObjectParameter($parameters[2]),
+ 'todo' => $this->generateObjectParameter($parameters[2], $event->getAffectedUser()),
];
case self::SUBJECT_OBJECT_ADD . '_todo_self':
case self::SUBJECT_OBJECT_DELETE . '_todo_self':
@@ -140,7 +140,7 @@ class Todo extends Event {
case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self':
return [
'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
- 'todo' => $this->generateObjectParameter($parameters[2]),
+ 'todo' => $this->generateObjectParameter($parameters[2], $event->getAffectedUser()),
];
}
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php b/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
index 27604952124..b0b2cc936a5 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
@@ -91,7 +91,9 @@ class EventTest extends TestCase {
* @param bool $calendarAppEnabled
*/
public function testGenerateObjectParameter(int $id, string $name, ?array $link, bool $calendarAppEnabled = true): void {
+ $affectedUser = 'otheruser';
if ($link) {
+ $affectedUser = $link['owner'];
$generatedLink = [
'view' => 'dayGridMonth',
'timeRange' => 'now',
@@ -124,7 +126,40 @@ class EventTest extends TestCase {
if ($link && $calendarAppEnabled) {
$result['link'] = 'fullLink';
}
- $this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter]));
+ $this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter, $affectedUser]));
+ }
+
+ public function testGenerateObjectParameterWithSharedCalendar(): void {
+ $link = [
+ 'object_uri' => 'someuuid.ics',
+ 'calendar_uri' => 'personal',
+ 'owner' => 'sharer'
+ ];
+ $generatedLink = [
+ 'view' => 'dayGridMonth',
+ 'timeRange' => 'now',
+ 'mode' => 'sidebar',
+ 'objectId' => base64_encode('/remote.php/dav/calendars/sharee/' . $link['calendar_uri'] . '_shared_by_sharer/' . $link['object_uri']),
+ 'recurrenceId' => 'next'
+ ];
+ $this->appManager->expects($this->once())
+ ->method('isEnabledForUser')
+ ->with('calendar')
+ ->willReturn(true);
+ $this->url->expects($this->once())
+ ->method('getWebroot');
+ $this->url->expects($this->once())
+ ->method('linkToRouteAbsolute')
+ ->with('calendar.view.indexview.timerange.edit', $generatedLink)
+ ->willReturn('fullLink');
+ $objectParameter = ['id' => 42, 'name' => 'calendar', 'link' => $link];
+ $result = [
+ 'type' => 'calendar-event',
+ 'id' => 42,
+ 'name' => 'calendar',
+ 'link' => 'fullLink',
+ ];
+ $this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter, 'sharee']));
}
public function dataGenerateObjectParameterThrows() {
@@ -143,6 +178,6 @@ class EventTest extends TestCase {
public function testGenerateObjectParameterThrows($eventData, string $exception = InvalidArgumentException::class): void {
$this->expectException($exception);
- $this->invokePrivate($this->provider, 'generateObjectParameter', [$eventData]);
+ $this->invokePrivate($this->provider, 'generateObjectParameter', [$eventData, 'no_user']);
}
}