From cca2ade199f09c2e4c2c00c86e776dcc3b51d60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 20 Jan 2016 21:08:23 +0100 Subject: [PATCH 1/4] Adding pre oc 9.0 CardDAV endpoint for migration of old clients --- apps/dav/appinfo/info.xml | 4 +- apps/dav/appinfo/v1/carddav.php | 70 ++++++++++++++++++++++ apps/dav/appinfo/v1/webdav.php | 3 +- apps/dav/lib/carddav/addressbookroot.php | 3 + apps/dav/lib/carddav/carddavbackend.php | 17 +++++- apps/dav/lib/connector/sabre/auth.php | 6 +- apps/dav/lib/connector/sabre/principal.php | 45 ++++++++------ 7 files changed, 122 insertions(+), 26 deletions(-) create mode 100644 apps/dav/appinfo/v1/carddav.php diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index f035d19d86..647ad279ba 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -14,7 +14,9 @@ appinfo/v1/webdav.php appinfo/v1/webdav.php appinfo/v2/remote.php - + + appinfo/v1/carddav.php + appinfo/v1/carddav.php appinfo/v1/publicwebdav.php diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php new file mode 100644 index 0000000000..e0c79c75b7 --- /dev/null +++ b/apps/dav/appinfo/v1/carddav.php @@ -0,0 +1,70 @@ + + * + * @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 + * + */ + +// 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(); diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php index d75c3526bd..3d3e51e84b 100644 --- a/apps/dav/appinfo/v1/webdav.php +++ b/apps/dav/appinfo/v1/webdav.php @@ -40,7 +40,8 @@ $serverFactory = new \OCA\DAV\Connector\Sabre\ServerFactory( // Backends $authBackend = new \OCA\DAV\Connector\Sabre\Auth( \OC::$server->getSession(), - \OC::$server->getUserSession() + \OC::$server->getUserSession(), + 'principals/' ); $requestUri = \OC::$server->getRequest()->getRequestUri(); diff --git a/apps/dav/lib/carddav/addressbookroot.php b/apps/dav/lib/carddav/addressbookroot.php index 2680135dec..99c36c2e76 100644 --- a/apps/dav/lib/carddav/addressbookroot.php +++ b/apps/dav/lib/carddav/addressbookroot.php @@ -40,6 +40,9 @@ class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot { function getName() { + if ($this->principalPrefix === 'principals') { + return parent::getName(); + } // Grabbing all the components of the principal path. $parts = explode('/', $this->principalPrefix); diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index 9ca166c22a..b2a54adc49 100644 --- a/apps/dav/lib/carddav/carddavbackend.php +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -93,11 +93,11 @@ class CardDavBackend implements BackendInterface, SyncSupport { * @return array */ function getAddressBooksForUser($principalUri) { + $principalUri = $this->convertPrincipal($principalUri, true); $query = $this->db->getQueryBuilder(); $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken']) ->from('addressbooks') - ->where($query->expr()->eq('principaluri', $query->createParameter('principaluri'))) - ->setParameter('principaluri', $principalUri); + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))); $addressBooks = []; @@ -106,7 +106,7 @@ class CardDavBackend implements BackendInterface, SyncSupport { $addressBooks[$row['id']] = [ 'id' => $row['id'], 'uri' => $row['uri'], - 'principaluri' => $row['principaluri'], + 'principaluri' => $this->convertPrincipal($row['principaluri'], false), '{DAV:}displayname' => $row['displayname'], '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], '{http://calendarserver.org/ns/}getctag' => $row['synctoken'], @@ -919,4 +919,15 @@ class CardDavBackend implements BackendInterface, SyncSupport { public function 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; + } } diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php index cc679e44db..a046e07848 100644 --- a/apps/dav/lib/connector/sabre/auth.php +++ b/apps/dav/lib/connector/sabre/auth.php @@ -49,12 +49,14 @@ class Auth extends AbstractBasic { /** * @param ISession $session * @param IUserSession $userSession + * @param string $principalPrefix */ public function __construct(ISession $session, - IUserSession $userSession) { + IUserSession $userSession, + $principalPrefix = 'principals/users/') { $this->session = $session; $this->userSession = $userSession; - $this->principalPrefix = 'principals/users/'; + $this->principalPrefix = $principalPrefix; } /** diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php index 5f02d1271d..0f60ec3374 100644 --- a/apps/dav/lib/connector/sabre/principal.php +++ b/apps/dav/lib/connector/sabre/principal.php @@ -46,12 +46,20 @@ class Principal implements BackendInterface { /** @var IGroupManager */ private $groupManager; + /** @var string */ + private $principalPrefix; + /** * @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->groupManager = $groupManager; + $this->principalPrefix = trim($principalPrefix, '/'); } /** @@ -70,7 +78,7 @@ class Principal implements BackendInterface { public function getPrincipalsByPrefix($prefixPath) { $principals = []; - if ($prefixPath === 'principals/users') { + if ($prefixPath === $this->principalPrefix) { foreach($this->userManager->search('') as $user) { $principals[] = $this->userToPrincipal($user); } @@ -88,20 +96,15 @@ class Principal implements BackendInterface { * @return array */ public function getPrincipalByPath($path) { - $elements = explode('/', $path); - if ($elements[0] !== 'principals') { - return null; - } - if ($elements[1] !== 'users') { - return null; - } - $name = $elements[2]; - $user = $this->userManager->get($name); + list($prefix, $name) = URLUtil::splitPath($path); - if (!is_null($user)) { - return $this->userToPrincipal($user); - } + if ($prefix === $this->principalPrefix) { + $user = $this->userManager->get($name); + if (!is_null($user)) { + return $this->userToPrincipal($user); + } + } return null; } @@ -132,7 +135,7 @@ class Principal implements BackendInterface { public function getGroupMembership($principal) { list($prefix, $name) = URLUtil::splitPath($principal); - if ($prefix === 'principals/users') { + if ($prefix === $this->principalPrefix) { $user = $this->userManager->get($name); if (!$user) { throw new Exception('Principal not found'); @@ -141,11 +144,11 @@ class Principal implements BackendInterface { $groups = $this->groupManager->getUserGroups($user); $groups = array_map(function($group) { /** @var IGroup $group */ - return 'principals/groups/' . $group->getGID(); + return $this->principalPrefix . '/' . $group->getGID(); }, $groups); - $groups[]= 'principals/users/'.$name.'/calendar-proxy-read'; - $groups[]= 'principals/users/'.$name.'/calendar-proxy-write'; +// $groups[]= $this->principalPrefix . '/' . $name . '/calendar-proxy-read'; +// $groups[]= $this->principalPrefix . '/' . $name . '/calendar-proxy-write'; return $groups; } return []; @@ -200,7 +203,7 @@ class Principal implements BackendInterface { $userId = $user->getUID(); $displayName = $user->getDisplayName(); $principal = [ - 'uri' => "principals/users/$userId", + 'uri' => $this->principalPrefix . '/' . $userId, '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName, ]; @@ -212,4 +215,8 @@ class Principal implements BackendInterface { return $principal; } + public function getPrincipalPrefix() { + return $this->principalPrefix; + } + } From a67f7ad1f36c0a4a2232e31befaec15cd8a0f0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 20 Jan 2016 21:39:08 +0100 Subject: [PATCH 2/4] Remove calendar-proxy support - did this ever work? --- apps/dav/lib/connector/sabre/principal.php | 2 -- apps/dav/tests/unit/connector/sabre/principal.php | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/dav/lib/connector/sabre/principal.php b/apps/dav/lib/connector/sabre/principal.php index 0f60ec3374..4f26390e3c 100644 --- a/apps/dav/lib/connector/sabre/principal.php +++ b/apps/dav/lib/connector/sabre/principal.php @@ -147,8 +147,6 @@ class Principal implements BackendInterface { return $this->principalPrefix . '/' . $group->getGID(); }, $groups); -// $groups[]= $this->principalPrefix . '/' . $name . '/calendar-proxy-read'; -// $groups[]= $this->principalPrefix . '/' . $name . '/calendar-proxy-write'; return $groups; } return []; diff --git a/apps/dav/tests/unit/connector/sabre/principal.php b/apps/dav/tests/unit/connector/sabre/principal.php index d6bc7cd405..07bfd5d263 100644 --- a/apps/dav/tests/unit/connector/sabre/principal.php +++ b/apps/dav/tests/unit/connector/sabre/principal.php @@ -211,10 +211,7 @@ class Principal extends TestCase { ->method('getUserGroups') ->willReturn([]); - $expectedResponse = [ - 'principals/users/foo/calendar-proxy-read', - 'principals/users/foo/calendar-proxy-write' - ]; + $expectedResponse = []; $response = $this->connector->getGroupMembership('principals/users/foo'); $this->assertSame($expectedResponse, $response); } From 0c9a469f7439be154854fc8933c2be950895fe25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 1 Feb 2016 14:56:31 +0100 Subject: [PATCH 3/4] Adding pre oc 9.0 CalDAV endpoint for migration of old clients --- apps/dav/appinfo/info.xml | 8 +++- apps/dav/appinfo/v1/caldav.php | 69 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 apps/dav/appinfo/v1/caldav.php diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 647ad279ba..fd13ed486b 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -14,9 +14,13 @@ appinfo/v1/webdav.php appinfo/v1/webdav.php appinfo/v2/remote.php - + appinfo/v1/carddav.php - appinfo/v1/carddav.php + appinfo/v1/carddav.php + + appinfo/caldav.php + appinfo/caldav.php + appinfo/v1/publicwebdav.php diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php new file mode 100644 index 0000000000..f860ced387 --- /dev/null +++ b/apps/dav/appinfo/v1/caldav.php @@ -0,0 +1,69 @@ + + * + * @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 + * + */ + +// 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(); From 6a550d44e958a57fc1cc79de0b10e3e6dfb1b194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 5 Feb 2016 14:22:31 +0100 Subject: [PATCH 4/4] Fix path --- apps/dav/appinfo/info.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index fd13ed486b..4f3a93dbf8 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -18,8 +18,8 @@ appinfo/v1/carddav.php appinfo/v1/carddav.php - appinfo/caldav.php - appinfo/caldav.php + appinfo/v1/caldav.php + appinfo/v1/caldav.php appinfo/v1/publicwebdav.php