From 91da66a3787c2cc51440f7f5029600161dd040b7 Mon Sep 17 00:00:00 2001 From: Anna Larch Date: Wed, 29 Sep 2021 17:32:13 +0200 Subject: [PATCH 1/2] Scheduling plugin not updating responding attendee status take two Signed-off-by: Anna Larch --- apps/dav/lib/Controller/InvitationResponseController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dav/lib/Controller/InvitationResponseController.php b/apps/dav/lib/Controller/InvitationResponseController.php index eafbe6fbbd8..5b03fa69c70 100644 --- a/apps/dav/lib/Controller/InvitationResponseController.php +++ b/apps/dav/lib/Controller/InvitationResponseController.php @@ -200,7 +200,7 @@ class InvitationResponseController extends Controller { $iTipMessage->method = 'REPLY'; $iTipMessage->sequence = $row['sequence']; $iTipMessage->sender = $row['attendee']; - $iTipMessage->recipient = $row['organizer']; + $iTipMessage->recipient = $row['attendee']; $message = << Date: Fri, 8 Oct 2021 16:34:43 +0200 Subject: [PATCH 2/2] Update attendence for external users For local users it's possible to select their calendar via the principal url and first update their own attendance status. External users have no calendar event hence the recipient is the organizer. Signed-off-by: Daniel Kesselberg --- .../InvitationResponseServer.php | 6 ++ .../InvitationResponseController.php | 7 +- .../InvitationResponseControllerTest.php | 96 ++++++++++++++----- 3 files changed, 84 insertions(+), 25 deletions(-) diff --git a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php index 7b0ee1bbef2..a24fc6856b6 100644 --- a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php +++ b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php @@ -122,4 +122,10 @@ class InvitationResponseServer { $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 5b03fa69c70..6a234541d1d 100644 --- a/apps/dav/lib/Controller/InvitationResponseController.php +++ b/apps/dav/lib/Controller/InvitationResponseController.php @@ -200,7 +200,12 @@ class InvitationResponseController extends Controller { $iTipMessage->method = 'REPLY'; $iTipMessage->sequence = $row['sequence']; $iTipMessage->sender = $row['attendee']; - $iTipMessage->recipient = $row['attendee']; + + if ($this->responseServer->isExternalAttendee($row['attendee'])) { + $iTipMessage->recipient = $row['organizer']; + } else { + $iTipMessage->recipient = $row['attendee']; + } $message = << [false], + 'external attendee' => [true] + ]; + } + + /** + * @dataProvider attendeeProvider + */ + public function testAccept(bool $isExternalAttendee): void { $this->buildQueryExpects('TOKEN123', [ 'id' => 0, 'uid' => 'this-is-the-events-uid', @@ -109,21 +119,26 @@ EOF; $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); @@ -132,7 +147,10 @@ EOF; $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', @@ -165,21 +183,26 @@ EOF; $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); @@ -188,7 +211,10 @@ EOF; $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', @@ -222,21 +248,26 @@ EOF; $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); @@ -272,7 +303,10 @@ EOF; $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', @@ -305,21 +339,26 @@ EOF; $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); @@ -335,7 +374,10 @@ EOF; $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') @@ -383,20 +425,26 @@ EOF; $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');