2015-09-17 17:01:11 +03:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com>
|
|
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
|
|
* later.
|
|
|
|
* See the COPYING-README file.
|
|
|
|
*/
|
2015-10-01 09:32:24 +03:00
|
|
|
|
2015-09-17 17:01:11 +03:00
|
|
|
namespace Test\Repair;
|
|
|
|
|
2015-10-01 09:32:24 +03:00
|
|
|
|
|
|
|
use OC\Repair\RepairInvalidShares;
|
|
|
|
use OC\Share\Constants;
|
2016-04-22 16:35:39 +03:00
|
|
|
use OCP\Migration\IOutput;
|
|
|
|
use OCP\Migration\IRepairStep;
|
2015-10-01 09:32:24 +03:00
|
|
|
use Test\TestCase;
|
|
|
|
|
2015-09-17 17:01:11 +03:00
|
|
|
/**
|
|
|
|
* Tests for repairing invalid shares
|
|
|
|
*
|
2015-11-03 03:52:41 +03:00
|
|
|
* @group DB
|
|
|
|
*
|
2015-09-17 17:01:11 +03:00
|
|
|
* @see \OC\Repair\RepairInvalidShares
|
|
|
|
*/
|
2015-10-01 09:32:24 +03:00
|
|
|
class RepairInvalidSharesTest extends TestCase {
|
2015-09-17 17:01:11 +03:00
|
|
|
|
2016-04-22 16:35:39 +03:00
|
|
|
/** @var IRepairStep */
|
2015-09-17 17:01:11 +03:00
|
|
|
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('8.0.0.0'));
|
|
|
|
|
|
|
|
$this->connection = \OC::$server->getDatabaseConnection();
|
2015-10-01 09:32:24 +03:00
|
|
|
$this->deleteAllShares();
|
2015-09-17 17:01:11 +03:00
|
|
|
|
2015-10-01 09:32:24 +03:00
|
|
|
/** @var \OCP\IConfig $config */
|
|
|
|
$this->repair = new RepairInvalidShares($config, $this->connection);
|
2015-09-17 17:01:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function tearDown() {
|
2015-10-01 09:32:24 +03:00
|
|
|
$this->deleteAllShares();
|
2015-09-17 17:01:11 +03:00
|
|
|
|
|
|
|
parent::tearDown();
|
|
|
|
}
|
|
|
|
|
2015-10-01 09:32:24 +03:00
|
|
|
protected function deleteAllShares() {
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->delete('share')->execute();
|
|
|
|
}
|
|
|
|
|
2015-09-17 17:01:11 +03:00
|
|
|
/**
|
|
|
|
* Test remove expiration date for non-link shares
|
|
|
|
*/
|
|
|
|
public function testRemoveExpirationDateForNonLinkShares() {
|
|
|
|
// user share with bogus expiration date
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values([
|
2015-10-01 09:32:24 +03:00
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
|
2015-09-17 17:01:11 +03:00
|
|
|
'share_with' => $qb->expr()->literal('recipientuser1'),
|
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal('folder'),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal(1),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
'expiration' => $qb->expr()->literal('2015-09-25 00:00:00')
|
|
|
|
])
|
|
|
|
->execute();
|
|
|
|
|
2015-10-20 11:11:25 +03:00
|
|
|
$bogusShareId = $this->getLastShareId();
|
2015-09-17 17:01:11 +03:00
|
|
|
|
|
|
|
// link share with expiration date
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values([
|
2015-10-01 09:32:24 +03:00
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
|
2015-09-17 17:01:11 +03:00
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal('folder'),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal(1),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
'expiration' => $qb->expr()->literal('2015-09-25 00:00:00'),
|
|
|
|
'token' => $qb->expr()->literal('abcdefg')
|
|
|
|
])->execute();
|
|
|
|
|
2016-04-22 16:35:39 +03:00
|
|
|
/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
|
|
|
|
$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
|
|
|
|
->disableOriginalConstructor()
|
|
|
|
->getMock();
|
|
|
|
|
|
|
|
$this->repair->run($outputMock);
|
2015-09-17 17:01:11 +03:00
|
|
|
|
|
|
|
$results = $this->connection->getQueryBuilder()
|
|
|
|
->select('*')
|
|
|
|
->from('share')
|
|
|
|
->orderBy('share_type', 'ASC')
|
|
|
|
->execute()
|
|
|
|
->fetchAll();
|
|
|
|
|
|
|
|
$this->assertCount(2, $results);
|
|
|
|
|
|
|
|
$userShare = $results[0];
|
|
|
|
$linkShare = $results[1];
|
|
|
|
$this->assertEquals($bogusShareId, $userShare['id'], 'sanity check');
|
|
|
|
$this->assertNull($userShare['expiration'], 'bogus expiration date was removed');
|
|
|
|
$this->assertNotNull($linkShare['expiration'], 'valid link share expiration date still there');
|
|
|
|
}
|
2015-10-19 16:39:39 +03:00
|
|
|
|
2016-06-23 17:37:03 +03:00
|
|
|
/**
|
|
|
|
* Test remove expiration date for non-link shares
|
|
|
|
*/
|
|
|
|
public function testAddShareLinkDeletePermission() {
|
|
|
|
$oldPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE;
|
|
|
|
$newPerms = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
|
|
|
|
|
|
|
|
// share with old permissions
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values([
|
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
|
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal('folder'),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal($oldPerms),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
])
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
$bogusShareId = $this->getLastShareId();
|
|
|
|
|
|
|
|
// share with read-only permissions
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values([
|
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
|
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal('folder'),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal(\OCP\Constants::PERMISSION_READ),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
])
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
$keepThisShareId = $this->getLastShareId();
|
|
|
|
|
|
|
|
// user share to keep
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values([
|
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
|
|
|
|
'share_with' => $qb->expr()->literal('recipientuser1'),
|
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal('folder'),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal(3),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
])
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
$keepThisShareId2 = $this->getLastShareId();
|
|
|
|
|
|
|
|
/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
|
|
|
|
$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
|
|
|
|
->disableOriginalConstructor()
|
|
|
|
->getMock();
|
|
|
|
|
|
|
|
$this->repair->run($outputMock);
|
|
|
|
|
|
|
|
$results = $this->connection->getQueryBuilder()
|
|
|
|
->select('*')
|
|
|
|
->from('share')
|
|
|
|
->orderBy('permissions', 'ASC')
|
|
|
|
->execute()
|
|
|
|
->fetchAll();
|
|
|
|
|
|
|
|
$this->assertCount(3, $results);
|
|
|
|
|
|
|
|
$untouchedShare = $results[0];
|
|
|
|
$untouchedShare2 = $results[1];
|
|
|
|
$updatedShare = $results[2];
|
|
|
|
$this->assertEquals($keepThisShareId, $untouchedShare['id'], 'sanity check');
|
|
|
|
$this->assertEquals($keepThisShareId2, $untouchedShare2['id'], 'sanity check');
|
|
|
|
$this->assertEquals($bogusShareId, $updatedShare['id'], 'sanity check');
|
|
|
|
$this->assertEquals($newPerms, $updatedShare['permissions'], 'delete permission was added');
|
|
|
|
}
|
|
|
|
|
2015-10-19 16:39:39 +03:00
|
|
|
/**
|
|
|
|
* Test remove shares where the parent share does not exist anymore
|
|
|
|
*/
|
|
|
|
public function testSharesNonExistingParent() {
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$shareValues = [
|
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_USER),
|
|
|
|
'share_with' => $qb->expr()->literal('recipientuser1'),
|
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal('folder'),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal(1),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
'expiration' => $qb->expr()->literal('2015-09-25 00:00:00')
|
|
|
|
];
|
|
|
|
|
|
|
|
// valid share
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values($shareValues)
|
|
|
|
->execute();
|
|
|
|
$parent = $this->getLastShareId();
|
|
|
|
|
|
|
|
// share with existing parent
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values(array_merge($shareValues, [
|
|
|
|
'parent' => $qb->expr()->literal($parent),
|
|
|
|
]))->execute();
|
|
|
|
$validChild = $this->getLastShareId();
|
|
|
|
|
|
|
|
// share with non-existing parent
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values(array_merge($shareValues, [
|
|
|
|
'parent' => $qb->expr()->literal($parent + 100),
|
|
|
|
]))->execute();
|
|
|
|
$invalidChild = $this->getLastShareId();
|
|
|
|
|
|
|
|
$query = $this->connection->getQueryBuilder();
|
|
|
|
$result = $query->select('id')
|
|
|
|
->from('share')
|
|
|
|
->orderBy('id', 'ASC')
|
|
|
|
->execute();
|
|
|
|
$rows = $result->fetchAll();
|
2015-11-19 19:18:22 +03:00
|
|
|
$this->assertEquals([['id' => $parent], ['id' => $validChild], ['id' => $invalidChild]], $rows);
|
2015-10-19 16:39:39 +03:00
|
|
|
$result->closeCursor();
|
|
|
|
|
2016-04-22 16:35:39 +03:00
|
|
|
/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
|
|
|
|
$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
|
|
|
|
->disableOriginalConstructor()
|
|
|
|
->getMock();
|
|
|
|
|
|
|
|
$this->repair->run($outputMock);
|
2015-10-19 16:39:39 +03:00
|
|
|
|
|
|
|
$query = $this->connection->getQueryBuilder();
|
|
|
|
$result = $query->select('id')
|
|
|
|
->from('share')
|
|
|
|
->orderBy('id', 'ASC')
|
|
|
|
->execute();
|
|
|
|
$rows = $result->fetchAll();
|
2015-11-19 19:18:22 +03:00
|
|
|
$this->assertEquals([['id' => $parent], ['id' => $validChild]], $rows);
|
2015-10-19 16:39:39 +03:00
|
|
|
$result->closeCursor();
|
|
|
|
}
|
|
|
|
|
2016-11-07 14:25:05 +03:00
|
|
|
public function fileSharePermissionsProvider() {
|
|
|
|
return [
|
|
|
|
// unchanged for folder
|
|
|
|
[
|
|
|
|
'folder',
|
|
|
|
31,
|
|
|
|
31,
|
|
|
|
],
|
|
|
|
// unchanged for read-write + share
|
|
|
|
[
|
|
|
|
'file',
|
|
|
|
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE,
|
|
|
|
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE,
|
|
|
|
],
|
|
|
|
// fixed for all perms
|
|
|
|
[
|
|
|
|
'file',
|
|
|
|
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_SHARE,
|
|
|
|
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE,
|
|
|
|
],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test adjusting file share permissions
|
|
|
|
*
|
|
|
|
* @dataProvider fileSharePermissionsProvider
|
|
|
|
*/
|
|
|
|
public function testFileSharePermissions($itemType, $testPerms, $expectedPerms) {
|
|
|
|
$qb = $this->connection->getQueryBuilder();
|
|
|
|
$qb->insert('share')
|
|
|
|
->values([
|
|
|
|
'share_type' => $qb->expr()->literal(Constants::SHARE_TYPE_LINK),
|
|
|
|
'uid_owner' => $qb->expr()->literal('user1'),
|
|
|
|
'item_type' => $qb->expr()->literal($itemType),
|
|
|
|
'item_source' => $qb->expr()->literal(123),
|
|
|
|
'item_target' => $qb->expr()->literal('/123'),
|
|
|
|
'file_source' => $qb->expr()->literal(123),
|
|
|
|
'file_target' => $qb->expr()->literal('/test'),
|
|
|
|
'permissions' => $qb->expr()->literal($testPerms),
|
|
|
|
'stime' => $qb->expr()->literal(time()),
|
|
|
|
])
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
$shareId = $this->getLastShareId();
|
|
|
|
|
|
|
|
/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
|
|
|
|
$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
|
|
|
|
->disableOriginalConstructor()
|
|
|
|
->getMock();
|
|
|
|
|
|
|
|
$this->repair->run($outputMock);
|
|
|
|
|
|
|
|
$results = $this->connection->getQueryBuilder()
|
|
|
|
->select('*')
|
|
|
|
->from('share')
|
|
|
|
->orderBy('permissions', 'ASC')
|
|
|
|
->execute()
|
|
|
|
->fetchAll();
|
|
|
|
|
|
|
|
$this->assertCount(1, $results);
|
|
|
|
|
|
|
|
$updatedShare = $results[0];
|
|
|
|
|
|
|
|
$this->assertEquals($expectedPerms, $updatedShare['permissions']);
|
|
|
|
}
|
|
|
|
|
2015-10-19 16:39:39 +03:00
|
|
|
/**
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
protected function getLastShareId() {
|
2015-11-19 19:18:22 +03:00
|
|
|
return $this->connection->lastInsertId('*PREFIX*share');
|
2015-10-19 16:39:39 +03:00
|
|
|
}
|
2015-09-17 17:01:11 +03:00
|
|
|
}
|
|
|
|
|