[Pkg-owncloud-commits] [owncloud] 114/129: Add a repair step that checks for group membership on shares
David Prévot
taffit at moszumanska.debian.org
Thu Nov 5 01:04:29 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch stable8
in repository owncloud.
commit 3f3bcbeb4728f8f2fd7ea380576862a27a7e05ba
Author: Joas Schilling <nickvergessen at owncloud.com>
Date: Mon Oct 19 16:41:43 2015 +0200
Add a repair step that checks for group membership on shares
---
core/command/maintenance/repair.php | 17 ++-
lib/private/repair.php | 13 ++
lib/repair/oldgroupmembershipshares.php | 117 ++++++++++++++++++
tests/lib/repair/oldgroupmembershipsharestest.php | 138 ++++++++++++++++++++++
4 files changed, 284 insertions(+), 1 deletion(-)
diff --git a/core/command/maintenance/repair.php b/core/command/maintenance/repair.php
index 5df362f..f7c0cc4 100644
--- a/core/command/maintenance/repair.php
+++ b/core/command/maintenance/repair.php
@@ -26,6 +26,7 @@ namespace OC\Core\Command\Maintenance;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Repair extends Command {
@@ -49,10 +50,24 @@ class Repair extends Command {
protected function configure() {
$this
->setName('maintenance:repair')
- ->setDescription('repair this installation');
+ ->setDescription('repair this installation')
+ ->addOption(
+ 'include-expensive',
+ null,
+ InputOption::VALUE_NONE,
+ 'Use this option when you want to include resource and load expensive tasks'
+ )
+ ;
}
protected function execute(InputInterface $input, OutputInterface $output) {
+ $includeExpensive = $input->getOption('include-expensive');
+ if ($includeExpensive) {
+ foreach ($this->repair->getExpensiveRepairSteps() as $step) {
+ $this->repair->addStep($step);
+ }
+ }
+
$maintenanceMode = $this->config->getSystemValue('maintenance', false);
$this->config->setSystemValue('maintenance', true);
diff --git a/lib/private/repair.php b/lib/private/repair.php
index 20219e3..f6ac7eb 100644
--- a/lib/private/repair.php
+++ b/lib/private/repair.php
@@ -34,6 +34,7 @@ use OC\Repair\AssetCache;
use OC\Repair\CleanTags;
use OC\Repair\Collation;
use OC\Repair\DropOldJobs;
+use OC\Repair\OldGroupMembershipShares;
use OC\Repair\RemoveGetETagEntries;
use OC\Repair\SqliteAutoincrement;
use OC\Repair\DropOldTables;
@@ -119,6 +120,18 @@ class Repair extends BasicEmitter {
}
/**
+ * Returns expensive repair steps to be run on the
+ * command line with a special option.
+ *
+ * @return array of RepairStep instances
+ */
+ public static function getExpensiveRepairSteps() {
+ return [
+ new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()),
+ ];
+ }
+
+ /**
* Returns the repair steps to be run before an
* upgrade.
*
diff --git a/lib/repair/oldgroupmembershipshares.php b/lib/repair/oldgroupmembershipshares.php
new file mode 100644
index 0000000..2d701ac
--- /dev/null
+++ b/lib/repair/oldgroupmembershipshares.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen at owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, 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 OC\Repair;
+
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\Share;
+
+class OldGroupMembershipShares extends BasicEmitter implements RepairStep {
+
+ /** @var \OCP\IDBConnection */
+ protected $connection;
+
+ /** @var \OCP\IGroupManager */
+ protected $groupManager;
+
+ /**
+ * @var array [gid => [uid => (bool)]]
+ */
+ protected $memberships;
+
+ /**
+ * @param IDBConnection $connection
+ * @param IGroupManager $groupManager
+ */
+ public function __construct(IDBConnection $connection, IGroupManager $groupManager) {
+ $this->connection = $connection;
+ $this->groupManager = $groupManager;
+ }
+
+ /**
+ * Returns the step's name
+ *
+ * @return string
+ */
+ public function getName() {
+ return 'Remove shares of old group memberships';
+ }
+
+ /**
+ * Run repair step.
+ * Must throw exception on error.
+ *
+ * @throws \Exception in case of failure
+ */
+ public function run() {
+ $deletedEntries = 0;
+
+ $query = $this->connection->getQueryBuilder();
+ $query->select(['s1.id', $query->createFunction('s1.`share_with` AS `user`'), $query->createFunction('s2.`share_with` AS `group`')])
+ ->from('share', 's1')
+ ->where($query->expr()->isNotNull('s1.parent'))
+ // \OC\Share\Constant::$shareTypeGroupUserUnique === 2
+ ->andWhere($query->expr()->eq('s1.share_type', $query->expr()->literal(2)))
+ ->andWhere($query->expr()->isNotNull('s2.id'))
+ ->andWhere($query->expr()->eq('s2.share_type', $query->expr()->literal(Share::SHARE_TYPE_GROUP)))
+ ->leftJoin('s1', 'share', 's2', $query->expr()->eq('s1.parent', 's2.id'));
+
+ $deleteQuery = $this->connection->getQueryBuilder();
+ $deleteQuery->delete('share')
+ ->where($query->expr()->eq('id', $deleteQuery->createParameter('share')));
+
+ $result = $query->execute();
+ while ($row = $result->fetch()) {
+ if (!$this->isMember($row['group'], $row['user'])) {
+ $deletedEntries += $deleteQuery->setParameter('share', (int) $row['id'])
+ ->execute();
+ }
+ }
+ $result->closeCursor();
+
+ if ($deletedEntries) {
+ $this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore'));
+ }
+ }
+
+ /**
+ * @param string $gid
+ * @param string $uid
+ * @return bool
+ */
+ protected function isMember($gid, $uid) {
+ if (isset($this->memberships[$gid][$uid])) {
+ return $this->memberships[$gid][$uid];
+ }
+
+ $isMember = $this->groupManager->isInGroup($uid, $gid);
+ if (!isset($this->memberships[$gid])) {
+ $this->memberships[$gid] = [];
+ }
+ $this->memberships[$gid][$uid] = $isMember;
+
+ return $isMember;
+ }
+}
diff --git a/tests/lib/repair/oldgroupmembershipsharestest.php b/tests/lib/repair/oldgroupmembershipsharestest.php
new file mode 100644
index 0000000..74f68bd
--- /dev/null
+++ b/tests/lib/repair/oldgroupmembershipsharestest.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Copyright (c) 2015 Vincent Petry <pvince81 at owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Repair;
+
+use OC\Repair\OldGroupMembershipShares;
+use OC\Share\Constants;
+
+class OldGroupMembershipSharesTest extends \Test\TestCase {
+
+ /** @var OldGroupMembershipShares */
+ protected $repair;
+
+ /** @var \OCP\IDBConnection */
+ protected $connection;
+
+ /** @var \OCP\IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $groupManager;
+
+ protected function setUp() {
+ parent::setUp();
+
+ /** \OCP\IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
+ $this->groupManager = $this->getMockBuilder('OCP\IGroupManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->connection = \OC::$server->getDatabaseConnection();
+
+ $this->deleteAllShares();
+ }
+
+ protected function tearDown() {
+ $this->deleteAllShares();
+
+ parent::tearDown();
+ }
+
+ protected function deleteAllShares() {
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('share')->execute();
+ }
+
+ public function testRun() {
+ $repair = new OldGroupMembershipShares(
+ $this->connection,
+ $this->groupManager
+ );
+
+ $this->groupManager->expects($this->exactly(2))
+ ->method('isInGroup')
+ ->willReturnMap([
+ ['member', 'group', true],
+ ['not-a-member', 'group', false],
+ ]);
+
+ $parent = $this->createShare(Constants::SHARE_TYPE_GROUP, 'group', null);
+ $group2 = $this->createShare(Constants::SHARE_TYPE_GROUP, 'group2', $parent);
+ $user1 = $this->createShare(Constants::SHARE_TYPE_USER, 'user1', $parent);
+
+ // \OC\Share\Constant::$shareTypeGroupUserUnique === 2
+ $member = $this->createShare(2, 'member', $parent);
+ $notAMember = $this->createShare(2, 'not-a-member', $parent);
+
+ $query = $this->connection->getQueryBuilder();
+ $result = $query->select('id')
+ ->from('share')
+ ->orderBy('id', 'ASC')
+ ->execute();
+ $rows = $result->fetchAll();
+ $this->assertSame([['id' => $parent], ['id' => $group2], ['id' => $user1], ['id' => $member], ['id' => $notAMember]], $rows);
+ $result->closeCursor();
+
+ $repair->run();
+
+ $query = $this->connection->getQueryBuilder();
+ $result = $query->select('id')
+ ->from('share')
+ ->orderBy('id', 'ASC')
+ ->execute();
+ $rows = $result->fetchAll();
+ $this->assertSame([['id' => $parent], ['id' => $group2], ['id' => $user1], ['id' => $member]], $rows);
+ $result->closeCursor();
+ }
+
+ /**
+ * @param string $shareType
+ * @param string $shareWith
+ * @param null|int $parent
+ * @return int
+ */
+ protected function createShare($shareType, $shareWith, $parent) {
+ $qb = $this->connection->getQueryBuilder();
+ $shareValues = [
+ 'share_type' => $qb->expr()->literal($shareType),
+ 'share_with' => $qb->expr()->literal($shareWith),
+ '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'),
+ ];
+
+ if ($parent) {
+ $shareValues['parent'] = $qb->expr()->literal($parent);
+ }
+
+ $qb = $this->connection->getQueryBuilder();
+ $qb->insert('share')
+ ->values($shareValues)
+ ->execute();
+
+ return $this->getLastShareId();
+ }
+
+ /**
+ * @return int
+ */
+ protected function getLastShareId() {
+ // select because lastInsertId does not work with OCI
+ $query = $this->connection->getQueryBuilder();
+ $result = $query->select('id')
+ ->from('share')
+ ->orderBy('id', 'DESC')
+ ->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
+ return $row['id'];
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git
More information about the Pkg-owncloud-commits
mailing list