summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/lib/AppFramework/AppTest.php51
-rw-r--r--tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php56
-rw-r--r--tests/lib/Files/EtagTest.php4
-rw-r--r--tests/lib/Repair/RepairUnmergedSharesTest.php449
4 files changed, 558 insertions, 2 deletions
diff --git a/tests/lib/AppFramework/AppTest.php b/tests/lib/AppFramework/AppTest.php
index 7288e686d52..92ebd1f81e7 100644
--- a/tests/lib/AppFramework/AppTest.php
+++ b/tests/lib/AppFramework/AppTest.php
@@ -162,4 +162,55 @@ class AppTest extends \Test\TestCase {
App::main($this->controllerName, $this->controllerMethod, $this->container, []);
}
+ public function testCoreApp() {
+ $this->container['AppName'] = 'core';
+ $this->container['OC\Core\Controller\Foo'] = $this->controller;
+
+ $return = array(null, array(), array(), null, new Response());
+ $this->dispatcher->expects($this->once())
+ ->method('dispatch')
+ ->with($this->equalTo($this->controller),
+ $this->equalTo($this->controllerMethod))
+ ->will($this->returnValue($return));
+
+ $this->io->expects($this->never())
+ ->method('setOutput');
+
+ App::main('Foo', $this->controllerMethod, $this->container);
+ }
+
+ public function testSettingsApp() {
+ $this->container['AppName'] = 'settings';
+ $this->container['OC\Settings\Controller\Foo'] = $this->controller;
+
+ $return = array(null, array(), array(), null, new Response());
+ $this->dispatcher->expects($this->once())
+ ->method('dispatch')
+ ->with($this->equalTo($this->controller),
+ $this->equalTo($this->controllerMethod))
+ ->will($this->returnValue($return));
+
+ $this->io->expects($this->never())
+ ->method('setOutput');
+
+ App::main('Foo', $this->controllerMethod, $this->container);
+ }
+
+ public function testApp() {
+ $this->container['AppName'] = 'bar';
+ $this->container['OCA\Bar\Controller\Foo'] = $this->controller;
+
+ $return = array(null, array(), array(), null, new Response());
+ $this->dispatcher->expects($this->once())
+ ->method('dispatch')
+ ->with($this->equalTo($this->controller),
+ $this->equalTo($this->controllerMethod))
+ ->will($this->returnValue($return));
+
+ $this->io->expects($this->never())
+ ->method('setOutput');
+
+ App::main('Foo', $this->controllerMethod, $this->container);
+ }
+
}
diff --git a/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php
index 487b83c0bef..bfd810bc6b9 100644
--- a/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php
+++ b/tests/lib/AppFramework/Middleware/Security/SecurityMiddlewareTest.php
@@ -35,22 +35,38 @@ use OC\Appframework\Middleware\Security\Exceptions\StrictCookieMissingException;
use OC\AppFramework\Middleware\Security\SecurityMiddleware;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\Security\CSP\ContentSecurityPolicy;
+use OC\Security\CSP\ContentSecurityPolicyManager;
+use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\ILogger;
+use OCP\INavigationManager;
+use OCP\IRequest;
+use OCP\IURLGenerator;
class SecurityMiddlewareTest extends \Test\TestCase {
+ /** @var SecurityMiddleware|\PHPUnit_Framework_MockObject_MockObject */
private $middleware;
+ /** @var Controller|\PHPUnit_Framework_MockObject_MockObject */
private $controller;
+ /** @var SecurityException */
private $secException;
+ /** @var SecurityException */
private $secAjaxException;
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
private $request;
+ /** @var ControllerMethodReflector */
private $reader;
+ /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
private $logger;
+ /** @var INavigationManager|\PHPUnit_Framework_MockObject_MockObject */
private $navigationManager;
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
private $urlGenerator;
+ /** @var ContentSecurityPolicyManager|\PHPUnit_Framework_MockObject_MockObject */
private $contentSecurityPolicyManager;
protected function setUp() {
@@ -354,6 +370,46 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->middleware->beforeController(__CLASS__, __FUNCTION__);
}
+ public function dataCsrfOcsController() {
+ $controller = $this->getMockBuilder('OCP\AppFramework\Controller')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $ocsController = $this->getMockBuilder('OCP\AppFramework\OCSController')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ return [
+ [$controller, false, true],
+ [$controller, true, true],
+
+ [$ocsController, false, true],
+ [$ocsController, true, false],
+ ];
+ }
+
+ /**
+ * @dataProvider dataCsrfOcsController
+ * @param Controller $controller
+ * @param bool $hasOcsApiHeader
+ * @param bool $exception
+ */
+ public function testCsrfOcsController(Controller $controller, $hasOcsApiHeader, $exception) {
+ $this->request
+ ->method('getHeader')
+ ->with('OCS-APIREQUEST')
+ ->willReturn($hasOcsApiHeader ? 'true' : null);
+ $this->request->expects($this->once())
+ ->method('passesStrictCookieCheck')
+ ->willReturn(true);
+
+ try {
+ $this->middleware->beforeController($controller, 'foo');
+ $this->assertFalse($exception);
+ } catch (CrossSiteRequestForgeryException $e) {
+ $this->assertTrue($exception);
+ }
+ }
+
/**
* @NoCSRFRequired
* @NoAdminRequired
diff --git a/tests/lib/Files/EtagTest.php b/tests/lib/Files/EtagTest.php
index d8e44000f9c..67ddd6ca514 100644
--- a/tests/lib/Files/EtagTest.php
+++ b/tests/lib/Files/EtagTest.php
@@ -34,8 +34,8 @@ class EtagTest extends \Test\TestCase {
\OC_Hook::clear('OC_Filesystem', 'setup');
$application = new \OCA\Files_Sharing\AppInfo\Application();
$application->registerMountProviders();
- \OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
- \OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
+ \OCP\Share::registerBackend('file', 'OCA\Files_Sharing\ShareBackend\File');
+ \OCP\Share::registerBackend('folder', 'OCA\Files_Sharing\ShareBackend\Folder', 'file');
$config = \OC::$server->getConfig();
$this->datadir = $config->getSystemValue('datadirectory');
diff --git a/tests/lib/Repair/RepairUnmergedSharesTest.php b/tests/lib/Repair/RepairUnmergedSharesTest.php
new file mode 100644
index 00000000000..fe9b3e5b96f
--- /dev/null
+++ b/tests/lib/Repair/RepairUnmergedSharesTest.php
@@ -0,0 +1,449 @@
+<?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 Test\Repair;
+
+
+use OC\Repair\RepairUnmergedShares;
+use OC\Share\Constants;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+use Test\TestCase;
+use OC\Share20\DefaultShareProvider;
+
+/**
+ * Tests for repairing invalid shares
+ *
+ * @group DB
+ *
+ * @see \OC\Repair\RepairUnmergedShares
+ */
+class RepairUnmergedSharesTest extends TestCase {
+
+ /** @var IRepairStep */
+ private $repair;
+
+ /** @var \OCP\IDBConnection */
+ private $connection;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $config = $this->getMockBuilder('OCP\IConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $config->expects($this->any())
+ ->method('getSystemValue')
+ ->with('version')
+ ->will($this->returnValue('9.0.3.0'));
+
+ $this->connection = \OC::$server->getDatabaseConnection();
+ $this->deleteAllShares();
+
+ $user1 = $this->getMock('\OCP\IUser');
+ $user1->expects($this->any())
+ ->method('getUID')
+ ->will($this->returnValue('user1'));
+
+ $user2 = $this->getMock('\OCP\IUser');
+ $user2->expects($this->any())
+ ->method('getUID')
+ ->will($this->returnValue('user2'));
+
+ $users = [$user1, $user2];
+
+ $groupManager = $this->getMock('\OCP\IGroupManager');
+ $groupManager->expects($this->any())
+ ->method('getUserGroupIds')
+ ->will($this->returnValueMap([
+ // owner
+ [$user1, ['samegroup1', 'samegroup2']],
+ // recipient
+ [$user2, ['recipientgroup1', 'recipientgroup2']],
+ ]));
+
+ $userManager = $this->getMock('\OCP\IUserManager');
+ $userManager->expects($this->once())
+ ->method('countUsers')
+ ->will($this->returnValue([2]));
+ $userManager->expects($this->once())
+ ->method('callForAllUsers')
+ ->will($this->returnCallback(function(\Closure $closure) use ($users) {
+ foreach ($users as $user) {
+ $closure($user);
+ }
+ }));
+
+ /** @var \OCP\IConfig $config */
+ $this->repair = new RepairUnmergedShares($config, $this->connection, $userManager, $groupManager);
+ }
+
+ protected function tearDown() {
+ $this->deleteAllShares();
+
+ parent::tearDown();
+ }
+
+ protected function deleteAllShares() {
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('share')->execute();
+ }
+
+ private function createShare($type, $sourceId, $recipient, $targetName, $permissions, $parentId = null) {
+ $qb = $this->connection->getQueryBuilder();
+ $values = [
+ 'share_type' => $qb->expr()->literal($type),
+ 'share_with' => $qb->expr()->literal($recipient),
+ 'uid_owner' => $qb->expr()->literal('user1'),
+ 'item_type' => $qb->expr()->literal('folder'),
+ 'item_source' => $qb->expr()->literal($sourceId),
+ 'item_target' => $qb->expr()->literal('/' . $sourceId),
+ 'file_source' => $qb->expr()->literal($sourceId),
+ 'file_target' => $qb->expr()->literal($targetName),
+ 'permissions' => $qb->expr()->literal($permissions),
+ 'stime' => $qb->expr()->literal(time()),
+ ];
+ if ($parentId !== null) {
+ $values['parent'] = $qb->expr()->literal($parentId);
+ }
+ $qb->insert('share')
+ ->values($values)
+ ->execute();
+
+ return $this->connection->lastInsertId('*PREFIX*share');
+ }
+
+ private function getShareById($id) {
+ $query = $this->connection->getQueryBuilder();
+ $results = $query
+ ->select('*')
+ ->from('share')
+ ->where($query->expr()->eq('id', $query->expr()->literal($id)))
+ ->execute()
+ ->fetchAll();
+
+ if (!empty($results)) {
+ return $results[0];
+ }
+ return null;
+ }
+
+ public function sharesDataProvider() {
+ /**
+ * For all these test cases we have the following situation:
+ *
+ * - "user1" is the share owner
+ * - "user2" is the recipient, and member of "recipientgroup1" and "recipientgroup2"
+ * - "user1" is member of "samegroup1", "samegroup2" for same group tests
+ */
+ return [
+ [
+ // #0 legitimate share:
+ // - outsider shares with group1, group2
+ // - recipient renamed, resulting in subshares
+ // - one subshare for each group share
+ // - targets of subshare all match
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 31],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test renamed', 31, 0],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test renamed', 31, 1],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ ['/test', 31],
+ ['/test', 31],
+ // leave them alone
+ ['/test renamed', 31],
+ ['/test renamed', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #1 broken share:
+ // - outsider shares with group1, group2
+ // - only one subshare for two group shares
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 31],
+ // child of the previous one
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (2)', 31, 1],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ ['/test', 31],
+ ['/test', 31],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #2 bogus share
+ // - outsider shares with group1, group2
+ // - one subshare for each group share
+ // - but the targets do not match when grouped
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 31],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (2)', 31, 0],
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (3)', 31, 1],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ ['/test', 31],
+ ['/test', 31],
+ // reset to original name
+ ['/test', 31],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #3 bogus share
+ // - outsider shares with group1, group2
+ // - one subshare for each group share
+ // - first subshare not renamed (as in real world scenario)
+ // - but the targets do not match when grouped
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 31],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test', 31, 0],
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (2)', 31, 1],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ ['/test', 31],
+ ['/test', 31],
+ // reset to original name
+ ['/test', 31],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #4 bogus share:
+ // - outsider shares with group1, group2
+ // - one subshare for each group share
+ // - non-matching targets
+ // - recipient deletes one duplicate (unshare from self, permissions 0)
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 15],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (2)', 0, 0],
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (3)', 15, 1],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ ['/test', 31],
+ ['/test', 15],
+ // subshares repaired and permissions restored to the max allowed
+ ['/test', 31],
+ ['/test', 15],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #5 bogus share:
+ // - outsider shares with group1, group2
+ // - one subshare for each group share
+ // - non-matching targets
+ // - recipient deletes ALL duplicates (unshare from self, permissions 0)
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 15],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (2)', 0, 0],
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (3)', 0, 1],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ ['/test', 31],
+ ['/test', 15],
+ // subshares target repaired but left "deleted" as it was the user's choice
+ ['/test', 0],
+ ['/test', 0],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #6 bogus share:
+ // - outsider shares with group1, group2 and also user2
+ // - one subshare for each group share
+ // - one extra share entry for direct share to user2
+ // - non-matching targets
+ // - user share has more permissions
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 1],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup2', '/test', 15],
+ // child of the previous ones
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (2)', 1, 0],
+ [DefaultShareProvider::SHARE_TYPE_USERGROUP, 123, 'user2', '/test (3)', 15, 1],
+ [Constants::SHARE_TYPE_USER, 123, 'user2', '/test (4)', 31],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (5)', 31],
+ ],
+ [
+ ['/test', 1],
+ ['/test', 15],
+ // subshares repaired
+ ['/test', 1],
+ ['/test', 15],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (5)', 31],
+ ]
+ ],
+ [
+ // #7 bogus share:
+ // - outsider shares with group1 and also user2
+ // - no subshare at all
+ // - one extra share entry for direct share to user2
+ // - non-matching targets
+ // - user share has more permissions
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 1],
+ [Constants::SHARE_TYPE_USER, 123, 'user2', '/test (2)', 31],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (5)', 31],
+ ],
+ [
+ ['/test', 1],
+ // user share repaired
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (5)', 31],
+ ]
+ ],
+ [
+ // #8 legitimate share with own group:
+ // - insider shares with both groups the user is already in
+ // - no subshares in this case
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'samegroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'samegroup2', '/test', 31],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ // leave all alone
+ ['/test', 31],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #9 legitimate shares:
+ // - group share with same group
+ // - group share with other group
+ // - user share where recipient renamed
+ // - user share where recipient did not rename
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'samegroup1', '/test', 31],
+ [Constants::SHARE_TYPE_GROUP, 123, 'recipientgroup1', '/test', 31],
+ [Constants::SHARE_TYPE_USER, 123, 'user3', '/test legit rename', 31],
+ [Constants::SHARE_TYPE_USER, 123, 'user4', '/test', 31],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ // leave all alone
+ ['/test', 31],
+ ['/test', 31],
+ ['/test legit rename', 31],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ [
+ // #10 legitimate share:
+ // - outsider shares with group and user directly with different permissions
+ // - no subshares
+ // - same targets
+ [
+ [Constants::SHARE_TYPE_GROUP, 123, 'samegroup1', '/test', 1],
+ [Constants::SHARE_TYPE_USER, 123, 'user3', '/test', 31],
+ // different unrelated share
+ [Constants::SHARE_TYPE_GROUP, 456, 'recipientgroup1', '/test (4)', 31],
+ ],
+ [
+ // leave all alone
+ ['/test', 1],
+ ['/test', 31],
+ // leave unrelated alone
+ ['/test (4)', 31],
+ ]
+ ],
+ ];
+ }
+
+ /**
+ * Test merge shares from group shares
+ *
+ * @dataProvider sharesDataProvider
+ */
+ public function testMergeGroupShares($shares, $expectedShares) {
+ $shareIds = [];
+
+ foreach ($shares as $share) {
+ // if parent
+ if (isset($share[5])) {
+ // adjust to real id
+ $share[5] = $shareIds[$share[5]];
+ } else {
+ $share[5] = null;
+ }
+ $shareIds[] = $this->createShare($share[0], $share[1], $share[2], $share[3], $share[4], $share[5]);
+ }
+
+ /** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+ $outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->repair->run($outputMock);
+
+ foreach ($expectedShares as $index => $expectedShare) {
+ $share = $this->getShareById($shareIds[$index]);
+ $this->assertEquals($expectedShare[0], $share['file_target']);
+ $this->assertEquals($expectedShare[1], $share['permissions']);
+ }
+ }
+}
+