diff --git a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php index 90e2e478e1ce3..af3d7c1269a93 100644 --- a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php +++ b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php @@ -124,4 +124,10 @@ public function handleITipMessage(Message $iTipMessage) { $schedulingPlugin = $this->server->getPlugin('caldav-schedule'); $schedulingPlugin->scheduleLocalDelivery($iTipMessage); } + + public function isExternalAttendee(string $principalUri): bool { + /** @var \Sabre\DAVACL\Plugin $aclPlugin */ + $aclPlugin = $this->server->getPlugin('acl'); + return $aclPlugin->getPrincipalByUri($principalUri) === null; + } } diff --git a/apps/dav/lib/Controller/InvitationResponseController.php b/apps/dav/lib/Controller/InvitationResponseController.php index f6923152dcea6..de22e3ba6a9e6 100644 --- a/apps/dav/lib/Controller/InvitationResponseController.php +++ b/apps/dav/lib/Controller/InvitationResponseController.php @@ -198,7 +198,12 @@ private function buildITipResponse(array $row, string $partStat, int $guests = n $iTipMessage->method = 'REPLY'; $iTipMessage->sequence = $row['sequence']; $iTipMessage->sender = $row['attendee']; - $iTipMessage->recipient = $row['organizer']; + + if ($this->responseServer->isExternalAttendee($row['attendee'])) { + $iTipMessage->recipient = $row['organizer']; + } else { + $iTipMessage->recipient = $row['attendee']; + } $message = <<. * */ + namespace OCA\DAV\Tests\Unit\DAV\Controller; use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer; @@ -77,7 +78,17 @@ protected function setUp(): void { ); } - public function testAccept() { + public function attendeeProvider(): array { + return [ + 'local attendee' => [false], + 'external attendee' => [true] + ]; + } + + /** + * @dataProvider attendeeProvider + */ + public function testAccept(bool $isExternalAttendee): void { $this->buildQueryExpects('TOKEN123', [ 'id' => 0, 'uid' => 'this-is-the-events-uid', @@ -110,21 +121,26 @@ public function testAccept() { $called = false; $this->responseServer->expects($this->once()) ->method('handleITipMessage') - ->willReturnCallback(function (Message $iTipMessage) use (&$called, $expected) { + ->willReturnCallback(function (Message $iTipMessage) use (&$called, $isExternalAttendee, $expected) { $called = true; $this->assertEquals('this-is-the-events-uid', $iTipMessage->uid); $this->assertEquals('VEVENT', $iTipMessage->component); $this->assertEquals('REPLY', $iTipMessage->method); $this->assertEquals(null, $iTipMessage->sequence); $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->sender); - $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + if ($isExternalAttendee) { + $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + } else { + $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->recipient); + } $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; $this->assertEquals($expected, $iTipMessage->message->serialize()); }); - - + $this->responseServer->expects($this->once()) + ->method('isExternalAttendee') + ->willReturn($isExternalAttendee); $response = $this->controller->accept('TOKEN123'); $this->assertInstanceOf(TemplateResponse::class, $response); @@ -133,7 +149,10 @@ public function testAccept() { $this->assertTrue($called); } - public function testAcceptSequence() { + /** + * @dataProvider attendeeProvider + */ + public function testAcceptSequence(bool $isExternalAttendee): void { $this->buildQueryExpects('TOKEN123', [ 'id' => 0, 'uid' => 'this-is-the-events-uid', @@ -166,21 +185,26 @@ public function testAcceptSequence() { $called = false; $this->responseServer->expects($this->once()) ->method('handleITipMessage') - ->willReturnCallback(function (Message $iTipMessage) use (&$called, $expected) { + ->willReturnCallback(function (Message $iTipMessage) use (&$called, $isExternalAttendee, $expected) { $called = true; $this->assertEquals('this-is-the-events-uid', $iTipMessage->uid); $this->assertEquals('VEVENT', $iTipMessage->component); $this->assertEquals('REPLY', $iTipMessage->method); $this->assertEquals(1337, $iTipMessage->sequence); $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->sender); - $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + if ($isExternalAttendee) { + $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + } else { + $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->recipient); + } $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; $this->assertEquals($expected, $iTipMessage->message->serialize()); }); - - + $this->responseServer->expects($this->once()) + ->method('isExternalAttendee') + ->willReturn($isExternalAttendee); $response = $this->controller->accept('TOKEN123'); $this->assertInstanceOf(TemplateResponse::class, $response); @@ -189,7 +213,10 @@ public function testAcceptSequence() { $this->assertTrue($called); } - public function testAcceptRecurrenceId() { + /** + * @dataProvider attendeeProvider + */ + public function testAcceptRecurrenceId(bool $isExternalAttendee): void { $this->buildQueryExpects('TOKEN123', [ 'id' => 0, 'uid' => 'this-is-the-events-uid', @@ -223,21 +250,26 @@ public function testAcceptRecurrenceId() { $called = false; $this->responseServer->expects($this->once()) ->method('handleITipMessage') - ->willReturnCallback(function (Message $iTipMessage) use (&$called, $expected) { + ->willReturnCallback(function (Message $iTipMessage) use (&$called, $isExternalAttendee, $expected) { $called = true; $this->assertEquals('this-is-the-events-uid', $iTipMessage->uid); $this->assertEquals('VEVENT', $iTipMessage->component); $this->assertEquals('REPLY', $iTipMessage->method); $this->assertEquals(0, $iTipMessage->sequence); $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->sender); - $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + if ($isExternalAttendee) { + $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + } else { + $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->recipient); + } $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; $this->assertEquals($expected, $iTipMessage->message->serialize()); }); - - + $this->responseServer->expects($this->once()) + ->method('isExternalAttendee') + ->willReturn($isExternalAttendee); $response = $this->controller->accept('TOKEN123'); $this->assertInstanceOf(TemplateResponse::class, $response); @@ -273,7 +305,10 @@ public function testAcceptExpiredToken() { $this->assertEquals([], $response->getParams()); } - public function testDecline() { + /** + * @dataProvider attendeeProvider + */ + public function testDecline(bool $isExternalAttendee): void { $this->buildQueryExpects('TOKEN123', [ 'id' => 0, 'uid' => 'this-is-the-events-uid', @@ -306,21 +341,26 @@ public function testDecline() { $called = false; $this->responseServer->expects($this->once()) ->method('handleITipMessage') - ->willReturnCallback(function (Message $iTipMessage) use (&$called, $expected) { + ->willReturnCallback(function (Message $iTipMessage) use (&$called, $isExternalAttendee, $expected) { $called = true; $this->assertEquals('this-is-the-events-uid', $iTipMessage->uid); $this->assertEquals('VEVENT', $iTipMessage->component); $this->assertEquals('REPLY', $iTipMessage->method); $this->assertEquals(null, $iTipMessage->sequence); $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->sender); - $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + if ($isExternalAttendee) { + $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + } else { + $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->recipient); + } $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; $this->assertEquals($expected, $iTipMessage->message->serialize()); }); - - + $this->responseServer->expects($this->once()) + ->method('isExternalAttendee') + ->willReturn($isExternalAttendee); $response = $this->controller->decline('TOKEN123'); $this->assertInstanceOf(TemplateResponse::class, $response); @@ -336,7 +376,10 @@ public function testOptions() { $this->assertEquals(['token' => 'TOKEN123'], $response->getParams()); } - public function testProcessMoreOptionsResult() { + /** + * @dataProvider attendeeProvider + */ + public function testProcessMoreOptionsResult(bool $isExternalAttendee): void { $this->request->expects($this->at(0)) ->method('getParam') ->with('partStat') @@ -384,20 +427,26 @@ public function testProcessMoreOptionsResult() { $called = false; $this->responseServer->expects($this->once()) ->method('handleITipMessage') - ->willReturnCallback(function (Message $iTipMessage) use (&$called, $expected) { + ->willReturnCallback(function (Message $iTipMessage) use (&$called, $isExternalAttendee, $expected) { $called = true; $this->assertEquals('this-is-the-events-uid', $iTipMessage->uid); $this->assertEquals('VEVENT', $iTipMessage->component); $this->assertEquals('REPLY', $iTipMessage->method); $this->assertEquals(null, $iTipMessage->sequence); $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->sender); - $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + if ($isExternalAttendee) { + $this->assertEquals('mailto:organizer@foo.bar', $iTipMessage->recipient); + } else { + $this->assertEquals('mailto:attendee@foo.bar', $iTipMessage->recipient); + } $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; $this->assertEquals($expected, $iTipMessage->message->serialize()); }); - + $this->responseServer->expects($this->once()) + ->method('isExternalAttendee') + ->willReturn($isExternalAttendee); $response = $this->controller->processMoreOptionsResult('TOKEN123');