]> source.dussan.org Git - nextcloud-server.git/commitdiff
Generate storage config ids when missing
authorVincent Petry <pvince81@owncloud.com>
Mon, 16 Mar 2015 11:18:01 +0000 (12:18 +0100)
committerVincent Petry <pvince81@owncloud.com>
Mon, 16 Mar 2015 11:18:01 +0000 (12:18 +0100)
When reading in old mount.json files, they do not contain config ids.
Since these are needed to be able to use the UI and the new service
classes, these will be generated automatically.

The config grouping is based on a config hash.

apps/files_external/controller/globalstoragescontroller.php
apps/files_external/controller/userstoragescontroller.php
apps/files_external/lib/config.php
apps/files_external/personal.php
apps/files_external/service/storagesservice.php
apps/files_external/settings.php
apps/files_external/tests/service/globalstoragesservicetest.php
apps/files_external/tests/service/userstoragesservicetest.php

index e5aff4f95a24ca06ddd9b79cdccef83f7fd4825d..815f24ee2beaeacc4b5c1479ff05b807ec05f909 100644 (file)
@@ -15,6 +15,7 @@ namespace OCA\Files_External\Controller;
 use \OCP\IConfig;
 use \OCP\IUserSession;
 use \OCP\IRequest;
+use \OCP\IL10N;
 use \OCP\AppFramework\Http\DataResponse;
 use \OCP\AppFramework\Controller;
 use \OCP\AppFramework\Http;
@@ -24,15 +25,17 @@ use \OCA\Files_external\Lib\StorageConfig;
 
 class GlobalStoragesController extends StoragesController {
        /**
-        * @param string $appName
-        * @param IRequest $request
-        * @param IConfig $config
-        * @param GlobalStoragesService $globalStoragesService
+        * Creates a new global storages controller.
+        *
+        * @param string $AppName application name
+        * @param IRequest $request request object
+        * @param IL10N $l10n l10n service
+        * @param GlobalStoragesService $globalStoragesService storage service
         */
        public function __construct(
                $AppName,
                IRequest $request,
-               \OCP\IL10N $l10n,
+               IL10N $l10n,
                GlobalStoragesService $globalStoragesService
        ){
                parent::__construct(
index 64202b5e5428f2e2fd090353a2a7003b60f80a31..ed7ec453ccda95cd4a01b22934459db532079a99 100644 (file)
@@ -15,6 +15,7 @@ namespace OCA\Files_External\Controller;
 use \OCP\IConfig;
 use \OCP\IUserSession;
 use \OCP\IRequest;
+use \OCP\IL10N;
 use \OCP\AppFramework\Http\DataResponse;
 use \OCP\AppFramework\Controller;
 use \OCP\AppFramework\Http;
@@ -24,15 +25,17 @@ use \OCA\Files_external\Lib\StorageConfig;
 
 class UserStoragesController extends StoragesController {
        /**
-        * @param string $appName
-        * @param IRequest $request
-        * @param IConfig $config
-        * @param UserStoragesService $userStoragesService
+        * Creates a new user storages controller.
+        *
+        * @param string $AppName application name
+        * @param IRequest $request request object
+        * @param IL10N $l10n l10n service
+        * @param UserStoragesService $userStoragesService storage service
         */
        public function __construct(
                $AppName,
                IRequest $request,
-               \OCP\IL10N $l10n,
+               IL10N $l10n,
                UserStoragesService $userStoragesService
        ){
                parent::__construct(
index 23750dbb3fab268ee4ffeb645a7a4bd38389e5a9..884e596bdd491371ae51d32bc0ded26024f590ba 100644 (file)
@@ -894,12 +894,14 @@ class OC_Mount_Config {
         * This is mostly used to find out whether configurations
         * are the same.
         */
-       private static function makeConfigHash($config) {
+       public static function makeConfigHash($config) {
                $data = json_encode(
                        array(
                                'c' => $config['class'],
                                'm' => $config['mountpoint'],
-                               'o' => $config['options']
+                               'o' => $config['options'],
+                               'p' => isset($config['priority']) ? $config['priority'] : -1,
+                               'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
                        )
                );
                return hash('md5', $data);
index a279163ff701a2e79d6e3a7adf8893b50e6c7cc4..8b43544225978f7c223301fb9347e553e5234ed3 100644 (file)
@@ -24,9 +24,29 @@ OCP\Util::addScript('files_external', 'settings');
 OCP\Util::addStyle('files_external', 'settings');
 $backends = OC_Mount_Config::getPersonalBackends();
 
+$mounts = OC_Mount_Config::getPersonalMountPoints();
+$hasId = true;
+foreach ($mounts as $mount) {
+       if (!isset($mount['id'])) {
+               // some mount points are missing ids
+               $hasId = false;
+               break;
+       }
+}
+
+if (!$hasId) {
+       $service = new \OCA\Files_external\Service\UserStoragesService(\OC::$server->getUserSession());
+       // this will trigger the new storage code which will automatically
+       // generate storage config ids
+       $service->getAllStorages();
+       // re-read updated config
+       $mounts = OC_Mount_Config::getPersonalMountPoints();
+       // TODO: use the new storage config format in the template
+}
+
 $tmpl = new OCP\Template('files_external', 'settings');
 $tmpl->assign('isAdminPage', false);
-$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
+$tmpl->assign('mounts', $mounts);
 $tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
 $tmpl->assign('backends', $backends);
 return $tmpl->fetchPage();
index 46a485a169c47d7ad0951a02d579fa9bcc6cc611..73a0ae76475228efe6870511f9870d42891890ce 100644 (file)
@@ -29,6 +29,39 @@ abstract class StoragesService {
                return \OC_Mount_Config::readData();
        }
 
+       /**
+        * Copy legacy storage options into the given storage config object.
+        *
+        * @param StorageConfig $storageConfig storage config to populate
+        * @param string $mountType mount type
+        * @param string $applicable applicable user or group
+        * @param array $storageOptions legacy storage options
+        * @return StorageConfig populated storage config
+        */
+       protected function populateStorageConfigWithLegacyOptions(&$storageConfig, $mountType, $applicable, $storageOptions) {
+               $storageConfig->setBackendClass($storageOptions['class']);
+               $storageConfig->setBackendOptions($storageOptions['options']);
+               if (isset($storageOptions['mountOptions'])) {
+                       $storageConfig->setMountOptions($storageOptions['mountOptions']);
+               }
+               if (isset($storageOptions['priority'])) {
+                       $storageConfig->setPriority($storageOptions['priority']);
+               }
+
+               if ($mountType === \OC_Mount_Config::MOUNT_TYPE_USER) {
+                       $applicableUsers = $storageConfig->getApplicableUsers();
+                       if ($applicable !== 'all') {
+                               $applicableUsers[] = $applicable;
+                               $storageConfig->setApplicableUsers($applicableUsers);
+                       }
+               } else if ($mountType === \OC_Mount_Config::MOUNT_TYPE_GROUP) {
+                       $applicableGroups = $storageConfig->getApplicableGroups();
+                       $applicableGroups[] = $applicable;
+                       $storageConfig->setApplicableGroups($applicableGroups);
+               }
+               return $storageConfig;
+       }
+
        /**
         * Read the external storages config
         *
@@ -55,9 +88,25 @@ abstract class StoragesService {
 
                // group by storage id
                $storages = [];
+
+               // for storages without id (legacy), group by config hash for
+               // later processing
+               $storagesWithConfigHash = [];
+
                foreach ($mountPoints as $mountType => $applicables) {
                        foreach ($applicables as $applicable => $mountPaths) {
                                foreach ($mountPaths as $rootMountPath => $storageOptions) {
+                                       $currentStorage = null;
+
+                                       /**
+                                        * Flag whether the config that was read already has an id.
+                                        * If not, it will use a config hash instead and generate
+                                        * a proper id later
+                                        *
+                                        * @var boolean
+                                        */
+                                       $hasId = false;
+
                                        // the root mount point is in the format "/$user/files/the/mount/point"
                                        // we remove the "/$user/files" prefix
                                        $parts = explode('/', trim($rootMountPath, '/'), 3);
@@ -73,46 +122,60 @@ abstract class StoragesService {
 
                                        $relativeMountPath = $parts[2];
 
-                                       $configId = (int)$storageOptions['id'];
-                                       if (isset($storages[$configId])) {
-                                               $currentStorage = $storages[$configId];
+                                       // note: we cannot do this after the loop because the decrypted config
+                                       // options might be needed for the config hash
+                                       $storageOptions['options'] = \OC_Mount_Config::decryptPasswords($storageOptions['options']);
+
+                                       if (isset($storageOptions['id'])) {
+                                               $configId = (int)$storageOptions['id'];
+                                               if (isset($storages[$configId])) {
+                                                       $currentStorage = $storages[$configId];
+                                               }
+                                               $hasId = true;
                                        } else {
+                                               // missing id in legacy config, need to generate
+                                               // but at this point we don't know the max-id, so use
+                                               // first group it by config hash
+                                               $storageOptions['mountpoint'] = $rootMountPath;
+                                               $configId = \OC_Mount_Config::makeConfigHash($storageOptions);
+                                               if (isset($storagesWithConfigHash[$configId])) {
+                                                       $currentStorage = $storagesWithConfigHash[$configId];
+                                               }
+                                       }
+
+                                       if (is_null($currentStorage)) {
+                                               // create new
                                                $currentStorage = new StorageConfig($configId);
                                                $currentStorage->setMountPoint($relativeMountPath);
                                        }
 
-                                       $currentStorage->setBackendClass($storageOptions['class']);
-                                       $currentStorage->setBackendOptions($storageOptions['options']);
-                                       if (isset($storageOptions['mountOptions'])) {
-                                               $currentStorage->setMountOptions($storageOptions['mountOptions']);
-                                       }
-                                       if (isset($storageOptions['priority'])) {
-                                               $currentStorage->setPriority($storageOptions['priority']);
-                                       }
+                                       $this->populateStorageConfigWithLegacyOptions(
+                                               $currentStorage,
+                                               $mountType,
+                                               $applicable,
+                                               $storageOptions
+                                       );
 
-                                       if ($mountType === \OC_Mount_Config::MOUNT_TYPE_USER) {
-                                               $applicableUsers = $currentStorage->getApplicableUsers();
-                                               if ($applicable !== 'all') {
-                                                       $applicableUsers[] = $applicable;
-                                                       $currentStorage->setApplicableUsers($applicableUsers);
-                                               }
-                                       } else if ($mountType === \OC_Mount_Config::MOUNT_TYPE_GROUP) {
-                                               $applicableGroups = $currentStorage->getApplicableGroups();
-                                               $applicableGroups[] = $applicable;
-                                               $currentStorage->setApplicableGroups($applicableGroups);
+                                       if ($hasId) {
+                                               $storages[$configId] = $currentStorage;
+                                       } else {
+                                               $storagesWithConfigHash[$configId] = $currentStorage;
                                        }
-                                       $storages[$configId] = $currentStorage;
                                }
                        }
                }
 
-               // decrypt passwords
-               foreach ($storages as &$storage) {
-                       $storage->setBackendOptions(
-                               \OC_Mount_Config::decryptPasswords(
-                                       $storage->getBackendOptions()
-                               )
-                       );
+               // process storages with config hash, they must get a real id
+               if (!empty($storagesWithConfigHash)) {
+                       $nextId = $this->generateNextId($storages);
+                       foreach ($storagesWithConfigHash as $storage) {
+                               $storage->setId($nextId);
+                               $storages[$nextId] = $storage;
+                               $nextId++;
+                       }
+
+                       // re-save the config with the generated ids
+                       $this->writeConfig($storages);
                }
 
                return $storages;
@@ -176,6 +239,15 @@ abstract class StoragesService {
                return $allStorages[$id];
        }
 
+       /**
+        * Gets all storages
+        *
+        * @return array array of storage configs
+        */
+       public function getAllStorages() {
+               return $this->readConfig();
+       }
+
        /**
         * Add new storage to the configuration
         *
index dec329e82a2bba16d1e644e8f7d78f71be9f2ae5..3144e1a2ab6284e337cec424ca5f82785008ca48 100644 (file)
@@ -42,9 +42,29 @@ foreach ($backends as $class => $backend)
        }
 }
 
+$mounts = OC_Mount_Config::getSystemMountPoints();
+$hasId = true;
+foreach ($mounts as $mount) {
+       if (!isset($mount['id'])) {
+               // some mount points are missing ids
+               $hasId = false;
+               break;
+       }
+}
+
+if (!$hasId) {
+       $service = new \OCA\Files_external\Service\GlobalStoragesService();
+       // this will trigger the new storage code which will automatically
+       // generate storage config ids
+       $service->getAllStorages();
+       // re-read updated config
+       $mounts = OC_Mount_Config::getSystemMountPoints();
+       // TODO: use the new storage config format in the template
+}
+
 $tmpl = new OCP\Template('files_external', 'settings');
 $tmpl->assign('isAdminPage', true);
-$tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints());
+$tmpl->assign('mounts', $mounts);
 $tmpl->assign('backends', $backends);
 $tmpl->assign('personal_backends', $personal_backends);
 $tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
index f5cdcfa3907f76411abc5f0fb93af679cf0e0b80..4c038bc489e754593be76a726c76de3774891655 100644 (file)
@@ -708,4 +708,108 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
                }
        }
 
+       /**
+        * Test reading in a legacy config and generating config ids.
+        */
+       public function testReadLegacyConfigAndGenerateConfigId() {
+               $configFile = $this->dataDir . '/mount.json';
+
+               $legacyBackendOptions = [
+                       'user' => 'someuser',
+                       'password' => 'somepassword',
+               ];
+               $legacyBackendOptions = \OC_Mount_Config::encryptPasswords($legacyBackendOptions);
+
+               $legacyConfig = [
+                       'class' => '\OC\Files\Storage\SMB',
+                       'options' => $legacyBackendOptions,
+                       'mountOptions' => ['preview' => false],
+               ];
+               // different mount options
+               $legacyConfig2 = [
+                       'class' => '\OC\Files\Storage\SMB',
+                       'options' => $legacyBackendOptions,
+                       'mountOptions' => ['preview' => true],
+               ];
+
+               $legacyBackendOptions2 = $legacyBackendOptions;
+               $legacyBackendOptions2 = ['user' => 'someuser2', 'password' => 'somepassword2'];
+               $legacyBackendOptions2 = \OC_Mount_Config::encryptPasswords($legacyBackendOptions2);
+
+               // different config
+               $legacyConfig3 = [
+                       'class' => '\OC\Files\Storage\SMB',
+                       'options' => $legacyBackendOptions2,
+                       'mountOptions' => ['preview' => true],
+               ];
+
+               $json = [
+                       'user' => [
+                               'user1' => [
+                                       '/$user/files/somemount' => $legacyConfig,
+                               ],
+                               // same config
+                               'user2' => [
+                                       '/$user/files/somemount' => $legacyConfig,
+                               ],
+                               // different mountOptions
+                               'user3' => [
+                                       '/$user/files/somemount' => $legacyConfig2,
+                               ],
+                               // different mount point
+                               'user4' => [
+                                       '/$user/files/anothermount' => $legacyConfig,
+                               ],
+                               // different storage config
+                               'user5' => [
+                                       '/$user/files/somemount' => $legacyConfig3,
+                               ],
+                       ],
+                       'group' => [
+                               'group1' => [
+                                       // will get grouped with user configs
+                                       '/$user/files/somemount' => $legacyConfig,
+                               ],
+                       ],
+               ];
+
+               file_put_contents($configFile, json_encode($json));
+
+               $allStorages = $this->service->getAllStorages();
+
+               $this->assertCount(4, $allStorages);
+
+               $storage1 = $allStorages[1];
+               $storage2 = $allStorages[2];
+               $storage3 = $allStorages[3];
+               $storage4 = $allStorages[4];
+
+               $this->assertEquals('/somemount', $storage1->getMountPoint());
+               $this->assertEquals('someuser', $storage1->getBackendOptions()['user']);
+               $this->assertEquals('somepassword', $storage1->getBackendOptions()['password']);
+               $this->assertEquals(['user1', 'user2'], $storage1->getApplicableUsers());
+               $this->assertEquals(['group1'], $storage1->getApplicableGroups());
+               $this->assertEquals(['preview' => false], $storage1->getMountOptions());
+
+               $this->assertEquals('/somemount', $storage2->getMountPoint());
+               $this->assertEquals('someuser', $storage2->getBackendOptions()['user']);
+               $this->assertEquals('somepassword', $storage2->getBackendOptions()['password']);
+               $this->assertEquals(['user3'], $storage2->getApplicableUsers());
+               $this->assertEquals([], $storage2->getApplicableGroups());
+               $this->assertEquals(['preview' => true], $storage2->getMountOptions());
+
+               $this->assertEquals('/anothermount', $storage3->getMountPoint());
+               $this->assertEquals('someuser', $storage3->getBackendOptions()['user']);
+               $this->assertEquals('somepassword', $storage3->getBackendOptions()['password']);
+               $this->assertEquals(['user4'], $storage3->getApplicableUsers());
+               $this->assertEquals([], $storage3->getApplicableGroups());
+               $this->assertEquals(['preview' => false], $storage3->getMountOptions());
+
+               $this->assertEquals('/somemount', $storage4->getMountPoint());
+               $this->assertEquals('someuser2', $storage4->getBackendOptions()['user']);
+               $this->assertEquals('somepassword2', $storage4->getBackendOptions()['password']);
+               $this->assertEquals(['user5'], $storage4->getApplicableUsers());
+               $this->assertEquals([], $storage4->getApplicableGroups());
+               $this->assertEquals(['preview' => true], $storage4->getMountOptions());
+       }
 }
index 77b3842b3186919adabfd01400ab02122fbf4747..dd3f9e1b92c86b3ea2a6279f5ea31bc31dd921a9 100644 (file)
@@ -201,4 +201,54 @@ class UserStoragesServiceTest extends StoragesServiceTest {
                $this->assertEquals('', $backendOptions['password']);
                $this->assertNotEmpty($backendOptions['password_encrypted']);
        }
+
+       /**
+        * Test reading in a legacy config and generating config ids.
+        */
+       public function testReadLegacyConfigAndGenerateConfigId() {
+               $configFile = $this->dataDir . '/' . $this->userId . '/mount.json';
+
+               $legacyBackendOptions = [
+                       'user' => 'someuser',
+                       'password' => 'somepassword',
+               ];
+               $legacyBackendOptions = \OC_Mount_Config::encryptPasswords($legacyBackendOptions);
+
+               $legacyConfig = [
+                       'class' => '\OC\Files\Storage\SMB',
+                       'options' => $legacyBackendOptions,
+                       'mountOptions' => ['preview' => false],
+               ];
+               // different mount options
+               $legacyConfig2 = [
+                       'class' => '\OC\Files\Storage\SMB',
+                       'options' => $legacyBackendOptions,
+                       'mountOptions' => ['preview' => true],
+               ];
+
+               $json = ['user' => []];
+               $json['user'][$this->userId] = [
+                       '/$user/files/somemount' => $legacyConfig,
+                       '/$user/files/anothermount' => $legacyConfig2,
+               ];
+
+               file_put_contents($configFile, json_encode($json));
+
+               $allStorages = $this->service->getAllStorages();
+
+               $this->assertCount(2, $allStorages);
+
+               $storage1 = $allStorages[1];
+               $storage2 = $allStorages[2];
+
+               $this->assertEquals('/somemount', $storage1->getMountPoint());
+               $this->assertEquals('someuser', $storage1->getBackendOptions()['user']);
+               $this->assertEquals('somepassword', $storage1->getBackendOptions()['password']);
+               $this->assertEquals(['preview' => false], $storage1->getMountOptions());
+
+               $this->assertEquals('/anothermount', $storage2->getMountPoint());
+               $this->assertEquals('someuser', $storage2->getBackendOptions()['user']);
+               $this->assertEquals('somepassword', $storage2->getBackendOptions()['password']);
+               $this->assertEquals(['preview' => true], $storage2->getMountOptions());
+       }
 }