From: Georg Ehrke Date: Wed, 1 Nov 2017 21:00:53 +0000 (+0100) Subject: ensure uid for calendar objects is unique X-Git-Tag: v12.0.4RC1~25^2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3059191444bd538ff24d46e096a1ee13d0fc3898;p=nextcloud-server.git ensure uid for calendar objects is unique Signed-off-by: Georg Ehrke --- diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 830f877468b..191e9f1ac9a 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -948,6 +948,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/AbstractCalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php index a7bf4432c64..bcf6cb763ea 100644 --- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php @@ -133,13 +133,15 @@ abstract class AbstractCalDavBackendTest extends TestCase { protected function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') { + $randomPart = self::getUniqueID(); + $calData = <<assertCount(0, $calendarObjects); } + /** + * @expectedException \Sabre\DAV\Exception\BadRequest + * @expectedExceptionMessage Calendar object with uid already exists in this calendar collection. + */ + public function testMultipleCalendarObjectsWithSameUID() { + $calendarId = $this->createTestCalendar(); + + $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; + + $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 = <<<'EOD' + $calData = []; + $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 +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 @@ -287,21 +335,39 @@ 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); @@ -317,9 +383,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') @@ -362,7 +434,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);