summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib')
-rw-r--r--apps/dav/lib/AppInfo/PluginManager.php170
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php5
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php5
-rw-r--r--apps/dav/lib/Command/CreateCalendar.php2
-rw-r--r--apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php18
-rw-r--r--apps/dav/lib/DAV/Sharing/Backend.php24
-rw-r--r--apps/dav/lib/RootCollection.php19
-rw-r--r--apps/dav/lib/Server.php16
8 files changed, 237 insertions, 22 deletions
diff --git a/apps/dav/lib/AppInfo/PluginManager.php b/apps/dav/lib/AppInfo/PluginManager.php
new file mode 100644
index 00000000000..9cdf358c80e
--- /dev/null
+++ b/apps/dav/lib/AppInfo/PluginManager.php
@@ -0,0 +1,170 @@
+<?php
+/**
+ * @author Vincent Petry <pvince81@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH.
+ * @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/>
+ *
+ */
+namespace OCA\DAV\AppInfo;
+
+use OCP\App\IAppManager;
+use OC\ServerContainer;
+use OCP\AppFramework\QueryException;
+
+/**
+ * Manager for DAV plugins from apps, used to register them
+ * to the Sabre server.
+ */
+class PluginManager {
+
+ /**
+ * @var ServerContainer
+ */
+ private $container;
+
+ /**
+ * @var IAppManager
+ */
+ private $appManager;
+
+ /**
+ * App plugins
+ *
+ * @var array
+ */
+ private $plugins = null;
+
+ /**
+ * App collections
+ *
+ * @var array
+ */
+ private $collections = null;
+
+ /**
+ * Contstruct a PluginManager
+ *
+ * @param ServerContainer $container server container for resolving plugin classes
+ * @param IAppManager $appManager app manager to loading apps and their info
+ */
+ public function __construct(ServerContainer $container, IAppManager $appManager) {
+ $this->container = $container;
+ $this->appManager = $appManager;
+ }
+
+ /**
+ * Returns an array of app-registered plugins
+ *
+ * @return array
+ */
+ public function getAppPlugins() {
+ if (null === $this->plugins) {
+ $this->populate();
+ }
+ return $this->plugins;
+ }
+
+ /**
+ * Returns an array of app-registered collections
+ *
+ * @return array
+ */
+ public function getAppCollections() {
+ if (null === $this->collections) {
+ $this->populate();
+ }
+ return $this->collections;
+ }
+
+ /**
+ * Retrieve plugin and collection list and populate attributes
+ */
+ private function populate() {
+ $this->plugins = [];
+ $this->collections = [];
+ foreach ($this->appManager->getInstalledApps() as $app) {
+ // load plugins and collections from info.xml
+ $info = $this->appManager->getAppInfo($app);
+ if (!isset($info['types']) || !in_array('dav', $info['types'], true)) {
+ continue;
+ }
+ // FIXME: switch to public API once available
+ // load app to make sure its classes are available
+ \OC_App::loadApp($app);
+ $this->loadSabrePluginsFromInfoXml($this->extractPluginList($info));
+ $this->loadSabreCollectionsFromInfoXml($this->extractCollectionList($info));
+ }
+ }
+
+ private function extractPluginList(array $array) {
+ if (isset($array['sabre']) && is_array($array['sabre'])) {
+ if (isset($array['sabre']['plugins']) && is_array($array['sabre']['plugins'])) {
+ if (isset($array['sabre']['plugins']['plugin'])) {
+ $items = $array['sabre']['plugins']['plugin'];
+ if (!is_array($items)) {
+ $items = [$items];
+ }
+ return $items;
+ }
+ }
+ }
+ return [];
+ }
+
+ private function extractCollectionList(array $array) {
+ if (isset($array['sabre']) && is_array($array['sabre'])) {
+ if (isset($array['sabre']['collections']) && is_array($array['sabre']['collections'])) {
+ if (isset($array['sabre']['collections']['collection'])) {
+ $items = $array['sabre']['collections']['collection'];
+ if (!is_array($items)) {
+ $items = [$items];
+ }
+ return $items;
+ }
+ }
+ }
+ return [];
+ }
+
+ private function loadSabrePluginsFromInfoXml(array $plugins) {
+ foreach ($plugins as $plugin) {
+ try {
+ $this->plugins[] = $this->container->query($plugin);
+ } catch (QueryException $e) {
+ if (class_exists($plugin)) {
+ $this->plugins[] = new $plugin();
+ } else {
+ throw new \Exception("Sabre plugin class '$plugin' is unknown and could not be loaded");
+ }
+ }
+ }
+ }
+
+ private function loadSabreCollectionsFromInfoXml(array $collections) {
+ foreach ($collections as $collection) {
+ try {
+ $this->collections[] = $this->container->query($collection);
+ } catch (QueryException $e) {
+ if (class_exists($collection)) {
+ $this->collections[] = new $collection();
+ } else {
+ throw new \Exception("Sabre collection class '$collection' is unknown and could not be loaded");
+ }
+ }
+ }
+ }
+
+}
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 83ef06f29e1..2c34f6d6d31 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -32,6 +32,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\DAV\Sharing\Backend;
use OCP\IDBConnection;
+use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;
@@ -158,6 +159,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @param IDBConnection $db
* @param Principal $principalBackend
* @param IUserManager $userManager
+ * @param IGroupManager $groupManager
* @param ISecureRandom $random
* @param EventDispatcherInterface $dispatcher
* @param bool $legacyEndpoint
@@ -165,13 +167,14 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public function __construct(IDBConnection $db,
Principal $principalBackend,
IUserManager $userManager,
+ IGroupManager $groupManager,
ISecureRandom $random,
EventDispatcherInterface $dispatcher,
$legacyEndpoint = false) {
$this->db = $db;
$this->principalBackend = $principalBackend;
$this->userManager = $userManager;
- $this->sharingBackend = new Backend($this->db, $principalBackend, 'calendar');
+ $this->sharingBackend = new Backend($this->db, $this->userManager, $groupManager, $principalBackend, 'calendar');
$this->random = $random;
$this->dispatcher = $dispatcher;
$this->legacyEndpoint = $legacyEndpoint;
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index 2e4acad6dfe..7c73a2cb941 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -33,6 +33,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCA\DAV\DAV\Sharing\Backend;
use OCA\DAV\DAV\Sharing\IShareable;
use OCP\IDBConnection;
+use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
use PDO;
@@ -88,17 +89,19 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @param IDBConnection $db
* @param Principal $principalBackend
* @param IUserManager $userManager
+ * @param IGroupManager $groupManager
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(IDBConnection $db,
Principal $principalBackend,
IUserManager $userManager,
+ IGroupManager $groupManager,
EventDispatcherInterface $dispatcher) {
$this->db = $db;
$this->principalBackend = $principalBackend;
$this->userManager = $userManager;
$this->dispatcher = $dispatcher;
- $this->sharingBackend = new Backend($this->db, $principalBackend, 'addressbook');
+ $this->sharingBackend = new Backend($this->db, $this->userManager, $groupManager, $principalBackend, 'addressbook');
}
/**
diff --git a/apps/dav/lib/Command/CreateCalendar.php b/apps/dav/lib/Command/CreateCalendar.php
index 24990352fab..adc86faa190 100644
--- a/apps/dav/lib/Command/CreateCalendar.php
+++ b/apps/dav/lib/Command/CreateCalendar.php
@@ -79,7 +79,7 @@ class CreateCalendar extends Command {
$dispatcher = \OC::$server->getEventDispatcher();
$name = $input->getArgument('name');
- $caldav = new CalDavBackend($this->dbConnection, $principalBackend, $this->userManager, $random, $dispatcher);
+ $caldav = new CalDavBackend($this->dbConnection, $principalBackend, $this->userManager, $this->groupManager, $random, $dispatcher);
$caldav->createCalendar("principals/users/$user", $name, []);
}
}
diff --git a/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php b/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php
index ca2195fc65a..ba7ea13c548 100644
--- a/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php
@@ -27,28 +27,34 @@
namespace OCA\DAV\Connector\Sabre;
+use OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden;
+use OCP\Files\StorageNotAvailableException;
use OCP\ILogger;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\Exception\NotAuthenticated;
+use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\Exception\PreconditionFailed;
use Sabre\DAV\Exception\ServiceUnavailable;
class ExceptionLoggerPlugin extends \Sabre\DAV\ServerPlugin {
protected $nonFatalExceptions = [
- 'Sabre\DAV\Exception\NotAuthenticated' => true,
+ NotAuthenticated::class => true,
// If tokenauth can throw this exception (which is basically as
// NotAuthenticated. So not fatal.
- 'OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden' => true,
+ PasswordLoginForbidden::class => true,
// the sync client uses this to find out whether files exist,
// so it is not always an error, log it as debug
- 'Sabre\DAV\Exception\NotFound' => true,
+ NotFound::class => true,
// this one mostly happens when the same file is uploaded at
// exactly the same time from two clients, only one client
// wins, the second one gets "Precondition failed"
- 'Sabre\DAV\Exception\PreconditionFailed' => true,
+ PreconditionFailed::class => true,
// forbidden can be expected when trying to upload to
// read-only folders for example
- 'Sabre\DAV\Exception\Forbidden' => true,
+ Forbidden::class => true,
// Happens when an external storage or federated share is temporarily
// not available
- 'Sabre\DAV\Exception\StorageNotAvailableException' => true,
+ StorageNotAvailableException::class => true,
];
/** @var string */
diff --git a/apps/dav/lib/DAV/Sharing/Backend.php b/apps/dav/lib/DAV/Sharing/Backend.php
index 6cc5e3b6f50..aa4b137f2b0 100644
--- a/apps/dav/lib/DAV/Sharing/Backend.php
+++ b/apps/dav/lib/DAV/Sharing/Backend.php
@@ -26,11 +26,17 @@ namespace OCA\DAV\DAV\Sharing;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\IUserManager;
class Backend {
/** @var IDBConnection */
private $db;
+ /** @var IUserManager */
+ private $userManager;
+ /** @var IGroupManager */
+ private $groupManager;
/** @var Principal */
private $principalBackend;
/** @var string */
@@ -42,11 +48,15 @@ class Backend {
/**
* @param IDBConnection $db
+ * @param IUserManager $userManager
+ * @param IGroupManager $groupManager
* @param Principal $principalBackend
* @param string $resourceType
*/
- public function __construct(IDBConnection $db, Principal $principalBackend, $resourceType) {
+ public function __construct(IDBConnection $db, IUserManager $userManager, IGroupManager $groupManager, Principal $principalBackend, $resourceType) {
$this->db = $db;
+ $this->userManager = $userManager;
+ $this->groupManager = $groupManager;
$this->principalBackend = $principalBackend;
$this->resourceType = $resourceType;
}
@@ -81,6 +91,18 @@ class Backend {
return;
}
+ $principal = explode('/', $parts[1], 3);
+ if (count($principal) !== 3 || $principal[0] !== 'principals' || !in_array($principal[1], ['users', 'groups'], true)) {
+ // Invalid principal
+ return;
+ }
+
+ if (($principal[1] === 'users' && !$this->userManager->userExists($principal[2])) ||
+ ($principal[1] === 'groups' && !$this->groupManager->groupExists($principal[2]))) {
+ // User or group does not exist
+ return;
+ }
+
// remove the share if it already exists
$this->unshare($shareable, $element['href']);
$access = self::ACCESS_READ;
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index a243ec6d00a..e4ba1f2c02a 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -41,15 +41,14 @@ class RootCollection extends SimpleCollection {
$config = \OC::$server->getConfig();
$random = \OC::$server->getSecureRandom();
$userManager = \OC::$server->getUserManager();
+ $groupManager = \OC::$server->getGroupManager();
$db = \OC::$server->getDatabaseConnection();
$dispatcher = \OC::$server->getEventDispatcher();
$userPrincipalBackend = new Principal(
$userManager,
- \OC::$server->getGroupManager()
- );
- $groupPrincipalBackend = new GroupPrincipalBackend(
- \OC::$server->getGroupManager()
+ $groupManager
);
+ $groupPrincipalBackend = new GroupPrincipalBackend($groupManager);
// as soon as debug mode is enabled we allow listing of principals
$disableListing = !$config->getSystemValue('debug', false);
@@ -62,7 +61,7 @@ class RootCollection extends SimpleCollection {
$systemPrincipals->disableListing = $disableListing;
$filesCollection = new Files\RootCollection($userPrincipalBackend, 'principals/users');
$filesCollection->disableListing = $disableListing;
- $caldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $random, $dispatcher);
+ $caldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $random, $dispatcher);
$calendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users');
$calendarRoot->disableListing = $disableListing;
$publicCalendarRoot = new PublicCalendarRoot($caldavBackend);
@@ -71,28 +70,28 @@ class RootCollection extends SimpleCollection {
$systemTagCollection = new SystemTag\SystemTagsByIdCollection(
\OC::$server->getSystemTagManager(),
\OC::$server->getUserSession(),
- \OC::$server->getGroupManager()
+ $groupManager
);
$systemTagRelationsCollection = new SystemTag\SystemTagsRelationsCollection(
\OC::$server->getSystemTagManager(),
\OC::$server->getSystemTagObjectMapper(),
\OC::$server->getUserSession(),
- \OC::$server->getGroupManager(),
+ $groupManager,
\OC::$server->getEventDispatcher()
);
$commentsCollection = new Comments\RootCollection(
\OC::$server->getCommentsManager(),
- \OC::$server->getUserManager(),
+ $userManager,
\OC::$server->getUserSession(),
\OC::$server->getEventDispatcher(),
\OC::$server->getLogger()
);
- $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, \OC::$server->getUserManager(), $dispatcher);
+ $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher);
$usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, 'principals/users');
$usersAddressBookRoot->disableListing = $disableListing;
- $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, \OC::$server->getUserManager(), $dispatcher);
+ $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher);
$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, 'principals/system');
$systemAddressBookRoot->disableListing = $disableListing;
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index bfb67e2e5fe..719e4974755 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -55,8 +55,8 @@ use OCP\SabrePluginEvent;
use Sabre\CardDAV\VCFExportPlugin;
use Sabre\DAV\Auth\Plugin;
use OCA\DAV\Connector\Sabre\TagsPlugin;
-use Sabre\HTTP\Auth\Bearer;
use SearchDAV\DAV\SearchPlugin;
+use OCA\DAV\AppInfo\PluginManager;
class Server {
@@ -187,7 +187,7 @@ class Server {
}
// wait with registering these until auth is handled and the filesystem is setup
- $this->server->on('beforeMethod', function () {
+ $this->server->on('beforeMethod', function () use ($root) {
// custom properties plugin must be the last one
$userSession = \OC::$server->getUserSession();
$user = $userSession->getUser();
@@ -255,6 +255,18 @@ class Server {
)));
}
}
+
+ // register plugins from apps
+ $pluginManager = new PluginManager(
+ \OC::$server,
+ \OC::$server->getAppManager()
+ );
+ foreach ($pluginManager->getAppPlugins() as $appPlugin) {
+ $this->server->addPlugin($appPlugin);
+ }
+ foreach ($pluginManager->getAppCollections() as $appCollection) {
+ $root->addChild($appCollection);
+ }
});
}