From 4df08f296b6242f9df7b1fc729801b7bd221be25 Mon Sep 17 00:00:00 2001 From: Georg Ehrke Date: Wed, 1 Nov 2017 22:00:53 +0100 Subject: [PATCH] ensure uid for calendar objects is unique Signed-off-by: Georg Ehrke --- apps/dav/lib/CalDAV/CalDavBackend.php | 14 +++ .../unit/CalDAV/AbstractCalDavBackend.php | 4 +- .../tests/unit/CalDAV/CalDavBackendTest.php | 109 ++++++++++++++++-- 3 files changed, 117 insertions(+), 10 deletions(-) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 2c34f6d6d3..4947d40156 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -957,6 +957,20 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription function createCalendarObject($calendarId, $objectUri, $calendarData) { $extraData = $this->getDenormalizedData($calendarData); + $q = $this->db->getQueryBuilder(); + $q->select($q->createFunction('COUNT(*)')) + ->from('calendarobjects') + ->where($q->expr()->eq('calendarid', $q->createNamedParameter($calendarId))) + ->andWhere($q->expr()->eq('uid', $q->createNamedParameter($extraData['uid']))); + + $result = $q->execute(); + $count = (int) $result->fetchColumn(); + $result->closeCursor(); + + if ($count !== 0) { + throw new \Sabre\DAV\Exception\BadRequest('Calendar object with uid already exists in this calendar collection.'); + } + $query = $this->db->getQueryBuilder(); $query->insert('calendarobjects') ->values([ diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php index eef69aadf4..a82933f459 100644 --- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php +++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php @@ -137,13 +137,15 @@ abstract class AbstractCalDavBackend extends TestCase { protected function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') { + $randomPart = self::getUniqueID(); + $calData = <<assertCount(0, $calendarObjects); } - public function testMultiCalendarObjects() { - + /** + * @expectedException \Sabre\DAV\Exception\BadRequest + * @expectedExceptionMessage Calendar object with uid already exists in this calendar collection. + */ + public function testMultipleCalendarObjectsWithSameUID() { $calendarId = $this->createTestCalendar(); - // create an event $calData = <<<'EOD' BEGIN:VCALENDAR VERSION:2.0 PRODID:ownCloud Calendar BEGIN:VEVENT CREATED;VALUE=DATE-TIME:20130910T125139Z -UID:47d15e3ec8 +UID:47d15e3ec8-1 LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z DTSTAMP;VALUE=DATE-TIME:20130910T125139Z SUMMARY:Test Event @@ -295,21 +297,85 @@ CLASS:PUBLIC END:VEVENT END:VCALENDAR EOD; + + $uri0 = static::getUniqueID('event'); + $uri1 = static::getUniqueID('event'); + $this->backend->createCalendarObject($calendarId, $uri0, $calData); + $this->backend->createCalendarObject($calendarId, $uri1, $calData); + } + + public function testMultiCalendarObjects() { + + $calendarId = $this->createTestCalendar(); + + // create an event + $calData = []; + $calData[] = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8-1 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + + $calData[] = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8-2 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + + $calData[] = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8-3 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + $uri0 = static::getUniqueID('card'); $this->dispatcher->expects($this->at(0)) ->method('dispatch') ->with('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject'); - $this->backend->createCalendarObject($calendarId, $uri0, $calData); + $this->backend->createCalendarObject($calendarId, $uri0, $calData[0]); $uri1 = static::getUniqueID('card'); $this->dispatcher->expects($this->at(0)) ->method('dispatch') ->with('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject'); - $this->backend->createCalendarObject($calendarId, $uri1, $calData); + $this->backend->createCalendarObject($calendarId, $uri1, $calData[1]); $uri2 = static::getUniqueID('card'); $this->dispatcher->expects($this->at(0)) ->method('dispatch') ->with('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject'); - $this->backend->createCalendarObject($calendarId, $uri2, $calData); + $this->backend->createCalendarObject($calendarId, $uri2, $calData[2]); // get all the cards $calendarObjects = $this->backend->getCalendarObjects($calendarId); @@ -325,9 +391,15 @@ EOD; $this->assertArrayHasKey('etag', $card); $this->assertArrayHasKey('size', $card); $this->assertArrayHasKey('classification', $card); - $this->assertEquals($calData, $card['calendardata']); } + usort($calendarObjects, function($a, $b) { + return $a['id'] - $b['id']; + }); + + $this->assertEquals($calData[1], $calendarObjects[0]['calendardata']); + $this->assertEquals($calData[2], $calendarObjects[1]['calendardata']); + // delete the card $this->dispatcher->expects($this->at(0)) ->method('dispatch') @@ -370,7 +442,26 @@ EOD; public function testGetCalendarObjectByUID() { $calendarId = $this->createTestCalendar(); - $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); + $uri = static::getUniqueID('calobj'); + $calData = <<<'EOD' +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:20130912T130000Z +DTEND;VALUE=DATE-TIME:20130912T140000Z +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + + + $this->backend->createCalendarObject($calendarId, $uri, $calData); $co = $this->backend->getCalendarObjectByUID(self::UNIT_TEST_USER, '47d15e3ec8'); $this->assertNotNull($co);