Merge pull request #21817 from owncloud/support-old-carddav-endpoint

Adding pre oc 9.0 CardDAV endpoint for migration of old clients
This commit is contained in:
Thomas Müller 2016-02-08 15:46:38 +01:00
commit 33eed35ae4
9 changed files with 193 additions and 29 deletions

View File

@ -14,6 +14,12 @@
<files>appinfo/v1/webdav.php</files> <files>appinfo/v1/webdav.php</files>
<webdav>appinfo/v1/webdav.php</webdav> <webdav>appinfo/v1/webdav.php</webdav>
<dav>appinfo/v2/remote.php</dav> <dav>appinfo/v2/remote.php</dav>
<!-- carddav endpoints as used before ownCloud 9.0 -->
<contacts>appinfo/v1/carddav.php</contacts>
<carddav>appinfo/v1/carddav.php</carddav>
<!-- caldav endpoints as used before ownCloud 9.0 -->
<calendar>appinfo/v1/caldav.php</calendar>
<caldav>appinfo/v1/caldav.php</caldav>
</remote> </remote>
<public> <public>
<webdav>appinfo/v1/publicwebdav.php</webdav> <webdav>appinfo/v1/publicwebdav.php</webdav>

View File

@ -0,0 +1,69 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
// Backends
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Connector\Sabre\Auth;
use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
use OCA\DAV\Connector\Sabre\MaintenancePlugin;
use OCA\DAV\Connector\Sabre\Principal;
use Sabre\CalDAV\CalendarRoot;
$authBackend = new Auth(
\OC::$server->getSession(),
\OC::$server->getUserSession(),
'principals/'
);
$principalBackend = new Principal(
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
'principals/'
);
$db = \OC::$server->getDatabaseConnection();
$calDavBackend = new CalDavBackend($db, $principalBackend);
// Root nodes
$principalCollection = new \Sabre\CalDAV\Principal\Collection($principalBackend);
$principalCollection->disableListing = true; // Disable listing
$addressBookRoot = new CalendarRoot($principalBackend, $calDavBackend);
$addressBookRoot->disableListing = true; // Disable listing
$nodes = array(
$principalCollection,
$addressBookRoot,
);
// Fire up server
$server = new \Sabre\DAV\Server($nodes);
$server->httpRequest->setUrl(\OC::$server->getRequest()->getRequestUri());
$server->setBaseUri($baseuri);
// Add plugins
$server->addPlugin(new MaintenancePlugin());
$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, 'ownCloud'));
$server->addPlugin(new \Sabre\CalDAV\Plugin());
$server->addPlugin(new \Sabre\DAVACL\Plugin());
$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
$server->addPlugin(new ExceptionLoggerPlugin('caldav', \OC::$server->getLogger()));
// And off we go!
$server->exec();

View File

@ -0,0 +1,70 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
// Backends
use OCA\DAV\CardDAV\AddressBookRoot;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Connector\Sabre\AppEnabledPlugin;
use OCA\DAV\Connector\Sabre\Auth;
use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
use OCA\DAV\Connector\Sabre\MaintenancePlugin;
use OCA\DAV\Connector\Sabre\Principal;
use Sabre\CardDAV\Plugin;
$authBackend = new Auth(
\OC::$server->getSession(),
\OC::$server->getUserSession(),
'principals/'
);
$principalBackend = new Principal(
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
'principals/'
);
$db = \OC::$server->getDatabaseConnection();
$cardDavBackend = new CardDavBackend($db, $principalBackend);
// Root nodes
$principalCollection = new \Sabre\CalDAV\Principal\Collection($principalBackend);
$principalCollection->disableListing = true; // Disable listing
$addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend);
$addressBookRoot->disableListing = true; // Disable listing
$nodes = array(
$principalCollection,
$addressBookRoot,
);
// Fire up server
$server = new \Sabre\DAV\Server($nodes);
$server->httpRequest->setUrl(\OC::$server->getRequest()->getRequestUri());
$server->setBaseUri($baseuri);
// Add plugins
$server->addPlugin(new MaintenancePlugin());
$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, 'ownCloud'));
$server->addPlugin(new Plugin());
$server->addPlugin(new \Sabre\DAVACL\Plugin());
$server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin());
$server->addPlugin(new ExceptionLoggerPlugin('carddav', \OC::$server->getLogger()));
// And off we go!
$server->exec();

View File

@ -40,7 +40,8 @@ $serverFactory = new \OCA\DAV\Connector\Sabre\ServerFactory(
// Backends // Backends
$authBackend = new \OCA\DAV\Connector\Sabre\Auth( $authBackend = new \OCA\DAV\Connector\Sabre\Auth(
\OC::$server->getSession(), \OC::$server->getSession(),
\OC::$server->getUserSession() \OC::$server->getUserSession(),
'principals/'
); );
$requestUri = \OC::$server->getRequest()->getRequestUri(); $requestUri = \OC::$server->getRequest()->getRequestUri();

View File

@ -40,6 +40,9 @@ class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot {
function getName() { function getName() {
if ($this->principalPrefix === 'principals') {
return parent::getName();
}
// Grabbing all the components of the principal path. // Grabbing all the components of the principal path.
$parts = explode('/', $this->principalPrefix); $parts = explode('/', $this->principalPrefix);

View File

@ -93,11 +93,11 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @return array * @return array
*/ */
function getAddressBooksForUser($principalUri) { function getAddressBooksForUser($principalUri) {
$principalUri = $this->convertPrincipal($principalUri, true);
$query = $this->db->getQueryBuilder(); $query = $this->db->getQueryBuilder();
$query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken']) $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])
->from('addressbooks') ->from('addressbooks')
->where($query->expr()->eq('principaluri', $query->createParameter('principaluri'))) ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri)));
->setParameter('principaluri', $principalUri);
$addressBooks = []; $addressBooks = [];
@ -106,7 +106,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$addressBooks[$row['id']] = [ $addressBooks[$row['id']] = [
'id' => $row['id'], 'id' => $row['id'],
'uri' => $row['uri'], 'uri' => $row['uri'],
'principaluri' => $row['principaluri'], 'principaluri' => $this->convertPrincipal($row['principaluri'], false),
'{DAV:}displayname' => $row['displayname'], '{DAV:}displayname' => $row['displayname'],
'{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
'{http://calendarserver.org/ns/}getctag' => $row['synctoken'], '{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
@ -921,4 +921,15 @@ class CardDavBackend implements BackendInterface, SyncSupport {
public function applyShareAcl($addressBookId, $acl) { public function applyShareAcl($addressBookId, $acl) {
return $this->sharingBackend->applyShareAcl($addressBookId, $acl); return $this->sharingBackend->applyShareAcl($addressBookId, $acl);
} }
private function convertPrincipal($principalUri, $toV2) {
if ($this->principalBackend->getPrincipalPrefix() === 'principals') {
list(, $name) = URLUtil::splitPath($principalUri);
if ($toV2 === true) {
return "principals/users/$name";
}
return "principals/$name";
}
return $principalUri;
}
} }

View File

@ -49,12 +49,14 @@ class Auth extends AbstractBasic {
/** /**
* @param ISession $session * @param ISession $session
* @param IUserSession $userSession * @param IUserSession $userSession
* @param string $principalPrefix
*/ */
public function __construct(ISession $session, public function __construct(ISession $session,
IUserSession $userSession) { IUserSession $userSession,
$principalPrefix = 'principals/users/') {
$this->session = $session; $this->session = $session;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->principalPrefix = 'principals/users/'; $this->principalPrefix = $principalPrefix;
} }
/** /**

View File

@ -46,12 +46,20 @@ class Principal implements BackendInterface {
/** @var IGroupManager */ /** @var IGroupManager */
private $groupManager; private $groupManager;
/** @var string */
private $principalPrefix;
/** /**
* @param IUserManager $userManager * @param IUserManager $userManager
* @param IGroupManager $groupManager
* @param string $principalPrefix
*/ */
public function __construct(IUserManager $userManager, IGroupManager $groupManager) { public function __construct(IUserManager $userManager,
IGroupManager $groupManager,
$principalPrefix = 'principals/users/') {
$this->userManager = $userManager; $this->userManager = $userManager;
$this->groupManager = $groupManager; $this->groupManager = $groupManager;
$this->principalPrefix = trim($principalPrefix, '/');
} }
/** /**
@ -70,7 +78,7 @@ class Principal implements BackendInterface {
public function getPrincipalsByPrefix($prefixPath) { public function getPrincipalsByPrefix($prefixPath) {
$principals = []; $principals = [];
if ($prefixPath === 'principals/users') { if ($prefixPath === $this->principalPrefix) {
foreach($this->userManager->search('') as $user) { foreach($this->userManager->search('') as $user) {
$principals[] = $this->userToPrincipal($user); $principals[] = $this->userToPrincipal($user);
} }
@ -88,20 +96,15 @@ class Principal implements BackendInterface {
* @return array * @return array
*/ */
public function getPrincipalByPath($path) { public function getPrincipalByPath($path) {
$elements = explode('/', $path); list($prefix, $name) = URLUtil::splitPath($path);
if ($elements[0] !== 'principals') {
return null;
}
if ($elements[1] !== 'users') {
return null;
}
$name = $elements[2];
$user = $this->userManager->get($name);
if (!is_null($user)) { if ($prefix === $this->principalPrefix) {
return $this->userToPrincipal($user); $user = $this->userManager->get($name);
}
if (!is_null($user)) {
return $this->userToPrincipal($user);
}
}
return null; return null;
} }
@ -132,7 +135,7 @@ class Principal implements BackendInterface {
public function getGroupMembership($principal) { public function getGroupMembership($principal) {
list($prefix, $name) = URLUtil::splitPath($principal); list($prefix, $name) = URLUtil::splitPath($principal);
if ($prefix === 'principals/users') { if ($prefix === $this->principalPrefix) {
$user = $this->userManager->get($name); $user = $this->userManager->get($name);
if (!$user) { if (!$user) {
throw new Exception('Principal not found'); throw new Exception('Principal not found');
@ -141,11 +144,9 @@ class Principal implements BackendInterface {
$groups = $this->groupManager->getUserGroups($user); $groups = $this->groupManager->getUserGroups($user);
$groups = array_map(function($group) { $groups = array_map(function($group) {
/** @var IGroup $group */ /** @var IGroup $group */
return 'principals/groups/' . $group->getGID(); return $this->principalPrefix . '/' . $group->getGID();
}, $groups); }, $groups);
$groups[]= 'principals/users/'.$name.'/calendar-proxy-read';
$groups[]= 'principals/users/'.$name.'/calendar-proxy-write';
return $groups; return $groups;
} }
return []; return [];
@ -200,7 +201,7 @@ class Principal implements BackendInterface {
$userId = $user->getUID(); $userId = $user->getUID();
$displayName = $user->getDisplayName(); $displayName = $user->getDisplayName();
$principal = [ $principal = [
'uri' => "principals/users/$userId", 'uri' => $this->principalPrefix . '/' . $userId,
'{DAV:}displayname' => is_null($displayName) ? $userId : $displayName, '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
]; ];
@ -212,4 +213,8 @@ class Principal implements BackendInterface {
return $principal; return $principal;
} }
public function getPrincipalPrefix() {
return $this->principalPrefix;
}
} }

View File

@ -211,10 +211,7 @@ class Principal extends TestCase {
->method('getUserGroups') ->method('getUserGroups')
->willReturn([]); ->willReturn([]);
$expectedResponse = [ $expectedResponse = [];
'principals/users/foo/calendar-proxy-read',
'principals/users/foo/calendar-proxy-write'
];
$response = $this->connector->getGroupMembership('principals/users/foo'); $response = $this->connector->getGroupMembership('principals/users/foo');
$this->assertSame($expectedResponse, $response); $this->assertSame($expectedResponse, $response);
} }