diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2016-02-08 21:41:40 +0100 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2016-02-08 21:41:40 +0100 |
commit | b77a4b0c6a3c34587316350dbf0ee222fd681b49 (patch) | |
tree | db8937d969d168f58a3f26d2871cccddf1a62e7a /apps | |
parent | 75bbd4f8b64209eaf120f1382d7cec6286e68c84 (diff) | |
parent | 2f1a60a64dc94f80a664639c1c0dddc399035fd8 (diff) | |
download | nextcloud-server-b77a4b0c6a3c34587316350dbf0ee222fd681b49.tar.gz nextcloud-server-b77a4b0c6a3c34587316350dbf0ee222fd681b49.zip |
Merge pull request #22112 from owncloud/dav-filesreport
Provide REPORT method on files DAV to filter/search files
Diffstat (limited to 'apps')
-rw-r--r-- | apps/dav/lib/connector/sabre/filesreportplugin.php | 321 | ||||
-rw-r--r-- | apps/dav/lib/connector/sabre/serverfactory.php | 11 | ||||
-rw-r--r-- | apps/dav/tests/unit/connector/sabre/filesreportplugin.php | 519 |
3 files changed, 850 insertions, 1 deletions
diff --git a/apps/dav/lib/connector/sabre/filesreportplugin.php b/apps/dav/lib/connector/sabre/filesreportplugin.php new file mode 100644 index 00000000000..5bdd7a71ddc --- /dev/null +++ b/apps/dav/lib/connector/sabre/filesreportplugin.php @@ -0,0 +1,321 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Connector\Sabre; + +use OC\Files\View; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\PreconditionFailed; +use Sabre\DAV\Exception\ReportNotSupported; +use Sabre\DAV\Exception\BadRequest; +use Sabre\DAV\ServerPlugin; +use Sabre\DAV\Tree; +use Sabre\DAV\Xml\Element\Response; +use Sabre\DAV\Xml\Response\MultiStatus; +use Sabre\DAV\PropFind; +use OCP\SystemTag\ISystemTagObjectMapper; +use OCP\IUserSession; +use OCP\Files\Folder; +use OCP\IGroupManager; +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\TagNotFoundException; + +class FilesReportPlugin extends ServerPlugin { + + // namespace + const NS_OWNCLOUD = 'http://owncloud.org/ns'; + const REPORT_NAME = '{http://owncloud.org/ns}filter-files'; + const SYSTEMTAG_PROPERTYNAME = '{http://owncloud.org/ns}systemtag'; + + /** + * Reference to main server object + * + * @var \Sabre\DAV\Server + */ + private $server; + + /** + * @var Tree + */ + private $tree; + + /** + * @var View + */ + private $fileView; + + /** + * @var ISystemTagManager + */ + private $tagManager; + + /** + * @var ISystemTagObjectMapper + */ + private $tagMapper; + + /** + * @var IUserSession + */ + private $userSession; + + /** + * @var IGroupManager + */ + private $groupManager; + + /** + * @var Folder + */ + private $userFolder; + + /** + * @param Tree $tree + * @param View $view + */ + public function __construct(Tree $tree, + View $view, + ISystemTagManager $tagManager, + ISystemTagObjectMapper $tagMapper, + IUserSession $userSession, + IGroupManager $groupManager, + Folder $userFolder + ) { + $this->tree = $tree; + $this->fileView = $view; + $this->tagManager = $tagManager; + $this->tagMapper = $tagMapper; + $this->userSession = $userSession; + $this->groupManager = $groupManager; + $this->userFolder = $userFolder; + } + + /** + * This initializes the plugin. + * + * This function is called by \Sabre\DAV\Server, after + * addPlugin is called. + * + * This method should set up the required event subscriptions. + * + * @param \Sabre\DAV\Server $server + * @return void + */ + public function initialize(\Sabre\DAV\Server $server) { + + $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc'; + + $this->server = $server; + $this->server->on('report', array($this, 'onReport')); + } + + /** + * Returns a list of reports this plugin supports. + * + * This will be used in the {DAV:}supported-report-set property. + * + * @param string $uri + * @return array + */ + public function getSupportedReportSet($uri) { + return [self::REPORT_NAME]; + } + + /** + * REPORT operations to look for files + * + * @param string $reportName + * @param [] $report + * @param string $uri + * @return bool + * @throws NotFound + * @throws ReportNotSupported + */ + public function onReport($reportName, $report, $uri) { + $reportTargetNode = $this->server->tree->getNodeForPath($uri); + if (!$reportTargetNode instanceof Directory || $reportName !== self::REPORT_NAME) { + throw new ReportNotSupported(); + } + + $ns = '{' . $this::NS_OWNCLOUD . '}'; + $requestedProps = []; + $filterRules = []; + + // parse report properties and gather filter info + foreach ($report as $reportProps) { + $name = $reportProps['name']; + if ($name === $ns . 'filter-rules') { + $filterRules = $reportProps['value']; + } else if ($name === '{DAV:}prop') { + // propfind properties + foreach ($reportProps['value'] as $propVal) { + $requestedProps[] = $propVal['name']; + } + } + } + + if (empty($filterRules)) { + // an empty filter would return all existing files which would be slow + throw new BadRequest('Missing filter-rule block in request'); + } + + // gather all file ids matching filter + try { + $resultFileIds = $this->processFilterRules($filterRules); + } catch (TagNotFoundException $e) { + throw new PreconditionFailed('Cannot filter by non-existing tag', 0, $e); + } + + // find sabre nodes by file id, restricted to the root node path + $results = $this->findNodesByFileIds($reportTargetNode, $resultFileIds); + + $responses = $this->prepareResponses($requestedProps, $results); + + $xml = $this->server->xml->write( + '{DAV:}multistatus', + new MultiStatus($responses) + ); + + $this->server->httpResponse->setStatus(207); + $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); + $this->server->httpResponse->setBody($xml); + + return false; + } + + /** + * Find file ids matching the given filter rules + * + * @param array $filterRules + * @return array array of unique file id results + * + * @throws TagNotFoundException whenever a tag was not found + */ + public function processFilterRules($filterRules) { + $ns = '{' . $this::NS_OWNCLOUD . '}'; + $resultFileIds = []; + $systemTagIds = []; + foreach ($filterRules as $filterRule) { + if ($filterRule['name'] === $ns . 'systemtag') { + $systemTagIds[] = $filterRule['value']; + } + } + + // check user permissions, if applicable + if (!$this->isAdmin()) { + // check visibility/permission + $tags = $this->tagManager->getTagsByIds($systemTagIds); + $unknownTagIds = []; + foreach ($tags as $tag) { + if (!$tag->isUserVisible()) { + $unknownTagIds[] = $tag->getId(); + } + } + + if (!empty($unknownTagIds)) { + throw new TagNotFoundException('Tag with ids ' . implode(', ', $unknownTagIds) . ' not found'); + } + } + + // fetch all file ids and intersect them + foreach ($systemTagIds as $systemTagId) { + $fileIds = $this->tagMapper->getObjectIdsForTags($systemTagId, 'files'); + + if (empty($resultFileIds)) { + $resultFileIds = $fileIds; + } else { + $resultFileIds = array_intersect($resultFileIds, $fileIds); + } + } + return $resultFileIds; + } + + /** + * Prepare propfind response for the given nodes + * + * @param string[] $requestedProps requested properties + * @param Node[] nodes nodes for which to fetch and prepare responses + * @return Response[] + */ + public function prepareResponses($requestedProps, $nodes) { + $responses = []; + foreach ($nodes as $node) { + $propFind = new PropFind($node->getPath(), $requestedProps); + + $this->server->getPropertiesByNode($propFind, $node); + // copied from Sabre Server's getPropertiesForPath + $result = $propFind->getResultForMultiStatus(); + $result['href'] = $propFind->getPath(); + + $resourceType = $this->server->getResourceTypeForNode($node); + if (in_array('{DAV:}collection', $resourceType) || in_array('{DAV:}principal', $resourceType)) { + $result['href'] .= '/'; + } + + $responses[] = new Response( + rtrim($this->server->getBaseUri(), '/') . $node->getPath(), + $result, + 200 + ); + } + return $responses; + } + + /** + * Find Sabre nodes by file ids + * + * @param Node $rootNode root node for search + * @param array $fileIds file ids + * @return Node[] array of Sabre nodes + */ + public function findNodesByFileIds($rootNode, $fileIds) { + $folder = $this->userFolder; + if (trim($rootNode->getPath(), '/') !== '') { + $folder = $folder->get($rootNode->getPath()); + } + + $results = []; + foreach ($fileIds as $fileId) { + $entry = $folder->getById($fileId); + if ($entry) { + $entry = current($entry); + if ($entry instanceof \OCP\Files\File) { + $results[] = new File($this->fileView, $entry); + } else if ($entry instanceof \OCP\Files\Folder) { + $results[] = new Directory($this->fileView, $entry); + } + } + } + + return $results; + } + + /** + * Returns whether the currently logged in user is an administrator + */ + private function isAdmin() { + $user = $this->userSession->getUser(); + if ($user !== null) { + return $this->groupManager->isAdmin($user->getUID()); + } + return false; + } +} diff --git a/apps/dav/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php index fa4fda46870..9a828787a0d 100644 --- a/apps/dav/lib/connector/sabre/serverfactory.php +++ b/apps/dav/lib/connector/sabre/serverfactory.php @@ -115,7 +115,7 @@ class ServerFactory { // wait with registering these until auth is handled and the filesystem is setup $server->on('beforeMethod', function () use ($server, $objectTree, $viewCallBack) { // ensure the skeleton is copied - \OC::$server->getUserFolder(); + $userFolder = \OC::$server->getUserFolder(); /** @var \OC\Files\View $view */ $view = $viewCallBack(); @@ -135,6 +135,15 @@ class ServerFactory { if($this->userSession->isLoggedIn()) { $server->addPlugin(new \OCA\DAV\Connector\Sabre\TagsPlugin($objectTree, $this->tagManager)); $server->addPlugin(new \OCA\DAV\Connector\Sabre\CommentPropertiesPlugin(\OC::$server->getCommentsManager(), $this->userSession)); + $server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesReportPlugin( + $objectTree, + $view, + \OC::$server->getSystemTagManager(), + \OC::$server->getSystemTagObjectMapper(), + $this->userSession, + \OC::$server->getGroupManager(), + $userFolder + )); // custom properties plugin must be the last one $server->addPlugin( new \Sabre\DAV\PropertyStorage\Plugin( diff --git a/apps/dav/tests/unit/connector/sabre/filesreportplugin.php b/apps/dav/tests/unit/connector/sabre/filesreportplugin.php new file mode 100644 index 00000000000..853e52f5039 --- /dev/null +++ b/apps/dav/tests/unit/connector/sabre/filesreportplugin.php @@ -0,0 +1,519 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\Unit\Sabre\Connector; + +use OCA\DAV\Connector\Sabre\FilesReportPlugin as FilesReportPluginImplementation; +use Sabre\DAV\Exception\NotFound; +use OCP\SystemTag\ISystemTagObjectMapper; +use OC\Files\View; +use OCP\Files\Folder; +use OCP\IGroupManager; +use OCP\SystemTag\ISystemTagManager; + +class FilesReportPlugin extends \Test\TestCase { + /** @var \Sabre\DAV\Server */ + private $server; + + /** @var \Sabre\DAV\Tree */ + private $tree; + + /** @var ISystemTagObjectMapper */ + private $tagMapper; + + /** @var ISystemTagManager */ + private $tagManager; + + /** @var \OCP\IUserSession */ + private $userSession; + + /** @var FilesReportPluginImplementation */ + private $plugin; + + /** @var View **/ + private $view; + + /** @var IGroupManager **/ + private $groupManager; + + /** @var Folder **/ + private $userFolder; + + public function setUp() { + parent::setUp(); + $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree') + ->disableOriginalConstructor() + ->getMock(); + + $this->view = $this->getMockBuilder('\OC\Files\View') + ->disableOriginalConstructor() + ->getMock(); + + $this->server = $this->getMockBuilder('\Sabre\DAV\Server') + ->setConstructorArgs([$this->tree]) + ->setMethods(['getRequestUri']) + ->getMock(); + + $this->groupManager = $this->getMockBuilder('\OCP\IGroupManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->userFolder = $this->getMockBuilder('\OCP\Files\Folder') + ->disableOriginalConstructor() + ->getMock(); + + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + $this->tagMapper = $this->getMock('\OCP\SystemTag\ISystemTagObjectMapper'); + $this->userSession = $this->getMock('\OCP\IUserSession'); + + $user = $this->getMock('\OCP\IUser'); + $user->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('testuser')); + $this->userSession->expects($this->any()) + ->method('getUser') + ->will($this->returnValue($user)); + + $this->plugin = new FilesReportPluginImplementation( + $this->tree, + $this->view, + $this->tagManager, + $this->tagMapper, + $this->userSession, + $this->groupManager, + $this->userFolder + ); + } + + /** + * @expectedException \Sabre\DAV\Exception\ReportNotSupported + */ + public function testOnReportInvalidNode() { + $path = 'totally/unrelated/13'; + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/' . $path) + ->will($this->returnValue($this->getMock('\Sabre\DAV\INode'))); + + $this->server->expects($this->any()) + ->method('getRequestUri') + ->will($this->returnValue($path)); + $this->plugin->initialize($this->server); + + $this->plugin->onReport(FilesReportPluginImplementation::REPORT_NAME, [], '/' . $path); + } + + /** + * @expectedException \Sabre\DAV\Exception\ReportNotSupported + */ + public function testOnReportInvalidReportName() { + $path = 'test'; + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/' . $path) + ->will($this->returnValue($this->getMock('\Sabre\DAV\INode'))); + + $this->server->expects($this->any()) + ->method('getRequestUri') + ->will($this->returnValue($path)); + $this->plugin->initialize($this->server); + + $this->plugin->onReport('{whoever}whatever', [], '/' . $path); + } + + public function testOnReport() { + $path = 'test'; + + $parameters = [ + [ + 'name' => '{DAV:}prop', + 'value' => [ + ['name' => '{DAV:}getcontentlength', 'value' => ''], + ['name' => '{http://owncloud.org/ns}size', 'value' => ''], + ], + ], + [ + 'name' => '{http://owncloud.org/ns}filter-rules', + 'value' => [ + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'], + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'], + ], + ], + ]; + + $this->groupManager->expects($this->any()) + ->method('isAdmin') + ->will($this->returnValue(true)); + + $this->tagMapper->expects($this->at(0)) + ->method('getObjectIdsForTags') + ->with('123', 'files') + ->will($this->returnValue(['111', '222'])); + $this->tagMapper->expects($this->at(1)) + ->method('getObjectIdsForTags') + ->with('456', 'files') + ->will($this->returnValue(['111', '222', '333'])); + + $reportTargetNode = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory') + ->disableOriginalConstructor() + ->getMock(); + + $response = $this->getMockBuilder('Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + + $response->expects($this->once()) + ->method('setHeader') + ->with('Content-Type', 'application/xml; charset=utf-8'); + + $response->expects($this->once()) + ->method('setStatus') + ->with(207); + + $response->expects($this->once()) + ->method('setBody'); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/' . $path) + ->will($this->returnValue($reportTargetNode)); + + $filesNode1 = $this->getMockBuilder('\OCP\Files\Folder') + ->disableOriginalConstructor() + ->getMock(); + $filesNode2 = $this->getMockBuilder('\OCP\Files\File') + ->disableOriginalConstructor() + ->getMock(); + + $this->userFolder->expects($this->at(0)) + ->method('getById') + ->with('111') + ->will($this->returnValue([$filesNode1])); + $this->userFolder->expects($this->at(1)) + ->method('getById') + ->with('222') + ->will($this->returnValue([$filesNode2])); + + $this->server->expects($this->any()) + ->method('getRequestUri') + ->will($this->returnValue($path)); + $this->server->httpResponse = $response; + $this->plugin->initialize($this->server); + + $this->plugin->onReport(FilesReportPluginImplementation::REPORT_NAME, $parameters, '/' . $path); + } + + public function testFindNodesByFileIdsRoot() { + $filesNode1 = $this->getMockBuilder('\OCP\Files\Folder') + ->disableOriginalConstructor() + ->getMock(); + $filesNode1->expects($this->once()) + ->method('getName') + ->will($this->returnValue('first node')); + + $filesNode2 = $this->getMockBuilder('\OCP\Files\File') + ->disableOriginalConstructor() + ->getMock(); + $filesNode2->expects($this->once()) + ->method('getName') + ->will($this->returnValue('second node')); + + $reportTargetNode = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory') + ->disableOriginalConstructor() + ->getMock(); + $reportTargetNode->expects($this->any()) + ->method('getPath') + ->will($this->returnValue('/')); + + $this->userFolder->expects($this->at(0)) + ->method('getById') + ->with('111') + ->will($this->returnValue([$filesNode1])); + $this->userFolder->expects($this->at(1)) + ->method('getById') + ->with('222') + ->will($this->returnValue([$filesNode2])); + + $result = $this->plugin->findNodesByFileIds($reportTargetNode, ['111', '222']); + + $this->assertCount(2, $result); + $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\Directory', $result[0]); + $this->assertEquals('first node', $result[0]->getName()); + $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\File', $result[1]); + $this->assertEquals('second node', $result[1]->getName()); + } + + public function testFindNodesByFileIdsSubDir() { + $filesNode1 = $this->getMockBuilder('\OCP\Files\Folder') + ->disableOriginalConstructor() + ->getMock(); + $filesNode1->expects($this->once()) + ->method('getName') + ->will($this->returnValue('first node')); + + $filesNode2 = $this->getMockBuilder('\OCP\Files\File') + ->disableOriginalConstructor() + ->getMock(); + $filesNode2->expects($this->once()) + ->method('getName') + ->will($this->returnValue('second node')); + + $reportTargetNode = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory') + ->disableOriginalConstructor() + ->getMock(); + $reportTargetNode->expects($this->any()) + ->method('getPath') + ->will($this->returnValue('/sub1/sub2')); + + + $subNode = $this->getMockBuilder('\OCP\Files\Folder') + ->disableOriginalConstructor() + ->getMock(); + + $this->userFolder->expects($this->at(0)) + ->method('get') + ->with('/sub1/sub2') + ->will($this->returnValue($subNode)); + + $subNode->expects($this->at(0)) + ->method('getById') + ->with('111') + ->will($this->returnValue([$filesNode1])); + $subNode->expects($this->at(1)) + ->method('getById') + ->with('222') + ->will($this->returnValue([$filesNode2])); + + $result = $this->plugin->findNodesByFileIds($reportTargetNode, ['111', '222']); + + $this->assertCount(2, $result); + $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\Directory', $result[0]); + $this->assertEquals('first node', $result[0]->getName()); + $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\File', $result[1]); + $this->assertEquals('second node', $result[1]->getName()); + } + + public function testPrepareResponses() { + $requestedProps = ['{DAV:}getcontentlength', '{http://owncloud.org/ns}fileid', '{DAV:}resourcetype']; + + $node1 = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory') + ->disableOriginalConstructor() + ->getMock(); + $node2 = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\File') + ->disableOriginalConstructor() + ->getMock(); + + $node1->expects($this->once()) + ->method('getInternalFileId') + ->will($this->returnValue('111')); + $node2->expects($this->once()) + ->method('getInternalFileId') + ->will($this->returnValue('222')); + $node2->expects($this->once()) + ->method('getSize') + ->will($this->returnValue(1024)); + + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesPlugin($this->tree, $this->view)); + $this->plugin->initialize($this->server); + $responses = $this->plugin->prepareResponses($requestedProps, [$node1, $node2]); + + $this->assertCount(2, $responses); + + $this->assertEquals(200, $responses[0]->getHttpStatus()); + $this->assertEquals(200, $responses[1]->getHttpStatus()); + + $props1 = $responses[0]->getResponseProperties(); + $this->assertEquals('111', $props1[200]['{http://owncloud.org/ns}fileid']); + $this->assertNull($props1[404]['{DAV:}getcontentlength']); + $this->assertInstanceOf('\Sabre\DAV\Xml\Property\ResourceType', $props1[200]['{DAV:}resourcetype']); + $resourceType1 = $props1[200]['{DAV:}resourcetype']->getValue(); + $this->assertEquals('{DAV:}collection', $resourceType1[0]); + + $props2 = $responses[1]->getResponseProperties(); + $this->assertEquals('1024', $props2[200]['{DAV:}getcontentlength']); + $this->assertEquals('222', $props2[200]['{http://owncloud.org/ns}fileid']); + $this->assertInstanceOf('\Sabre\DAV\Xml\Property\ResourceType', $props2[200]['{DAV:}resourcetype']); + $this->assertCount(0, $props2[200]['{DAV:}resourcetype']->getValue()); + } + + public function testProcessFilterRulesSingle() { + $this->groupManager->expects($this->any()) + ->method('isAdmin') + ->will($this->returnValue(true)); + + $this->tagMapper->expects($this->once()) + ->method('getObjectIdsForTags') + ->with('123') + ->will($this->returnValue(['111', '222'])); + + $rules = [ + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'], + ]; + + $this->assertEquals(['111', '222'], $this->plugin->processFilterRules($rules)); + } + + public function testProcessFilterRulesAndCondition() { + $this->groupManager->expects($this->any()) + ->method('isAdmin') + ->will($this->returnValue(true)); + + $this->tagMapper->expects($this->at(0)) + ->method('getObjectIdsForTags') + ->with('123') + ->will($this->returnValue(['111', '222'])); + $this->tagMapper->expects($this->at(1)) + ->method('getObjectIdsForTags') + ->with('456') + ->will($this->returnValue(['222', '333'])); + + $rules = [ + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'], + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'], + ]; + + $this->assertEquals(['222'], array_values($this->plugin->processFilterRules($rules))); + } + + public function testProcessFilterRulesInvisibleTagAsAdmin() { + $this->groupManager->expects($this->any()) + ->method('isAdmin') + ->will($this->returnValue(true)); + + $tag1 = $this->getMock('\OCP\SystemTag\ISystemTag'); + $tag1->expects($this->any()) + ->method('getId') + ->will($this->returnValue('123')); + $tag1->expects($this->any()) + ->method('isUserVisible') + ->will($this->returnValue(true)); + + $tag2 = $this->getMock('\OCP\SystemTag\ISystemTag'); + $tag2->expects($this->any()) + ->method('getId') + ->will($this->returnValue('123')); + $tag2->expects($this->any()) + ->method('isUserVisible') + ->will($this->returnValue(false)); + + // no need to fetch tags to check permissions + $this->tagManager->expects($this->never()) + ->method('getTagsByIds'); + + $this->tagMapper->expects($this->at(0)) + ->method('getObjectIdsForTags') + ->with('123') + ->will($this->returnValue(['111', '222'])); + $this->tagMapper->expects($this->at(1)) + ->method('getObjectIdsForTags') + ->with('456') + ->will($this->returnValue(['222', '333'])); + + $rules = [ + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'], + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'], + ]; + + $this->assertEquals(['222'], array_values($this->plugin->processFilterRules($rules))); + } + + /** + * @expectedException \OCP\SystemTag\TagNotFoundException + */ + public function testProcessFilterRulesInvisibleTagAsUser() { + $this->groupManager->expects($this->any()) + ->method('isAdmin') + ->will($this->returnValue(false)); + + $tag1 = $this->getMock('\OCP\SystemTag\ISystemTag'); + $tag1->expects($this->any()) + ->method('getId') + ->will($this->returnValue('123')); + $tag1->expects($this->any()) + ->method('isUserVisible') + ->will($this->returnValue(true)); + + $tag2 = $this->getMock('\OCP\SystemTag\ISystemTag'); + $tag2->expects($this->any()) + ->method('getId') + ->will($this->returnValue('123')); + $tag2->expects($this->any()) + ->method('isUserVisible') + ->will($this->returnValue(false)); // invisible + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['123', '456']) + ->will($this->returnValue([$tag1, $tag2])); + + $rules = [ + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'], + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'], + ]; + + $this->plugin->processFilterRules($rules); + } + + public function testProcessFilterRulesVisibleTagAsUser() { + $this->groupManager->expects($this->any()) + ->method('isAdmin') + ->will($this->returnValue(false)); + + $tag1 = $this->getMock('\OCP\SystemTag\ISystemTag'); + $tag1->expects($this->any()) + ->method('getId') + ->will($this->returnValue('123')); + $tag1->expects($this->any()) + ->method('isUserVisible') + ->will($this->returnValue(true)); + + $tag2 = $this->getMock('\OCP\SystemTag\ISystemTag'); + $tag2->expects($this->any()) + ->method('getId') + ->will($this->returnValue('123')); + $tag2->expects($this->any()) + ->method('isUserVisible') + ->will($this->returnValue(true)); + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['123', '456']) + ->will($this->returnValue([$tag1, $tag2])); + + $this->tagMapper->expects($this->at(0)) + ->method('getObjectIdsForTags') + ->with('123') + ->will($this->returnValue(['111', '222'])); + $this->tagMapper->expects($this->at(1)) + ->method('getObjectIdsForTags') + ->with('456') + ->will($this->returnValue(['222', '333'])); + + $rules = [ + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'], + ['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'], + ]; + + $this->assertEquals(['222'], array_values($this->plugin->processFilterRules($rules))); + } +} |