diff --git a/apps/encryption/appinfo/app.php b/apps/encryption/appinfo/app.php
index 6bbf211336..0e8ce56227 100644
--- a/apps/encryption/appinfo/app.php
+++ b/apps/encryption/appinfo/app.php
@@ -24,6 +24,8 @@
namespace OCA\Encryption\AppInfo;
$app = new Application();
-$app->registerEncryptionModule();
-$app->registerHooks();
-$app->registerSettings();
+if (\OC::$server->getEncryptionManager()->isReady()) {
+ $app->registerEncryptionModule();
+ $app->registerHooks();
+ $app->registerSettings();
+}
diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php
index 34845ecf1e..6b67b6d95b 100644
--- a/apps/encryption/appinfo/application.php
+++ b/apps/encryption/appinfo/application.php
@@ -40,13 +40,10 @@ use OCP\IConfig;
class Application extends \OCP\AppFramework\App {
- /**
- * @var IManager
- */
+
+ /** @var IManager */
private $encryptionManager;
- /**
- * @var IConfig
- */
+ /** @var IConfig */
private $config;
/**
@@ -59,6 +56,10 @@ class Application extends \OCP\AppFramework\App {
$this->registerServices();
}
+ /**
+ * register hooks
+ */
+
public function registerHooks() {
if (!$this->config->getSystemValue('maintenance', false)) {
diff --git a/apps/encryption/appinfo/info.xml b/apps/encryption/appinfo/info.xml
index e4a7d790e9..53a2459f86 100644
--- a/apps/encryption/appinfo/info.xml
+++ b/apps/encryption/appinfo/info.xml
@@ -16,7 +16,7 @@
based on AES 128 or 256 bit keys. More information is available in
the Encryption documentation
-Encryption
+ ownCloud Default Encryption Module
AGPL
Bjoern Schiessle, Clark Tomlinson
8
diff --git a/apps/encryption/appinfo/register_command.php b/apps/encryption/appinfo/register_command.php
new file mode 100644
index 0000000000..8a9df8ea3e
--- /dev/null
+++ b/apps/encryption/appinfo/register_command.php
@@ -0,0 +1,15 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+use OCA\Encryption\Command\MigrateKeys;
+
+$userManager = OC::$server->getUserManager();
+$view = new \OC\Files\View();
+$config = \OC::$server->getConfig();
+$connection = \OC::$server->getDatabaseConnection();
+$application->add(new MigrateKeys($userManager, $view, $connection, $config));
diff --git a/apps/encryption/appinfo/version b/apps/encryption/appinfo/version
new file mode 100644
index 0000000000..3eefcb9dd5
--- /dev/null
+++ b/apps/encryption/appinfo/version
@@ -0,0 +1 @@
+1.0.0
diff --git a/apps/encryption/command/migratekeys.php b/apps/encryption/command/migratekeys.php
new file mode 100644
index 0000000000..b814d697a2
--- /dev/null
+++ b/apps/encryption/command/migratekeys.php
@@ -0,0 +1,105 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Encryption\Command;
+
+use OC\DB\Connection;
+use OC\Files\View;
+use OC\User\Manager;
+use OCA\Encryption\Migration;
+use OCP\IConfig;
+use OCP\IUserBackend;
+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 \OC\User\Manager */
+ private $userManager;
+
+ /** @var View */
+ private $view;
+ /** @var \OC\DB\Connection */
+ private $connection;
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param Manager $userManager
+ * @param View $view
+ * @param Connection $connection
+ * @param IConfig $config
+ */
+ public function __construct(Manager $userManager,
+ View $view,
+ Connection $connection,
+ IConfig $config) {
+
+ $this->userManager = $userManager;
+ $this->view = $view;
+ $this->connection = $connection;
+ $this->config = $config;
+ 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);
+
+ $users = $input->getArgument('user_id');
+ if (!empty($users)) {
+ foreach ($users as $user) {
+ if ($this->userManager->userExists($user)) {
+ $output->writeln("Migrating keys $user");
+ $migration->reorganizeFolderStructureForUser($user);
+ } else {
+ $output->writeln("Unknown user $user");
+ }
+ }
+ } 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 $name");
+
+ $limit = 500;
+ $offset = 0;
+ do {
+ $users = $backend->getUsers('', $limit, $offset);
+ foreach ($users as $user) {
+ $output->writeln(" $user");
+ $migration->reorganizeFolderStructureForUser($user);
+ }
+ $offset += $limit;
+ } while(count($users) >= $limit);
+ }
+ }
+
+ }
+}
diff --git a/apps/encryption/hooks/userhooks.php b/apps/encryption/hooks/userhooks.php
index c39fa34108..e61d4f9c11 100644
--- a/apps/encryption/hooks/userhooks.php
+++ b/apps/encryption/hooks/userhooks.php
@@ -142,7 +142,6 @@ class UserHooks implements IHook {
}
// ensure filesystem is loaded
- // Todo: update?
if (!\OC\Files\Filesystem::$loaded) {
\OC_Util::setupFS($params['uid']);
}
diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php
index c026aa6a90..9ada920055 100644
--- a/apps/encryption/lib/crypto/crypt.php
+++ b/apps/encryption/lib/crypto/crypt.php
@@ -231,7 +231,7 @@ class Crypt {
* @param string $password
* @return bool|string
*/
- public function decryptPrivateKey($privateKey, $password) {
+ public function decryptPrivateKey($privateKey, $password = '') {
$header = $this->parseHeader($privateKey);
@@ -273,7 +273,7 @@ class Crypt {
* @return string
* @throws DecryptionFailedException
*/
- public function symmetricDecryptFileContent($keyFileContents, $passPhrase = '', $cipher = self::DEFAULT_CIPHER) {
+ public function symmetricDecryptFileContent($keyFileContents, $passPhrase, $cipher = self::DEFAULT_CIPHER) {
// Remove Padding
$noPadding = $this->removePadding($keyFileContents);
diff --git a/apps/encryption/lib/keymanager.php b/apps/encryption/lib/keymanager.php
index 87adf75c92..c098347a0a 100644
--- a/apps/encryption/lib/keymanager.php
+++ b/apps/encryption/lib/keymanager.php
@@ -338,7 +338,7 @@ class KeyManager {
$uid = $this->getPublicShareKeyId();
$shareKey = $this->getShareKey($path, $uid);
$privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.privateKey');
- $privateKey = $this->crypt->symmetricDecryptFileContent($privateKey);
+ $privateKey = $this->crypt->decryptPrivateKey($privateKey);
} else {
$shareKey = $this->getShareKey($path, $uid);
$privateKey = $this->session->getPrivateKey();
diff --git a/apps/encryption/lib/migration.php b/apps/encryption/lib/migration.php
new file mode 100644
index 0000000000..e4e5595efa
--- /dev/null
+++ b/apps/encryption/lib/migration.php
@@ -0,0 +1,319 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 along with this library. If not, see .
+ *
+ */
+
+namespace OCA\Encryption;
+
+
+use OC\DB\Connection;
+use OC\Files\View;
+use OCP\IConfig;
+
+class Migration {
+
+ private $moduleId;
+ /** @var \OC\Files\View */
+ private $view;
+ /** @var \OC\DB\Connection */
+ private $connection;
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param IConfig $config
+ * @param View $view
+ * @param Connection $connection
+ */
+ public function __construct(IConfig $config, View $view, Connection $connection) {
+ $this->view = $view;
+ $this->view->getUpdater()->disable();
+ $this->connection = $connection;
+ $this->moduleId = \OCA\Encryption\Crypto\Encryption::ID;
+ $this->config = $config;
+ }
+
+ public function __destruct() {
+ $this->view->deleteAll('files_encryption/public_keys');
+ $this->updateFileCache();
+ }
+
+ /**
+ * update file cache, copy unencrypted_size to the 'size' column
+ */
+ private function updateFileCache() {
+ $query = $this->connection->createQueryBuilder();
+ $query->update('`*PREFIX*filecache`')
+ ->set('`size`', '`unencrypted_size`')
+ ->where($query->expr()->eq('`encrypted`', ':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 (\OC_App::isEnabled('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() {
+
+ // delete left-over from old encryption which is no longer needed
+ $this->config->deleteAppValue('files_encryption', 'installed_version');
+ $this->config->deleteAppValue('files_encryption', 'ocsid');
+ $this->config->deleteAppValue('files_encryption', 'types');
+ $this->config->deleteAppValue('files_encryption', 'enabled');
+
+
+ $query = $this->connection->createQueryBuilder();
+ $query->update('`*PREFIX*appconfig`')
+ ->set('`appid`', ':newappid')
+ ->where($query->expr()->eq('`appid`', ':oldappid'))
+ ->setParameter('oldappid', 'files_encryption')
+ ->setParameter('newappid', 'encryption');
+ $query->execute();
+
+ $query = $this->connection->createQueryBuilder();
+ $query->update('`*PREFIX*preferences`')
+ ->set('`appid`', ':newappid')
+ ->where($query->expr()->eq('`appid`', ':oldappid'))
+ ->setParameter('oldappid', 'files_encryption')
+ ->setParameter('newappid', 'encryption');
+ $query->execute();
+ }
+
+ /**
+ * 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 $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';
+ $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';
+ $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) {
+
+ $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);
+ $this->createPathForKeys(dirname($target));
+ $this->view->rename($user . '/' . $path . '/' . $file, $target);
+ }
+ }
+ }
+ closedir($dh);
+ }
+ }
+
+ /**
+ * generate target directory
+ *
+ * @param string $user
+ * @param string $filePath
+ * @param string $filename
+ * @param bool $trash
+ * @return string
+ */
+ private function getTargetDir($user, $filePath, $filename, $trash) {
+ if ($trash) {
+ $targetDir = $user . '/files_encryption/keys/files_trashbin/' . substr($filePath, strlen('/files_trashbin/keys/')) . '/' . $this->moduleId . '/' . $filename;
+ } else {
+ $targetDir = $user . '/files_encryption/keys/files/' . substr($filePath, strlen('/files_encryption/keys/')) . '/' . $this->moduleId . '/' . $filename;
+ }
+
+ return $targetDir;
+ }
+
+ /**
+ * 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);
+ }
+ }
+ }
+ }
+}
diff --git a/apps/encryption/tests/lib/KeyManagerTest.php b/apps/encryption/tests/lib/KeyManagerTest.php
index 1e51341a7e..251628d99f 100644
--- a/apps/encryption/tests/lib/KeyManagerTest.php
+++ b/apps/encryption/tests/lib/KeyManagerTest.php
@@ -268,7 +268,7 @@ class KeyManagerTest extends TestCase {
->willReturn(true);
$this->cryptMock->expects($this->once())
- ->method('symmetricDecryptFileContent')
+ ->method('decryptPrivateKey')
->willReturn(true);
$this->cryptMock->expects($this->once())
diff --git a/apps/encryption/tests/lib/MigrationTest.php b/apps/encryption/tests/lib/MigrationTest.php
new file mode 100644
index 0000000000..f56ff5cc2f
--- /dev/null
+++ b/apps/encryption/tests/lib/MigrationTest.php
@@ -0,0 +1,356 @@
+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 along with this library. If not, see .
+ *
+ */
+
+namespace OCA\Encryption\Tests;
+
+use OCA\Encryption\Migration;
+
+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;
+
+ public static function setUpBeforeClass() {
+ parent::setUpBeforeClass();
+ \OC_User::createUser(self::TEST_ENCRYPTION_MIGRATION_USER1, 'foo');
+ \OC_User::createUser(self::TEST_ENCRYPTION_MIGRATION_USER2, 'foo');
+ \OC_User::createUser(self::TEST_ENCRYPTION_MIGRATION_USER3, 'foo');
+ }
+
+ public static function tearDownAfterClass() {
+ \OC_User::deleteUser(self::TEST_ENCRYPTION_MIGRATION_USER1);
+ \OC_User::deleteUser(self::TEST_ENCRYPTION_MIGRATION_USER2);
+ \OC_User::deleteUser(self::TEST_ENCRYPTION_MIGRATION_USER3);
+ parent::tearDownAfterClass();
+ }
+
+
+ public function setUp() {
+ $this->view = new \OC\Files\View();
+ $this->moduleId = \OCA\Encryption\Crypto\Encryption::ID;
+ }
+
+ protected function createDummyShareKeys($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');
+ }
+ }
+
+ protected function createDummyUserKeys($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');
+ }
+
+ protected function createDummyFileKeys($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');
+ }
+
+ protected function createDummyFilesInTrash($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');
+ }
+
+ 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->createDummyFilesInTrash(self::TEST_ENCRYPTION_MIGRATION_USER2);
+
+ // no user for system wide mount points
+ $this->createDummyFileKeys('');
+ $this->createDummyShareKeys('');
+
+ $this->createDummySystemWideKeys();
+
+ $m = new Migration(\OC::$server->getConfig(), new \OC\Files\View(), \OC::$server->getDatabaseConnection());
+ $m->reorganizeFolderStructure();
+
+ $this->assertTrue(
+ $this->view->file_exists(
+ self::TEST_ENCRYPTION_MIGRATION_USER1 . '/files_encryption/' .
+ $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER1 . '.publicKey')
+ );
+ $this->assertTrue(
+ $this->view->file_exists(
+ self::TEST_ENCRYPTION_MIGRATION_USER2 . '/files_encryption/' .
+ $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER2 . '.publicKey')
+ );
+ $this->assertTrue(
+ $this->view->file_exists(
+ self::TEST_ENCRYPTION_MIGRATION_USER3 . '/files_encryption/' .
+ $this->moduleId . '/' . self::TEST_ENCRYPTION_MIGRATION_USER3 . '.publicKey')
+ );
+ $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);
+
+ }
+
+ protected function verifyFilesInTrash($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')
+ );
+ }
+
+ protected function verifyNewKeyPath($uid) {
+ // private key
+ if ($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');
+
+ // delete default values set by the encryption app during initialization
+
+ /** @var \OC\DB\Connection $connection */
+ $connection = \OC::$server->getDatabaseConnection();
+ $query = $connection->createQueryBuilder();
+ $query->delete('`*PREFIX*appconfig`')
+ ->where($query->expr()->eq('`appid`', ':appid'))
+ ->setParameter('appid', 'encryption');
+ $query->execute();
+ $query = $connection->createQueryBuilder();
+ $query->delete('`*PREFIX*preferences`')
+ ->where($query->expr()->eq('`appid`', ':appid'))
+ ->setParameter('appid', 'encryption');
+ $query->execute();
+ }
+
+ public function testUpdateDB() {
+ $this->prepareDB();
+
+ $m = new Migration(\OC::$server->getConfig(), new \OC\Files\View(), \OC::$server->getDatabaseConnection());
+ $m->updateDB();
+
+ $this->verifyDB('`*PREFIX*appconfig`', 'files_encryption', 0);
+ $this->verifyDB('`*PREFIX*preferences`', 'files_encryption', 0);
+ $this->verifyDB('`*PREFIX*appconfig`', 'encryption', 3);
+ $this->verifyDB('`*PREFIX*preferences`', 'encryption', 1);
+
+ }
+
+ public function verifyDB($table, $appid, $expected) {
+ /** @var \OC\DB\Connection $connection */
+ $connection = \OC::$server->getDatabaseConnection();
+ $query = $connection->createQueryBuilder();
+ $query->select('`appid`')
+ ->from($table)
+ ->where($query->expr()->eq('`appid`', ':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());
+ \Test_Helper::invokePrivate($m, 'updateFileCache');
+
+ // check results
+
+ /** @var \OC\DB\Connection $connection */
+ $connection = \OC::$server->getDatabaseConnection();
+ $query = $connection->createQueryBuilder();
+ $query->select('*')
+ ->from('`*PREFIX*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 \OC\DB\Connection $connection */
+ $connection = \OC::$server->getDatabaseConnection();
+ $query = $connection->createQueryBuilder();
+ $query->delete('`*PREFIX*filecache`');
+ $query->execute();
+ $query = $connection->createQueryBuilder();
+ $result = $query->select('`fileid`')
+ ->from('`*PREFIX*filecache`')
+ ->setMaxResults(1)->execute()->fetchAll();
+ $this->assertEmpty($result);
+ $query = $connection->createQueryBuilder();
+ $query->insert('`*PREFIX*filecache`')
+ ->values(
+ array(
+ '`storage`' => ':storage',
+ '`path_hash`' => ':path_hash',
+ '`encrypted`' => ':encrypted',
+ '`size`' => ':size',
+ '`unencrypted_size`' => ':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->createQueryBuilder();
+ $result = $query->select('`fileid`')
+ ->from('`*PREFIX*filecache`')
+ ->execute()->fetchAll();
+ $this->assertSame(19, count($result));
+ }
+
+}
diff --git a/lib/base.php b/lib/base.php
index f0c54640b1..80f2736fcf 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -728,6 +728,7 @@ class OC {
new \OC\Encryption\Util(
new \OC\Files\View(),
\OC::$server->getUserManager(),
+ \OC::$server->getGroupManager(),
\OC::$server->getConfig()),
\OC\Files\Filesystem::getMountManager(),
\OC::$server->getEncryptionManager(),
diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php
index 9d97819313..925c20c74c 100644
--- a/lib/private/encryption/keys/storage.php
+++ b/lib/private/encryption/keys/storage.php
@@ -266,7 +266,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
$filename = $this->util->stripPartialFileExtension($filename);
// in case of system wide mount points the keys are stored directly in the data directory
- if ($this->util->isSystemWideMountPoint($filename)) {
+ if ($this->util->isSystemWideMountPoint($filename, $owner)) {
$keyPath = $this->keys_base_dir . $filename . '/';
} else {
$keyPath = '/' . $owner . $this->keys_base_dir . $filename . '/';
@@ -287,7 +287,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
list($owner, $source) = $this->util->getUidAndFilename($source);
list(, $target) = $this->util->getUidAndFilename($target);
- $systemWide = $this->util->isSystemWideMountPoint($target);
+ $systemWide = $this->util->isSystemWideMountPoint($target, $owner);
if ($systemWide) {
$sourcePath = $this->keys_base_dir . $source . '/';
@@ -315,7 +315,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
list($owner, $source) = $this->util->getUidAndFilename($source);
list(, $target) = $this->util->getUidAndFilename($target);
- $systemWide = $this->util->isSystemWideMountPoint($target);
+ $systemWide = $this->util->isSystemWideMountPoint($target, $owner);
if ($systemWide) {
$sourcePath = $this->keys_base_dir . $source . '/';
diff --git a/lib/private/encryption/manager.php b/lib/private/encryption/manager.php
index 74cad0a75b..89abad4934 100644
--- a/lib/private/encryption/manager.php
+++ b/lib/private/encryption/manager.php
@@ -22,24 +22,34 @@
namespace OC\Encryption;
+use OC\Files\Storage\Shared;
use OC\Files\Storage\Wrapper\Encryption;
+use OC\Files\View;
use OCP\Encryption\IEncryptionModule;
+use OCP\Encryption\IManager;
use OCP\Files\Mount\IMountPoint;
+use OCP\IConfig;
+use OCP\ILogger;
-class Manager implements \OCP\Encryption\IManager {
+class Manager implements IManager {
/** @var array */
protected $encryptionModules;
- /** @var \OCP\IConfig */
+ /** @var IConfig */
protected $config;
+ /** @var ILogger */
+ protected $logger;
+
/**
- * @param \OCP\IConfig $config
+ * @param IConfig $config
+ * @param ILogger $logger
*/
- public function __construct(\OCP\IConfig $config) {
+ public function __construct(IConfig $config, ILogger $logger) {
$this->encryptionModules = array();
$this->config = $config;
+ $this->logger = $logger;
}
/**
@@ -58,6 +68,24 @@ class Manager implements \OCP\Encryption\IManager {
return $enabled === 'yes';
}
+ /**
+ * check if new encryption is ready
+ *
+ * @return boolean
+ */
+ public function isReady() {
+ // check if we are still in transit between the old and the new encryption
+ $oldEncryption = $this->config->getAppValue('files_encryption', 'installed_version');
+ if (!empty($oldEncryption)) {
+ $warning = 'Installation is in transit between the old Encryption (ownCloud <= 8.0)
+ and the new encryption. Please enable the "ownCloud Default Encryption Module"
+ and run \'occ encryption:migrate\'';
+ $this->logger->warning($warning);
+ return false;
+ }
+ return true;
+ }
+
/**
* Registers an encryption module
*
@@ -185,10 +213,14 @@ class Manager implements \OCP\Encryption\IManager {
'mountPoint' => $mountPoint,
'mount' => $mount];
- if (!($storage instanceof \OC\Files\Storage\Shared)) {
+ if (!($storage instanceof Shared)) {
$manager = \OC::$server->getEncryptionManager();
- $util = new \OC\Encryption\Util(
- new \OC\Files\View(), \OC::$server->getUserManager(), \OC::$server->getConfig());
+ $util = new Util(
+ new View(),
+ \OC::$server->getUserManager(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getConfig()
+ );
$user = \OC::$server->getUserSession()->getUser();
$logger = \OC::$server->getLogger();
$uid = $user ? $user->getUID() : null;
diff --git a/lib/private/encryption/util.php b/lib/private/encryption/util.php
index e7cf607c7b..98a38012db 100644
--- a/lib/private/encryption/util.php
+++ b/lib/private/encryption/util.php
@@ -24,6 +24,7 @@ namespace OC\Encryption;
use OC\Encryption\Exceptions\EncryptionHeaderKeyExistsException;
use OC\Encryption\Exceptions\EncryptionHeaderToLargeException;
+use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
use OC\Files\View;
use OCP\Encryption\IEncryptionModule;
use OCP\IConfig;
@@ -65,15 +66,20 @@ class Util {
/** @var array paths excluded from encryption */
protected $excludedPaths;
+ /** @var \OC\Group\Manager $manager */
+ protected $groupManager;
+
/**
*
* @param \OC\Files\View $view
* @param \OC\User\Manager $userManager
+ * @param \OC\Group\Manager $groupManager
* @param IConfig $config
*/
public function __construct(
\OC\Files\View $view,
\OC\User\Manager $userManager,
+ \OC\Group\Manager $groupManager,
IConfig $config) {
$this->ocHeaderKeys = [
@@ -82,6 +88,7 @@ class Util {
$this->view = $view;
$this->userManager = $userManager;
+ $this->groupManager = $groupManager;
$this->config = $config;
$this->excludedPaths[] = 'files_encryption';
@@ -92,6 +99,7 @@ class Util {
*
* @param array $header
* @return string
+ * @throws ModuleDoesNotExistsException
*/
public function getEncryptionModuleId(array $header = null) {
$id = '';
@@ -99,6 +107,14 @@ class Util {
if (isset($header[$encryptionModuleKey])) {
$id = $header[$encryptionModuleKey];
+ } elseif (isset($header['cipher'])) {
+ if (class_exists('\OCA\Encryption\Crypto\Encryption')) {
+ // fall back to default encryption if the user migrated from
+ // ownCloud <= 8.0 with the old encryption
+ $id = \OCA\Encryption\Crypto\Encryption::ID;
+ } else {
+ throw new ModuleDoesNotExistsException('ownCloud default encryption module missing');
+ }
}
return $id;
@@ -294,15 +310,15 @@ class Util {
/**
* check if the file is stored on a system wide mount point
* @param string $path relative to /data/user with leading '/'
+ * @param string $uid
* @return boolean
*/
- public function isSystemWideMountPoint($path) {
- $normalizedPath = ltrim($path, '/');
+ public function isSystemWideMountPoint($path, $uid) {
if (\OCP\App::isEnabled("files_external")) {
$mounts = \OC_Mount_Config::getSystemMountPoints();
foreach ($mounts as $mount) {
- if ($mount['mountpoint'] == substr($normalizedPath, 0, strlen($mount['mountpoint']))) {
- if ($this->isMountPointApplicableToUser($mount)) {
+ if (strpos($path, '/files/' . $mount['mountpoint']) === 0) {
+ if ($this->isMountPointApplicableToUser($mount, $uid)) {
return true;
}
}
@@ -311,6 +327,29 @@ class Util {
return false;
}
+ /**
+ * check if mount point is applicable to user
+ *
+ * @param array $mount contains $mount['applicable']['users'], $mount['applicable']['groups']
+ * @param string $uid
+ * @return boolean
+ */
+ private function isMountPointApplicableToUser($mount, $uid) {
+ $acceptedUids = array('all', $uid);
+ // check if mount point is applicable for the user
+ $intersection = array_intersect($acceptedUids, $mount['applicable']['users']);
+ if (!empty($intersection)) {
+ return true;
+ }
+ // check if mount point is applicable for group where the user is a member
+ foreach ($mount['applicable']['groups'] as $gid) {
+ if ($this->groupManager->isInGroup($uid, $gid)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* check if it is a path which is excluded by ownCloud from encryption
*
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 5697139bd6..01bd861e3a 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -154,7 +154,8 @@ class Encryption extends Wrapper {
* @return bool
*/
public function unlink($path) {
- if ($this->util->isExcluded($path)) {
+ $fullPath = $this->getFullPath($path);
+ if ($this->util->isExcluded($fullPath)) {
return $this->storage->unlink($path);
}
@@ -175,7 +176,8 @@ class Encryption extends Wrapper {
* @return bool
*/
public function rename($path1, $path2) {
- if ($this->util->isExcluded($path1)) {
+ $fullPath1 = $this->getFullPath($path1);
+ if ($this->util->isExcluded($fullPath1)) {
return $this->storage->rename($path1, $path2);
}
@@ -204,8 +206,9 @@ class Encryption extends Wrapper {
* @return bool
*/
public function copy($path1, $path2) {
- if ($this->util->isExcluded($path1)) {
- return $this->storage->rename($path1, $path2);
+ $fullPath1 = $this->getFullPath($path1);
+ if ($this->util->isExcluded($fullPath1)) {
+ return $this->storage->copy($path1, $path2);
}
$source = $this->getFullPath($path1);
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index 9ba98e61d3..4a1df84010 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -280,7 +280,7 @@ class Encryption extends Wrapper {
if ($this->position === 0) {
$this->writeHeader();
- $this->size+=$this->util->getHeaderSize();
+ $this->size = $this->util->getHeaderSize();
}
$length = 0;
@@ -293,7 +293,7 @@ class Encryption extends Wrapper {
// for seekable streams the pointer is moved back to the beginning of the encrypted block
// flush will start writing there when the position moves to another block
- $positionInFile = floor($this->position / $this->unencryptedBlockSize) *
+ $positionInFile = (int)floor($this->position / $this->unencryptedBlockSize) *
$this->util->getBlockSize() + $this->util->getHeaderSize();
$resultFseek = parent::stream_seek($positionInFile);
diff --git a/lib/private/server.php b/lib/private/server.php
index 6df7722973..ea673ea148 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -84,11 +84,16 @@ class Server extends SimpleContainer implements IServerContainer {
});
$this->registerService('EncryptionManager', function (Server $c) {
- return new Encryption\Manager($c->getConfig());
+ return new Encryption\Manager($c->getConfig(), $c->getLogger());
});
$this->registerService('EncryptionFileHelper', function (Server $c) {
- $util = new \OC\Encryption\Util(new \OC\Files\View(), $c->getUserManager(), $c->getConfig());
+ $util = new \OC\Encryption\Util(
+ new \OC\Files\View(),
+ $c->getUserManager(),
+ $c->getGroupManager(),
+ $c->getConfig()
+ );
return new Encryption\File($util);
});
@@ -437,7 +442,12 @@ class Server extends SimpleContainer implements IServerContainer {
*/
function getEncryptionKeyStorage($encryptionModuleId) {
$view = new \OC\Files\View();
- $util = new \OC\Encryption\Util($view, \OC::$server->getUserManager(), \OC::$server->getConfig());
+ $util = new \OC\Encryption\Util(
+ $view,
+ \OC::$server->getUserManager(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getConfig()
+ );
return $this->query('EncryptionKeyStorageFactory')->get($encryptionModuleId, $view, $util);
}
diff --git a/settings/admin.php b/settings/admin.php
index 976d0a5c3f..5cfe2654f6 100644
--- a/settings/admin.php
+++ b/settings/admin.php
@@ -82,7 +82,12 @@ $excludedGroupsList = $appConfig->getValue('core', 'shareapi_exclude_groups_list
$excludedGroupsList = explode(',', $excludedGroupsList); // FIXME: this should be JSON!
$template->assign('shareExcludedGroupsList', implode('|', $excludedGroupsList));
$template->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled());
+$backends = \OC::$server->getUserManager()->getBackends();
+$externalBackends = (count($backends) > 1) ? true : false;
+$template->assign('encryptionReady', \OC::$server->getEncryptionManager()->isReady());
+$template->assign('externalBackendsEnabled', $externalBackends);
$encryptionModules = \OC::$server->getEncryptionManager()->getEncryptionModules();
+
try {
$defaultEncryptionModule = \OC::$server->getEncryptionManager()->getDefaultEncryptionModule();
$defaultEncryptionModuleId = $defaultEncryptionModule->getId();
diff --git a/settings/application.php b/settings/application.php
index be127da31a..59fe9f6b65 100644
--- a/settings/application.php
+++ b/settings/application.php
@@ -23,8 +23,10 @@
namespace OC\Settings;
+use OC\Files\View;
use OC\Settings\Controller\AppSettingsController;
use OC\Settings\Controller\CheckSetupController;
+use OC\Settings\Controller\EncryptionController;
use OC\Settings\Controller\GroupsController;
use OC\Settings\Controller\LogSettingsController;
use OC\Settings\Controller\MailSettingsController;
@@ -65,6 +67,17 @@ class Application extends App {
$c->query('DefaultMailAddress')
);
});
+ $container->registerService('EncryptionController', function(IContainer $c) {
+ return new EncryptionController(
+ $c->query('AppName'),
+ $c->query('Request'),
+ $c->query('L10N'),
+ $c->query('Config'),
+ $c->query('DatabaseConnection'),
+ $c->query('UserManager'),
+ new View()
+ );
+ });
$container->registerService('AppSettingsController', function(IContainer $c) {
return new AppSettingsController(
$c->query('AppName'),
@@ -207,5 +220,8 @@ class Application extends App {
$container->registerService('Util', function(IContainer $c) {
return new \OC_Util();
});
+ $container->registerService('DatabaseConnection', function(IContainer $c) {
+ return $c->query('ServerContainer')->getDatabaseConnection();
+ });
}
}
diff --git a/settings/controller/encryptioncontroller.php b/settings/controller/encryptioncontroller.php
new file mode 100644
index 0000000000..800982d1f0
--- /dev/null
+++ b/settings/controller/encryptioncontroller.php
@@ -0,0 +1,122 @@
+
+ *
+ * @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
+ *
+ */
+
+
+namespace OC\Settings\Controller;
+use OC\Files\View;
+use OCA\Encryption\Migration;
+use OCP\IL10N;
+use OCP\AppFramework\Controller;
+use OCP\IRequest;
+use OCP\IConfig;
+use OC\DB\Connection;
+use OCP\IUserManager;
+
+/**
+ * @package OC\Settings\Controller
+ */
+class EncryptionController extends Controller {
+
+ /** @var \OCP\IL10N */
+ private $l10n;
+
+ /** @var Connection */
+ private $connection;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var IUserManager */
+ private $userManager;
+
+ /** @var View */
+ private $view;
+
+ /**
+ * @param string $appName
+ * @param IRequest $request
+ * @param \OCP\IL10N $l10n
+ * @param \OCP\IConfig $config
+ * @param \OC\DB\Connection $connection
+ * @param IUserManager $userManager
+ * @param View $view
+ */
+ public function __construct($appName,
+ IRequest $request,
+ IL10N $l10n,
+ IConfig $config,
+ Connection $connection,
+ IUserManager $userManager,
+ View $view) {
+ parent::__construct($appName, $request);
+ $this->l10n = $l10n;
+ $this->config = $config;
+ $this->connection = $connection;
+ $this->view = $view;
+ $this->userManager = $userManager;
+ }
+
+ /**
+ * start migration
+ *
+ * @return array
+ */
+ public function startMigration() {
+ // allow as long execution on the web server as possible
+ set_time_limit(0);
+ $migration = new Migration($this->config, $this->view, $this->connection);
+ $migration->reorganizeSystemFolderStructure();
+ $migration->updateDB();
+
+ try {
+
+ 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);
+ }
+
+ } catch (\Exception $e) {
+ return array(
+ 'data' => array(
+ 'message' => (string)$this->l10n->t('A problem occurred, please check your log files (Error: %s)', [$e->getMessage()]),
+ ),
+ 'status' => 'error',
+ );
+ }
+
+ return array('data' =>
+ array('message' =>
+ (string) $this->l10n->t('Migration Completed')
+ ),
+ 'status' => 'success'
+ );
+
+ }
+
+}
diff --git a/settings/js/admin.js b/settings/js/admin.js
index 34f58db868..9cdb7f5b0f 100644
--- a/settings/js/admin.js
+++ b/settings/js/admin.js
@@ -55,7 +55,7 @@ $(document).ready(function(){
});
$('#encryptionEnabled').change(function() {
- $('#encryptionAPI div#selectEncryptionModules').toggleClass('hidden');
+ $('#encryptionAPI div#EncryptionSettingsArea').toggleClass('hidden');
});
$('#encryptionAPI input').change(function() {
@@ -70,6 +70,26 @@ $(document).ready(function(){
OC.AppConfig.setValue('core', $(this).attr('name'), value);
});
+ $('#startmigration').click(function(event){
+ $(window).on('beforeunload.encryption', function(e) {
+ return t('settings', 'Migration in progress. Please wait until the migration is finished');
+ });
+ event.preventDefault();
+ $('#startmigration').prop('disabled', true);
+ OC.msg.startAction('#startmigration_msg', t('settings', 'Migration started …'));
+ $.post(OC.generateUrl('/settings/admin/startmigration'), '', function(data){
+ OC.msg.finishedAction('#startmigration_msg', data);
+ if (data['status'] === 'success') {
+ $('#encryptionAPI div#selectEncryptionModules').toggleClass('hidden');
+ $('#encryptionAPI div#migrationWarning').toggleClass('hidden');
+ } else {
+ $('#startmigration').prop('disabled', false);
+ }
+ $(window).off('beforeunload.encryption');
+
+ });
+ });
+
$('#shareAPI input:not(#excludedGroups)').change(function() {
var value = $(this).val();
if ($(this).attr('type') === 'checkbox') {
diff --git a/settings/routes.php b/settings/routes.php
index 1bb1481214..462b4ab543 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -42,6 +42,7 @@ $application->registerRoutes($this, [
['name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST'],
['name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST'],
['name' => 'MailSettings#sendTestMail', 'url' => '/settings/admin/mailtest', 'verb' => 'POST'],
+ ['name' => 'Encryption#startMigration', 'url' => '/settings/admin/startmigration', 'verb' => 'POST'],
['name' => 'AppSettings#listCategories', 'url' => '/settings/apps/categories', 'verb' => 'GET'],
['name' => 'AppSettings#viewApps', 'url' => '/settings/apps', 'verb' => 'GET'],
['name' => 'AppSettings#listApps', 'url' => '/settings/apps/list', 'verb' => 'GET'],
diff --git a/settings/templates/admin.php b/settings/templates/admin.php
index 4bc497df76..55c0018e5a 100644
--- a/settings/templates/admin.php
+++ b/settings/templates/admin.php
@@ -300,27 +300,50 @@ if ($_['cronErrors']) {
-
t('Server Side Encryption'));?>
-
- />
-
-
-
-
+
t('Server Side Encryption')); ?>
+
+
+ />
+
+
+
+
diff --git a/tests/lib/encryption/managertest.php b/tests/lib/encryption/managertest.php
index 4fcbc3b998..f123f43831 100644
--- a/tests/lib/encryption/managertest.php
+++ b/tests/lib/encryption/managertest.php
@@ -7,36 +7,45 @@ use Test\TestCase;
class ManagerTest extends TestCase {
+ /** @var Manager */
+ private $manager;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ private $config;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ private $logger;
+
+ public function setUp() {
+ parent::setUp();
+ $this->config = $this->getMock('\OCP\IConfig');
+ $this->logger = $this->getMock('\OCP\ILogger');
+ $this->manager = new Manager($this->config, $this->logger);
+
+ }
+
public function testManagerIsDisabled() {
- $config = $this->getMock('\OCP\IConfig');
- $m = new Manager($config);
- $this->assertFalse($m->isEnabled());
+ $this->assertFalse($this->manager->isEnabled());
}
public function testManagerIsDisabledIfEnabledButNoModules() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn(true);
- $m = new Manager($config);
- $this->assertFalse($m->isEnabled());
+ $this->config->expects($this->any())->method('getAppValue')->willReturn(true);
+ $this->assertFalse($this->manager->isEnabled());
}
public function testManagerIsDisabledIfDisabledButModules() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn(false);
+ $this->config->expects($this->any())->method('getAppValue')->willReturn(false);
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn(0);
$em->expects($this->any())->method('getDisplayName')->willReturn('TestDummyModule0');
- $m = new Manager($config);
- $m->registerEncryptionModule($em);
- $this->assertFalse($m->isEnabled());
+ $this->manager->registerEncryptionModule($em);
+ $this->assertFalse($this->manager->isEnabled());
}
public function testManagerIsEnabled() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getSystemValue')->willReturn(true);
- $config->expects($this->any())->method('getAppValue')->willReturn('yes');
- $m = new Manager($config);
- $this->assertTrue($m->isEnabled());
+ $this->config->expects($this->any())->method('getSystemValue')->willReturn(true);
+ $this->config->expects($this->any())->method('getAppValue')->willReturn('yes');
+ $this->assertTrue($this->manager->isEnabled());
}
/**
@@ -44,30 +53,26 @@ class ManagerTest extends TestCase {
* @expectedExceptionMessage Id "0" already used by encryption module "TestDummyModule0"
*/
public function testModuleRegistration() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn('yes');
+ $this->config->expects($this->any())->method('getAppValue')->willReturn('yes');
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn(0);
$em->expects($this->any())->method('getDisplayName')->willReturn('TestDummyModule0');
- $m = new Manager($config);
- $m->registerEncryptionModule($em);
- $this->assertSame(1, count($m->getEncryptionModules()));
- $m->registerEncryptionModule($em);
+ $this->manager->registerEncryptionModule($em);
+ $this->assertSame(1, count($this->manager->getEncryptionModules()));
+ $this->manager->registerEncryptionModule($em);
}
public function testModuleUnRegistration() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn(true);
+ $this->config->expects($this->any())->method('getAppValue')->willReturn(true);
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn(0);
$em->expects($this->any())->method('getDisplayName')->willReturn('TestDummyModule0');
- $m = new Manager($config);
- $m->registerEncryptionModule($em);
+ $this->manager->registerEncryptionModule($em);
$this->assertSame(1,
- count($m->getEncryptionModules())
+ count($this->manager->getEncryptionModules())
);
- $m->unregisterEncryptionModule($em);
- $this->assertEmpty($m->getEncryptionModules());
+ $this->manager->unregisterEncryptionModule($em);
+ $this->assertEmpty($this->manager->getEncryptionModules());
}
/**
@@ -75,40 +80,34 @@ class ManagerTest extends TestCase {
* @expectedExceptionMessage Module with id: unknown does not exists.
*/
public function testGetEncryptionModuleUnknown() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn(true);
+ $this->config->expects($this->any())->method('getAppValue')->willReturn(true);
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn(0);
$em->expects($this->any())->method('getDisplayName')->willReturn('TestDummyModule0');
- $m = new Manager($config);
- $m->registerEncryptionModule($em);
- $this->assertSame(1, count($m->getEncryptionModules()));
- $m->getEncryptionModule('unknown');
+ $this->manager->registerEncryptionModule($em);
+ $this->assertSame(1, count($this->manager->getEncryptionModules()));
+ $this->manager->getEncryptionModule('unknown');
}
public function testGetEncryptionModule() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn(true);
+ $this->config->expects($this->any())->method('getAppValue')->willReturn(true);
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn(0);
$em->expects($this->any())->method('getDisplayName')->willReturn('TestDummyModule0');
- $m = new Manager($config);
- $m->registerEncryptionModule($em);
- $this->assertSame(1, count($m->getEncryptionModules()));
- $en0 = $m->getEncryptionModule(0);
+ $this->manager->registerEncryptionModule($em);
+ $this->assertSame(1, count($this->manager->getEncryptionModules()));
+ $en0 = $this->manager->getEncryptionModule(0);
$this->assertEquals(0, $en0->getId());
}
public function testGetDefaultEncryptionModule() {
- $config = $this->getMock('\OCP\IConfig');
- $config->expects($this->any())->method('getAppValue')->willReturn(true);
+ $this->config->expects($this->any())->method('getAppValue')->willReturn(true);
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn(0);
$em->expects($this->any())->method('getDisplayName')->willReturn('TestDummyModule0');
- $m = new Manager($config);
- $m->registerEncryptionModule($em);
- $this->assertSame(1, count($m->getEncryptionModules()));
- $en0 = $m->getEncryptionModule(0);
+ $this->manager->registerEncryptionModule($em);
+ $this->assertSame(1, count($this->manager->getEncryptionModules()));
+ $en0 = $this->manager->getEncryptionModule(0);
$this->assertEquals(0, $en0->getId());
}
diff --git a/tests/lib/encryption/utiltest.php b/tests/lib/encryption/utiltest.php
index 03aefe6115..dc6205e16f 100644
--- a/tests/lib/encryption/utiltest.php
+++ b/tests/lib/encryption/utiltest.php
@@ -20,9 +20,15 @@ class UtilTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $userManager;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $groupManager;
+
/** @var \PHPUnit_Framework_MockObject_MockObject */
private $config;
+ /** @var \OC\Encryption\Util */
+ private $util;
+
public function setUp() {
parent::setUp();
$this->view = $this->getMockBuilder('OC\Files\View')
@@ -33,18 +39,28 @@ class UtilTest extends TestCase {
->disableOriginalConstructor()
->getMock();
+ $this->groupManager = $this->getMockBuilder('OC\Group\Manager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
$this->config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
+ $this->util = new Util(
+ $this->view,
+ $this->userManager,
+ $this->groupManager,
+ $this->config
+ );
+
}
/**
* @dataProvider providesHeadersForEncryptionModule
*/
public function testGetEncryptionModuleId($expected, $header) {
- $u = new Util($this->view, $this->userManager, $this->config);
- $id = $u->getEncryptionModuleId($header);
+ $id = $this->util->getEncryptionModuleId($header);
$this->assertEquals($expected, $id);
}
@@ -61,8 +77,7 @@ class UtilTest extends TestCase {
*/
public function testReadHeader($header, $expected, $moduleId) {
$expected['oc_encryption_module'] = $moduleId;
- $u = new Util($this->view, $this->userManager, $this->config);
- $result = $u->readHeader($header);
+ $result = $this->util->readHeader($header);
$this->assertSameSize($expected, $result);
foreach ($expected as $key => $value) {
$this->assertArrayHasKey($key, $result);
@@ -78,8 +93,7 @@ class UtilTest extends TestCase {
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn($moduleId);
- $u = new Util($this->view, $this->userManager, $this->config);
- $result = $u->createHeader($header, $em);
+ $result = $this->util->createHeader($header, $em);
$this->assertEquals($expected, $result);
}
@@ -102,23 +116,20 @@ class UtilTest extends TestCase {
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn('moduleId');
- $u = new Util($this->view, $this->userManager, $this->config);
- $u->createHeader($header, $em);
+ $this->util->createHeader($header, $em);
}
/**
* @dataProvider providePathsForTestIsExcluded
*/
- public function testIsEcluded($path, $expected) {
+ public function testIsExcluded($path, $expected) {
$this->userManager
->expects($this->any())
->method('userExists')
->will($this->returnCallback(array($this, 'isExcludedCallback')));
- $u = new Util($this->view, $this->userManager, $this->config);
-
$this->assertSame($expected,
- $u->isExcluded($path)
+ $this->util->isExcluded($path)
);
}
diff --git a/tests/lib/files/storage/wrapper/encryption.php b/tests/lib/files/storage/wrapper/encryption.php
index ec3770260a..3256f772df 100644
--- a/tests/lib/files/storage/wrapper/encryption.php
+++ b/tests/lib/files/storage/wrapper/encryption.php
@@ -34,8 +34,11 @@ class Encryption extends \Test\Files\Storage\Storage {
$config = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()
->getMock();
+ $groupManager = $this->getMockBuilder('\OC\Group\Manager')
+ ->disableOriginalConstructor()
+ ->getMock();
- $util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $config]);
+ $util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $groupManager, $config]);
$util->expects($this->any())
->method('getUidAndFilename')
->willReturnCallback(function ($path) {
diff --git a/tests/lib/files/stream/encryption.php b/tests/lib/files/stream/encryption.php
index 6964d203f1..f52fd0e16c 100644
--- a/tests/lib/files/stream/encryption.php
+++ b/tests/lib/files/stream/encryption.php
@@ -27,12 +27,15 @@ class Encryption extends \Test\TestCase {
$config = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()
->getMock();
+ $groupManager = $this->getMockBuilder('\OC\Group\Manager')
+ ->disableOriginalConstructor()
+ ->getMock();
$file = $this->getMockBuilder('\OC\Encryption\File')
->disableOriginalConstructor()
->setMethods(['getAccessList'])
->getMock();
$file->expects($this->any())->method('getAccessList')->willReturn([]);
- $util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $config]);
+ $util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $groupManager, $config]);
$util->expects($this->any())
->method('getUidAndFilename')
->willReturn(['user1', $internalPath]);