From 7baa4ea1a48df31139fe6d36169cbc690208db62 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 7 Nov 2016 12:25:05 +0100 Subject: Add repair step to fix file share permissions Signed-off-by: Lukas Reschke --- lib/private/Repair/RepairInvalidShares.php | 33 ++++++++++++++ tests/lib/Repair/RepairInvalidSharesTest.php | 67 ++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php index 6cb690057bb..05267be72cf 100644 --- a/lib/private/Repair/RepairInvalidShares.php +++ b/lib/private/Repair/RepairInvalidShares.php @@ -27,6 +27,7 @@ namespace OC\Repair; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; +use Doctrine\DBAL\Platforms\OraclePlatform; /** * Repairs shares with invalid data @@ -91,6 +92,35 @@ class RepairInvalidShares implements IRepairStep { } } + /** + * Adjust file share permissions + */ + private function adjustFileSharePermissions(IOutput $out) { + $mask = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE; + $builder = $this->connection->getQueryBuilder(); + + + if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { + $permsFunc = $builder->createFunction( + 'bitand(' . $builder->getColumnName('permissions') . ', ' . $mask . ')' + ); + } else { + $permsFunc = $builder->createFunction( + '(' . $builder->getColumnName('permissions') . ' & ' . $mask . ')' + ); + } + $builder + ->update('share') + ->set('permissions', $permsFunc) + ->where($builder->expr()->eq('item_type', $builder->expr()->literal('file'))) + ->andWhere($builder->expr()->neq('permissions', $permsFunc)); + + $updatedEntries = $builder->execute(); + if ($updatedEntries > 0) { + $out->info('Fixed file share permissions for ' . $updatedEntries . ' shares'); + } + } + /** * Remove shares where the parent share does not exist anymore */ @@ -137,6 +167,9 @@ class RepairInvalidShares implements IRepairStep { // this situation was only possible before 9.1 $this->addShareLinkDeletePermission($out); } + if (version_compare($ocVersionFromBeforeUpdate, '9.2.0.2', '<')) { + $this->adjustFileSharePermissions($out); + } $this->removeSharesNonExistingParent($out); } diff --git a/tests/lib/Repair/RepairInvalidSharesTest.php b/tests/lib/Repair/RepairInvalidSharesTest.php index 1ac42e53bf6..83dbed7d202 100644 --- a/tests/lib/Repair/RepairInvalidSharesTest.php +++ b/tests/lib/Repair/RepairInvalidSharesTest.php @@ -278,6 +278,73 @@ class RepairInvalidSharesTest extends TestCase { $result->closeCursor(); } + 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']); + } + /** * @return int */ -- cgit v1.2.3 From 5d01004368c4b1a3898831955fac58a86184af5a Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Thu, 22 Dec 2016 10:20:22 +0100 Subject: Adjust version to Nextcloud Signed-off-by: Lukas Reschke --- lib/private/Repair/RepairInvalidShares.php | 2 +- version.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php index 05267be72cf..e0f66049784 100644 --- a/lib/private/Repair/RepairInvalidShares.php +++ b/lib/private/Repair/RepairInvalidShares.php @@ -167,7 +167,7 @@ class RepairInvalidShares implements IRepairStep { // this situation was only possible before 9.1 $this->addShareLinkDeletePermission($out); } - if (version_compare($ocVersionFromBeforeUpdate, '9.2.0.2', '<')) { + if (version_compare($ocVersionFromBeforeUpdate, '12.0.0.11', '<')) { $this->adjustFileSharePermissions($out); } diff --git a/version.php b/version.php index 6db26c8c66c..90f4e65055a 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(12, 0, 0, 11); +$OC_Version = array(12, 0, 0, 12); // The human readable string $OC_VersionString = '12.0 alpha'; -- cgit v1.2.3 From 4128a08333746638e7a872ca89f1431cae68161d Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 5 Jan 2017 11:45:10 +0100 Subject: Add bitwise AND and OR to the expression builder Signed-off-by: Joas Schilling --- .../ExpressionBuilder/ExpressionBuilder.php | 38 +++++++++++++++++++++- lib/public/DB/QueryBuilder/IExpressionBuilder.php | 21 ++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php index f9170e97a02..f172260df79 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php @@ -30,6 +30,8 @@ use OC\DB\QueryBuilder\Literal; use OC\DB\QueryBuilder\QueryFunction; use OC\DB\QueryBuilder\QuoteHelper; use OCP\DB\QueryBuilder\IExpressionBuilder; +use OCP\DB\QueryBuilder\ILiteral; +use OCP\DB\QueryBuilder\IQueryFunction; use OCP\IDBConnection; class ExpressionBuilder implements IExpressionBuilder { @@ -39,12 +41,16 @@ class ExpressionBuilder implements IExpressionBuilder { /** @var QuoteHelper */ protected $helper; + /** @var IDBConnection */ + protected $connection; + /** * Initializes a new ExpressionBuilder. * * @param \OCP\IDBConnection $connection */ public function __construct(IDBConnection $connection) { + $this->connection = $connection; $this->helper = new QuoteHelper(); $this->expressionBuilder = new DoctrineExpressionBuilder($connection); } @@ -344,13 +350,43 @@ class ExpressionBuilder implements IExpressionBuilder { return $this->expressionBuilder->notIn($x, $y); } + /** + * Binary AND Operator copies a bit to the result if it exists in both operands. + * + * @param string|ILiteral $x The field or value to check + * @param int $y Bitmap that must be set + * @return IQueryFunction + * @since 12.0.0 + */ + public function bitwiseAnd($x, $y) { + return new QueryFunction($this->connection->getDatabasePlatform()->getBitAndComparisonExpression( + $this->helper->quoteColumnName($x), + $y + )); + } + + /** + * Binary OR Operator copies a bit if it exists in either operand. + * + * @param string|ILiteral $x The field or value to check + * @param int $y Bitmap that must be set + * @return IQueryFunction + * @since 12.0.0 + */ + public function bitwiseOr($x, $y) { + return new QueryFunction($this->connection->getDatabasePlatform()->getBitOrComparisonExpression( + $this->helper->quoteColumnName($x), + $y + )); + } + /** * Quotes a given input parameter. * * @param mixed $input The parameter to be quoted. * @param mixed|null $type One of the IQueryBuilder::PARAM_* constants * - * @return Literal + * @return ILiteral */ public function literal($input, $type = null) { return new Literal($this->expressionBuilder->literal($input, $type)); diff --git a/lib/public/DB/QueryBuilder/IExpressionBuilder.php b/lib/public/DB/QueryBuilder/IExpressionBuilder.php index 8164c738ca5..c123875b803 100644 --- a/lib/public/DB/QueryBuilder/IExpressionBuilder.php +++ b/lib/public/DB/QueryBuilder/IExpressionBuilder.php @@ -305,6 +305,27 @@ interface IExpressionBuilder { */ public function notIn($x, $y, $type = null); + + /** + * Creates a bitwise AND comparison + * + * @param string|ILiteral $x The field or value to check + * @param int $y Bitmap that must be set + * @return IQueryFunction + * @since 12.0.0 + */ + public function bitwiseAnd($x, $y); + + /** + * Creates a bitwise OR comparison + * + * @param string|ILiteral $x The field or value to check + * @param int $y Bitmap that must be set + * @return IQueryFunction + * @since 12.0.0 + */ + public function bitwiseOr($x, $y); + /** * Quotes a given input parameter. * -- cgit v1.2.3 From 22e74cf5ac65dde9a6154fcc32a89ba7231cb01f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 5 Jan 2017 11:45:43 +0100 Subject: Use the new expression Signed-off-by: Joas Schilling --- lib/private/Repair/RepairInvalidShares.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php index e0f66049784..04624c910dd 100644 --- a/lib/private/Repair/RepairInvalidShares.php +++ b/lib/private/Repair/RepairInvalidShares.php @@ -99,16 +99,7 @@ class RepairInvalidShares implements IRepairStep { $mask = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE; $builder = $this->connection->getQueryBuilder(); - - if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) { - $permsFunc = $builder->createFunction( - 'bitand(' . $builder->getColumnName('permissions') . ', ' . $mask . ')' - ); - } else { - $permsFunc = $builder->createFunction( - '(' . $builder->getColumnName('permissions') . ' & ' . $mask . ')' - ); - } + $permsFunc = $builder->expr()->bitwiseAnd('permissions', $mask); $builder ->update('share') ->set('permissions', $permsFunc) -- cgit v1.2.3