summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoeland Jago Douma <rullzer@owncloud.com>2016-05-30 14:56:19 +0200
committerRoeland Jago Douma <roeland@famdouma.nl>2016-06-10 12:44:49 +0200
commit1b66db72d916a763b1c22613b9df5c42e93593a8 (patch)
tree8c53f3fe90b25e86ddc48b09cba4801d85de02de
parenta0d8702a1c168a178846ceba849b1521e6462b0f (diff)
downloadnextcloud-server-1b66db72d916a763b1c22613b9df5c42e93593a8.tar.gz
nextcloud-server-1b66db72d916a763b1c22613b9df5c42e93593a8.zip
Repair job to fix permissions for avatars
Fixes #22978 On some older installations the permissions for the userRoot and the avatars are not correct. This breaks since we now use the Node API in the avatar code. This repair job makes sure that the permissions are set correctly. * Unit tests added
-rw-r--r--lib/private/Repair.php2
-rw-r--r--lib/private/Repair/AvatarPermissions.php107
-rw-r--r--tests/lib/Repair/AvatarPermissionsTest.php180
3 files changed, 289 insertions, 0 deletions
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index 710bbbbaedf..bb2967d7e6e 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -29,6 +29,7 @@
namespace OC;
use OC\Repair\AssetCache;
+use OC\Repair\AvatarPermissions;
use OC\Repair\CleanTags;
use OC\Repair\Collation;
use OC\Repair\DropOldJobs;
@@ -134,6 +135,7 @@ class Repair implements IOutput{
new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new SharePropagation(\OC::$server->getConfig()),
new RemoveOldShares(\OC::$server->getDatabaseConnection()),
+ new AvatarPermissions(\OC::$server->getDatabaseConnection()),
];
}
diff --git a/lib/private/Repair/AvatarPermissions.php b/lib/private/Repair/AvatarPermissions.php
new file mode 100644
index 00000000000..1d96a79ac1f
--- /dev/null
+++ b/lib/private/Repair/AvatarPermissions.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * @author Roeland Jago Douma <rullzer@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 OC\Repair;
+
+use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+/**
+ * Class AvatarPermissions
+ *
+ * @package OC\Repair
+ */
+class AvatarPermissions implements IRepairStep {
+ /** @var IDBConnection */
+ private $connection;
+
+ /**
+ * AvatarPermissions constructor.
+ *
+ * @param IDBConnection $connection
+ */
+ public function __construct(IDBConnection $connection) {
+ $this->connection = $connection;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return 'Fix permissions so avatars can be stored again';
+ }
+
+ /**
+ * @param IOutput $output
+ */
+ public function run(IOutput $output) {
+ $output->startProgress(2);
+ $this->fixUserRootPermissions();
+ $output->advance();
+ $this->fixAvatarPermissions();
+ $output->finishProgress();
+ }
+
+ /**
+ * Make sure all user roots have permissions 23 (all but share)
+ */
+ protected function fixUserRootPermissions() {
+ $qb = $this->connection->getQueryBuilder();
+ $qb2 = $this->connection->getQueryBuilder();
+
+ $qb->select('numeric_id')
+ ->from('storages')
+ ->where($qb->expr()->like('id', $qb2->createParameter('like')));
+
+ $qb2->update('filecache')
+ ->set('permissions', $qb2->createNamedParameter(23))
+ ->where($qb2->expr()->eq('path', $qb2->createNamedParameter('')))
+ ->andWhere($qb2->expr()->in('storage', $qb2->createFunction($qb->getSQL())))
+ ->andWhere($qb2->expr()->neq('permissions', $qb2->createNamedParameter(23)))
+ ->setParameter('like', 'home::%');
+
+
+ $qb2->execute();
+ }
+
+ /**
+ * Make sure all avatar files in the user roots have permission 27
+ */
+ protected function fixAvatarPermissions() {
+ $qb = $this->connection->getQueryBuilder();
+ $qb2 = $this->connection->getQueryBuilder();
+
+ $qb->select('numeric_id')
+ ->from('storages')
+ ->where($qb->expr()->like('id', $qb2->createParameter('like')));
+
+ $qb2->update('filecache')
+ ->set('permissions', $qb2->createNamedParameter(27))
+ ->where($qb2->expr()->like('path', $qb2->createNamedParameter('avatar.%')))
+ ->andWhere($qb2->expr()->in('storage', $qb2->createFunction($qb->getSQL())))
+ ->andWhere($qb2->expr()->neq('permissions', $qb2->createNamedParameter(27)))
+ ->setParameter('like', 'home::%');
+
+ $qb2->execute();
+ }
+
+}
+
diff --git a/tests/lib/Repair/AvatarPermissionsTest.php b/tests/lib/Repair/AvatarPermissionsTest.php
new file mode 100644
index 00000000000..fb0b29daeb0
--- /dev/null
+++ b/tests/lib/Repair/AvatarPermissionsTest.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * @author Roeland Jago Douma <rullzer@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;
+
+/**
+ * Test for fixing the userRoot and avatar permissions
+ *
+ * @group DB
+ *
+ * @see \OC\Repair\AvatarPermissionsTest
+ */
+class AvatarPermissionsTest extends \Test\TestCase {
+
+ /** @var \OC\Repair\AvatarPermissions */
+ protected $repair;
+
+ /** @var \OCP\IDBConnection */
+ protected $connection;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->connection = \OC::$server->getDatabaseConnection();
+ $this->repair = new \OC\Repair\AvatarPermissions($this->connection);
+ $this->cleanUpTables();
+ }
+
+ protected function tearDown() {
+ $this->cleanUpTables();
+
+ parent::tearDown();
+ }
+
+ protected function cleanUpTables() {
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('filecache')->execute();
+ $qb->delete('storages')->execute();
+ }
+
+ public function dataFixUserRootPermissions() {
+ return [
+ ['home::user', '', 0, 23],
+ ['home::user', 'foo', 0, 0],
+ ['home::user', 'avatar.jpg', 0, 0],
+ ['ABC::user', '', 0, 0],
+ ['ABC::user', 'foo', 0, 0],
+ ];
+ }
+
+ /**
+ * @dataProvider dataFixUserRootPermissions
+ *
+ * @param string $storageId
+ * @param string $path
+ * @param int $permissionsBefore
+ * @param int $permissionsAfter
+ */
+ public function testFixUserRootPermissions($storageId, $path, $permissionsBefore, $permissionsAfter) {
+ $userStorage = $this->addStorage($storageId);
+ $userHome = $this->addFileCacheEntry($userStorage, $path, $permissionsBefore);
+
+ $this->invokePrivate($this->repair, 'fixUserRootPermissions', []);
+
+ $this->verifyPermissions($userHome, $permissionsAfter);
+ }
+
+ public function dataFixAvatarPermissions() {
+ return [
+ ['home::user', '', 0, 0],
+ ['home::user', 'avatar.jpg', 0, 27],
+ ['home::user', 'avatar.png', 0, 27],
+ ['home::user', 'avatar.32.png', 0, 27],
+ ['home::user', 'mine.txt', 0, 0],
+ ['ABC::user', '', 0, 0],
+ ['ABC::user', 'avatar.jpg', 0, 0],
+ ['ABC::user', 'avatar.png', 0, 0],
+ ['ABC::user', 'avatar.32.png', 0, 0],
+ ['ABC::user', 'mine.txt', 0, 0],
+ ];
+ }
+
+ /**
+ * @dataProvider dataFixAvatarPermissions
+ *
+ * @param string $storageId
+ * @param string $path
+ * @param int $permissionsBefore
+ * @param int $permissionsAfter
+ */
+ public function testFixAvatarPermissions($storageId, $path, $permissionsBefore, $permissionsAfter) {
+ $userStorage = $this->addStorage($storageId);
+ $userHome = $this->addFileCacheEntry($userStorage, $path, $permissionsBefore);
+
+ $this->invokePrivate($this->repair, 'fixAvatarPermissions', []);
+
+ $this->verifyPermissions($userHome, $permissionsAfter);
+ }
+
+ /**
+ * Add a new storage
+ *
+ * @param string $id
+ * @return int The numeric id
+ */
+ protected function addStorage($id) {
+ $qb = $this->connection->getQueryBuilder();
+
+ $qb->insert('storages')
+ ->values([
+ 'id' => $qb->createNamedParameter($id)
+ ]);
+
+ $qb->execute();
+
+ return $qb->getLastInsertId();
+ }
+
+ /**
+ * Add a filecache entry
+ *
+ * @param int $storage
+ * @param string $path
+ * @param int $permissions
+ *
+ * @return int The fileid
+ */
+ protected function addFileCacheEntry($storage, $path, $permissions) {
+ $qb = $this->connection->getQueryBuilder();
+
+ $qb->insert('filecache')
+ ->values([
+ 'path' => $qb->createNamedParameter($path),
+ 'storage' => $qb->createNamedParameter($storage),
+ 'permissions' => $qb->createNamedParameter($permissions),
+ ]);
+
+ $qb->execute();
+
+ return $qb->getLastInsertId();
+ }
+
+ /**
+ * @param int $fileId
+ * @param int $permissions
+ */
+ protected function verifyPermissions($fileId, $permissions) {
+ $qb = $this->connection->getQueryBuilder();
+
+ $qb->select('permissions')
+ ->from('filecache')
+ ->where($qb->expr()->eq('fileid', $qb->createNamedParameter($fileId)));
+
+ $cursor = $qb->execute();
+
+ $data = $cursor->fetch();
+ $cursor->closeCursor();
+
+ $this->assertSame($permissions, (int)$data['permissions']);
+ }
+
+
+}