this was a migration step to ownCloud 8.0 to restructure the encryption folder which is no longer needed
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>pull/8603/head
parent
0f3ba9444e
commit
8042e6b8fb
@ -1,127 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2016, ownCloud, Inc. |
||||
* |
||||
* @author Björn Schießle <bjoern@schiessle.org> |
||||
* @author Thomas Müller <thomas.mueller@tmit.eu> |
||||
* |
||||
* @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 OCA\Encryption\Command; |
||||
|
||||
use OC\Files\View; |
||||
use OCA\Encryption\Migration; |
||||
use OCP\IConfig; |
||||
use OCP\IDBConnection; |
||||
use OCP\ILogger; |
||||
use OCP\IUserBackend; |
||||
use OCP\IUserManager; |
||||
use Symfony\Component\Console\Command\Command; |
||||
use Symfony\Component\Console\Input\InputArgument; |
||||
use Symfony\Component\Console\Input\InputInterface; |
||||
use Symfony\Component\Console\Output\OutputInterface; |
||||
|
||||
class MigrateKeys extends Command { |
||||
|
||||
/** @var IUserManager */ |
||||
private $userManager; |
||||
/** @var View */ |
||||
private $view; |
||||
/** @var IDBConnection */ |
||||
private $connection; |
||||
/** @var IConfig */ |
||||
private $config; |
||||
/** @var ILogger */ |
||||
private $logger; |
||||
|
||||
/** |
||||
* @param IUserManager $userManager |
||||
* @param View $view |
||||
* @param IDBConnection $connection |
||||
* @param IConfig $config |
||||
* @param ILogger $logger |
||||
*/ |
||||
public function __construct(IUserManager $userManager, |
||||
View $view, |
||||
IDBConnection $connection, |
||||
IConfig $config, |
||||
ILogger $logger) { |
||||
|
||||
$this->userManager = $userManager; |
||||
$this->view = $view; |
||||
$this->connection = $connection; |
||||
$this->config = $config; |
||||
$this->logger = $logger; |
||||
parent::__construct(); |
||||
} |
||||
|
||||
protected function configure() { |
||||
$this |
||||
->setName('encryption:migrate') |
||||
->setDescription('initial migration to encryption 2.0') |
||||
->addArgument( |
||||
'user_id', |
||||
InputArgument::OPTIONAL | InputArgument::IS_ARRAY, |
||||
'will migrate keys of the given user(s)' |
||||
); |
||||
} |
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) { |
||||
|
||||
// perform system reorganization |
||||
$migration = new Migration($this->config, $this->view, $this->connection, $this->logger); |
||||
|
||||
$users = $input->getArgument('user_id'); |
||||
if (!empty($users)) { |
||||
foreach ($users as $user) { |
||||
if ($this->userManager->userExists($user)) { |
||||
$output->writeln("Migrating keys <info>$user</info>"); |
||||
$migration->reorganizeFolderStructureForUser($user); |
||||
} else { |
||||
$output->writeln("<error>Unknown user $user</error>"); |
||||
} |
||||
} |
||||
} else { |
||||
$output->writeln("Reorganize system folder structure"); |
||||
$migration->reorganizeSystemFolderStructure(); |
||||
$migration->updateDB(); |
||||
foreach($this->userManager->getBackends() as $backend) { |
||||
$name = get_class($backend); |
||||
|
||||
if ($backend instanceof IUserBackend) { |
||||
$name = $backend->getBackendName(); |
||||
} |
||||
|
||||
$output->writeln("Migrating keys for users on backend <info>$name</info>"); |
||||
|
||||
$limit = 500; |
||||
$offset = 0; |
||||
do { |
||||
$users = $backend->getUsers('', $limit, $offset); |
||||
foreach ($users as $user) { |
||||
$output->writeln(" <info>$user</info>"); |
||||
$migration->reorganizeFolderStructureForUser($user); |
||||
} |
||||
$offset += $limit; |
||||
} while(count($users) >= $limit); |
||||
} |
||||
} |
||||
|
||||
$migration->finalCleanUp(); |
||||
|
||||
} |
||||
} |
||||
@ -1,395 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2016, ownCloud, Inc. |
||||
* |
||||
* @author Björn Schießle <bjoern@schiessle.org> |
||||
* @author Joas Schilling <coding@schilljs.com> |
||||
* @author Morris Jobke <hey@morrisjobke.de> |
||||
* @author Robin Appelman <robin@icewind.nl> |
||||
* |
||||
* @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 OCA\Encryption; |
||||
|
||||
|
||||
use OC\Files\View; |
||||
use OCP\App\IAppManager; |
||||
use OCP\IConfig; |
||||
use OCP\IDBConnection; |
||||
use OCP\ILogger; |
||||
|
||||
class Migration { |
||||
|
||||
private $moduleId; |
||||
/** @var \OC\Files\View */ |
||||
private $view; |
||||
/** @var \OCP\IDBConnection */ |
||||
private $connection; |
||||
/** @var IConfig */ |
||||
private $config; |
||||
/** @var ILogger */ |
||||
private $logger; |
||||
/** @var string*/ |
||||
protected $installedVersion; |
||||
/** @var IAppManager */ |
||||
protected $appManager; |
||||
|
||||
/** |
||||
* @param IConfig $config |
||||
* @param View $view |
||||
* @param IDBConnection $connection |
||||
* @param ILogger $logger |
||||
*/ |
||||
public function __construct(IConfig $config, View $view, IDBConnection $connection, ILogger $logger, IAppManager $appManager) { |
||||
$this->view = $view; |
||||
$this->view->disableCacheUpdate(); |
||||
$this->connection = $connection; |
||||
$this->moduleId = \OCA\Encryption\Crypto\Encryption::ID; |
||||
$this->config = $config; |
||||
$this->logger = $logger; |
||||
$this->installedVersion = $this->config->getAppValue('files_encryption', 'installed_version', '-1'); |
||||
$this->appManager = $appManager; |
||||
} |
||||
|
||||
public function finalCleanUp() { |
||||
$this->view->deleteAll('files_encryption/public_keys'); |
||||
$this->updateFileCache(); |
||||
$this->config->deleteAppValue('files_encryption', 'installed_version'); |
||||
} |
||||
|
||||
/** |
||||
* update file cache, copy unencrypted_size to the 'size' column |
||||
*/ |
||||
private function updateFileCache() { |
||||
// make sure that we don't update the file cache multiple times |
||||
// only update during the first run |
||||
if ($this->installedVersion !== '-1') { |
||||
$query = $this->connection->getQueryBuilder(); |
||||
$query->update('filecache') |
||||
->set('size', 'unencrypted_size') |
||||
->where($query->expr()->eq('encrypted', $query->createParameter('encrypted'))) |
||||
->setParameter('encrypted', 1); |
||||
$query->execute(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* iterate through users and reorganize the folder structure |
||||
*/ |
||||
public function reorganizeFolderStructure() { |
||||
$this->reorganizeSystemFolderStructure(); |
||||
|
||||
$limit = 500; |
||||
$offset = 0; |
||||
do { |
||||
$users = \OCP\User::getUsers('', $limit, $offset); |
||||
foreach ($users as $user) { |
||||
$this->reorganizeFolderStructureForUser($user); |
||||
} |
||||
$offset += $limit; |
||||
} while (count($users) >= $limit); |
||||
} |
||||
|
||||
/** |
||||
* reorganize system wide folder structure |
||||
*/ |
||||
public function reorganizeSystemFolderStructure() { |
||||
|
||||
$this->createPathForKeys('/files_encryption'); |
||||
|
||||
// backup system wide folders |
||||
$this->backupSystemWideKeys(); |
||||
|
||||
// rename system wide mount point |
||||
$this->renameFileKeys('', '/files_encryption/keys'); |
||||
|
||||
// rename system private keys |
||||
$this->renameSystemPrivateKeys(); |
||||
|
||||
$storage = $this->view->getMount('')->getStorage(); |
||||
$storage->getScanner()->scan('files_encryption'); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* reorganize folder structure for user |
||||
* |
||||
* @param string $user |
||||
*/ |
||||
public function reorganizeFolderStructureForUser($user) { |
||||
// backup all keys |
||||
\OC_Util::tearDownFS(); |
||||
\OC_Util::setupFS($user); |
||||
if ($this->backupUserKeys($user)) { |
||||
// rename users private key |
||||
$this->renameUsersPrivateKey($user); |
||||
$this->renameUsersPublicKey($user); |
||||
// rename file keys |
||||
$path = '/files_encryption/keys'; |
||||
$this->renameFileKeys($user, $path); |
||||
$trashPath = '/files_trashbin/keys'; |
||||
if ($this->appManager->isEnabledForUser('files_trashbin') && $this->view->is_dir($user . '/' . $trashPath)) { |
||||
$this->renameFileKeys($user, $trashPath, true); |
||||
$this->view->deleteAll($trashPath); |
||||
} |
||||
// delete old folders |
||||
$this->deleteOldKeys($user); |
||||
$this->view->getMount('/' . $user)->getStorage()->getScanner()->scan('files_encryption'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* update database |
||||
*/ |
||||
public function updateDB() { |
||||
|
||||
// make sure that we don't update the file cache multiple times |
||||
// only update during the first run |
||||
if ($this->installedVersion === '-1') { |
||||
return; |
||||
} |
||||
|
||||
// delete left-over from old encryption which is no longer needed |
||||
$this->config->deleteAppValue('files_encryption', 'ocsid'); |
||||
$this->config->deleteAppValue('files_encryption', 'types'); |
||||
$this->config->deleteAppValue('files_encryption', 'enabled'); |
||||
|
||||
$oldAppValues = $this->connection->getQueryBuilder(); |
||||
$oldAppValues->select('*') |
||||
->from('appconfig') |
||||
->where($oldAppValues->expr()->eq('appid', $oldAppValues->createParameter('appid'))) |
||||
->setParameter('appid', 'files_encryption'); |
||||
$appSettings = $oldAppValues->execute(); |
||||
|
||||
while ($row = $appSettings->fetch()) { |
||||
// 'installed_version' gets deleted at the end of the migration process |
||||
if ($row['configkey'] !== 'installed_version' ) { |
||||
$this->config->setAppValue('encryption', $row['configkey'], $row['configvalue']); |
||||
$this->config->deleteAppValue('files_encryption', $row['configkey']); |
||||
} |
||||
} |
||||
|
||||
$oldPreferences = $this->connection->getQueryBuilder(); |
||||
$oldPreferences->select('*') |
||||
->from('preferences') |
||||
->where($oldPreferences->expr()->eq('appid', $oldPreferences->createParameter('appid'))) |
||||
->setParameter('appid', 'files_encryption'); |
||||
$preferenceSettings = $oldPreferences->execute(); |
||||
|
||||
while ($row = $preferenceSettings->fetch()) { |
||||
$this->config->setUserValue($row['userid'], 'encryption', $row['configkey'], $row['configvalue']); |
||||
$this->config->deleteUserValue($row['userid'], 'files_encryption', $row['configkey']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* create backup of system-wide keys |
||||
*/ |
||||
private function backupSystemWideKeys() { |
||||
$backupDir = 'encryption_migration_backup_' . date("Y-m-d_H-i-s"); |
||||
$this->view->mkdir($backupDir); |
||||
$this->view->copy('files_encryption', $backupDir . '/files_encryption'); |
||||
} |
||||
|
||||
/** |
||||
* create backup of user specific keys |
||||
* |
||||
* @param string $user |
||||
* @return bool |
||||
*/ |
||||
private function backupUserKeys($user) { |
||||
$encryptionDir = $user . '/files_encryption'; |
||||
if ($this->view->is_dir($encryptionDir)) { |
||||
$backupDir = $user . '/encryption_migration_backup_' . date("Y-m-d_H-i-s"); |
||||
$this->view->mkdir($backupDir); |
||||
$this->view->copy($encryptionDir, $backupDir); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* rename system-wide private keys |
||||
*/ |
||||
private function renameSystemPrivateKeys() { |
||||
$dh = $this->view->opendir('files_encryption'); |
||||
$this->createPathForKeys('/files_encryption/' . $this->moduleId ); |
||||
if (is_resource($dh)) { |
||||
while (($privateKey = readdir($dh)) !== false) { |
||||
if (!\OC\Files\Filesystem::isIgnoredDir($privateKey) ) { |
||||
if (!$this->view->is_dir('/files_encryption/' . $privateKey)) { |
||||
$this->view->rename('files_encryption/' . $privateKey, 'files_encryption/' . $this->moduleId . '/' . $privateKey); |
||||
$this->renameSystemPublicKey($privateKey); |
||||
} |
||||
} |
||||
} |
||||
closedir($dh); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* rename system wide public key |
||||
* |
||||
* @param string $privateKey private key for which we want to rename the corresponding public key |
||||
*/ |
||||
private function renameSystemPublicKey($privateKey) { |
||||
$publicKey = substr($privateKey,0 , strrpos($privateKey, '.privateKey')) . '.publicKey'; |
||||
$this->view->rename('files_encryption/public_keys/' . $publicKey, 'files_encryption/' . $this->moduleId . '/' . $publicKey); |
||||
} |
||||
|
||||
/** |
||||
* rename user-specific private keys |
||||
* |
||||
* @param string $user |
||||
*/ |
||||
private function renameUsersPrivateKey($user) { |
||||
$oldPrivateKey = $user . '/files_encryption/' . $user . '.privateKey'; |
||||
$newPrivateKey = $user . '/files_encryption/' . $this->moduleId . '/' . $user . '.privateKey'; |
||||
if ($this->view->file_exists($oldPrivateKey)) { |
||||
$this->createPathForKeys(dirname($newPrivateKey)); |
||||
$this->view->rename($oldPrivateKey, $newPrivateKey); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* rename user-specific public keys |
||||
* |
||||
* @param string $user |
||||
*/ |
||||
private function renameUsersPublicKey($user) { |
||||
$oldPublicKey = '/files_encryption/public_keys/' . $user . '.publicKey'; |
||||
$newPublicKey = $user . '/files_encryption/' . $this->moduleId . '/' . $user . '.publicKey'; |
||||
if ($this->view->file_exists($oldPublicKey)) { |
||||
$this->createPathForKeys(dirname($newPublicKey)); |
||||
$this->view->rename($oldPublicKey, $newPublicKey); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* rename file keys |
||||
* |
||||
* @param string $user |
||||
* @param string $path |
||||
* @param bool $trash |
||||
*/ |
||||
private function renameFileKeys($user, $path, $trash = false) { |
||||
|
||||
if ($this->view->is_dir($user . '/' . $path) === false) { |
||||
$this->logger->info('Skip dir /' . $user . '/' . $path . ': does not exist'); |
||||
return; |
||||
} |
||||
|
||||
$dh = $this->view->opendir($user . '/' . $path); |
||||
|
||||
if (is_resource($dh)) { |
||||
while (($file = readdir($dh)) !== false) { |
||||
if (!\OC\Files\Filesystem::isIgnoredDir($file)) { |
||||
if ($this->view->is_dir($user . '/' . $path . '/' . $file)) { |
||||
$this->renameFileKeys($user, $path . '/' . $file, $trash); |
||||
} else { |
||||
$target = $this->getTargetDir($user, $path, $file, $trash); |
||||
if ($target !== false) { |
||||
$this->createPathForKeys(dirname($target)); |
||||
$this->view->rename($user . '/' . $path . '/' . $file, $target); |
||||
} else { |
||||
$this->logger->warning( |
||||
'did not move key "' . $file |
||||
. '" could not find the corresponding file in /data/' . $user . '/files.' |
||||
. 'Most likely the key was already moved in a previous migration run and is already on the right place.'); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
closedir($dh); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* get system mount points |
||||
* wrap static method so that it can be mocked for testing |
||||
* |
||||
* @internal |
||||
* @return array |
||||
*/ |
||||
protected function getSystemMountPoints() { |
||||
return \OC_Mount_Config::getSystemMountPoints(); |
||||
} |
||||
|
||||
/** |
||||
* generate target directory |
||||
* |
||||
* @param string $user |
||||
* @param string $keyPath |
||||
* @param string $filename |
||||
* @param bool $trash |
||||
* @return string |
||||
*/ |
||||
private function getTargetDir($user, $keyPath, $filename, $trash) { |
||||
if ($trash) { |
||||
$filePath = substr($keyPath, strlen('/files_trashbin/keys/')); |
||||
$targetDir = $user . '/files_encryption/keys/files_trashbin/' . $filePath . '/' . $this->moduleId . '/' . $filename; |
||||
} else { |
||||
$filePath = substr($keyPath, strlen('/files_encryption/keys/')); |
||||
$targetDir = $user . '/files_encryption/keys/files/' . $filePath . '/' . $this->moduleId . '/' . $filename; |
||||
} |
||||
|
||||
if ($user === '') { |
||||
// for system wide mounts we need to check if the mount point really exists |
||||
$normalized = \OC\Files\Filesystem::normalizePath($filePath); |
||||
$systemMountPoints = $this->getSystemMountPoints(); |
||||
foreach ($systemMountPoints as $mountPoint) { |
||||
$normalizedMountPoint = \OC\Files\Filesystem::normalizePath($mountPoint['mountpoint']) . '/'; |
||||
if (strpos($normalized, $normalizedMountPoint) === 0) |
||||
return $targetDir; |
||||
} |
||||
} else if ($trash === false && $this->view->file_exists('/' . $user. '/files/' . $filePath)) { |
||||
return $targetDir; |
||||
} else if ($trash === true && $this->view->file_exists('/' . $user. '/files_trashbin/' . $filePath)) { |
||||
return $targetDir; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* delete old keys |
||||
* |
||||
* @param string $user |
||||
*/ |
||||
private function deleteOldKeys($user) { |
||||
$this->view->deleteAll($user . '/files_encryption/keyfiles'); |
||||
$this->view->deleteAll($user . '/files_encryption/share-keys'); |
||||
} |
||||
|
||||
/** |
||||
* create directories for the keys recursively |
||||
* |
||||
* @param string $path |
||||
*/ |
||||
private function createPathForKeys($path) { |
||||
if (!$this->view->file_exists($path)) { |
||||
$sub_dirs = explode('/', $path); |
||||
$dir = ''; |
||||
foreach ($sub_dirs as $sub_dir) { |
||||
$dir .= '/' . $sub_dir; |
||||
if (!$this->view->is_dir($dir)) { |
||||
$this->view->mkdir($dir); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,597 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2016, ownCloud, Inc. |
||||
* |
||||
* @author Björn Schießle <bjoern@schiessle.org> |
||||
* @author Joas Schilling <coding@schilljs.com> |
||||
* @author Morris Jobke <hey@morrisjobke.de> |
||||
* @author Robin Appelman <robin@icewind.nl> |
||||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
||||
* |
||||
* @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 OCA\Encryption\Tests; |
||||
|
||||
use OC\Files\View; |
||||
use OCA\Encryption\Migration; |
||||
use OCP\ILogger; |
||||
|
||||
/** |
||||
* Class MigrationTest |
||||
* |
||||
* @package OCA\Encryption\Tests |
||||
* @group DB |
||||
*/ |
||||
class MigrationTest extends \Test\TestCase { |
||||
|
||||
const TEST_ENCRYPTION_MIGRATION_USER1='test_encryption_user1'; |
||||
const TEST_ENCRYPTION_MIGRATION_USER2='test_encryption_user2'; |
||||
const TEST_ENCRYPTION_MIGRATION_USER3='test_encryption_user3'; |
||||
|
||||
/** @var \OC\Files\View */ |
||||
private $view; |
||||
private $public_share_key_id = 'share_key_id'; |
||||
private $recovery_key_id = 'recovery_key_id'; |
||||
private $moduleId; |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject|ILogger */ |
||||
private $logger; |
||||
|
||||
public static function setUpBeforeClass() { |
||||
parent::setUpBeforeClass(); |
||||
\OC::$server->getUserManager()->createUser(self::TEST_ENCRYPTION_MIGRATION_USER1, 'foo'); |
||||
\OC::$server->getUserManager()->createUser(self::TEST_ENCRYPTION_MIGRATION_USER2, 'foo'); |
||||
\OC::$server->getUserManager()->createUser(self::TEST_ENCRYPTION_MIGRATION_USER3, 'foo'); |
||||
} |
||||
|
||||
public static function tearDownAfterClass() { |
||||
$user = \OC::$server->getUserManager()->get(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
if ($user !== null) { $user->delete(); } |
||||
$user = \OC::$server->getUserManager()->get(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
if ($user !== null) { $user->delete(); } |
||||
$user = \OC::$server->getUserManager()->get(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
if ($user !== null) { $user->delete(); } |
||||
parent::tearDownAfterClass(); |
||||
} |
||||
|
||||
|
||||
public function setUp() { |
||||
$this->logger = $this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(); |
||||
$this->view = new \OC\Files\View(); |
||||
$this->moduleId = \OCA\Encryption\Crypto\Encryption::ID; |
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function createDummyShareKeys($uid) { |
||||
$this->loginAsUser($uid); |
||||
|
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder1/folder2/folder3/file3'); |
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder1/folder2/file2'); |
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder1/file.1'); |
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder2/file.2.1'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/folder3/file3/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/folder3/file3/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/folder3/file3/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/file2/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/file2/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/file2/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/file.1/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/file.1/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/file.1/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder2/file.2.1/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder2/file.2.1/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder2/file.2.1/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey' , 'data'); |
||||
if ($this->public_share_key_id) { |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder2/file.2.1/' . $this->public_share_key_id . '.shareKey' , 'data'); |
||||
} |
||||
if ($this->recovery_key_id) { |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder2/file.2.1/' . $this->recovery_key_id . '.shareKey' , 'data'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function createDummyUserKeys($uid) { |
||||
$this->loginAsUser($uid); |
||||
|
||||
$this->view->mkdir($uid . '/files_encryption/'); |
||||
$this->view->mkdir('/files_encryption/public_keys'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/' . $uid . '.privateKey', 'privateKey'); |
||||
$this->view->file_put_contents('/files_encryption/public_keys/' . $uid . '.publicKey', 'publicKey'); |
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function createDummyFileKeys($uid) { |
||||
$this->loginAsUser($uid); |
||||
|
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder1/folder2/folder3/file3'); |
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder1/folder2/file2'); |
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder1/file.1'); |
||||
$this->view->mkdir($uid . '/files_encryption/keys/folder2/file.2.1'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/folder3/file3/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/folder2/file2/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder1/file.1/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_encryption/keys/folder2/file.2.1/fileKey' , 'data'); |
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function createDummyFiles($uid) { |
||||
$this->loginAsUser($uid); |
||||
|
||||
$this->view->mkdir($uid . '/files/folder1/folder2/folder3/file3'); |
||||
$this->view->mkdir($uid . '/files/folder1/folder2/file2'); |
||||
$this->view->mkdir($uid . '/files/folder1/file.1'); |
||||
$this->view->mkdir($uid . '/files/folder2/file.2.1'); |
||||
$this->view->file_put_contents($uid . '/files/folder1/folder2/folder3/file3/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files/folder1/folder2/file2/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files/folder1/file.1/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files/folder2/file.2.1/fileKey' , 'data'); |
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function createDummyFilesInTrash($uid) { |
||||
$this->loginAsUser($uid); |
||||
|
||||
$this->view->mkdir($uid . '/files_trashbin/keys/file1.d5457864'); |
||||
$this->view->mkdir($uid . '/files_trashbin/keys/folder1.d7437648723/file2'); |
||||
$this->view->file_put_contents($uid . '/files_trashbin/keys/file1.d5457864/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_trashbin/keys/file1.d5457864/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_trashbin/keys/folder1.d7437648723/file2/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey' , 'data'); |
||||
|
||||
$this->view->file_put_contents($uid . '/files_trashbin/keys/file1.d5457864/fileKey' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_trashbin/keys/folder1.d7437648723/file2/fileKey' , 'data'); |
||||
|
||||
// create the files itself |
||||
$this->view->mkdir($uid . '/files_trashbin/folder1.d7437648723'); |
||||
$this->view->file_put_contents($uid . '/files_trashbin/file1.d5457864' , 'data'); |
||||
$this->view->file_put_contents($uid . '/files_trashbin/folder1.d7437648723/file2' , 'data'); |
||||
} |
||||
|
||||
protected function createDummySystemWideKeys() { |
||||
$this->view->mkdir('files_encryption'); |
||||
$this->view->mkdir('files_encryption/public_keys'); |
||||
$this->view->file_put_contents('files_encryption/systemwide_1.privateKey', 'data'); |
||||
$this->view->file_put_contents('files_encryption/systemwide_2.privateKey', 'data'); |
||||
$this->view->file_put_contents('files_encryption/public_keys/systemwide_1.publicKey', 'data'); |
||||
$this->view->file_put_contents('files_encryption/public_keys/systemwide_2.publicKey', 'data'); |
||||
} |
||||
|
||||
public function testMigrateToNewFolderStructure() { |
||||
$this->createDummyUserKeys(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
$this->createDummyUserKeys(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
$this->createDummyUserKeys(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
|
||||
$this->createDummyShareKeys(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
$this->createDummyShareKeys(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
$this->createDummyShareKeys(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
|
||||
$this->createDummyFileKeys(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
$this->createDummyFileKeys(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
$this->createDummyFileKeys(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
|
||||
$this->createDummyFiles(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
$this->createDummyFiles(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
$this->createDummyFiles(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
|
||||
$this->createDummyFilesInTrash(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
|
||||
// no user for system wide mount points |
||||
$this->createDummyFileKeys(''); |
||||
$this->createDummyShareKeys(''); |
||||
|
||||
$this->createDummySystemWideKeys(); |
||||
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Encryption\Migration $m */ |
||||
$m = $this->getMockBuilder(Migration::class) |
||||
->setConstructorArgs( |
||||
[ |
||||
\OC::$server->getConfig(), |
||||
new \OC\Files\View(), |
||||
\OC::$server->getDatabaseConnection(), |
||||
$this->logger, |
||||
\OC::$server->getAppManager() |
||||
] |
||||
)->setMethods(['getSystemMountPoints'])->getMock(); |
||||
|
||||
$m->expects($this->any())->method('getSystemMountPoints') |
||||
->will($this->returnValue([['mountpoint' => 'folder1'], ['mountpoint' => 'folder2']])); |
||||
|
||||
$m->reorganizeFolderStructure(); |
||||
// even if it runs twice folder should always move only once |
||||
$m->reorganizeFolderStructure(); |
||||
|
||||
$this->loginAsUser(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
|
||||
$this->assertTrue( |
||||
$this->view->file_exists( |
||||
self::TEST_ENCRYPTION_MIGRATION_USER1 . '/files_encryption/' . |
||||
$this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.publicKey') |
||||
); |
||||
|
||||
$this->loginAsUser(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
|
||||
$this->assertTrue( |
||||
$this->view->file_exists( |
||||
self::TEST_ENCRYPTION_MIGRATION_USER2 . '/files_encryption/' . |
||||
$this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.publicKey') |
||||
); |
||||
|
||||
$this->loginAsUser(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
|
||||
$this->assertTrue( |
||||
$this->view->file_exists( |
||||
self::TEST_ENCRYPTION_MIGRATION_USER3 . '/files_encryption/' . |
||||
$this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.publicKey') |
||||
); |
||||
|
||||
$this->loginAsUser(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
|
||||
$this->assertTrue( |
||||
$this->view->file_exists( |
||||
'/files_encryption/' . $this->moduleId . '/systemwide_1.publicKey') |
||||
); |
||||
$this->assertTrue( |
||||
$this->view->file_exists( |
||||
'/files_encryption/' . $this->moduleId . '/systemwide_2.publicKey') |
||||
); |
||||
|
||||
$this->verifyNewKeyPath(self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
$this->verifyNewKeyPath(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
$this->verifyNewKeyPath(self::TEST_ENCRYPTION_MIGRATION_USER3); |
||||
// system wide keys |
||||
$this->verifyNewKeyPath(''); |
||||
// trash |
||||
$this->verifyFilesInTrash(self::TEST_ENCRYPTION_MIGRATION_USER2); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function verifyFilesInTrash($uid) { |
||||
$this->loginAsUser($uid); |
||||
|
||||
// share keys |
||||
$this->assertTrue( |
||||
$this->view->file_exists($uid . '/files_encryption/keys/files_trashbin/file1.d5457864/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey') |
||||
); |
||||
$this->assertTrue( |
||||
$this->view->file_exists($uid . '/files_encryption/keys/files_trashbin/file1.d5457864/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey') |
||||
); |
||||
$this->assertTrue( |
||||
$this->view->file_exists($uid . '/files_encryption/keys/files_trashbin/folder1.d7437648723/file2/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey') |
||||
); |
||||
|
||||
// file keys |
||||
$this->assertTrue( |
||||
$this->view->file_exists($uid . '/files_encryption/keys/files_trashbin/file1.d5457864/' . $this->moduleId . '/fileKey') |
||||
); |
||||
|
||||
$this->assertTrue( |
||||
$this->view->file_exists($uid . '/files_encryption/keys/files_trashbin/file1.d5457864/' . $this->moduleId . '/fileKey') |
||||
); |
||||
$this->assertTrue( |
||||
$this->view->file_exists($uid . '/files_encryption/keys/files_trashbin/folder1.d7437648723/file2/' . $this->moduleId . '/fileKey') |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @param string $uid |
||||
*/ |
||||
protected function verifyNewKeyPath($uid) { |
||||
// private key |
||||
if ($uid !== '') { |
||||
$this->loginAsUser($uid); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/' . $this->moduleId . '/'. $uid . '.privateKey')); |
||||
} |
||||
// file keys |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/folder3/file3/' . $this->moduleId . '/fileKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/file2/' . $this->moduleId . '/fileKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/file.1/' . $this->moduleId . '/fileKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder2/file.2.1/' .$this->moduleId . '/fileKey')); |
||||
// share keys |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/folder3/file3/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/folder3/file3/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/folder3/file3/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/file2/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/file2/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/folder2/file2/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/file.1/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/file.1/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder1/file.1/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder2/file.2.1/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder2/file.2.1/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.shareKey')); |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder2/file.2.1/' . $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.shareKey')); |
||||
if ($this->public_share_key_id) { |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder2/file.2.1/' . $this->moduleId . '/' . $this->public_share_key_id . '.shareKey')); |
||||
} |
||||
if ($this->recovery_key_id) { |
||||
$this->assertTrue($this->view->file_exists($uid . '/files_encryption/keys/files/folder2/file.2.1/' . $this->moduleId . '/' . $this->recovery_key_id . '.shareKey')); |
||||
} |
||||
} |
||||
|
||||
private function prepareDB() { |
||||
$config = \OC::$server->getConfig(); |
||||
$config->setAppValue('files_encryption', 'recoveryKeyId', 'recovery_id'); |
||||
$config->setAppValue('files_encryption', 'publicShareKeyId', 'share_id'); |
||||
$config->setAppValue('files_encryption', 'recoveryAdminEnabled', '1'); |
||||
$config->setUserValue(self::TEST_ENCRYPTION_MIGRATION_USER1, 'files_encryption', 'recoverKeyEnabled', '1'); |
||||
|
||||
//$this->invokePrivate($config, 'cache', [[]]); |
||||
$cache = $this->invokePrivate(\OC::$server->getAppConfig(), 'cache'); |
||||
unset($cache['encryption']); |
||||
unset($cache['files_encryption']); |
||||
$this->invokePrivate(\OC::$server->getAppConfig(), 'cache', [$cache]); |
||||
|
||||
$cache = $this->invokePrivate($config, 'userCache'); |
||||
unset($cache[self::TEST_ENCRYPTION_MIGRATION_USER1]); |
||||
$this->invokePrivate(\OC::$server->getAppConfig(), 'userCache', [$cache]); |
||||
|
||||
// delete default values set by the encryption app during initialization |
||||
|
||||
/** @var \OCP\IDBConnection $connection */ |
||||
$connection = \OC::$server->getDatabaseConnection(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->delete('appconfig') |
||||
->where($query->expr()->eq('appid', $query->createParameter('appid'))) |
||||
->setParameter('appid', 'encryption'); |
||||
$query->execute(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->delete('preferences') |
||||
->where($query->expr()->eq('appid', $query->createParameter('appid'))) |
||||
->setParameter('appid', 'encryption'); |
||||
$query->execute(); |
||||
} |
||||
|
||||
public function testUpdateDB() { |
||||
$this->prepareDB(); |
||||
|
||||
$m = new Migration(\OC::$server->getConfig(), new \OC\Files\View(), \OC::$server->getDatabaseConnection(), $this->logger, \OC::$server->getAppManager()); |
||||
$this->invokePrivate($m, 'installedVersion', ['0.7']); |
||||
$m->updateDB(); |
||||
|
||||
$this->verifyDB('appconfig', 'files_encryption', 0); |
||||
$this->verifyDB('preferences', 'files_encryption', 0); |
||||
$this->verifyDB('appconfig', 'encryption', 3); |
||||
$this->verifyDB('preferences', 'encryption', 1); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* test update db if the db already contain some existing new values |
||||
*/ |
||||
public function testUpdateDBExistingNewConfig() { |
||||
$this->prepareDB(); |
||||
$config = \OC::$server->getConfig(); |
||||
$config->setAppValue('encryption', 'publicShareKeyId', 'wrong_share_id'); |
||||
$config->setUserValue(self::TEST_ENCRYPTION_MIGRATION_USER1, 'encryption', 'recoverKeyEnabled', '9'); |
||||
|
||||
$m = new Migration(\OC::$server->getConfig(), new \OC\Files\View(), \OC::$server->getDatabaseConnection(), $this->logger, \OC::$server->getAppManager()); |
||||
$this->invokePrivate($m, 'installedVersion', ['0.7']); |
||||
$m->updateDB(); |
||||
|
||||
$this->verifyDB('appconfig', 'files_encryption', 0); |
||||
$this->verifyDB('preferences', 'files_encryption', 0); |
||||
$this->verifyDB('appconfig', 'encryption', 3); |
||||
$this->verifyDB('preferences', 'encryption', 1); |
||||
|
||||
// check if the existing values where overwritten correctly |
||||
/** @var \OC\DB\Connection $connection */ |
||||
$connection = \OC::$server->getDatabaseConnection(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->select('configvalue') |
||||
->from('appconfig') |
||||
->where($query->expr()->andX( |
||||
$query->expr()->eq('appid', $query->createParameter('appid')), |
||||
$query->expr()->eq('configkey', $query->createParameter('configkey')) |
||||
)) |
||||
->setParameter('appid', 'encryption') |
||||
->setParameter('configkey', 'publicShareKeyId'); |
||||
$result = $query->execute(); |
||||
$value = $result->fetch(); |
||||
$this->assertTrue(isset($value['configvalue'])); |
||||
$this->assertSame('share_id', $value['configvalue']); |
||||
|
||||
$query = $connection->getQueryBuilder(); |
||||
$query->select('configvalue') |
||||
->from('preferences') |
||||
->where($query->expr()->andX( |
||||
$query->expr()->eq('appid', $query->createParameter('appid')), |
||||
$query->expr()->eq('configkey', $query->createParameter('configkey')), |
||||
$query->expr()->eq('userid', $query->createParameter('userid')) |
||||
)) |
||||
->setParameter('appid', 'encryption') |
||||
->setParameter('configkey', 'recoverKeyEnabled') |
||||
->setParameter('userid', self::TEST_ENCRYPTION_MIGRATION_USER1); |
||||
$result = $query->execute(); |
||||
$value = $result->fetch(); |
||||
$this->assertTrue(isset($value['configvalue'])); |
||||
$this->assertSame('1', $value['configvalue']); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @param string $table |
||||
* @param string $appid |
||||
* @param integer $expected |
||||
*/ |
||||
public function verifyDB($table, $appid, $expected) { |
||||
/** @var \OCP\IDBConnection $connection */ |
||||
$connection = \OC::$server->getDatabaseConnection(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->select('appid') |
||||
->from($table) |
||||
->where($query->expr()->eq('appid', $query->createParameter('appid'))) |
||||
->setParameter('appid', $appid); |
||||
$result = $query->execute(); |
||||
$values = $result->fetchAll(); |
||||
$this->assertSame($expected, |
||||
count($values) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* test update of the file cache |
||||
*/ |
||||
public function testUpdateFileCache() { |
||||
$this->prepareFileCache(); |
||||
$m = new Migration(\OC::$server->getConfig(), new \OC\Files\View(), \OC::$server->getDatabaseConnection(), $this->logger, \OC::$server->getAppManager()); |
||||
$this->invokePrivate($m, 'installedVersion', ['0.7']); |
||||
self::invokePrivate($m, 'updateFileCache'); |
||||
|
||||
// check results |
||||
|
||||
/** @var \OCP\IDBConnection $connection */ |
||||
$connection = \OC::$server->getDatabaseConnection(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->select('*') |
||||
->from('filecache'); |
||||
$result = $query->execute(); |
||||
$entries = $result->fetchAll(); |
||||
foreach($entries as $entry) { |
||||
if ((int)$entry['encrypted'] === 1) { |
||||
$this->assertSame((int)$entry['unencrypted_size'], (int)$entry['size']); |
||||
} else { |
||||
$this->assertSame((int)$entry['unencrypted_size'] - 2, (int)$entry['size']); |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
public function prepareFileCache() { |
||||
/** @var \OCP\IDBConnection $connection */ |
||||
$connection = \OC::$server->getDatabaseConnection(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->delete('filecache'); |
||||
$query->execute(); |
||||
$query = $connection->getQueryBuilder(); |
||||
$result = $query->select('fileid') |
||||
->from('filecache') |
||||
->setMaxResults(1)->execute()->fetchAll(); |
||||
$this->assertEmpty($result); |
||||
$query = $connection->getQueryBuilder(); |
||||
$query->insert('filecache') |
||||
->values( |
||||
array( |
||||
'storage' => $query->createParameter('storage'), |
||||
'path_hash' => $query->createParameter('path_hash'), |
||||
'encrypted' => $query->createParameter('encrypted'), |
||||
'size' => $query->createParameter('size'), |
||||
'unencrypted_size' => $query->createParameter('unencrypted_size'), |
||||
) |
||||
); |
||||
for ($i = 1; $i < 20; $i++) { |
||||
$query->setParameter('storage', 1) |
||||
->setParameter('path_hash', $i) |
||||
->setParameter('encrypted', $i % 2) |
||||
->setParameter('size', $i) |
||||
->setParameter('unencrypted_size', $i + 2); |
||||
$this->assertSame(1, |
||||
$query->execute() |
||||
); |
||||
} |
||||
$query = $connection->getQueryBuilder(); |
||||
$result = $query->select('fileid') |
||||
->from('filecache') |
||||
->execute()->fetchAll(); |
||||
$this->assertSame(19, count($result)); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider dataTestGetTargetDir |
||||
*/ |
||||
public function testGetTargetDir($user, $keyPath, $filename, $trash, $systemMounts, $expected) { |
||||
|
||||
$view = $this->getMockBuilder(View::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$view->expects($this->any())->method('file_exists')->willReturn(true); |
||||
|
||||
$m = $this->getMockBuilder(Migration::class) |
||||
->setConstructorArgs( |
||||
[ |
||||
\OC::$server->getConfig(), |
||||
$view, |
||||
\OC::$server->getDatabaseConnection(), |
||||
$this->logger, |
||||
\OC::$server->getAppManager() |
||||
] |
||||
)->setMethods(['getSystemMountPoints'])->getMock(); |
||||
|
||||
$m->expects($this->any())->method('getSystemMountPoints') |
||||
->willReturn($systemMounts); |
||||
|
||||
$this->assertSame($expected, |
||||
$this->invokePrivate($m, 'getTargetDir', [$user, $keyPath, $filename, $trash]) |
||||
); |
||||
} |
||||
|
||||
public function dataTestGetTargetDir() { |
||||
return [ |
||||
[ |
||||
'user1', |
||||
'/files_encryption/keys/foo/bar.txt', |
||||
'user1.shareKey', |
||||
false, |
||||
[], |
||||
'user1/files_encryption/keys/files/foo/bar.txt/OC_DEFAULT_MODULE/user1.shareKey' |
||||
], |
||||
[ |
||||
'user1', |
||||
'/files_trashbin/keys/foo/bar.txt', |
||||
'user1.shareKey', |
||||
true, |
||||
[], |
||||
'user1/files_encryption/keys/files_trashbin/foo/bar.txt/OC_DEFAULT_MODULE/user1.shareKey' |
||||
], |
||||
[ |
||||
'', |
||||
'/files_encryption/keys/foo/bar.txt', |
||||
'user1.shareKey', |
||||
false, |
||||
[['mountpoint' => 'foo']], |
||||
'/files_encryption/keys/files/foo/bar.txt/OC_DEFAULT_MODULE/user1.shareKey' |
||||
], |
||||
[ |
||||
'', |
||||
'/files_encryption/keys/foo/bar.txt', |
||||
'user1.shareKey', |
||||
false, |
||||
[['mountpoint' => 'foobar']], |
||||
false |
||||
], |
||||
[ |
||||
'', |
||||
'/files_encryption/keys/foobar/bar.txt', |
||||
'user1.shareKey', |
||||
false, |
||||
[['mountpoint' => 'foo']], |
||||
false |
||||
] |
||||
]; |
||||
} |
||||
|
||||
} |
||||
@ -1,161 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2016, ownCloud, Inc. |
||||
* |
||||
* @author Björn Schießle <bjoern@schiessle.org> |
||||
* @author Joas Schilling <coding@schilljs.com> |
||||
* @author Ko- <k.stoffelen@cs.ru.nl> |
||||
* @author Lukas Reschke <lukas@statuscode.ch> |
||||
* @author Morris Jobke <hey@morrisjobke.de> |
||||
* |
||||
* @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\Settings\Controller; |
||||
|
||||
use OC\Files\View; |
||||
use OCA\Encryption\Migration; |
||||
use OCP\App\IAppManager; |
||||
use OCP\IDBConnection; |
||||
use OCP\IL10N; |
||||
use OCP\AppFramework\Controller; |
||||
use OCP\ILogger; |
||||
use OCP\IRequest; |
||||
use OCP\IConfig; |
||||
use OCP\IUserManager; |
||||
|
||||
/** |
||||
* @package OC\Settings\Controller |
||||
*/ |
||||
class EncryptionController extends Controller { |
||||
|
||||
/** @var IL10N */ |
||||
private $l10n; |
||||
|
||||
/** @var IDBConnection */ |
||||
private $connection; |
||||
|
||||
/** @var IConfig */ |
||||
private $config; |
||||
|
||||
/** @var IUserManager */ |
||||
private $userManager; |
||||
|
||||
/** @var View */ |
||||
private $view; |
||||
|
||||
/** @var ILogger */ |
||||
private $logger; |
||||
|
||||
/** @var IAppManager */ |
||||
private $appManager; |
||||
|
||||
/** |
||||
* @param string $appName |
||||
* @param IRequest $request |
||||
* @param IL10N $l10n |
||||
* @param IConfig $config |
||||
* @param IDBConnection $connection |
||||
* @param IUserManager $userManager |
||||
* @param View $view |
||||
* @param ILogger $logger |
||||
* @param IAppManager $appManager |
||||
*/ |
||||
public function __construct($appName, |
||||
IRequest $request, |
||||
IL10N $l10n, |
||||
IConfig $config, |
||||
IDBConnection $connection, |
||||
IUserManager $userManager, |
||||
View $view, |
||||
ILogger $logger, |
||||
IAppManager $appManager) { |
||||
parent::__construct($appName, $request); |
||||
$this->l10n = $l10n; |
||||
$this->config = $config; |
||||
$this->connection = $connection; |
||||
$this->view = $view; |
||||
$this->userManager = $userManager; |
||||
$this->logger = $logger; |
||||
$this->appManager = $appManager; |
||||
} |
||||
|
||||
/** |
||||
* @param IConfig $config |
||||
* @param View $view |
||||
* @param IDBConnection $connection |
||||
* @param ILogger $logger |
||||
* @param IAppManager $appManager |
||||
* @return Migration |
||||
*/ |
||||
protected function getMigration(IConfig $config, |
||||
View $view, |
||||
IDBConnection $connection, |
||||
ILogger $logger, |
||||
IAppManager $appManager) { |
||||
return new Migration($config, $view, $connection, $logger, $appManager); |
||||
} |
||||
|
||||
/** |
||||
* start migration |
||||
* |
||||
* @return array |
||||
*/ |
||||
public function startMigration() { |
||||
// allow as long execution on the web server as possible |
||||
if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { |
||||
@set_time_limit(0); |
||||
} |
||||
|
||||
try { |
||||
|
||||
$migration = $this->getMigration($this->config, $this->view, $this->connection, $this->logger, $this->appManager); |
||||
$migration->reorganizeSystemFolderStructure(); |
||||
$migration->updateDB(); |
||||
|
||||
foreach ($this->userManager->getBackends() as $backend) { |
||||
$limit = 500; |
||||
$offset = 0; |
||||
do { |
||||
$users = $backend->getUsers('', $limit, $offset); |
||||
foreach ($users as $user) { |
||||
$migration->reorganizeFolderStructureForUser($user); |
||||
} |
||||
$offset += $limit; |
||||
} while (count($users) >= $limit); |
||||
} |
||||
|
||||
$migration->finalCleanUp(); |
||||
|
||||
} catch (\Exception $e) { |
||||
return [ |
||||
'data' => [ |
||||
'message' => (string)$this->l10n->t('A problem occurred, please check your log files (Error: %s)', [$e->getMessage()]), |
||||
], |
||||
'status' => 'error', |
||||
]; |
||||
} |
||||
|
||||
return [ |
||||
'data' => [ |
||||
'message' => (string) $this->l10n->t('Migration Completed'), |
||||
], |
||||
'status' => 'success', |
||||
]; |
||||
} |
||||
|
||||
} |
||||
@ -1,164 +0,0 @@ |
||||
<?php |
||||
/** |
||||
* @author Lukas Reschke <lukas@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 Tests\Settings\Controller; |
||||
|
||||
use OC\DB\Connection; |
||||
use OC\Files\View; |
||||
use OC\Settings\Controller\EncryptionController; |
||||
use OCP\App\IAppManager; |
||||
use OCA\Encryption\Migration; |
||||
use OCP\IConfig; |
||||
use OCP\IL10N; |
||||
use OCP\ILogger; |
||||
use OCP\IRequest; |
||||
use OCP\IUserManager; |
||||
use OCP\UserInterface; |
||||
use Test\TestCase; |
||||
|
||||
/** |
||||
* Class EncryptionControllerTest |
||||
* |
||||
* @package Tests\Settings\Controller |
||||
*/ |
||||
class EncryptionControllerTest extends TestCase { |
||||
/** @var IRequest */ |
||||
private $request; |
||||
/** @var IL10N */ |
||||
private $l10n; |
||||
/** @var IConfig */ |
||||
private $config; |
||||
/** @var Connection */ |
||||
private $connection; |
||||
/** @var IUserManager */ |
||||
private $userManager; |
||||
/** @var View */ |
||||
private $view; |
||||
/** @var ILogger */ |
||||
private $logger; |
||||
/** @var IAppManager */ |
||||
private $appManager; |
||||
/** @var EncryptionController */ |
||||
private $encryptionController; |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->request = $this->getMockBuilder(IRequest::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->l10n = $this->getMockBuilder(IL10N::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->l10n->expects($this->any()) |
||||
->method('t') |
||||
->will($this->returnCallback(function($message, array $replace) { |
||||
return vsprintf($message, $replace); |
||||
})); |
||||
$this->config = $this->getMockBuilder(IConfig::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->connection = $this->getMockBuilder(Connection::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->userManager = $this->getMockBuilder(IUserManager::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->view = $this->getMockBuilder(View::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->logger = $this->getMockBuilder(ILogger::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->appManager = $this->getMockBuilder('\\OCP\\App\\IAppManager') |
||||
->disableOriginalConstructor()->getMock(); |
||||
|
||||
$this->encryptionController = $this->getMockBuilder(EncryptionController::class) |
||||
->setConstructorArgs([ |
||||
'settings', |
||||
$this->request, |
||||
$this->l10n, |
||||
$this->config, |
||||
$this->connection, |
||||
$this->userManager, |
||||
$this->view, |
||||
$this->logger, |
||||
$this->appManager, |
||||
]) |
||||
->setMethods(['getMigration']) |
||||
->getMock(); |
||||
} |
||||
|
||||
public function testStartMigrationSuccessful() { |
||||
// we need to be able to autoload the class we're mocking |
||||
\OC_App::registerAutoloading('encryption', \OC_App::getAppPath('encryption')); |
||||
|
||||
$migration = $this->getMockBuilder(Migration::class) |
||||
->disableOriginalConstructor()->getMock(); |
||||
$this->encryptionController |
||||
->expects($this->once()) |
||||
->method('getMigration') |
||||
->with($this->config, $this->view, $this->connection, $this->logger) |
||||
->will($this->returnValue($migration)); |
||||
$migration |
||||
->expects($this->once()) |
||||
->method('reorganizeSystemFolderStructure'); |
||||
$migration |
||||
->expects($this->once()) |
||||
->method('updateDB'); |
||||
$backend = $this->getMockBuilder(UserInterface::class) |
||||
->getMock(); |
||||
$this->userManager |
||||
->expects($this->once()) |
||||
->method('getBackends') |
||||
->will($this->returnValue([$backend])); |
||||
$backend |
||||
->expects($this->once()) |
||||
->method('getUsers') |
||||
->will($this->returnValue(['User 1', 'User 2'])); |
||||
$migration |
||||
->expects($this->exactly(2)) |
||||
->method('reorganizeFolderStructureForUser') |
||||
->withConsecutive( |
||||
['User 1'], |
||||
['User 2'] |
||||
); |
||||
$migration |
||||
->expects($this->once()) |
||||
->method('finalCleanUp'); |
||||
|
||||
$expected = [ |
||||
'data' => [ |
||||
'message' => 'Migration Completed', |
||||
], |
||||
'status' => 'success', |
||||
]; |
||||
$this->assertSame($expected, $this->encryptionController->startMigration()); |
||||
} |
||||
|
||||
public function testStartMigrationException() { |
||||
$this->encryptionController |
||||
->expects($this->once()) |
||||
->method('getMigration') |
||||
->with($this->config, $this->view, $this->connection, $this->logger) |
||||
->will($this->throwException(new \Exception('My error message'))); |
||||
|
||||
$expected = [ |
||||
'data' => [ |
||||
'message' => 'A problem occurred, please check your log files (Error: My error message)', |
||||
], |
||||
'status' => 'error', |
||||
]; |
||||
$this->assertSame($expected, $this->encryptionController->startMigration()); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue