Skip to content

Commit

Permalink
Merge pull request #21964 from owncloud/calendar-sharing-3
Browse files Browse the repository at this point in the history
Add calendar sharing
  • Loading branch information
DeepDiver1975 committed Feb 4, 2016
2 parents 6a5b0ea + 81b9721 commit e64044d
Show file tree
Hide file tree
Showing 28 changed files with 1,149 additions and 129 deletions.
2 changes: 1 addition & 1 deletion apps/dav/appinfo/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

/** @var Symfony\Component\Console\Application $application */
$application->add(new CreateAddressBook($userManager, $groupManager, $dbConnection, $logger));
$application->add(new CreateCalendar($userManager, $dbConnection));
$application->add(new CreateCalendar($userManager, $groupManager, $dbConnection));
$application->add(new SyncSystemAddressBook($app->getSyncService()));

// the occ tool is *for now* only available in debug mode for developers to test
Expand Down
15 changes: 13 additions & 2 deletions apps/dav/command/createcalendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
namespace OCA\DAV\Command;

use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -33,16 +35,20 @@ class CreateCalendar extends Command {
/** @var IUserManager */
protected $userManager;

/** @var IGroupManager $groupManager */
private $groupManager;

/** @var \OCP\IDBConnection */
protected $dbConnection;

/**
* @param IUserManager $userManager
* @param IDBConnection $dbConnection
*/
function __construct(IUserManager $userManager, IDBConnection $dbConnection) {
function __construct(IUserManager $userManager, IGroupManager $groupManager, IDBConnection $dbConnection) {
parent::__construct();
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->dbConnection = $dbConnection;
}

Expand All @@ -63,8 +69,13 @@ protected function execute(InputInterface $input, OutputInterface $output) {
if (!$this->userManager->userExists($user)) {
throw new \InvalidArgumentException("User <$user> in unknown.");
}
$principalBackend = new Principal(
$this->userManager,
$this->groupManager
);

$name = $input->getArgument('name');
$caldav = new CalDavBackend($this->dbConnection);
$caldav = new CalDavBackend($this->dbConnection, $principalBackend);
$caldav->createCalendar("principals/users/$user", $name, []);
}
}
90 changes: 87 additions & 3 deletions apps/dav/lib/caldav/caldavbackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
namespace OCA\DAV\CalDAV;

use OCP\DB\QueryBuilder\IQueryBuilder;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\DAV\Sharing\Backend;
use Sabre\CalDAV\Backend\AbstractBackend;
use Sabre\CalDAV\Backend\SchedulingSupport;
use Sabre\CalDAV\Backend\SubscriptionSupport;
Expand All @@ -32,6 +34,7 @@
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV;
use Sabre\DAV\Exception\Forbidden;
use Sabre\HTTP\URLUtil;
use Sabre\VObject\DateTimeParser;
use Sabre\VObject\Reader;
use Sabre\VObject\RecurrenceIterator;
Expand Down Expand Up @@ -86,8 +89,24 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments',
];

public function __construct(\OCP\IDBConnection $db) {
/** @var \OCP\IDBConnection */
private $db;

/** @var Backend */
private $sharingBackend;

/** @var Principal */
private $principalBackend;

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

/**
Expand Down Expand Up @@ -153,10 +172,60 @@ function getCalendarsForUser($principalUri) {
$calendar[$xmlName] = $row[$dbName];
}

$calendars[] = $calendar;
$calendars[$calendar['id']] = $calendar;
}

$stmt->closeCursor();

// query for shared calendars
$principals = $this->principalBackend->getGroupMembership($principalUri);
$principals[]= $principalUri;

$fields = array_values($this->propertyMap);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
$fields[] = 'a.components';
$fields[] = 'a.principaluri';
$fields[] = 'a.transparent';
$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.principaluri', $query->createParameter('principaluri')))
->andWhere($query->expr()->eq('s.type', $query->createParameter('type')))
->setParameter('type', 'calendar')
->setParameter('principaluri', $principals, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
->execute();

while($row = $result->fetch()) {
list(, $name) = URLUtil::splitPath($row['principaluri']);
$uri = $row['uri'] . '_shared_by_' . $name;
$row['displayname'] = $row['displayname'] . "($name)";
$components = [];
if ($row['components']) {
$components = explode(',',$row['components']);
}
$calendar = [
'id' => $row['id'],
'uri' => $uri,
'principaluri' => $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'],
];

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

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

return $calendars;
return array_values($calendars);
}

/**
Expand Down Expand Up @@ -271,6 +340,8 @@ function deleteCalendar($calendarId) {

$stmt = $this->db->prepare('DELETE FROM `*PREFIX*calendarchanges` WHERE `calendarid` = ?');
$stmt->execute([$calendarId]);

$this->sharingBackend->deleteAllShares($calendarId);
}

/**
Expand Down Expand Up @@ -1173,4 +1244,17 @@ private function readBlob($cardData) {

return $cardData;
}

public function updateShares($shareable, $add, $remove) {
$this->sharingBackend->updateShares($shareable, $add, $remove);
}

public function getShares($resourceId) {
return $this->sharingBackend->getShares($resourceId);
}

public function applyShareAcl($addressBookId, $acl) {
return $this->sharingBackend->applyShareAcl($addressBookId, $acl);
}

}
102 changes: 102 additions & 0 deletions apps/dav/lib/caldav/calendar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace OCA\DAV\CalDAV;

use OCA\DAV\DAV\Sharing\IShareable;
use Sabre\DAV\Exception\Forbidden;

class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {

/**
* Updates the list of shares.
*
* The first array is a list of people that are to be added to the
* resource.
*
* Every element in the add array has the following properties:
* * href - A url. Usually a mailto: address
* * commonName - Usually a first and last name, or false
* * summary - A description of the share, can also be false
* * readOnly - A boolean value
*
* Every element in the remove array is just the address string.
*
* @param array $add
* @param array $remove
* @return void
*/
function updateShares(array $add, array $remove) {
/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
$calDavBackend->updateShares($this, $add, $remove);
}

/**
* Returns the list of people whom this resource is shared with.
*
* Every element in this array should have the following properties:
* * href - Often a mailto: address
* * commonName - Optional, for example a first + last name
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
* * readOnly - boolean
* * summary - Optional, a description for the share
*
* @return array
*/
function getShares() {
/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
return $calDavBackend->getShares($this->getResourceId());
}

/**
* @return int
*/
public function getResourceId() {
return $this->calendarInfo['id'];
}

function getACL() {
$acl = parent::getACL();

/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
return $calDavBackend->applyShareAcl($this->getResourceId(), $acl);
}

function getChildACL() {
$acl = parent::getChildACL();

/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
return $calDavBackend->applyShareAcl($this->getResourceId(), $acl);
}

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

function delete() {
if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
$principal = 'principal:' . parent::getOwner();
$shares = $this->getShares();
$shares = array_filter($shares, function($share) use ($principal){
return $share['href'] === $principal;
});
if (empty($shares)) {
throw new Forbidden();
}

/** @var CalDavBackend $calDavBackend */
$calDavBackend = $this->caldavBackend;
$calDavBackend->updateShares($this, [], [
'href' => $principal
]);
return;
}
parent::delete();
}
}
78 changes: 78 additions & 0 deletions apps/dav/lib/caldav/calendarhome.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace OCA\DAV\CalDAV;

use Sabre\CalDAV\Backend\NotificationSupport;
use Sabre\CalDAV\Backend\SchedulingSupport;
use Sabre\CalDAV\Backend\SubscriptionSupport;
use Sabre\CalDAV\Schedule\Inbox;
use Sabre\CalDAV\Schedule\Outbox;
use Sabre\CalDAV\Subscriptions\Subscription;
use Sabre\DAV\Exception\NotFound;

class CalendarHome extends \Sabre\CalDAV\CalendarHome {

/**
* @inheritdoc
*/
function getChildren() {
$calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
$objs = [];
foreach ($calendars as $calendar) {
$objs[] = new Calendar($this->caldavBackend, $calendar);
}

if ($this->caldavBackend instanceof SchedulingSupport) {
$objs[] = new Inbox($this->caldavBackend, $this->principalInfo['uri']);
$objs[] = new Outbox($this->principalInfo['uri']);
}

// We're adding a notifications node, if it's supported by the backend.
if ($this->caldavBackend instanceof NotificationSupport) {
$objs[] = new \Sabre\CalDAV\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
}

// If the backend supports subscriptions, we'll add those as well,
if ($this->caldavBackend instanceof SubscriptionSupport) {
foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) {
$objs[] = new Subscription($this->caldavBackend, $subscription);
}
}

return $objs;
}

/**
* @inheritdoc
*/
function getChild($name) {
// Special nodes
if ($name === 'inbox' && $this->caldavBackend instanceof SchedulingSupport) {
return new Inbox($this->caldavBackend, $this->principalInfo['uri']);
}
if ($name === 'outbox' && $this->caldavBackend instanceof SchedulingSupport) {
return new Outbox($this->principalInfo['uri']);
}
if ($name === 'notifications' && $this->caldavBackend instanceof NotificationSupport) {
return new \Sabre\CalDAv\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
}

// Calendars
foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) {
if ($calendar['uri'] === $name) {
return new Calendar($this->caldavBackend, $calendar);
}
}

if ($this->caldavBackend instanceof SubscriptionSupport) {
foreach ($this->caldavBackend->getSubscriptionsForUser($this->principalInfo['uri']) as $subscription) {
if ($subscription['uri'] === $name) {
return new Subscription($this->caldavBackend, $subscription);
}
}

}

throw new NotFound('Node with name \'' . $name . '\' could not be found');
}
}
10 changes: 10 additions & 0 deletions apps/dav/lib/caldav/calendarroot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace OCA\DAV\CalDAV;

class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {

function getChildForPrincipal(array $principal) {
return new CalendarHome($this->caldavBackend, $principal);
}
}
Loading

0 comments on commit e64044d

Please sign in to comment.