diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index df10b62fc5b64..d00962ac20adb 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -12,6 +12,9 @@ * @author Stefan Weil * @author Thomas Citharel * @author Thomas Müller + * @author Georg Ehrke + * @author Vinicius Cubas Brand + * @author Daniel Tygel * * @license AGPL-3.0 * @@ -298,6 +301,8 @@ function getCalendarsForUser($principalUri) { // query for shared calendars $principals = $this->principalBackend->getGroupMembership($principalUriOriginal, true); + $principals = array_merge($principals, $this->principalBackend->getCircleMembership($principalUriOriginal)); + $principals = array_map(function($principal) { return urldecode($principal); }, $principals); diff --git a/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php b/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php index 3e85615638b5c..5a4833398bda7 100644 --- a/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php @@ -46,6 +46,7 @@ class FilesReportPlugin extends ServerPlugin { const NS_OWNCLOUD = 'http://owncloud.org/ns'; const REPORT_NAME = '{http://owncloud.org/ns}filter-files'; const SYSTEMTAG_PROPERTYNAME = '{http://owncloud.org/ns}systemtag'; + const CIRCLE_PROPERTYNAME = '{http://nextcloud.com/ns}circle'; /** * Reference to main server object @@ -256,14 +257,19 @@ protected function processFilterRules($filterRules) { $ns = '{' . $this::NS_OWNCLOUD . '}'; $resultFileIds = null; $systemTagIds = []; + $circlesIds = []; $favoriteFilter = null; foreach ($filterRules as $filterRule) { if ($filterRule['name'] === $ns . 'systemtag') { $systemTagIds[] = $filterRule['value']; } + if ($filterRule['name'] === self::CIRCLE_PROPERTYNAME) { + $circlesIds[] = $filterRule['value']; + } if ($filterRule['name'] === $ns . 'favorite') { $favoriteFilter = true; } + } if ($favoriteFilter !== null) { @@ -282,6 +288,15 @@ protected function processFilterRules($filterRules) { } } + if (!empty($circlesIds)) { + $fileIds = $this->getCirclesFileIds($circlesIds); + if (empty($resultFileIds)) { + $resultFileIds = $fileIds; + } else { + $resultFileIds = array_intersect($fileIds, $resultFileIds); + } + } + return $resultFileIds; } @@ -328,6 +343,18 @@ private function getSystemTagFileIds($systemTagIds) { return $resultFileIds; } + /** + * @param array $circlesIds + * @return array + */ + private function getCirclesFileIds(array $circlesIds) { + if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) { + return array(); + } + return \OCA\Circles\Api\v1\Circles::getFilesForCircles($circlesIds); + } + + /** * Prepare propfind response for the given nodes * diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php index 2574fbcd4365f..fcd851a3e567c 100644 --- a/apps/dav/lib/Connector/Sabre/Principal.php +++ b/apps/dav/lib/Connector/Sabre/Principal.php @@ -12,6 +12,8 @@ * @author Thomas Müller * @author Thomas Tanghus * @author Vincent Petry + * @author Vinicius Cubas Brand + * @author Daniel Tygel * @author Georg Ehrke * * @license AGPL-3.0 @@ -66,6 +68,9 @@ class Principal implements BackendInterface { /** @var bool */ private $hasGroups; + /** @var bool */ + private $hasCircles; + /** * @param IUserManager $userManager * @param IGroupManager $groupManager @@ -86,7 +91,7 @@ public function __construct(IUserManager $userManager, $this->userSession = $userSession; $this->config = $config; $this->principalPrefix = trim($principalPrefix, '/'); - $this->hasGroups = ($principalPrefix === 'principals/users/'); + $this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/'); } /** @@ -131,6 +136,8 @@ public function getPrincipalByPath($path) { if ($user !== null) { return $this->userToPrincipal($user); } + } else if ($prefix === 'principals/circles') { + return $this->circleToPrincipal($name); } return null; } @@ -388,4 +395,59 @@ public function getPrincipalPrefix() { return $this->principalPrefix; } + /** + * @param string $circleUniqueId + * @return array|null + */ + protected function circleToPrincipal($circleUniqueId) { + if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) { + return null; + } + + $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId); + + 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 + * @return array + * @throws Exception + */ + public function getCircleMembership($principal) { + if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) { + return []; + } + + list($prefix, $name) = URLUtil::splitPath($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($user->getUID()); + $circles = array_map(function ($circle) { + /** @var \OCA\Circles\Model\Circle $group */ + return 'principals/circles/' . urlencode($circle->getUniqueId()); + }, $circles); + + return $circles; + } + + return []; + } + } diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php index 990cc4a808fdf..711068a74373d 100644 --- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php @@ -124,6 +124,7 @@ private function getShareTypes(\OCP\Files\Node $node) { \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL, + \OCP\Share::SHARE_TYPE_CIRCLE, \OCP\Share::SHARE_TYPE_ROOM, ]; foreach ($requestedShareTypes as $requestedShareType) { diff --git a/core/js/files/client.js b/core/js/files/client.js index 9de732b3bd412..f4ac2c919b6b9 100644 --- a/core/js/files/client.js +++ b/core/js/files/client.js @@ -500,7 +500,7 @@ /** * Fetches a flat list of files filtered by a given filter criteria. - * (currently only system tags is supported) + * (currently system tags and circles are supported) * * @param {Object} filter filter criteria * @param {Object} [filter.systemTagIds] list of system tag ids to filter by @@ -522,7 +522,8 @@ properties = options.properties; } - if (!filter || (!filter.systemTagIds && _.isUndefined(filter.favorite))) { + if (!filter || + (!filter.systemTagIds && _.isUndefined(filter.favorite) && !filter.circlesIds) ) { throw 'Missing filter argument'; } @@ -548,6 +549,9 @@ _.each(filter.systemTagIds, function(systemTagIds) { body += ' ' + escapeHTML(systemTagIds) + '\n'; }); + _.each(filter.circlesIds, function(circlesIds) { + body += ' ' + escapeHTML(circlesIds) + '\n'; + }); if (filter.favorite) { body += ' ' + (filter.favorite ? '1': '0') + '\n'; }