Skip to content

Commit

Permalink
[9.2] CalDAV calendar public sharing (#25351)
Browse files Browse the repository at this point in the history
* Proper work on Publishing

* Make little corrections

Function getPublishedStatus) is not working atm.

* Remove unnecessary implementation

* Fix publish-url property & getPublishStatus() fct

* Remove unnecessary line

* Fix annotations

* Use ressource ID instead of name

* Use urlgenerator to generate an absolute url

And pass Config the correct way too

* No need to call database twice

* Start work on returning CalDAV published calendars

* Add new root collection public-calendars which holds all public calendars

* Allow not-authenticated access to specific urls

* Fix requests for browser plugin as well as for the public calendar root folder

* Dirty hack to disable dav plugins on public calendar urls

* Fix DB call for MySQL databases

* correct get published status and minor fixes

* Fix some tests

* Fix wrong way to get publish status

* Allow public access to the principals/system/public

* Disable OPTIONS handling - done by sabre

* a few tests

* fix plugin test

* fix unpublishing test

* fix things (indentation, tests, comments, backend custom implementation

* fix indent once and for all

* move getPublicCalendar inside the caldav backend

* fix some bracket positions

* Add publicuri to oc_dav_shares table and start working with it

* test serializer

* fix getChild()

* add space between calendarname and owner name

* add can-be-published property

* add missing tests

* fix can-be-published

* use AllowedSharingModes for can-be-published & can-be-shared

* add calendarserver-sharing to the list of advertised features

* Add test for PublicCalendarRoot
  • Loading branch information
tcitworld authored and DeepDiver1975 committed Aug 29, 2016
1 parent 74bd2c5 commit 8308348
Show file tree
Hide file tree
Showing 20 changed files with 968 additions and 8 deletions.
8 changes: 8 additions & 0 deletions apps/dav/appinfo/database.xml
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,11 @@ CREATE TABLE calendarobjects (
<notnull>true</notnull>
<unsigned>true</unsigned>
</field>
<field>
<name>publicuri</name>
<type>text</type>
<length>255</length>
</field>
<index>
<name>dav_shares_index</name>
<unique>true</unique>
Expand All @@ -715,6 +720,9 @@ CREATE TABLE calendarobjects (
<field>
<name>type</name>
</field>
<field>
<name>publicuri</name>
</field>
</index>
</declaration>
</table>
Expand Down
2 changes: 1 addition & 1 deletion apps/dav/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<description>ownCloud WebDAV endpoint</description>
<licence>AGPL</licence>
<author>owncloud.org</author>
<version>0.2.5</version>
<version>0.2.6</version>
<default_enable/>
<types>
<filesystem/>
Expand Down
3 changes: 2 additions & 1 deletion apps/dav/appinfo/v1/caldav.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
'principals/'
);
$db = \OC::$server->getDatabaseConnection();
$calDavBackend = new CalDavBackend($db, $principalBackend);
$config = \OC::$server->getConfig();
$calDavBackend = new CalDavBackend($db, $principalBackend, $config);

$debugging = \OC::$server->getConfig()->getSystemValue('debug', false);

Expand Down
3 changes: 2 additions & 1 deletion apps/dav/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,12 @@ public function __construct (array $urlParams=array()) {
$container->registerService('CalDavBackend', function($c) {
/** @var IAppContainer $c */
$db = $c->getServer()->getDatabaseConnection();
$config = $c->getServer()->getConfig();
$principal = new Principal(
$c->getServer()->getUserManager(),
$c->getServer()->getGroupManager()
);
return new CalDavBackend($db, $principal);
return new CalDavBackend($db, $principal, $config);
});

$container->registerService('BirthdayService', function($c) {
Expand Down
165 changes: 164 additions & 1 deletion apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\DAV\Sharing\Backend;
use OCP\IConfig;
use OCP\IDBConnection;
use Sabre\CalDAV\Backend\AbstractBackend;
use Sabre\CalDAV\Backend\SchedulingSupport;
Expand All @@ -38,6 +39,7 @@
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch;
use Sabre\HTTP\URLUtil;
use Sabre\VObject\DateTimeParser;
Expand All @@ -63,6 +65,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
const MAX_DATE = '2038-01-01';

const ACCESS_PUBLIC = 4;
const CLASSIFICATION_PUBLIC = 0;
const CLASSIFICATION_PRIVATE = 1;
const CLASSIFICATION_CONFIDENTIAL = 2;
Expand Down Expand Up @@ -107,16 +110,21 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
/** @var Principal */
private $principalBackend;

/** @var IConfig */
private $config;

/**
* CalDavBackend constructor.
*
* @param IDBConnection $db
* @param Principal $principalBackend
* @param IConfig $config
*/
public function __construct(IDBConnection $db, Principal $principalBackend) {
public function __construct(IDBConnection $db, Principal $principalBackend, IConfig $config) {
$this->db = $db;
$this->principalBackend = $principalBackend;
$this->sharingBackend = new Backend($this->db, $principalBackend, 'calendar');
$this->config = $config;
}

/**
Expand Down Expand Up @@ -246,6 +254,121 @@ function getCalendarsForUser($principalUri) {
return array_values($calendars);
}

/**
* @return array
*/
public function getPublicCalendars() {
$fields = array_values($this->propertyMap);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
$fields[] = 'a.components';
$fields[] = 'a.principaluri';
$fields[] = 'a.transparent';
$fields[] = 's.access';
$fields[] = 's.publicuri';
$calendars = [];
$query = $this->db->getQueryBuilder();
$result = $query->select($fields)
->from('dav_shares', 's')
->join('s', 'calendars', 'a', $query->expr()->eq('s.resourceid', 'a.id'))
->where($query->expr()->in('s.access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
->andWhere($query->expr()->eq('s.type', $query->createNamedParameter('calendar')))
->execute();

while($row = $result->fetch()) {
list(, $name) = URLUtil::splitPath($row['principaluri']);
$row['displayname'] = $row['displayname'] . "($name)";
$components = [];
if ($row['components']) {
$components = explode(',',$row['components']);
}
$calendar = [
'id' => $row['id'],
'uri' => $row['publicuri'],
'principaluri' => $row['principaluri'],
'{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'),
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => (int)$row['access'] === Backend::ACCESS_READ,
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
];

foreach($this->propertyMap as $xmlName=>$dbName) {
$calendar[$xmlName] = $row[$dbName];
}

if (!isset($calendars[$calendar['id']])) {
$calendars[$calendar['id']] = $calendar;
}
}
$result->closeCursor();

return array_values($calendars);
}

/**
* @param string $uri
* @return array
* @throws NotFound
*/
public function getPublicCalendar($uri) {
$fields = array_values($this->propertyMap);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
$fields[] = 'a.components';
$fields[] = 'a.principaluri';
$fields[] = 'a.transparent';
$fields[] = 's.access';
$fields[] = 's.publicuri';
$query = $this->db->getQueryBuilder();
$result = $query->select($fields)
->from('dav_shares', 's')
->join('s', 'calendars', 'a', $query->expr()->eq('s.resourceid', 'a.id'))
->where($query->expr()->in('s.access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
->andWhere($query->expr()->eq('s.type', $query->createNamedParameter('calendar')))
->andWhere($query->expr()->eq('s.publicuri', $query->createNamedParameter($uri)))
->execute();

$row = $result->fetch(\PDO::FETCH_ASSOC);

$result->closeCursor();

if ($row === false) {
throw new NotFound('Node with name \'' . $uri . '\' could not be found');
}

list(, $name) = URLUtil::splitPath($row['principaluri']);
$row['displayname'] = $row['displayname'] . ' ' . "($name)";
$components = [];
if ($row['components']) {
$components = explode(',',$row['components']);
}
$uri = md5($this->config->getSystemValue('secret', '') . $row['id']);
$calendar = [
'id' => $row['id'],
'uri' => $uri,
'principaluri' => $row['principaluri'],
'{' . Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken']?$row['synctoken']:'0'),
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => (int)$row['access'] === Backend::ACCESS_READ,
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
];

foreach($this->propertyMap as $xmlName=>$dbName) {
$calendar[$xmlName] = $row[$dbName];
}

return $calendar;

}

/**
* @param string $principal
* @param string $uri
Expand Down Expand Up @@ -1415,6 +1538,46 @@ public function getShares($resourceId) {
return $this->sharingBackend->getShares($resourceId);
}

/**
* @param boolean $value
* @param \OCA\DAV\CalDAV\Calendar $calendar
*/
public function setPublishStatus($value, $calendar) {
$query = $this->db->getQueryBuilder();
if ($value) {
$query->insert('dav_shares')
->values([
'principaluri' => $query->createNamedParameter($calendar->getPrincipalURI()),
'type' => $query->createNamedParameter('calendar'),
'access' => $query->createNamedParameter(self::ACCESS_PUBLIC),
'resourceid' => $query->createNamedParameter($calendar->getResourceId()),
'publicuri' => $query->createNamedParameter(md5($this->config->getSystemValue('secret', '') . $calendar->getResourceId()))
]);
} else {
$query->delete('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId())))
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)));
}
$query->execute();
}

/**
* @param \OCA\DAV\CalDAV\Calendar $calendar
* @return boolean
*/
public function getPublishStatus($calendar) {
$query = $this->db->getQueryBuilder();
$result = $query->select($query->createFunction('COUNT(*)'))
->from('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId())))
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
->execute();

$row = $result->fetch();
$result->closeCursor();
return reset($row) > 0;
}

/**
* @param int $resourceId
* @param array $acl
Expand Down
36 changes: 36 additions & 0 deletions apps/dav/lib/CalDAV/Calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ public function getResourceId() {
return $this->calendarInfo['id'];
}

/**
* @return string
*/
public function getPrincipalURI() {
return $this->calendarInfo['principaluri'];
}

function getACL() {
$acl = [
[
Expand Down Expand Up @@ -116,6 +123,13 @@ function getACL() {
];
}
}
if ($this->isPublic()) {
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => 'principals/system/public',
'protected' => true,
];
}

/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
Expand Down Expand Up @@ -235,15 +249,37 @@ function calendarQuery(array $filters) {
return $uris;
}

/**
* @param boolean $value
*/
function setPublishStatus($value) {
$this->caldavBackend->setPublishStatus($value, $this);
}

/**
* @return boolean $value
*/
function getPublishStatus() {
return $this->caldavBackend->getPublishStatus($this);
}

private function canWrite() {
if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
}
return true;
}

private function isPublic() {
return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
}

private function isShared() {
return isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']);
}

public function isSubscription() {
return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
}

}
Loading

0 comments on commit 8308348

Please sign in to comment.