From 2da510af0b537e3bef7d0563eff828bade51fcbd Mon Sep 17 00:00:00 2001 From: Georg Ehrke Date: Mon, 28 May 2018 20:12:13 +0200 Subject: [PATCH] add resource / room principals Signed-off-by: Georg Ehrke --- apps/dav/appinfo/info.xml | 2 +- .../composer/composer/autoload_classmap.php | 4 + .../dav/composer/composer/autoload_static.php | 4 + apps/dav/lib/CalDAV/CalDavBackend.php | 3 + apps/dav/lib/CalDAV/CalendarRoot.php | 11 + apps/dav/lib/CalDAV/Plugin.php | 18 +- .../AbstractPrincipalBackend.php | 299 ++++++++++++++++++ .../ResourcePrincipalBackend.php | 42 +++ .../ResourceBooking/RoomPrincipalBackend.php | 42 +++ apps/dav/lib/CalDAV/Schedule/Plugin.php | 22 +- .../Version1005Date20180530124431.php | 87 +++++ apps/dav/lib/RootCollection.php | 33 +- apps/dav/lib/Server.php | 6 +- 13 files changed, 559 insertions(+), 14 deletions(-) create mode 100644 apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php create mode 100644 apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php create mode 100644 apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php create mode 100644 apps/dav/lib/Migration/Version1005Date20180530124431.php diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 2dcb986c84..96452493f9 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ WebDAV WebDAV endpoint WebDAV endpoint - 1.5.3 + 1.5.4 agpl owncloud.org DAV diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index e9736f26a5..fab91d1729 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -40,6 +40,9 @@ return array( 'OCA\\DAV\\CalDAV\\PublicCalendarRoot' => $baseDir . '/../lib/CalDAV/PublicCalendarRoot.php', 'OCA\\DAV\\CalDAV\\Publishing\\PublishPlugin' => $baseDir . '/../lib/CalDAV/Publishing/PublishPlugin.php', 'OCA\\DAV\\CalDAV\\Publishing\\Xml\\Publisher' => $baseDir . '/../lib/CalDAV/Publishing/Xml/Publisher.php', + 'OCA\\DAV\\CalDAV\\ResourceBooking\\AbstractPrincipalBackend' => $baseDir . '/../lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php', + 'OCA\\DAV\\CalDAV\\ResourceBooking\\ResourcePrincipalBackend' => $baseDir . '/../lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php', + 'OCA\\DAV\\CalDAV\\ResourceBooking\\RoomPrincipalBackend' => $baseDir . '/../lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php', 'OCA\\DAV\\CalDAV\\Schedule\\IMipPlugin' => $baseDir . '/../lib/CalDAV/Schedule/IMipPlugin.php', 'OCA\\DAV\\CalDAV\\Schedule\\Plugin' => $baseDir . '/../lib/CalDAV/Schedule/Plugin.php', 'OCA\\DAV\\CalDAV\\Search\\SearchPlugin' => $baseDir . '/../lib/CalDAV/Search/SearchPlugin.php', @@ -144,6 +147,7 @@ return array( 'OCA\\DAV\\Migration\\Version1004Date20170924124212' => $baseDir . '/../lib/Migration/Version1004Date20170924124212.php', 'OCA\\DAV\\Migration\\Version1004Date20170926103422' => $baseDir . '/../lib/Migration/Version1004Date20170926103422.php', 'OCA\\DAV\\Migration\\Version1005Date20180413093149' => $baseDir . '/../lib/Migration/Version1005Date20180413093149.php', + 'OCA\\DAV\\Migration\\Version1005Date20180530124431' => $baseDir . '/../lib/Migration/Version1005Date20180530124431.php', 'OCA\\DAV\\RootCollection' => $baseDir . '/../lib/RootCollection.php', 'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index b8b0411f18..ab714227fb 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -55,6 +55,9 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CalDAV\\PublicCalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/PublicCalendarRoot.php', 'OCA\\DAV\\CalDAV\\Publishing\\PublishPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/Publishing/PublishPlugin.php', 'OCA\\DAV\\CalDAV\\Publishing\\Xml\\Publisher' => __DIR__ . '/..' . '/../lib/CalDAV/Publishing/Xml/Publisher.php', + 'OCA\\DAV\\CalDAV\\ResourceBooking\\AbstractPrincipalBackend' => __DIR__ . '/..' . '/../lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php', + 'OCA\\DAV\\CalDAV\\ResourceBooking\\ResourcePrincipalBackend' => __DIR__ . '/..' . '/../lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php', + 'OCA\\DAV\\CalDAV\\ResourceBooking\\RoomPrincipalBackend' => __DIR__ . '/..' . '/../lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php', 'OCA\\DAV\\CalDAV\\Schedule\\IMipPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/Schedule/IMipPlugin.php', 'OCA\\DAV\\CalDAV\\Schedule\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Schedule/Plugin.php', 'OCA\\DAV\\CalDAV\\Search\\SearchPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/Search/SearchPlugin.php', @@ -159,6 +162,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Migration\\Version1004Date20170924124212' => __DIR__ . '/..' . '/../lib/Migration/Version1004Date20170924124212.php', 'OCA\\DAV\\Migration\\Version1004Date20170926103422' => __DIR__ . '/..' . '/../lib/Migration/Version1004Date20170926103422.php', 'OCA\\DAV\\Migration\\Version1005Date20180413093149' => __DIR__ . '/..' . '/../lib/Migration/Version1005Date20180413093149.php', + 'OCA\\DAV\\Migration\\Version1005Date20180530124431' => __DIR__ . '/..' . '/../lib/Migration/Version1005Date20180530124431.php', 'OCA\\DAV\\RootCollection' => __DIR__ . '/..' . '/../lib/RootCollection.php', 'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php', diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index b28c8534aa..de46dfeb24 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -76,6 +76,9 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription const PERSONAL_CALENDAR_URI = 'personal'; const PERSONAL_CALENDAR_NAME = 'Personal'; + const RESOURCE_BOOKING_CALENDAR_URI = 'calendar'; + const RESOURCE_BOOKING_CALENDAR_NAME = 'Calendar'; + /** * We need to specify a max date, because we need to stop *somewhere* * diff --git a/apps/dav/lib/CalDAV/CalendarRoot.php b/apps/dav/lib/CalDAV/CalendarRoot.php index 2c1c8bb4ef..f84e8a9678 100644 --- a/apps/dav/lib/CalDAV/CalendarRoot.php +++ b/apps/dav/lib/CalDAV/CalendarRoot.php @@ -27,4 +27,15 @@ class CalendarRoot extends \Sabre\CalDAV\CalendarRoot { function getChildForPrincipal(array $principal) { return new CalendarHome($this->caldavBackend, $principal); } + + function getName() { + if ($this->principalPrefix === 'principals/calendar-resources' || + $this->principalPrefix === 'principals/calendar-rooms') { + $parts = explode('/', $this->principalPrefix); + + return $parts[1]; + } + + return parent::getName(); + } } \ No newline at end of file diff --git a/apps/dav/lib/CalDAV/Plugin.php b/apps/dav/lib/CalDAV/Plugin.php index 4aa9762899..b9ec8241fa 100644 --- a/apps/dav/lib/CalDAV/Plugin.php +++ b/apps/dav/lib/CalDAV/Plugin.php @@ -25,15 +25,29 @@ namespace OCA\DAV\CalDAV; class Plugin extends \Sabre\CalDAV\Plugin { + const SYSTEM_CALENDAR_ROOT = 'system-calendars'; + /** * @inheritdoc */ - function getCalendarHomeForPrincipal($principalUrl) { + function getCalendarHomeForPrincipal($principalUrl):string { + + //TODO - debug this if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) { list(, $principalId) = \Sabre\Uri\split($principalUrl); - return self::CALENDAR_ROOT .'/' . $principalId; + return self::CALENDAR_ROOT . '/' . $principalId; } + if (strrpos($principalUrl, 'principals/calendar-resources', -strlen($principalUrl)) !== false) { + list(, $principalId) = \Sabre\Uri\split($principalUrl); + return self::SYSTEM_CALENDAR_ROOT . '/calendar-resources/' . $principalId; + } + if (strrpos($principalUrl, 'principals/calendar-rooms', -strlen($principalUrl)) !== false) { + list(, $principalId) = \Sabre\Uri\split($principalUrl); + return self::SYSTEM_CALENDAR_ROOT . '/calendar-rooms/' . $principalId; + } + + throw new \LogicException('This is not supposed to happen'); } } diff --git a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php new file mode 100644 index 0000000000..0b3b9cda14 --- /dev/null +++ b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php @@ -0,0 +1,299 @@ + + * + * @author Georg Ehrke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCA\DAV\CalDAV\ResourceBooking; + +use OCP\IDBConnection; +use OCP\IGroupManager; +use OCP\IUserSession; +use Sabre\DAVACL\PrincipalBackend\BackendInterface; +use Sabre\DAV\Exception; +use \Sabre\DAV\PropPatch; + +abstract class AbstractPrincipalBackend implements BackendInterface { + + /** @var IDBConnection */ + private $db; + + /** @var IUserSession */ + private $userSession; + + /** @var IGroupManager */ + private $groupManager; + + /** @var string */ + private $principalPrefix; + + /** @var string */ + private $dbTableName; + + /** + * @param IDBConnection $dbConnection + * @param IUserSession $userSession + * @param IGroupManager $groupManager + * @param string $principalPrefix + * @param string $dbPrefix + */ + public function __construct(IDBConnection $dbConnection, + IUserSession $userSession, + IGroupManager $groupManager, + $principalPrefix, $dbPrefix) { + $this->db = $dbConnection; + $this->userSession = $userSession; + $this->groupManager = $groupManager; + $this->principalPrefix = $principalPrefix; + $this->dbTableName = 'calendar_' . $dbPrefix . '_cache'; + } + + /** + * Returns a list of principals based on a prefix. + * + * This prefix will often contain something like 'principals'. You are only + * expected to return principals that are in this base path. + * + * You are expected to return at least a 'uri' for every user, you can + * return any additional properties if you wish so. Common properties are: + * {DAV:}displayname + * + * @param string $prefixPath + * @return string[] + */ + public function getPrincipalsByPrefix($prefixPath) { + $principals = []; + + if ($prefixPath === $this->principalPrefix) { + $query = $this->db->getQueryBuilder(); + $query->select(['backend_id', 'resource_id', 'email', 'displayname']) + ->from($this->dbTableName); + $stmt = $query->execute(); + + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + $principals[] = $this->rowToPrincipal($row); + } + + $stmt->closeCursor(); + } + + return $principals; + } + + /** + * Returns a specific principal, specified by it's path. + * The returned structure should be the exact same as from + * getPrincipalsByPrefix. + * + * @param string $path + * @return array + */ + public function getPrincipalByPath($path) { + if (strpos($path, $this->principalPrefix) !== 0) { + return null; + } + list(, $name) = \Sabre\Uri\split($path); + + list($backendId, $resourceId) = explode('-', $name, 2); + + $query = $this->db->getQueryBuilder(); + $query->select(['backend_id', 'resource_id', 'email', 'displayname']) + ->from($this->dbTableName) + ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId))) + ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId))); + $stmt = $query->execute(); + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + + if(!$row) { + return null; + } + + return $this->rowToPrincipal($row); + } + + /** + * Returns the list of members for a group-principal + * + * @param string $principal + * @return string[] + * @throws Exception + */ + public function getGroupMemberSet($principal) { + return []; + } + + /** + * Returns the list of groups a principal is a member of + * + * @param string $principal + * @return array + * @throws Exception + */ + public function getGroupMembership($principal) { + return []; + } + + /** + * Updates the list of group members for a group principal. + * + * The principals should be passed as a list of uri's. + * + * @param string $principal + * @param string[] $members + * @throws Exception + */ + public function setGroupMemberSet($principal, array $members) { + throw new Exception('Setting members of the group is not supported yet'); + } + + /** + * @param string $path + * @param PropPatch $propPatch + * @return int + */ + function updatePrincipal($path, PropPatch $propPatch) { + return 0; + } + + /** + * @param string $prefixPath + * @param array $searchProperties + * @param string $test + * @return array + */ + function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') { + $results = []; + if (\count($searchProperties) === 0) { + return []; + } + if ($prefixPath !== $this->principalPrefix) { + return []; + } + + $user = $this->userSession->getUser(); + if (!$user) { + return null; + } + $usersGroups = $this->groupManager->getUserGroupIds($user); + + foreach ($searchProperties as $prop => $value) { + switch ($prop) { + case '{http://sabredav.org/ns}email-address': + $query = $this->db->getQueryBuilder(); + $query->select(['backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions']) + ->from($this->dbTableName) + ->where($query->expr()->eq('email', $query->createNamedParameter($value))); + + $stmt = $query->execute(); + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + // TODO - check for group restrictions + $results[] = $this->rowToPrincipal($row)['uri']; + } + + $stmt->closeCursor(); + break; + + case '{DAV:}displayname': + $query = $this->db->getQueryBuilder(); + $query->select(['backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions']) + ->from($this->dbTableName) + ->where($query->expr()->eq('displayname', $query->createNamedParameter($value))); + + $stmt = $query->execute(); + while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + // TODO - check for group restrictions + $results[] = $this->rowToPrincipal($row)['uri']; + } + + $stmt->closeCursor(); + break; + + default: + $results[] = []; + break; + } + } + + // results is an array of arrays, so this is not the first search result + // but the results of the first searchProperty + if (count($results) === 1) { + return $results; + } + + switch ($test) { + case 'anyof': + return array_unique(array_merge(...$results)); + + case 'allof': + default: + return array_intersect(...$results); + } + } + + /** + * @param string $uri + * @param string $principalPrefix + * @return null|string + */ + function findByUri($uri, $principalPrefix) { + $user = $this->userSession->getUser(); + if (!$user) { + return null; + } + $usersGroups = $this->groupManager->getUserGroupIds($user); + + if (strpos($uri, 'mailto:') === 0) { + $email = substr($uri, 7); + $query = $this->db->getQueryBuilder(); + $query->select(['backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions']) + ->from($this->dbTableName) + ->where($query->expr()->eq('email', $query->createNamedParameter($email))); + + $stmt = $query->execute(); + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + + if(!$row) { + return null; + } + + return $this->rowToPrincipal($row)['uri']; + } + if (strpos($uri, 'principal:') === 0) { + $principal = substr($uri, 10); + $principal = $this->getPrincipalByPath($principal); + + if ($principal !== null) { + return $principal['uri']; + } + } + + return null; + } + + /** + * convert database row to principal + */ + private function rowToPrincipal($row) { + return [ + 'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'], + '{DAV:}displayname' => $row['displayname'], + '{http://sabredav.org/ns}email-address' => $row['email'] + ]; + } +} diff --git a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php new file mode 100644 index 0000000000..053be5dae3 --- /dev/null +++ b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php @@ -0,0 +1,42 @@ + + * + * @author Georg Ehrke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCA\DAV\CalDAV\ResourceBooking; + +use OCP\IDBConnection; +use OCP\IGroupManager; +use OCP\IUserSession; + +class ResourcePrincipalBackend extends AbstractPrincipalBackend { + + /** + * @param IDBConnection $dbConnection + * @param IUserSession $userSession + * @param IGroupManager $groupManager + */ + public function __construct(IDBConnection $dbConnection, + IUserSession $userSession, + IGroupManager $groupManager) { + parent::__construct($dbConnection, $userSession, $groupManager, + 'principals/calendar-resources', 'resources'); + } +} diff --git a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php new file mode 100644 index 0000000000..0052ee9e62 --- /dev/null +++ b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php @@ -0,0 +1,42 @@ + + * + * @author Georg Ehrke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCA\DAV\CalDAV\ResourceBooking; + +use OCP\IDBConnection; +use OCP\IGroupManager; +use OCP\IUserSession; + +class RoomPrincipalBackend extends AbstractPrincipalBackend { + + /** + * @param IDBConnection $dbConnection + * @param IUserSession $userSession + * @param IGroupManager $groupManager + */ + public function __construct(IDBConnection $dbConnection, + IUserSession $userSession, + IGroupManager $groupManager) { + parent::__construct($dbConnection, $userSession, $groupManager, + 'principals/calendar-rooms', 'rooms'); + } +} diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php index faf495a4de..b3f7232c2f 100644 --- a/apps/dav/lib/CalDAV/Schedule/Plugin.php +++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php @@ -80,20 +80,32 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { $principalUrl = $node->getPrincipalUrl(); $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl); - if (!$calendarHomePath) { return null; } + if (strpos($principalUrl, 'principals/users') === 0) { + $uri = CalDavBackend::PERSONAL_CALENDAR_URI; + $displayname = CalDavBackend::PERSONAL_CALENDAR_NAME; + } elseif (strpos($principalUrl, 'principals/calendar-resources') === 0 || + strpos($principalUrl, 'principals/calendar-rooms') === 0) { + $uri = CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI; + $displayname = CalDavBackend::RESOURCE_BOOKING_CALENDAR_NAME; + } else { + // How did we end up here? + // TODO - throw exception or just ignore? + return null; + } + /** @var CalendarHome $calendarHome */ $calendarHome = $this->server->tree->getNodeForPath($calendarHomePath); - if (!$calendarHome->childExists(CalDavBackend::PERSONAL_CALENDAR_URI)) { - $calendarHome->getCalDAVBackend()->createCalendar($principalUrl, CalDavBackend::PERSONAL_CALENDAR_URI, [ - '{DAV:}displayname' => CalDavBackend::PERSONAL_CALENDAR_NAME, + if (!$calendarHome->childExists($uri)) { + $calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [ + '{DAV:}displayname' => $displayname, ]); } - $result = $this->server->getPropertiesForPath($calendarHomePath . '/' . CalDavBackend::PERSONAL_CALENDAR_URI, [], 1); + $result = $this->server->getPropertiesForPath($calendarHomePath . '/' . $uri, [], 1); if (empty($result)) { return null; } diff --git a/apps/dav/lib/Migration/Version1005Date20180530124431.php b/apps/dav/lib/Migration/Version1005Date20180530124431.php new file mode 100644 index 0000000000..ae9a40dc5b --- /dev/null +++ b/apps/dav/lib/Migration/Version1005Date20180530124431.php @@ -0,0 +1,87 @@ + + * + * @author Georg Ehrke + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCA\DAV\Migration; + +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +/** + * Auto-generated migration step: Please modify to your needs! + */ +class Version1005Date20180530124431 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + * @since 13.0.0 + */ + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $types = ['resources', 'rooms']; + foreach($types as $type) { + if (!$schema->hasTable('calendar_' . $type . '_cache')) { + $table = $schema->createTable('calendar_' . $type . '_cache'); + + $table->addColumn('id', Type::BIGINT, [ + 'autoincrement' => true, + 'notnull' => true, + 'length' => 11, + 'unsigned' => true, + ]); + $table->addColumn('backend_id', Type::STRING, [ + 'notnull' => false, + 'length' => 64, + ]); + $table->addColumn('resource_id', Type::STRING, [ + 'notnull' => false, + 'length' => 64, + ]); + $table->addColumn('email', Type::STRING, [ + 'notnull' => false, + 'length' => 255, + ]); + $table->addColumn('displayname', Type::STRING, [ + 'notnull' => false, + 'length' => 255, + ]); + $table->addColumn('group_restrictions', Type::STRING, [ + 'notnull' => false, + 'length' => 4000, + ]); + + $table->setPrimaryKey(['id'], 'calendar_' . $type . '_cache_id_idx'); + $table->addIndex(['backend_id', 'resource_id'], 'calendar_' . $type . '_cache_backendresource_idx'); + $table->addIndex(['email'], 'calendar_' . $type . '_cache_email_idx'); + $table->addIndex(['displayname'], 'calendar_' . $type . '_cache_displayname_idx'); + } + } + + return $schema; + } +} diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php index b9f381b4b9..787e869770 100644 --- a/apps/dav/lib/RootCollection.php +++ b/apps/dav/lib/RootCollection.php @@ -27,6 +27,8 @@ namespace OCA\DAV; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\CalendarRoot; use OCA\DAV\CalDAV\PublicCalendarRoot; +use OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend; +use OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend; use OCA\DAV\CardDAV\AddressBookRoot; use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\Connector\Sabre\Principal; @@ -43,6 +45,7 @@ class RootCollection extends SimpleCollection { $random = \OC::$server->getSecureRandom(); $logger = \OC::$server->getLogger(); $userManager = \OC::$server->getUserManager(); + $userSession = \OC::$server->getUserSession(); $groupManager = \OC::$server->getGroupManager(); $shareManager = \OC::$server->getShareManager(); $db = \OC::$server->getDatabaseConnection(); @@ -55,6 +58,8 @@ class RootCollection extends SimpleCollection { $config ); $groupPrincipalBackend = new GroupPrincipalBackend($groupManager); + $calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager); + $calendarRoomPrincipalBackend = new RoomPrincipalBackend($db, $userSession, $groupManager); // as soon as debug mode is enabled we allow listing of principals $disableListing = !$config->getSystemValue('debug', false); @@ -65,11 +70,25 @@ class RootCollection extends SimpleCollection { $groupPrincipals->disableListing = $disableListing; $systemPrincipals = new Collection(new SystemPrincipalBackend(), 'principals/system'); $systemPrincipals->disableListing = $disableListing; + $calendarResourcePrincipals = new Collection($calendarResourcePrincipalBackend, 'principals/calendar-resources'); + $calendarResourcePrincipals->disableListing = $disableListing; + $calendarRoomPrincipals = new Collection($calendarRoomPrincipalBackend, 'principals/calendar-rooms'); + $calendarRoomPrincipals->disableListing = $disableListing; + + $filesCollection = new Files\RootCollection($userPrincipalBackend, 'principals/users'); $filesCollection->disableListing = $disableListing; $caldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $random, $logger, $dispatcher); - $calendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users'); - $calendarRoot->disableListing = $disableListing; + $userCalendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users'); + $userCalendarRoot->disableListing = $disableListing; + + $resourceCalendarCaldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $random, $logger, $dispatcher); + $resourceCalendarRoot = new CalendarRoot($calendarResourcePrincipalBackend, $caldavBackend, 'principals/calendar-resources'); + $resourceCalendarRoot->disableListing = $disableListing; + $roomCalendarCaldavBackend = new CalDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $random, $logger, $dispatcher); + $roomCalendarRoot = new CalendarRoot($calendarRoomPrincipalBackend, $roomCalendarCaldavBackend, 'principals/calendar-rooms'); + $roomCalendarRoot->disableListing = $disableListing; + $publicCalendarRoot = new PublicCalendarRoot($caldavBackend, $l10n, $config); $publicCalendarRoot->disableListing = $disableListing; @@ -111,9 +130,15 @@ class RootCollection extends SimpleCollection { new SimpleCollection('principals', [ $userPrincipals, $groupPrincipals, - $systemPrincipals]), + $systemPrincipals, + $calendarResourcePrincipals, + $calendarRoomPrincipals]), $filesCollection, - $calendarRoot, + $userCalendarRoot, + new SimpleCollection('system-calendars', [ + $resourceCalendarRoot, + $roomCalendarRoot, + ]), $publicCalendarRoot, new SimpleCollection('addressbooks', [ $usersAddressBookRoot, diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index a401fb5704..231ab91319 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -132,13 +132,15 @@ class Server { // acl $acl = new DavAclPlugin(); $acl->principalCollectionSet = [ - 'principals/users', 'principals/groups' + 'principals/users', 'principals/groups', + 'principals/calendar-resources', + 'principals/calendar-rooms', ]; $acl->defaultUsernamePath = 'principals/users'; $this->server->addPlugin($acl); // calendar plugins - if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'principals'])) { + if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'system-calendars', 'principals'])) { $this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());