Merge pull request #6512 from coletivoEITA/add_circles_sharing_to_caldav

Change CALDAV to allow calendars be shared with circles.
This commit is contained in:
Morris Jobke 2019-03-13 00:06:46 +01:00 committed by GitHub
commit f0c85a0f5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 114 additions and 8 deletions

View File

@ -47,6 +47,7 @@ $principalBackend = new Principal(
\OC::$server->getShareManager(), \OC::$server->getShareManager(),
\OC::$server->getUserSession(), \OC::$server->getUserSession(),
\OC::$server->getConfig(), \OC::$server->getConfig(),
\OC::$server->getAppManager(),
'principals/' 'principals/'
); );
$db = \OC::$server->getDatabaseConnection(); $db = \OC::$server->getDatabaseConnection();

View File

@ -48,6 +48,7 @@ $principalBackend = new Principal(
\OC::$server->getShareManager(), \OC::$server->getShareManager(),
\OC::$server->getUserSession(), \OC::$server->getUserSession(),
\OC::$server->getConfig(), \OC::$server->getConfig(),
\OC::$server->getAppManager(),
'principals/' 'principals/'
); );
$db = \OC::$server->getDatabaseConnection(); $db = \OC::$server->getDatabaseConnection();

View File

@ -12,6 +12,8 @@
* @author Stefan Weil <sw@weilnetz.de> * @author Stefan Weil <sw@weilnetz.de>
* @author Thomas Citharel <tcit@tcit.fr> * @author Thomas Citharel <tcit@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu> * @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vinicius Cubas Brand <vinicius@eita.org.br>
* @author Daniel Tygel <dtygel@eita.org.br>
* *
* @license AGPL-3.0 * @license AGPL-3.0
* *
@ -301,6 +303,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
// query for shared calendars // query for shared calendars
$principals = $this->principalBackend->getGroupMembership($principalUriOriginal, true); $principals = $this->principalBackend->getGroupMembership($principalUriOriginal, true);
$principals = array_merge($principals, $this->principalBackend->getCircleMembership($principalUriOriginal));
$principals = array_map(function($principal) { $principals = array_map(function($principal) {
return urldecode($principal); return urldecode($principal);
}, $principals); }, $principals);

View File

@ -167,8 +167,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
} }
$result->closeCursor(); $result->closeCursor();
// query for shared calendars // query for shared addressbooks
$principals = $this->principalBackend->getGroupMembership($principalUriOriginal, true); $principals = $this->principalBackend->getGroupMembership($principalUriOriginal, true);
$principals = array_merge($principals, $this->principalBackend->getCircleMembership($principalUriOriginal));
$principals = array_map(function($principal) { $principals = array_map(function($principal) {
return urldecode($principal); return urldecode($principal);
}, $principals); }, $principals);

View File

@ -78,7 +78,8 @@ class CreateCalendar extends Command {
$this->groupManager, $this->groupManager,
\OC::$server->getShareManager(), \OC::$server->getShareManager(),
\OC::$server->getUserSession(), \OC::$server->getUserSession(),
\OC::$server->getConfig() \OC::$server->getConfig(),
\OC::$server->getAppManager()
); );
$random = \OC::$server->getSecureRandom(); $random = \OC::$server->getSecureRandom();
$logger = \OC::$server->getLogger(); $logger = \OC::$server->getLogger();

View File

@ -13,6 +13,8 @@
* @author Thomas Tanghus <thomas@tanghus.net> * @author Thomas Tanghus <thomas@tanghus.net>
* @author Vincent Petry <pvince81@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com>
* @author Georg Ehrke <oc.list@georgehrke.com> * @author Georg Ehrke <oc.list@georgehrke.com>
* @author Vinicius Cubas Brand <vinicius@eita.org.br>
* @author Daniel Tygel <dtygel@eita.org.br>
* *
* @license AGPL-3.0 * @license AGPL-3.0
* *
@ -32,6 +34,9 @@
namespace OCA\DAV\Connector\Sabre; namespace OCA\DAV\Connector\Sabre;
use OCA\Circles\Exceptions\CircleDoesNotExistException;
use OCP\App\IAppManager;
use OCP\AppFramework\QueryException;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroup; use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
@ -60,12 +65,18 @@ class Principal implements BackendInterface {
/** @var IConfig */ /** @var IConfig */
private $config; private $config;
/** @var IAppManager */
private $appManager;
/** @var string */ /** @var string */
private $principalPrefix; private $principalPrefix;
/** @var bool */ /** @var bool */
private $hasGroups; private $hasGroups;
/** @var bool */
private $hasCircles;
/** /**
* @param IUserManager $userManager * @param IUserManager $userManager
* @param IGroupManager $groupManager * @param IGroupManager $groupManager
@ -79,14 +90,16 @@ class Principal implements BackendInterface {
IShareManager $shareManager, IShareManager $shareManager,
IUserSession $userSession, IUserSession $userSession,
IConfig $config, IConfig $config,
IAppManager $appManager,
$principalPrefix = 'principals/users/') { $principalPrefix = 'principals/users/') {
$this->userManager = $userManager; $this->userManager = $userManager;
$this->groupManager = $groupManager; $this->groupManager = $groupManager;
$this->shareManager = $shareManager; $this->shareManager = $shareManager;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->config = $config; $this->config = $config;
$this->appManager = $appManager;
$this->principalPrefix = trim($principalPrefix, '/'); $this->principalPrefix = trim($principalPrefix, '/');
$this->hasGroups = ($principalPrefix === 'principals/users/'); $this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
} }
/** /**
@ -131,6 +144,8 @@ class Principal implements BackendInterface {
if ($user !== null) { if ($user !== null) {
return $this->userToPrincipal($user); return $this->userToPrincipal($user);
} }
} else if ($prefix === 'principals/circles') {
return $this->circleToPrincipal($name);
} }
return null; return null;
} }
@ -388,4 +403,69 @@ class Principal implements BackendInterface {
return $this->principalPrefix; return $this->principalPrefix;
} }
/**
* @param string $circleUniqueId
* @return array|null
* @suppress PhanUndeclaredClassMethod
* @suppress PhanUndeclaredClassCatch
*/
protected function circleToPrincipal($circleUniqueId) {
if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
return null;
}
try {
$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
} catch(QueryException $ex) {
return null;
} catch(CircleDoesNotExistException $ex) {
return null;
}
if (!$circle) {
return null;
}
$principal = [
'uri' => 'principals/circles/' . $circleUniqueId,
'{DAV:}displayname' => $circle->getName(),
];
return $principal;
}
/**
* Returns the list of circles a principal is a member of
*
* @param string $principal
* @param bool $needGroups
* @return array
* @throws Exception
* @suppress PhanUndeclaredClassMethod
*/
public function getCircleMembership($principal):array {
if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
return [];
}
list($prefix, $name) = \Sabre\Uri\split($principal);
if ($this->hasCircles && $prefix === $this->principalPrefix) {
$user = $this->userManager->get($name);
if (!$user) {
throw new Exception('Principal not found');
}
$circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
$circles = array_map(function($circle) {
/** @var \OCA\Circles\Model\Circle $group */
return 'principals/circles/' . urlencode($circle->getUniqueId());
}, $circles);
return $circles;
}
return [];
}
} }

View File

@ -7,6 +7,8 @@
* @author Robin Appelman <robin@icewind.nl> * @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl> * @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Vincent Petry <pvince81@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com>
* @author Vinicius Cubas Brand <vinicius@eita.org.br>
* @author Daniel Tygel <dtygel@eita.org.br>
* *
* @license AGPL-3.0 * @license AGPL-3.0
* *
@ -125,6 +127,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
\OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_REMOTE,
\OCP\Share::SHARE_TYPE_EMAIL, \OCP\Share::SHARE_TYPE_EMAIL,
\OCP\Share::SHARE_TYPE_ROOM, \OCP\Share::SHARE_TYPE_ROOM,
\OCP\Share::SHARE_TYPE_CIRCLE,
]; ];
foreach ($requestedShareTypes as $requestedShareType) { foreach ($requestedShareTypes as $requestedShareType) {
// one of each type is enough to find out about the types // one of each type is enough to find out about the types

View File

@ -99,7 +99,7 @@ class Backend {
} }
$principal = explode('/', $parts[1], 3); $principal = explode('/', $parts[1], 3);
if (count($principal) !== 3 || $principal[0] !== 'principals' || !in_array($principal[1], ['users', 'groups'], true)) { if (count($principal) !== 3 || $principal[0] !== 'principals' || !in_array($principal[1], ['users', 'groups', 'circles'], true)) {
// Invalid principal // Invalid principal
return; return;
} }

View File

@ -58,7 +58,8 @@ class RootCollection extends SimpleCollection {
$groupManager, $groupManager,
$shareManager, $shareManager,
\OC::$server->getUserSession(), \OC::$server->getUserSession(),
$config $config,
\OC::$server->getAppManager()
); );
$groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager, $l10n); $groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager, $l10n);
$calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager, $logger); $calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager, $logger);

View File

@ -27,6 +27,7 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Connector\Sabre\Principal; use OCA\DAV\Connector\Sabre\Principal;
use OCP\App\IAppManager;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\ILogger; use OCP\ILogger;
@ -83,6 +84,7 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->createMock(ShareManager::class), $this->createMock(ShareManager::class),
$this->createMock(IUserSession::class), $this->createMock(IUserSession::class),
$this->createMock(IConfig::class), $this->createMock(IConfig::class),
$this->createMock(IAppManager::class),
]) ])
->setMethods(['getPrincipalByPath', 'getGroupMembership']) ->setMethods(['getPrincipalByPath', 'getGroupMembership'])
->getMock(); ->getMock();

View File

@ -35,6 +35,7 @@ use InvalidArgumentException;
use OCA\DAV\CardDAV\AddressBook; use OCA\DAV\CardDAV\AddressBook;
use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Connector\Sabre\Principal; use OCA\DAV\Connector\Sabre\Principal;
use OCP\App\IAppManager;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig; use OCP\IConfig;
use OCP\IDBConnection; use OCP\IDBConnection;
@ -131,6 +132,7 @@ class CardDavBackendTest extends TestCase {
$this->createMock(ShareManager::class), $this->createMock(ShareManager::class),
$this->createMock(IUserSession::class), $this->createMock(IUserSession::class),
$this->createMock(IConfig::class), $this->createMock(IConfig::class),
$this->createMock(IAppManager::class),
]) ])
->setMethods(['getPrincipalByPath', 'getGroupMembership']) ->setMethods(['getPrincipalByPath', 'getGroupMembership'])
->getMock(); ->getMock();

View File

@ -29,6 +29,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre; namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\User\User; use OC\User\User;
use OCP\App\IAppManager;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroup; use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
@ -59,19 +60,25 @@ class PrincipalTest extends TestCase {
/** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
private $config; private $config;
/** @var IAppManager | \PHPUnit_Framework_MockObject_MockObject */
private $appManager;
public function setUp() { public function setUp() {
$this->userManager = $this->createMock(IUserManager::class); $this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class); $this->groupManager = $this->createMock(IGroupManager::class);
$this->shareManager = $this->createMock(IManager::class); $this->shareManager = $this->createMock(IManager::class);
$this->userSession = $this->createMock(IUserSession::class); $this->userSession = $this->createMock(IUserSession::class);
$this->config = $this->createMock(IConfig::class); $this->config = $this->createMock(IConfig::class);
$this->appManager = $this->createMock(IAppManager::class);
$this->connector = new \OCA\DAV\Connector\Sabre\Principal( $this->connector = new \OCA\DAV\Connector\Sabre\Principal(
$this->userManager, $this->userManager,
$this->groupManager, $this->groupManager,
$this->shareManager, $this->shareManager,
$this->userSession, $this->userSession,
$this->config); $this->config,
$this->appManager
);
parent::setUp(); parent::setUp();
} }

View File

@ -61,7 +61,8 @@ class Application extends App {
\OC::$server->getGroupManager(), \OC::$server->getGroupManager(),
\OC::$server->getShareManager(), \OC::$server->getShareManager(),
\OC::$server->getUserSession(), \OC::$server->getUserSession(),
\OC::$server->getConfig() \OC::$server->getConfig(),
\OC::$server->getAppManager()
); );
}); });

View File

@ -51,7 +51,8 @@ class Application extends App {
$server->getGroupManager(), $server->getGroupManager(),
$server->getShareManager(), $server->getShareManager(),
$server->getUserSession(), $server->getUserSession(),
$server->getConfig() $server->getConfig(),
$server->getAppManager()
); );
}); });