db config backend for files_external
This commit is contained in:
parent
98bb8372f7
commit
a1898dc2bf
18 changed files with 1617 additions and 954 deletions
222
apps/files_external/appinfo/database.xml
Normal file
222
apps/files_external/appinfo/database.xml
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
<database>
|
||||||
|
<name>*dbname*</name>
|
||||||
|
<create>true</create>
|
||||||
|
<overwrite>false</overwrite>
|
||||||
|
<charset>utf8</charset>
|
||||||
|
<table>
|
||||||
|
<name>*dbprefix*external_mounts</name>
|
||||||
|
<declaration>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<default>0</default>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<autoincrement>1</autoincrement>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>mount_point</name>
|
||||||
|
<type>text</type>
|
||||||
|
<length>128</length>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>storage_backend</name>
|
||||||
|
<type>text</type>
|
||||||
|
<length>64</length>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>auth_backend</name>
|
||||||
|
<type>text</type>
|
||||||
|
<length>64</length>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>priority</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<default>100</default>
|
||||||
|
<length>4</length>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
</field>
|
||||||
|
<!-- admin = 1, personal = 2-->
|
||||||
|
<field>
|
||||||
|
<name>type</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<length>4</length>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
</field>
|
||||||
|
</declaration>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<name>*dbprefix*external_applicable</name>
|
||||||
|
<declaration>
|
||||||
|
<field>
|
||||||
|
<name>applicable_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<default>0</default>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<autoincrement>1</autoincrement>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<!--foreign key: external_mounts.mount_id-->
|
||||||
|
<name>mount_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<!-- possible mount types: global = 1, group = 2, user = 3 -->
|
||||||
|
<name>type</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<length>4</length>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<!-- user_id, group_id or null for global mounts -->
|
||||||
|
<name>value</name>
|
||||||
|
<type>text</type>
|
||||||
|
<length>64</length>
|
||||||
|
</field>
|
||||||
|
<index>
|
||||||
|
<name>mount_id_app_index</name>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
<index>
|
||||||
|
<name>applicable_value_index</name>
|
||||||
|
<field>
|
||||||
|
<name>type</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>value</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
<index>
|
||||||
|
<name>applicable_value_mount_index</name>
|
||||||
|
<unique>true</unique>
|
||||||
|
<field>
|
||||||
|
<name>type</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>value</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
</declaration>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<name>*dbprefix*external_config</name>
|
||||||
|
<declaration>
|
||||||
|
<field>
|
||||||
|
<name>config_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<default>0</default>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<autoincrement>1</autoincrement>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<!--foreign key: external_mounts.mount_id-->
|
||||||
|
<name>mount_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>key</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>value</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>4096</length>
|
||||||
|
</field>
|
||||||
|
|
||||||
|
<index>
|
||||||
|
<name>config_mount_id</name>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
<index>
|
||||||
|
<name>config_mount_key</name>
|
||||||
|
<unique>true</unique>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>key</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
</declaration>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<name>*dbprefix*external_options</name>
|
||||||
|
<declaration>
|
||||||
|
<field>
|
||||||
|
<name>option_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<default>0</default>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<autoincrement>1</autoincrement>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<!--foreign key: external_mounts.mount_id-->
|
||||||
|
<name>mount_id</name>
|
||||||
|
<type>integer</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>6</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>key</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>64</length>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>value</name>
|
||||||
|
<type>text</type>
|
||||||
|
<notnull>true</notnull>
|
||||||
|
<length>256</length>
|
||||||
|
</field>
|
||||||
|
|
||||||
|
<index>
|
||||||
|
<name>option_mount_id</name>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
<index>
|
||||||
|
<name>option_mount_key</name>
|
||||||
|
<unique>true</unique>
|
||||||
|
<field>
|
||||||
|
<name>mount_id</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
<field>
|
||||||
|
<name>key</name>
|
||||||
|
<sorting>ascending</sorting>
|
||||||
|
</field>
|
||||||
|
</index>
|
||||||
|
</declaration>
|
||||||
|
</table>
|
||||||
|
</database>
|
|
@ -14,7 +14,7 @@
|
||||||
<admin>admin-external-storage</admin>
|
<admin>admin-external-storage</admin>
|
||||||
</documentation>
|
</documentation>
|
||||||
<rememberlogin>false</rememberlogin>
|
<rememberlogin>false</rememberlogin>
|
||||||
<version>0.4.0</version>
|
<version>0.5.0</version>
|
||||||
<types>
|
<types>
|
||||||
<filesystem/>
|
<filesystem/>
|
||||||
</types>
|
</types>
|
||||||
|
|
30
apps/files_external/appinfo/update.php
Normal file
30
apps/files_external/appinfo/update.php
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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/>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
$installedVersion = \OC::$server->getConfig()->getAppValue('files_external', 'installed_version');
|
||||||
|
|
||||||
|
$app = new \OCA\Files_external\Appinfo\Application();
|
||||||
|
|
||||||
|
// Migration to db config
|
||||||
|
if (version_compare($installedVersion, '0.5.0', '<')) {
|
||||||
|
$migrator = $app->getContainer()->query('OCA\Files_external\Migration\StorageMigrator');
|
||||||
|
$migrator->migrateGlobal();
|
||||||
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
namespace OCA\Files_External\Config;
|
namespace OCA\Files_External\Config;
|
||||||
|
|
||||||
|
use OCA\Files_external\Migration\StorageMigrator;
|
||||||
use OCP\Files\Storage;
|
use OCP\Files\Storage;
|
||||||
use OC\Files\Mount\MountPoint;
|
use OC\Files\Mount\MountPoint;
|
||||||
use OCP\Files\Storage\IStorageFactory;
|
use OCP\Files\Storage\IStorageFactory;
|
||||||
|
@ -44,17 +45,22 @@ class ConfigAdapter implements IMountProvider {
|
||||||
|
|
||||||
/** @var UserGlobalStoragesService */
|
/** @var UserGlobalStoragesService */
|
||||||
private $userGlobalStoragesService;
|
private $userGlobalStoragesService;
|
||||||
|
/** @var StorageMigrator */
|
||||||
|
private $migrator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param UserStoragesService $userStoragesService
|
* @param UserStoragesService $userStoragesService
|
||||||
* @param UserGlobalStoragesService $userGlobalStoragesService
|
* @param UserGlobalStoragesService $userGlobalStoragesService
|
||||||
|
* @param StorageMigrator $migrator
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
UserStoragesService $userStoragesService,
|
UserStoragesService $userStoragesService,
|
||||||
UserGlobalStoragesService $userGlobalStoragesService
|
UserGlobalStoragesService $userGlobalStoragesService,
|
||||||
|
StorageMigrator $migrator
|
||||||
) {
|
) {
|
||||||
$this->userStoragesService = $userStoragesService;
|
$this->userStoragesService = $userStoragesService;
|
||||||
$this->userGlobalStoragesService = $userGlobalStoragesService;
|
$this->userGlobalStoragesService = $userGlobalStoragesService;
|
||||||
|
$this->migrator = $migrator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,6 +114,8 @@ class ConfigAdapter implements IMountProvider {
|
||||||
* @return \OCP\Files\Mount\IMountPoint[]
|
* @return \OCP\Files\Mount\IMountPoint[]
|
||||||
*/
|
*/
|
||||||
public function getMountsForUser(IUser $user, IStorageFactory $loader) {
|
public function getMountsForUser(IUser $user, IStorageFactory $loader) {
|
||||||
|
$this->migrator->migrateUser();
|
||||||
|
|
||||||
$mounts = [];
|
$mounts = [];
|
||||||
|
|
||||||
$this->userStoragesService->setUser($user);
|
$this->userStoragesService->setUser($user);
|
||||||
|
@ -124,7 +132,7 @@ class ConfigAdapter implements IMountProvider {
|
||||||
|
|
||||||
$mount = new MountPoint(
|
$mount = new MountPoint(
|
||||||
$impl,
|
$impl,
|
||||||
'/'.$user->getUID().'/files' . $storage->getMountPoint(),
|
'/' . $user->getUID() . '/files' . $storage->getMountPoint(),
|
||||||
null,
|
null,
|
||||||
$loader,
|
$loader,
|
||||||
$storage->getMountOptions()
|
$storage->getMountOptions()
|
||||||
|
@ -145,7 +153,7 @@ class ConfigAdapter implements IMountProvider {
|
||||||
$this->userStoragesService,
|
$this->userStoragesService,
|
||||||
$storage->getId(),
|
$storage->getId(),
|
||||||
$impl,
|
$impl,
|
||||||
'/'.$user->getUID().'/files' . $storage->getMountPoint(),
|
'/' . $user->getUID() . '/files' . $storage->getMountPoint(),
|
||||||
null,
|
null,
|
||||||
$loader,
|
$loader,
|
||||||
$storage->getMountOptions()
|
$storage->getMountOptions()
|
||||||
|
|
136
apps/files_external/migration/storagemigrator.php
Normal file
136
apps/files_external/migration/storagemigrator.php
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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 OCA\Files_external\Migration;
|
||||||
|
|
||||||
|
use OCA\Files_External\Service\BackendService;
|
||||||
|
use OCA\Files_External\Service\DBConfigService;
|
||||||
|
use OCA\Files_external\Service\GlobalLegacyStoragesService;
|
||||||
|
use OCA\Files_external\Service\GlobalStoragesService;
|
||||||
|
use OCA\Files_external\Service\LegacyStoragesService;
|
||||||
|
use OCA\Files_external\Service\StoragesService;
|
||||||
|
use OCA\Files_external\Service\UserLegacyStoragesService;
|
||||||
|
use OCA\Files_external\Service\UserStoragesService;
|
||||||
|
use OCP\IConfig;
|
||||||
|
use OCP\IDBConnection;
|
||||||
|
use OCP\ILogger;
|
||||||
|
use OCP\IUserSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate mount config from mount.json to the database
|
||||||
|
*/
|
||||||
|
class StorageMigrator {
|
||||||
|
/**
|
||||||
|
* @var BackendService
|
||||||
|
*/
|
||||||
|
private $backendService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DBConfigService
|
||||||
|
*/
|
||||||
|
private $dbConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IUserSession
|
||||||
|
*/
|
||||||
|
private $userSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IConfig
|
||||||
|
*/
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IDBConnection
|
||||||
|
*/
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ILogger
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StorageMigrator constructor.
|
||||||
|
*
|
||||||
|
* @param BackendService $backendService
|
||||||
|
* @param DBConfigService $dbConfig
|
||||||
|
* @param IUserSession $userSession
|
||||||
|
* @param IConfig $config
|
||||||
|
* @param IDBConnection $connection
|
||||||
|
* @param ILogger $logger
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
BackendService $backendService,
|
||||||
|
DBConfigService $dbConfig,
|
||||||
|
IUserSession $userSession,
|
||||||
|
IConfig $config,
|
||||||
|
IDBConnection $connection,
|
||||||
|
ILogger $logger
|
||||||
|
) {
|
||||||
|
$this->backendService = $backendService;
|
||||||
|
$this->dbConfig = $dbConfig;
|
||||||
|
$this->userSession = $userSession;
|
||||||
|
$this->config = $config;
|
||||||
|
$this->connection = $connection;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function migrate(LegacyStoragesService $legacyService, StoragesService $storageService) {
|
||||||
|
$existingStorage = $legacyService->getAllStorages();
|
||||||
|
|
||||||
|
$this->connection->beginTransaction();
|
||||||
|
try {
|
||||||
|
foreach ($existingStorage as $storage) {
|
||||||
|
$storageService->addStorage($storage);
|
||||||
|
}
|
||||||
|
$this->connection->commit();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->logException($e);
|
||||||
|
$this->connection->rollBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate admin configured storages
|
||||||
|
*/
|
||||||
|
public function migrateGlobal() {
|
||||||
|
$legacyService = new GlobalLegacyStoragesService($this->backendService);
|
||||||
|
$storageService = new GlobalStoragesService($this->backendService, $this->dbConfig);
|
||||||
|
|
||||||
|
$this->migrate($legacyService, $storageService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate personal storages configured by the current user
|
||||||
|
*/
|
||||||
|
public function migrateUser() {
|
||||||
|
$userId = $this->userSession->getUser()->getUID();
|
||||||
|
$userVersion = $this->config->getUserValue($userId, 'files_external', 'config_version', '0.0.0');
|
||||||
|
if (version_compare($userVersion, '0.5.0', '<')) {
|
||||||
|
$this->config->setUserValue($userId, 'files_external', 'config_version', '0.5.0');
|
||||||
|
$legacyService = new UserLegacyStoragesService($this->backendService, $this->userSession);
|
||||||
|
$storageService = new UserStoragesService($this->backendService, $this->dbConfig, $this->userSession);
|
||||||
|
|
||||||
|
$this->migrate($legacyService, $storageService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
376
apps/files_external/service/dbconfigservice.php
Normal file
376
apps/files_external/service/dbconfigservice.php
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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 OCA\Files_External\Service;
|
||||||
|
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
|
use OCP\IDBConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the mount config in the database
|
||||||
|
*/
|
||||||
|
class DBConfigService {
|
||||||
|
const MOUNT_TYPE_ADMIN = 1;
|
||||||
|
const MOUNT_TYPE_PERSONAl = 2;
|
||||||
|
|
||||||
|
const APPLICABLE_TYPE_GLOBAL = 1;
|
||||||
|
const APPLICABLE_TYPE_GROUP = 2;
|
||||||
|
const APPLICABLE_TYPE_USER = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IDBConnection
|
||||||
|
*/
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DBConfigService constructor.
|
||||||
|
*
|
||||||
|
* @param IDBConnection $connection
|
||||||
|
*/
|
||||||
|
public function __construct(IDBConnection $connection) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mountId
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getMountById($mountId) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
|
||||||
|
->from('external_mounts', 'm')
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)));
|
||||||
|
$mounts = $this->getMountsFromQuery($query);
|
||||||
|
if (count($mounts) > 0) {
|
||||||
|
return $mounts[0];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get admin defined mounts
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAdminMounts() {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
|
||||||
|
->from('external_mounts')
|
||||||
|
->where($builder->expr()->eq('type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, \PDO::PARAM_INT)));
|
||||||
|
return $this->getMountsFromQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getForQuery(IQueryBuilder $builder, $type, $value) {
|
||||||
|
$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
|
||||||
|
->from('external_mounts', 'm')
|
||||||
|
->innerJoin('m', 'external_applicable', 'a', 'm.mount_id = a.mount_id')
|
||||||
|
->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, \PDO::PARAM_INT)));
|
||||||
|
|
||||||
|
if (is_null($value)) {
|
||||||
|
$query = $query->andWhere($builder->expr()->isNull('a.value'));
|
||||||
|
} else {
|
||||||
|
$query = $query->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mounts by applicable
|
||||||
|
*
|
||||||
|
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||||
|
* @param string|null $value user_id, group_id or null for global mounts
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getMountsFor($type, $value) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $this->getForQuery($builder, $type, $value);
|
||||||
|
|
||||||
|
return $this->getMountsFromQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get admin defined mounts by applicable
|
||||||
|
*
|
||||||
|
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||||
|
* @param string|null $value user_id, group_id or null for global mounts
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAdminMountsFor($type, $value) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $this->getForQuery($builder, $type, $value);
|
||||||
|
$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, \PDO::PARAM_INT)));
|
||||||
|
|
||||||
|
return $this->getMountsFromQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get admin defined mounts for multiple applicable
|
||||||
|
*
|
||||||
|
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||||
|
* @param string[] $values user_ids or group_ids
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAdminMountsForMultiple($type, array $values) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$params = array_map(function ($value) use ($builder) {
|
||||||
|
return $builder->createNamedParameter($value, \PDO::PARAM_STR);
|
||||||
|
}, $values);
|
||||||
|
|
||||||
|
$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
|
||||||
|
->from('external_mounts', 'm')
|
||||||
|
->innerJoin('m', 'external_applicable', 'a', 'm.mount_id = a.mount_id')
|
||||||
|
->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, \PDO::PARAM_INT)))
|
||||||
|
->andWhere($builder->expr()->in('a.value', $params));
|
||||||
|
$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, \PDO::PARAM_INT)));
|
||||||
|
|
||||||
|
return $this->getMountsFromQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user defined mounts by applicable
|
||||||
|
*
|
||||||
|
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||||
|
* @param string|null $value user_id, group_id or null for global mounts
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUserMountsFor($type, $value) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $this->getForQuery($builder, $type, $value);
|
||||||
|
$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAl, \PDO::PARAM_INT)));
|
||||||
|
|
||||||
|
return $this->getMountsFromQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a mount to the database
|
||||||
|
*
|
||||||
|
* @param string $mountPoint
|
||||||
|
* @param string $storageBackend
|
||||||
|
* @param string $authBackend
|
||||||
|
* @param int $priority
|
||||||
|
* @param int $type self::MOUNT_TYPE_ADMIN or self::MOUNT_TYPE_PERSONAL
|
||||||
|
* @return int the id of the new mount
|
||||||
|
*/
|
||||||
|
public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
|
||||||
|
if (!$priority) {
|
||||||
|
$priority = 100;
|
||||||
|
}
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->insert('external_mounts')
|
||||||
|
->values([
|
||||||
|
'mount_point' => $builder->createNamedParameter($mountPoint, \PDO::PARAM_STR),
|
||||||
|
'storage_backend' => $builder->createNamedParameter($storageBackend, \PDO::PARAM_STR),
|
||||||
|
'auth_backend' => $builder->createNamedParameter($authBackend, \PDO::PARAM_STR),
|
||||||
|
'priority' => $builder->createNamedParameter($priority, \PDO::PARAM_INT),
|
||||||
|
'type' => $builder->createNamedParameter($type, \PDO::PARAM_INT)
|
||||||
|
]);
|
||||||
|
$query->execute();
|
||||||
|
return (int)$this->connection->lastInsertId('external_mounts');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a mount from the database
|
||||||
|
*
|
||||||
|
* @param int $mountId
|
||||||
|
*/
|
||||||
|
public function removeMount($mountId) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->delete('external_mounts')
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)));
|
||||||
|
$query->execute();
|
||||||
|
|
||||||
|
$query = $builder->delete('external_applicable')
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)));
|
||||||
|
$query->execute();
|
||||||
|
|
||||||
|
$query = $builder->delete('external_config')
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)));
|
||||||
|
$query->execute();
|
||||||
|
|
||||||
|
$query = $builder->delete('external_options')
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)));
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mountId
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setConfig($mountId, $key, $value) {
|
||||||
|
$count = $this->connection->insertIfNotExist('*PREFIX*external_config', [
|
||||||
|
'mount_id' => $mountId,
|
||||||
|
'key' => $key,
|
||||||
|
'value' => $value
|
||||||
|
], ['mount_id', 'key']);
|
||||||
|
if ($count === 0) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->update('external_config')
|
||||||
|
->set('value', $builder->createNamedParameter($value, \PDO::PARAM_STR))
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)))
|
||||||
|
->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, \PDO::PARAM_STR)));
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mountId
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setOption($mountId, $key, $value) {
|
||||||
|
$count = $this->connection->insertIfNotExist('*PREFIX*external_options', [
|
||||||
|
'mount_id' => $mountId,
|
||||||
|
'key' => $key,
|
||||||
|
'value' => json_encode($value)
|
||||||
|
], ['mount_id', 'key']);
|
||||||
|
if ($count === 0) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->update('external_options')
|
||||||
|
->set('value', $builder->createNamedParameter(json_encode($value), \PDO::PARAM_STR))
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)))
|
||||||
|
->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, \PDO::PARAM_STR)));
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addApplicable($mountId, $type, $value) {
|
||||||
|
$this->connection->insertIfNotExist('*PREFIX*external_applicable', [
|
||||||
|
'mount_id' => $mountId,
|
||||||
|
'type' => $type,
|
||||||
|
'value' => $value
|
||||||
|
], ['mount_id', 'type', 'value']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeApplicable($mountId, $type, $value) {
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$query = $builder->delete('external_applicable')
|
||||||
|
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, \PDO::PARAM_INT)))
|
||||||
|
->andWhere($builder->expr()->eq('type', $builder->createNamedParameter($type, \PDO::PARAM_INT)))
|
||||||
|
->andWhere($builder->expr()->eq('value', $builder->createNamedParameter($value, \PDO::PARAM_STR)));
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMountsFromQuery(IQueryBuilder $query) {
|
||||||
|
$result = $query->execute();
|
||||||
|
$mounts = $result->fetchAll();
|
||||||
|
|
||||||
|
$mountIds = array_map(function ($mount) {
|
||||||
|
return $mount['mount_id'];
|
||||||
|
}, $mounts);
|
||||||
|
|
||||||
|
$applicable = $this->getApplicableForMounts($mountIds);
|
||||||
|
$config = $this->getConfigForMounts($mountIds);
|
||||||
|
$options = $this->getOptionsForMounts($mountIds);
|
||||||
|
|
||||||
|
return array_map(function ($mount, $applicable, $config, $options) {
|
||||||
|
$mount['type'] = (int)$mount['type'];
|
||||||
|
$mount['priority'] = (int)$mount['priority'];
|
||||||
|
$mount['applicable'] = $applicable;
|
||||||
|
$mount['config'] = $config;
|
||||||
|
$mount['options'] = $options;
|
||||||
|
return $mount;
|
||||||
|
}, $mounts, $applicable, $config, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mount options from a table grouped by mount id
|
||||||
|
*
|
||||||
|
* @param string $table
|
||||||
|
* @param string[] $fields
|
||||||
|
* @param int[] $mountIds
|
||||||
|
* @return array [$mountId => [['field1' => $value1, ...], ...], ...]
|
||||||
|
*/
|
||||||
|
private function selectForMounts($table, array $fields, array $mountIds) {
|
||||||
|
if (count($mountIds) === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$builder = $this->connection->getQueryBuilder();
|
||||||
|
$fields[] = 'mount_id';
|
||||||
|
$placeHolders = array_map(function ($id) use ($builder) {
|
||||||
|
return $builder->createPositionalParameter($id, \PDO::PARAM_INT);
|
||||||
|
}, $mountIds);
|
||||||
|
$query = $builder->select($fields)
|
||||||
|
->from($table)
|
||||||
|
->where($builder->expr()->in('mount_id', $placeHolders));
|
||||||
|
$rows = $query->execute()->fetchAll();
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($mountIds as $mountId) {
|
||||||
|
$result[$mountId] = [];
|
||||||
|
}
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
if (isset($row['type'])) {
|
||||||
|
$row['type'] = (int)$row['type'];
|
||||||
|
}
|
||||||
|
$result[$row['mount_id']][] = $row;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int[] $mountIds
|
||||||
|
* @return array [$id => [['type' => $type, 'value' => $value], ...], ...]
|
||||||
|
*/
|
||||||
|
public function getApplicableForMounts($mountIds) {
|
||||||
|
return $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int[] $mountIds
|
||||||
|
* @return array [$id => ['key1' => $value1, ...], ...]
|
||||||
|
*/
|
||||||
|
public function getConfigForMounts($mountIds) {
|
||||||
|
$mountConfigs = $this->selectForMounts('external_config', ['key', 'value'], $mountIds);
|
||||||
|
return array_map([$this, 'createKeyValueMap'], $mountConfigs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int[] $mountIds
|
||||||
|
* @return array [$id => ['key1' => $value1, ...], ...]
|
||||||
|
*/
|
||||||
|
public function getOptionsForMounts($mountIds) {
|
||||||
|
$mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
|
||||||
|
$optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
|
||||||
|
return array_map(function (array $options) {
|
||||||
|
return array_map(function ($option) {
|
||||||
|
return json_decode($option);
|
||||||
|
}, $options);
|
||||||
|
}, $optionsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $keyValuePairs [['key'=>$key, 'value=>$value], ...]
|
||||||
|
* @return array ['key1' => $value1, ...]
|
||||||
|
*/
|
||||||
|
private function createKeyValueMap(array $keyValuePairs) {
|
||||||
|
$keys = array_map(function ($pair) {
|
||||||
|
return $pair['key'];
|
||||||
|
}, $keyValuePairs);
|
||||||
|
$values = array_map(function ($pair) {
|
||||||
|
return $pair['value'];
|
||||||
|
}, $keyValuePairs);
|
||||||
|
|
||||||
|
return array_combine($keys, $values);
|
||||||
|
}
|
||||||
|
}
|
44
apps/files_external/service/globallegacystoragesservice.php
Normal file
44
apps/files_external/service/globallegacystoragesservice.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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 OCA\Files_external\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read admin defined mounts from the legacy mount.json
|
||||||
|
*/
|
||||||
|
class GlobalLegacyStoragesService extends LegacyStoragesService {
|
||||||
|
/**
|
||||||
|
* @param BackendService $backendService
|
||||||
|
*/
|
||||||
|
public function __construct(BackendService $backendService) {
|
||||||
|
$this->backendService = $backendService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read legacy config data
|
||||||
|
*
|
||||||
|
* @return array list of mount configs
|
||||||
|
*/
|
||||||
|
protected function readLegacyConfig() {
|
||||||
|
// read global config
|
||||||
|
return \OC_Mount_Config::readData();
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,68 +33,6 @@ use \OCA\Files_external\NotFoundException;
|
||||||
* Service class to manage global external storages
|
* Service class to manage global external storages
|
||||||
*/
|
*/
|
||||||
class GlobalStoragesService extends StoragesService {
|
class GlobalStoragesService extends StoragesService {
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the storages to the configuration.
|
|
||||||
*
|
|
||||||
* @param array $storages map of storage id to storage config
|
|
||||||
*/
|
|
||||||
public function writeConfig($storages) {
|
|
||||||
// let the horror begin
|
|
||||||
$mountPoints = [];
|
|
||||||
foreach ($storages as $storageConfig) {
|
|
||||||
$mountPoint = $storageConfig->getMountPoint();
|
|
||||||
$oldBackendOptions = $storageConfig->getBackendOptions();
|
|
||||||
$storageConfig->setBackendOptions(
|
|
||||||
\OC_Mount_Config::encryptPasswords(
|
|
||||||
$oldBackendOptions
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// system mount
|
|
||||||
$rootMountPoint = '/$user/files/' . ltrim($mountPoint, '/');
|
|
||||||
|
|
||||||
$applicableUsers = $storageConfig->getApplicableUsers();
|
|
||||||
$applicableGroups = $storageConfig->getApplicableGroups();
|
|
||||||
foreach ($applicableUsers as $applicable) {
|
|
||||||
$this->addMountPoint(
|
|
||||||
$mountPoints,
|
|
||||||
\OC_Mount_Config::MOUNT_TYPE_USER,
|
|
||||||
$applicable,
|
|
||||||
$rootMountPoint,
|
|
||||||
$storageConfig
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($applicableGroups as $applicable) {
|
|
||||||
$this->addMountPoint(
|
|
||||||
$mountPoints,
|
|
||||||
\OC_Mount_Config::MOUNT_TYPE_GROUP,
|
|
||||||
$applicable,
|
|
||||||
$rootMountPoint,
|
|
||||||
$storageConfig
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if neither "applicableGroups" or "applicableUsers" were set, use "all" user
|
|
||||||
if (empty($applicableUsers) && empty($applicableGroups)) {
|
|
||||||
$this->addMountPoint(
|
|
||||||
$mountPoints,
|
|
||||||
\OC_Mount_Config::MOUNT_TYPE_USER,
|
|
||||||
'all',
|
|
||||||
$rootMountPoint,
|
|
||||||
$storageConfig
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore old backend options where the password was not encrypted,
|
|
||||||
// because we don't want to change the state of the original object
|
|
||||||
$storageConfig->setBackendOptions($oldBackendOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->writeLegacyConfig($mountPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers $signal for all applicable users of the given
|
* Triggers $signal for all applicable users of the given
|
||||||
* storage
|
* storage
|
||||||
|
|
209
apps/files_external/service/legacystoragesservice.php
Normal file
209
apps/files_external/service/legacystoragesservice.php
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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 OCA\Files_external\Service;
|
||||||
|
|
||||||
|
use \OCA\Files_external\Lib\StorageConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read mount config from legacy mount.json
|
||||||
|
*/
|
||||||
|
abstract class LegacyStoragesService {
|
||||||
|
/** @var BackendService */
|
||||||
|
protected $backendService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read legacy config data
|
||||||
|
*
|
||||||
|
* @return array list of mount configs
|
||||||
|
*/
|
||||||
|
abstract protected function readLegacyConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
) {
|
||||||
|
$backend = $this->backendService->getBackend($storageOptions['backend']);
|
||||||
|
if (!$backend) {
|
||||||
|
throw new \UnexpectedValueException('Invalid backend ' . $storageOptions['backend']);
|
||||||
|
}
|
||||||
|
$storageConfig->setBackend($backend);
|
||||||
|
if (isset($storageOptions['authMechanism']) && $storageOptions['authMechanism'] !== 'builtin::builtin') {
|
||||||
|
$authMechanism = $this->backendService->getAuthMechanism($storageOptions['authMechanism']);
|
||||||
|
} else {
|
||||||
|
$authMechanism = $backend->getLegacyAuthMechanism($storageOptions);
|
||||||
|
$storageOptions['authMechanism'] = 'null'; // to make error handling easier
|
||||||
|
}
|
||||||
|
if (!$authMechanism) {
|
||||||
|
throw new \UnexpectedValueException('Invalid authentication mechanism ' . $storageOptions['authMechanism']);
|
||||||
|
}
|
||||||
|
$storageConfig->setAuthMechanism($authMechanism);
|
||||||
|
$storageConfig->setBackendOptions($storageOptions['options']);
|
||||||
|
if (isset($storageOptions['mountOptions'])) {
|
||||||
|
$storageConfig->setMountOptions($storageOptions['mountOptions']);
|
||||||
|
}
|
||||||
|
if (!isset($storageOptions['priority'])) {
|
||||||
|
$storageOptions['priority'] = $backend->getPriority();
|
||||||
|
}
|
||||||
|
$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
|
||||||
|
*
|
||||||
|
* @return StorageConfig[] map of storage id to storage config
|
||||||
|
*/
|
||||||
|
public function getAllStorages() {
|
||||||
|
$mountPoints = $this->readLegacyConfig();
|
||||||
|
/**
|
||||||
|
* Here is the how the horribly messy mount point array looks like
|
||||||
|
* from the mount.json file:
|
||||||
|
*
|
||||||
|
* $storageOptions = $mountPoints[$mountType][$applicable][$mountPath]
|
||||||
|
*
|
||||||
|
* - $mountType is either "user" or "group"
|
||||||
|
* - $applicable is the name of a user or group (or the current user for personal mounts)
|
||||||
|
* - $mountPath is the mount point path (where the storage must be mounted)
|
||||||
|
* - $storageOptions is a map of storage options:
|
||||||
|
* - "priority": storage priority
|
||||||
|
* - "backend": backend identifier
|
||||||
|
* - "class": LEGACY backend class name
|
||||||
|
* - "options": backend-specific options
|
||||||
|
* - "authMechanism": authentication mechanism identifier
|
||||||
|
* - "mountOptions": mount-specific options (ex: disable previews, scanner, etc)
|
||||||
|
*/
|
||||||
|
// group by storage id
|
||||||
|
/** @var StorageConfig[] $storages */
|
||||||
|
$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('/', ltrim($rootMountPath, '/'), 3);
|
||||||
|
if (count($parts) < 3) {
|
||||||
|
// something went wrong, skip
|
||||||
|
\OCP\Util::writeLog(
|
||||||
|
'files_external',
|
||||||
|
'Could not parse mount point "' . $rootMountPath . '"',
|
||||||
|
\OCP\Util::ERROR
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$relativeMountPath = rtrim($parts[2], '/');
|
||||||
|
// 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['backend'])) {
|
||||||
|
$storageOptions['backend'] = $storageOptions['class']; // legacy compat
|
||||||
|
}
|
||||||
|
if (!isset($storageOptions['authMechanism'])) {
|
||||||
|
$storageOptions['authMechanism'] = null; // ensure config hash works
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$this->populateStorageConfigWithLegacyOptions(
|
||||||
|
$currentStorage,
|
||||||
|
$mountType,
|
||||||
|
$applicable,
|
||||||
|
$storageOptions
|
||||||
|
);
|
||||||
|
if ($hasId) {
|
||||||
|
$storages[$configId] = $currentStorage;
|
||||||
|
} else {
|
||||||
|
$storagesWithConfigHash[$configId] = $currentStorage;
|
||||||
|
}
|
||||||
|
} catch (\UnexpectedValueException $e) {
|
||||||
|
// dont die if a storage backend doesn't exist
|
||||||
|
\OCP\Util::writeLog(
|
||||||
|
'files_external',
|
||||||
|
'Could not load storage: "' . $e->getMessage() . '"',
|
||||||
|
\OCP\Util::ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert parameter values
|
||||||
|
foreach ($storages as $storage) {
|
||||||
|
$storage->getBackend()->validateStorageDefinition($storage);
|
||||||
|
$storage->getAuthMechanism()->validateStorageDefinition($storage);
|
||||||
|
}
|
||||||
|
return $storages;
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,89 +41,61 @@ abstract class StoragesService {
|
||||||
/** @var BackendService */
|
/** @var BackendService */
|
||||||
protected $backendService;
|
protected $backendService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DBConfigService
|
||||||
|
*/
|
||||||
|
protected $dbConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BackendService $backendService
|
* @param BackendService $backendService
|
||||||
|
* @param DBConfigService $dbConfigService
|
||||||
*/
|
*/
|
||||||
public function __construct(BackendService $backendService) {
|
public function __construct(BackendService $backendService, DBConfigService $dbConfigService) {
|
||||||
$this->backendService = $backendService;
|
$this->backendService = $backendService;
|
||||||
|
$this->dbConfig = $dbConfigService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function readDBConfig() {
|
||||||
* Read legacy config data
|
return $this->dbConfig->getAdminMounts();
|
||||||
*
|
|
||||||
* @return array list of mount configs
|
|
||||||
*/
|
|
||||||
protected function readLegacyConfig() {
|
|
||||||
// read global config
|
|
||||||
return \OC_Mount_Config::readData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function getStorageConfigFromDBMount(array $mount) {
|
||||||
* Write legacy config data
|
$applicableUsers = array_filter($mount['applicable'], function ($applicable) {
|
||||||
*
|
return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_USER;
|
||||||
* @param array $mountPoints
|
});
|
||||||
*/
|
$applicableUsers = array_map(function ($applicable) {
|
||||||
protected function writeLegacyConfig(array $mountPoints) {
|
return $applicable['value'];
|
||||||
// write global config
|
}, $applicableUsers);
|
||||||
\OC_Mount_Config::writeData(null, $mountPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$applicableGroups = array_filter($mount['applicable'], function ($applicable) {
|
||||||
* Copy legacy storage options into the given storage config object.
|
return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_GROUP;
|
||||||
*
|
});
|
||||||
* @param StorageConfig $storageConfig storage config to populate
|
$applicableGroups = array_map(function ($applicable) {
|
||||||
* @param string $mountType mount type
|
return $applicable['value'];
|
||||||
* @param string $applicable applicable user or group
|
}, $applicableGroups);
|
||||||
* @param array $storageOptions legacy storage options
|
|
||||||
*
|
|
||||||
* @return StorageConfig populated storage config
|
|
||||||
*/
|
|
||||||
protected function populateStorageConfigWithLegacyOptions(
|
|
||||||
&$storageConfig,
|
|
||||||
$mountType,
|
|
||||||
$applicable,
|
|
||||||
$storageOptions
|
|
||||||
) {
|
|
||||||
$backend = $this->backendService->getBackend($storageOptions['backend']);
|
|
||||||
if (!$backend) {
|
|
||||||
throw new \UnexpectedValueException('Invalid backend '.$storageOptions['backend']);
|
|
||||||
}
|
|
||||||
$storageConfig->setBackend($backend);
|
|
||||||
|
|
||||||
if (isset($storageOptions['authMechanism']) && $storageOptions['authMechanism'] !== 'builtin::builtin') {
|
try {
|
||||||
$authMechanism = $this->backendService->getAuthMechanism($storageOptions['authMechanism']);
|
$config = $this->createStorage(
|
||||||
} else {
|
$mount['mount_point'],
|
||||||
$authMechanism = $backend->getLegacyAuthMechanism($storageOptions);
|
$mount['storage_backend'],
|
||||||
$storageOptions['authMechanism'] = 'null'; // to make error handling easier
|
$mount['auth_backend'],
|
||||||
|
$mount['config'],
|
||||||
|
$mount['options'],
|
||||||
|
array_values($applicableUsers),
|
||||||
|
array_values($applicableGroups),
|
||||||
|
$mount['priority']
|
||||||
|
);
|
||||||
|
$config->setId((int)$mount['mount_id']);
|
||||||
|
return $config;
|
||||||
|
} catch (\UnexpectedValueException $e) {
|
||||||
|
// dont die if a storage backend doesn't exist
|
||||||
|
\OCP\Util::writeLog(
|
||||||
|
'files_external',
|
||||||
|
'Could not load storage: "' . $e->getMessage() . '"',
|
||||||
|
\OCP\Util::ERROR
|
||||||
|
);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
if (!$authMechanism) {
|
|
||||||
throw new \UnexpectedValueException('Invalid authentication mechanism '.$storageOptions['authMechanism']);
|
|
||||||
}
|
|
||||||
$storageConfig->setAuthMechanism($authMechanism);
|
|
||||||
|
|
||||||
$storageConfig->setBackendOptions($storageOptions['options']);
|
|
||||||
if (isset($storageOptions['mountOptions'])) {
|
|
||||||
$storageConfig->setMountOptions($storageOptions['mountOptions']);
|
|
||||||
}
|
|
||||||
if (!isset($storageOptions['priority'])) {
|
|
||||||
$storageOptions['priority'] = $backend->getPriority();
|
|
||||||
}
|
|
||||||
$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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,198 +104,19 @@ abstract class StoragesService {
|
||||||
* @return array map of storage id to storage config
|
* @return array map of storage id to storage config
|
||||||
*/
|
*/
|
||||||
protected function readConfig() {
|
protected function readConfig() {
|
||||||
$mountPoints = $this->readLegacyConfig();
|
$mounts = $this->readDBConfig();
|
||||||
|
$configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts);
|
||||||
|
$configs = array_filter($configs, function ($config) {
|
||||||
|
return $config instanceof StorageConfig;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
$keys = array_map(function (StorageConfig $config) {
|
||||||
* Here is the how the horribly messy mount point array looks like
|
return $config->getId();
|
||||||
* from the mount.json file:
|
}, $configs);
|
||||||
*
|
|
||||||
* $storageOptions = $mountPoints[$mountType][$applicable][$mountPath]
|
|
||||||
*
|
|
||||||
* - $mountType is either "user" or "group"
|
|
||||||
* - $applicable is the name of a user or group (or the current user for personal mounts)
|
|
||||||
* - $mountPath is the mount point path (where the storage must be mounted)
|
|
||||||
* - $storageOptions is a map of storage options:
|
|
||||||
* - "priority": storage priority
|
|
||||||
* - "backend": backend identifier
|
|
||||||
* - "class": LEGACY backend class name
|
|
||||||
* - "options": backend-specific options
|
|
||||||
* - "authMechanism": authentication mechanism identifier
|
|
||||||
* - "mountOptions": mount-specific options (ex: disable previews, scanner, etc)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// group by storage id
|
return array_combine($keys, $configs);
|
||||||
$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('/', ltrim($rootMountPath, '/'), 3);
|
|
||||||
if (count($parts) < 3) {
|
|
||||||
// something went wrong, skip
|
|
||||||
\OCP\Util::writeLog(
|
|
||||||
'files_external',
|
|
||||||
'Could not parse mount point "' . $rootMountPath . '"',
|
|
||||||
\OCP\Util::ERROR
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$relativeMountPath = rtrim($parts[2], '/');
|
|
||||||
|
|
||||||
// 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['backend'])) {
|
|
||||||
$storageOptions['backend'] = $storageOptions['class']; // legacy compat
|
|
||||||
}
|
|
||||||
if (!isset($storageOptions['authMechanism'])) {
|
|
||||||
$storageOptions['authMechanism'] = null; // ensure config hash works
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->populateStorageConfigWithLegacyOptions(
|
|
||||||
$currentStorage,
|
|
||||||
$mountType,
|
|
||||||
$applicable,
|
|
||||||
$storageOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($hasId) {
|
|
||||||
$storages[$configId] = $currentStorage;
|
|
||||||
} else {
|
|
||||||
$storagesWithConfigHash[$configId] = $currentStorage;
|
|
||||||
}
|
|
||||||
} catch (\UnexpectedValueException $e) {
|
|
||||||
// dont die if a storage backend doesn't exist
|
|
||||||
\OCP\Util::writeLog(
|
|
||||||
'files_external',
|
|
||||||
'Could not load storage: "' . $e->getMessage() . '"',
|
|
||||||
\OCP\Util::ERROR
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process storages with config hash, they must get a real id
|
|
||||||
if (!empty($storagesWithConfigHash)) {
|
|
||||||
$this->setRealStorageIds($storages, $storagesWithConfigHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert parameter values
|
|
||||||
foreach ($storages as $storage) {
|
|
||||||
$storage->getBackend()->validateStorageDefinition($storage);
|
|
||||||
$storage->getAuthMechanism()->validateStorageDefinition($storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $storages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace config hash ID with real IDs, for migrating legacy storages
|
|
||||||
*
|
|
||||||
* @param StorageConfig[] $storages Storages with real IDs
|
|
||||||
* @param StorageConfig[] $storagesWithConfigHash Storages with config hash IDs
|
|
||||||
*/
|
|
||||||
protected function setRealStorageIds(array &$storages, array $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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add mount point into the messy mount point structure
|
|
||||||
*
|
|
||||||
* @param array $mountPoints messy array of mount points
|
|
||||||
* @param string $mountType mount type
|
|
||||||
* @param string $applicable single applicable user or group
|
|
||||||
* @param string $rootMountPoint root mount point to use
|
|
||||||
* @param array $storageConfig storage config to set to the mount point
|
|
||||||
*/
|
|
||||||
protected function addMountPoint(&$mountPoints, $mountType, $applicable, $rootMountPoint, $storageConfig) {
|
|
||||||
if (!isset($mountPoints[$mountType])) {
|
|
||||||
$mountPoints[$mountType] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($mountPoints[$mountType][$applicable])) {
|
|
||||||
$mountPoints[$mountType][$applicable] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = [
|
|
||||||
'id' => $storageConfig->getId(),
|
|
||||||
'backend' => $storageConfig->getBackend()->getIdentifier(),
|
|
||||||
//'class' => $storageConfig->getBackend()->getClass(),
|
|
||||||
'authMechanism' => $storageConfig->getAuthMechanism()->getIdentifier(),
|
|
||||||
'options' => $storageConfig->getBackendOptions(),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!is_null($storageConfig->getPriority())) {
|
|
||||||
$options['priority'] = $storageConfig->getPriority();
|
|
||||||
}
|
|
||||||
|
|
||||||
$mountOptions = $storageConfig->getMountOptions();
|
|
||||||
if (!empty($mountOptions)) {
|
|
||||||
$options['mountOptions'] = $mountOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mountPoints[$mountType][$applicable][$rootMountPoint] = $options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the storages to the configuration.
|
|
||||||
*
|
|
||||||
* @param array $storages map of storage id to storage config
|
|
||||||
*/
|
|
||||||
abstract protected function writeConfig($storages);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a storage with status
|
* Get a storage with status
|
||||||
*
|
*
|
||||||
|
@ -333,19 +126,19 @@ abstract class StoragesService {
|
||||||
* @throws NotFoundException if the storage with the given id was not found
|
* @throws NotFoundException if the storage with the given id was not found
|
||||||
*/
|
*/
|
||||||
public function getStorage($id) {
|
public function getStorage($id) {
|
||||||
$allStorages = $this->readConfig();
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
|
||||||
if (!isset($allStorages[$id])) {
|
if (!is_array($mount)) {
|
||||||
throw new NotFoundException('Storage with id "' . $id . '" not found');
|
throw new NotFoundException('Storage with id "' . $id . '" not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $allStorages[$id];
|
return $this->getStorageConfigFromDBMount($mount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all storages, valid or not
|
* Gets all storages, valid or not
|
||||||
*
|
*
|
||||||
* @return array array of storage configs
|
* @return StorageConfig[] array of storage configs
|
||||||
*/
|
*/
|
||||||
public function getAllStorages() {
|
public function getAllStorages() {
|
||||||
return $this->readConfig();
|
return $this->readConfig();
|
||||||
|
@ -354,7 +147,7 @@ abstract class StoragesService {
|
||||||
/**
|
/**
|
||||||
* Gets all valid storages
|
* Gets all valid storages
|
||||||
*
|
*
|
||||||
* @return array
|
* @return StorageConfig[]
|
||||||
*/
|
*/
|
||||||
public function getStorages() {
|
public function getStorages() {
|
||||||
return array_filter($this->getAllStorages(), [$this, 'validateStorage']);
|
return array_filter($this->getAllStorages(), [$this, 'validateStorage']);
|
||||||
|
@ -392,24 +185,50 @@ abstract class StoragesService {
|
||||||
*/
|
*/
|
||||||
abstract public function getVisibilityType();
|
abstract public function getVisibilityType();
|
||||||
|
|
||||||
|
protected function getType() {
|
||||||
|
return DBConfigService::MOUNT_TYPE_ADMIN;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new storage to the configuration
|
* Add new storage to the configuration
|
||||||
*
|
*
|
||||||
* @param array $newStorage storage attributes
|
* @param StorageConfig $newStorage storage attributes
|
||||||
*
|
*
|
||||||
* @return StorageConfig storage config, with added id
|
* @return StorageConfig storage config, with added id
|
||||||
*/
|
*/
|
||||||
public function addStorage(StorageConfig $newStorage) {
|
public function addStorage(StorageConfig $newStorage) {
|
||||||
$allStorages = $this->readConfig();
|
$allStorages = $this->readConfig();
|
||||||
|
|
||||||
$configId = $this->generateNextId($allStorages);
|
$configId = $this->dbConfig->addMount(
|
||||||
|
$newStorage->getMountPoint(),
|
||||||
|
$newStorage->getBackend()->getIdentifier(),
|
||||||
|
$newStorage->getAuthMechanism()->getIdentifier(),
|
||||||
|
$newStorage->getPriority(),
|
||||||
|
$this->getType()
|
||||||
|
);
|
||||||
|
|
||||||
$newStorage->setId($configId);
|
$newStorage->setId($configId);
|
||||||
|
|
||||||
|
foreach ($newStorage->getApplicableUsers() as $user) {
|
||||||
|
$this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_USER, $user);
|
||||||
|
}
|
||||||
|
foreach ($newStorage->getApplicableGroups() as $group) {
|
||||||
|
$this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
|
||||||
|
}
|
||||||
|
foreach ($newStorage->getBackendOptions() as $key => $value) {
|
||||||
|
$this->dbConfig->setConfig($configId, $key, $value);
|
||||||
|
}
|
||||||
|
foreach ($newStorage->getMountOptions() as $key => $value) {
|
||||||
|
$this->dbConfig->setOption($configId, $key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($newStorage->getApplicableUsers()) === 0 && count($newStorage->getApplicableGroups()) === 0) {
|
||||||
|
$this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
|
}
|
||||||
|
|
||||||
// add new storage
|
// add new storage
|
||||||
$allStorages[$configId] = $newStorage;
|
$allStorages[$configId] = $newStorage;
|
||||||
|
|
||||||
$this->writeConfig($allStorages);
|
|
||||||
|
|
||||||
$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
|
$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
|
||||||
|
|
||||||
$newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS);
|
$newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS);
|
||||||
|
@ -442,11 +261,11 @@ abstract class StoragesService {
|
||||||
) {
|
) {
|
||||||
$backend = $this->backendService->getBackend($backendIdentifier);
|
$backend = $this->backendService->getBackend($backendIdentifier);
|
||||||
if (!$backend) {
|
if (!$backend) {
|
||||||
throw new \InvalidArgumentException('Unable to get backend for '.$backendIdentifier);
|
throw new \InvalidArgumentException('Unable to get backend for ' . $backendIdentifier);
|
||||||
}
|
}
|
||||||
$authMechanism = $this->backendService->getAuthMechanism($authMechanismIdentifier);
|
$authMechanism = $this->backendService->getAuthMechanism($authMechanismIdentifier);
|
||||||
if (!$authMechanism) {
|
if (!$authMechanism) {
|
||||||
throw new \InvalidArgumentException('Unable to get authentication mechanism for '.$authMechanismIdentifier);
|
throw new \InvalidArgumentException('Unable to get authentication mechanism for ' . $authMechanismIdentifier);
|
||||||
}
|
}
|
||||||
$newStorage = new StorageConfig();
|
$newStorage = new StorageConfig();
|
||||||
$newStorage->setMountPoint($mountPoint);
|
$newStorage->setMountPoint($mountPoint);
|
||||||
|
@ -519,21 +338,56 @@ abstract class StoragesService {
|
||||||
* @throws NotFoundException if the given storage does not exist in the config
|
* @throws NotFoundException if the given storage does not exist in the config
|
||||||
*/
|
*/
|
||||||
public function updateStorage(StorageConfig $updatedStorage) {
|
public function updateStorage(StorageConfig $updatedStorage) {
|
||||||
$allStorages = $this->readConfig();
|
|
||||||
|
|
||||||
$id = $updatedStorage->getId();
|
$id = $updatedStorage->getId();
|
||||||
if (!isset($allStorages[$id])) {
|
|
||||||
throw new NotFoundException('Storage with id "' . $id . '" not found');
|
|
||||||
}
|
|
||||||
$oldStorage = $allStorages[$id];
|
|
||||||
|
|
||||||
// ensure objectstore is persistent
|
$existingMount = $this->dbConfig->getMountById($id);
|
||||||
if ($objectstore = $oldStorage->getBackendOption('objectstore')) {
|
|
||||||
$updatedStorage->setBackendOption('objectstore', $objectstore);
|
if (!is_array($existingMount)) {
|
||||||
|
throw new NotFoundException('Storage with id "' . $id . '" not found while updating storage');
|
||||||
}
|
}
|
||||||
|
|
||||||
$allStorages[$id] = $updatedStorage;
|
$oldStorage = $this->getStorageConfigFromDBMount($existingMount);
|
||||||
$this->writeConfig($allStorages);
|
|
||||||
|
$removedUsers = array_diff($oldStorage->getApplicableUsers(), $updatedStorage->getApplicableUsers());
|
||||||
|
$removedGroups = array_diff($oldStorage->getApplicableGroups(), $updatedStorage->getApplicableGroups());
|
||||||
|
$addedUsers = array_diff($updatedStorage->getApplicableUsers(), $oldStorage->getApplicableUsers());
|
||||||
|
$addedGroups = array_diff($updatedStorage->getApplicableGroups(), $oldStorage->getApplicableGroups());
|
||||||
|
|
||||||
|
$oldUserCount = count($oldStorage->getApplicableUsers());
|
||||||
|
$oldGroupCount = count($oldStorage->getApplicableGroups());
|
||||||
|
$newUserCount = count($oldStorage->getApplicableUsers());
|
||||||
|
$newGroupCount = count($oldStorage->getApplicableGroups());
|
||||||
|
$wasGlobal = ($oldUserCount + $oldGroupCount) === 0;
|
||||||
|
$isGlobal = ($newUserCount + $newGroupCount) === 0;
|
||||||
|
|
||||||
|
foreach ($removedUsers as $user) {
|
||||||
|
$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user);
|
||||||
|
}
|
||||||
|
foreach ($removedGroups as $group) {
|
||||||
|
$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
|
||||||
|
}
|
||||||
|
foreach ($addedUsers as $user) {
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user);
|
||||||
|
}
|
||||||
|
foreach ($addedGroups as $group) {
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($wasGlobal && !$isGlobal) {
|
||||||
|
$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
|
} else if (!$wasGlobal && $isGlobal) {
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
$changedConfig = array_diff_assoc($updatedStorage->getBackendOptions(), $oldStorage->getBackendOptions());
|
||||||
|
$changedOptions = array_diff_assoc($updatedStorage->getMountOptions(), $oldStorage->getMountOptions());
|
||||||
|
|
||||||
|
foreach ($changedConfig as $key => $value) {
|
||||||
|
$this->dbConfig->setConfig($id, $key, $value);
|
||||||
|
}
|
||||||
|
foreach ($changedOptions as $key => $value) {
|
||||||
|
$this->dbConfig->setOption($id, $key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
$this->triggerChangeHooks($oldStorage, $updatedStorage);
|
$this->triggerChangeHooks($oldStorage, $updatedStorage);
|
||||||
|
|
||||||
|
@ -548,17 +402,15 @@ abstract class StoragesService {
|
||||||
* @throws NotFoundException if no storage was found with the given id
|
* @throws NotFoundException if no storage was found with the given id
|
||||||
*/
|
*/
|
||||||
public function removeStorage($id) {
|
public function removeStorage($id) {
|
||||||
$allStorages = $this->readConfig();
|
$existingMount = $this->dbConfig->getMountById($id);
|
||||||
|
|
||||||
if (!isset($allStorages[$id])) {
|
if (!is_array($existingMount)) {
|
||||||
throw new NotFoundException('Storage with id "' . $id . '" not found');
|
throw new NotFoundException('Storage with id "' . $id . '" not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
$deletedStorage = $allStorages[$id];
|
$this->dbConfig->removeMount($id);
|
||||||
unset($allStorages[$id]);
|
|
||||||
|
|
||||||
$this->writeConfig($allStorages);
|
|
||||||
|
|
||||||
|
$deletedStorage = $this->getStorageConfigFromDBMount($existingMount);
|
||||||
$this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount);
|
$this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount);
|
||||||
|
|
||||||
// delete oc_storages entries and oc_filecache
|
// delete oc_storages entries and oc_filecache
|
||||||
|
@ -577,24 +429,6 @@ abstract class StoragesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a configuration id to use for a new configuration entry.
|
|
||||||
*
|
|
||||||
* @param array $allStorages array of all storage configs
|
|
||||||
*
|
|
||||||
* @return int id
|
|
||||||
*/
|
|
||||||
protected function generateNextId($allStorages) {
|
|
||||||
if (empty($allStorages)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// note: this will mess up with with concurrency,
|
|
||||||
// but so did the mount.json. This horribly hack
|
|
||||||
// will disappear once we move to DB tables to
|
|
||||||
// store the config
|
|
||||||
return (max(array_keys($allStorages)) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the rusty storage id from oc_storages from the given storage config.
|
* Returns the rusty storage id from oc_storages from the given storage config.
|
||||||
*
|
*
|
||||||
|
|
|
@ -41,15 +41,17 @@ class UserGlobalStoragesService extends GlobalStoragesService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param BackendService $backendService
|
* @param BackendService $backendService
|
||||||
|
* @param DBConfigService $dbConfig
|
||||||
* @param IUserSession $userSession
|
* @param IUserSession $userSession
|
||||||
* @param IGroupManager $groupManager
|
* @param IGroupManager $groupManager
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
BackendService $backendService,
|
BackendService $backendService,
|
||||||
|
DBConfigService $dbConfig,
|
||||||
IUserSession $userSession,
|
IUserSession $userSession,
|
||||||
IGroupManager $groupManager
|
IGroupManager $groupManager
|
||||||
) {
|
) {
|
||||||
parent::__construct($backendService);
|
parent::__construct($backendService, $dbConfig);
|
||||||
$this->userSession = $userSession;
|
$this->userSession = $userSession;
|
||||||
$this->groupManager = $groupManager;
|
$this->groupManager = $groupManager;
|
||||||
}
|
}
|
||||||
|
@ -67,46 +69,27 @@ class UserGlobalStoragesService extends GlobalStoragesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function readDBConfig() {
|
||||||
* Read legacy config data
|
$userMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
|
||||||
*
|
$globalMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
* @return array list of mount configs
|
$groups = $this->groupManager->getUserGroupIds($this->getUser());
|
||||||
*/
|
if (is_array($groups) && count($groups) !== 0) {
|
||||||
protected function readLegacyConfig() {
|
$groupMounts = $this->dbConfig->getAdminMountsForMultiple(DBConfigService::APPLICABLE_TYPE_GROUP, $groups);
|
||||||
// read global config
|
} else {
|
||||||
$data = parent::readLegacyConfig();
|
$groupMounts = [];
|
||||||
$userId = $this->getUser()->getUID();
|
|
||||||
|
|
||||||
// don't use array_filter() with ARRAY_FILTER_USE_KEY, it's PHP 5.6+
|
|
||||||
if (isset($data[\OC_Mount_Config::MOUNT_TYPE_USER])) {
|
|
||||||
$newData = [];
|
|
||||||
foreach ($data[\OC_Mount_Config::MOUNT_TYPE_USER] as $key => $value) {
|
|
||||||
if (strtolower($key) === strtolower($userId) || $key === 'all') {
|
|
||||||
$newData[$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$data[\OC_Mount_Config::MOUNT_TYPE_USER] = $newData;
|
|
||||||
}
|
}
|
||||||
|
return array_merge($userMounts, $groupMounts, $globalMounts);
|
||||||
if (isset($data[\OC_Mount_Config::MOUNT_TYPE_GROUP])) {
|
|
||||||
$newData = [];
|
|
||||||
foreach ($data[\OC_Mount_Config::MOUNT_TYPE_GROUP] as $key => $value) {
|
|
||||||
if ($this->groupManager->isInGroup($userId, $key)) {
|
|
||||||
$newData[$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$data[\OC_Mount_Config::MOUNT_TYPE_GROUP] = $newData;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function addStorage(StorageConfig $newStorage) {
|
||||||
* Write legacy config data
|
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||||
*
|
}
|
||||||
* @param array $mountPoints
|
|
||||||
*/
|
public function updateStorage(StorageConfig $updatedStorage) {
|
||||||
protected function writeLegacyConfig(array $mountPoints) {
|
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeStorage($id) {
|
||||||
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +109,7 @@ class UserGlobalStoragesService extends GlobalStoragesService {
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($storagesByMountpoint as $storageList) {
|
foreach ($storagesByMountpoint as $storageList) {
|
||||||
$storage = array_reduce($storageList, function($carry, $item) {
|
$storage = array_reduce($storageList, function ($carry, $item) {
|
||||||
if (isset($carry)) {
|
if (isset($carry)) {
|
||||||
$carryPriorityType = $this->getPriorityType($carry);
|
$carryPriorityType = $this->getPriorityType($carry);
|
||||||
$itemPriorityType = $this->getPriorityType($item);
|
$itemPriorityType = $this->getPriorityType($item);
|
||||||
|
|
54
apps/files_external/service/userlegacystoragesservice.php
Normal file
54
apps/files_external/service/userlegacystoragesservice.php
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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 OCA\Files_external\Service;
|
||||||
|
|
||||||
|
use OCP\IUserSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read user defined mounts from the legacy mount.json
|
||||||
|
*/
|
||||||
|
class UserLegacyStoragesService extends LegacyStoragesService {
|
||||||
|
/**
|
||||||
|
* @var IUserSession
|
||||||
|
*/
|
||||||
|
private $userSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BackendService $backendService
|
||||||
|
* @param IUserSession $userSession
|
||||||
|
*/
|
||||||
|
public function __construct(BackendService $backendService, IUserSession $userSession) {
|
||||||
|
$this->backendService = $backendService;
|
||||||
|
$this->userSession = $userSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read legacy config data
|
||||||
|
*
|
||||||
|
* @return array list of storage configs
|
||||||
|
*/
|
||||||
|
protected function readLegacyConfig() {
|
||||||
|
// read user config
|
||||||
|
$user = $this->userSession->getUser()->getUID();
|
||||||
|
return \OC_Mount_Config::readData($user);
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,107 +35,26 @@ use \OCA\Files_External\Service\UserTrait;
|
||||||
* (aka personal storages)
|
* (aka personal storages)
|
||||||
*/
|
*/
|
||||||
class UserStoragesService extends StoragesService {
|
class UserStoragesService extends StoragesService {
|
||||||
|
|
||||||
use UserTrait;
|
use UserTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a user storages service
|
* Create a user storages service
|
||||||
*
|
*
|
||||||
* @param BackendService $backendService
|
* @param BackendService $backendService
|
||||||
|
* @param DBConfigService $dbConfig
|
||||||
* @param IUserSession $userSession user session
|
* @param IUserSession $userSession user session
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
BackendService $backendService,
|
BackendService $backendService,
|
||||||
|
DBConfigService $dbConfig,
|
||||||
IUserSession $userSession
|
IUserSession $userSession
|
||||||
) {
|
) {
|
||||||
$this->userSession = $userSession;
|
$this->userSession = $userSession;
|
||||||
parent::__construct($backendService);
|
parent::__construct($backendService, $dbConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function readDBConfig() {
|
||||||
* Read legacy config data
|
return $this->dbConfig->getUserMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
|
||||||
*
|
|
||||||
* @return array list of storage configs
|
|
||||||
*/
|
|
||||||
protected function readLegacyConfig() {
|
|
||||||
// read user config
|
|
||||||
$user = $this->getUser()->getUID();
|
|
||||||
return \OC_Mount_Config::readData($user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write legacy config data
|
|
||||||
*
|
|
||||||
* @param array $mountPoints
|
|
||||||
*/
|
|
||||||
protected function writeLegacyConfig(array $mountPoints) {
|
|
||||||
// write user config
|
|
||||||
$user = $this->getUser()->getUID();
|
|
||||||
\OC_Mount_Config::writeData($user, $mountPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the external storages config
|
|
||||||
*
|
|
||||||
* @return array map of storage id to storage config
|
|
||||||
*/
|
|
||||||
protected function readConfig() {
|
|
||||||
$user = $this->getUser()->getUID();
|
|
||||||
// TODO: in the future don't rely on the global config reading code
|
|
||||||
$storages = parent::readConfig();
|
|
||||||
|
|
||||||
$filteredStorages = [];
|
|
||||||
foreach ($storages as $configId => $storage) {
|
|
||||||
// filter out all bogus storages that aren't for the current user
|
|
||||||
if (!in_array($user, $storage->getApplicableUsers())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear applicable users, should not be used
|
|
||||||
$storage->setApplicableUsers([]);
|
|
||||||
|
|
||||||
// strip out unneeded applicableUser fields
|
|
||||||
$filteredStorages[$configId] = $storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $filteredStorages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the storages to the user's configuration.
|
|
||||||
*
|
|
||||||
* @param array $storages map of storage id to storage config
|
|
||||||
*/
|
|
||||||
public function writeConfig($storages) {
|
|
||||||
$user = $this->getUser()->getUID();
|
|
||||||
|
|
||||||
// let the horror begin
|
|
||||||
$mountPoints = [];
|
|
||||||
foreach ($storages as $storageConfig) {
|
|
||||||
$mountPoint = $storageConfig->getMountPoint();
|
|
||||||
$oldBackendOptions = $storageConfig->getBackendOptions();
|
|
||||||
$storageConfig->setBackendOptions(
|
|
||||||
\OC_Mount_Config::encryptPasswords(
|
|
||||||
$oldBackendOptions
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$rootMountPoint = '/' . $user . '/files/' . ltrim($mountPoint, '/');
|
|
||||||
|
|
||||||
$this->addMountPoint(
|
|
||||||
$mountPoints,
|
|
||||||
\OC_Mount_Config::MOUNT_TYPE_USER,
|
|
||||||
$user,
|
|
||||||
$rootMountPoint,
|
|
||||||
$storageConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
// restore old backend options where the password was not encrypted,
|
|
||||||
// because we don't want to change the state of the original object
|
|
||||||
$storageConfig->setBackendOptions($oldBackendOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->writeLegacyConfig($mountPoints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,6 +92,23 @@ class UserStoragesService extends StoragesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getType() {
|
||||||
|
return DBConfigService::MOUNT_TYPE_PERSONAl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new storage to the configuration
|
||||||
|
*
|
||||||
|
* @param StorageConfig $newStorage storage attributes
|
||||||
|
*
|
||||||
|
* @return StorageConfig storage config, with added id
|
||||||
|
*/
|
||||||
|
public function addStorage(StorageConfig $newStorage) {
|
||||||
|
$config = parent::addStorage($newStorage);
|
||||||
|
$this->dbConfig->addApplicable($config->getId(), DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the visibility type for this controller, used in validation
|
* Get the visibility type for this controller, used in validation
|
||||||
*
|
*
|
||||||
|
|
233
apps/files_external/tests/service/dbconfigservicetest.php
Normal file
233
apps/files_external/tests/service/dbconfigservicetest.php
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin Appelman <icewind@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 OCA\Files_External\Tests\Service;
|
||||||
|
|
||||||
|
|
||||||
|
use OCA\Files_External\Service\DBConfigService;
|
||||||
|
use OCP\IDBConnection;
|
||||||
|
use Test\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DB
|
||||||
|
*/
|
||||||
|
class DBConfigServiceTest extends TestCase {
|
||||||
|
/**
|
||||||
|
* @var DBConfigService
|
||||||
|
*/
|
||||||
|
private $dbConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IDBConnection
|
||||||
|
*/
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
private $mounts = [];
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
$this->connection = \OC::$server->getDatabaseConnection();
|
||||||
|
$this->dbConfig = new DBConfigService($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
foreach ($this->mounts as $mount) {
|
||||||
|
$this->dbConfig->removeMount($mount);
|
||||||
|
}
|
||||||
|
$this->mounts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
|
||||||
|
$id = $this->dbConfig->addMount($mountPoint, $storageBackend, $authBackend, $priority, $type);
|
||||||
|
$this->mounts[] = $id;
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddSimpleMount() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals('/test', $mount['mount_point']);
|
||||||
|
$this->assertEquals('foo', $mount['storage_backend']);
|
||||||
|
$this->assertEquals('bar', $mount['auth_backend']);
|
||||||
|
$this->assertEquals(100, $mount['priority']);
|
||||||
|
$this->assertEquals(DBConfigService::MOUNT_TYPE_ADMIN, $mount['type']);
|
||||||
|
$this->assertEquals([], $mount['applicable']);
|
||||||
|
$this->assertEquals([], $mount['config']);
|
||||||
|
$this->assertEquals([], $mount['options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddApplicable() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals([
|
||||||
|
['type' => DBConfigService::APPLICABLE_TYPE_USER, 'value' => 'test', 'mount_id' => $id]
|
||||||
|
], $mount['applicable']);
|
||||||
|
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, 'bar');
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals([
|
||||||
|
['type' => DBConfigService::APPLICABLE_TYPE_USER, 'value' => 'test', 'mount_id' => $id],
|
||||||
|
['type' => DBConfigService::APPLICABLE_TYPE_GROUP, 'value' => 'bar', 'mount_id' => $id],
|
||||||
|
['type' => DBConfigService::APPLICABLE_TYPE_GLOBAL, 'value' => null, 'mount_id' => $id]
|
||||||
|
], $mount['applicable']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddApplicableDouble() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals([
|
||||||
|
['type' => DBConfigService::APPLICABLE_TYPE_USER, 'value' => 'test', 'mount_id' => $id]
|
||||||
|
], $mount['applicable']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeleteMount() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
|
||||||
|
$this->dbConfig->removeMount($id);
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(null, $mount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRemoveApplicable() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals([], $mount['applicable']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetConfig() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->setConfig($id, 'foo', 'bar');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(['foo' => 'bar'], $mount['config']);
|
||||||
|
|
||||||
|
$this->dbConfig->setConfig($id, 'foo2', 'bar2');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(['foo' => 'bar', 'foo2' => 'bar2'], $mount['config']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetConfigOverwrite() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->setConfig($id, 'foo', 'bar');
|
||||||
|
$this->dbConfig->setConfig($id, 'asd', '1');
|
||||||
|
$this->dbConfig->setConfig($id, 'foo', 'qwerty');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(['foo' => 'qwerty', 'asd' => '1'], $mount['config']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetOption() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->setOption($id, 'foo', 'bar');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(['foo' => 'bar'], $mount['options']);
|
||||||
|
|
||||||
|
$this->dbConfig->setOption($id, 'foo2', 'bar2');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(['foo' => 'bar', 'foo2' => 'bar2'], $mount['options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetOptionOverwrite() {
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->setOption($id, 'foo', 'bar');
|
||||||
|
$this->dbConfig->setOption($id, 'asd', '1');
|
||||||
|
$this->dbConfig->setOption($id, 'foo', 'qwerty');
|
||||||
|
|
||||||
|
$mount = $this->dbConfig->getMountById($id);
|
||||||
|
$this->assertEquals(['foo' => 'qwerty', 'asd' => '1'], $mount['options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetMountsFor() {
|
||||||
|
$mounts = $this->dbConfig->getMountsFor(DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->assertEquals([], $mounts);
|
||||||
|
|
||||||
|
$id = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
|
||||||
|
$mounts = $this->dbConfig->getMountsFor(DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->assertCount(1, $mounts);
|
||||||
|
$this->assertEquals($id, $mounts[0]['mount_id']);
|
||||||
|
$this->assertEquals([['type' => DBConfigService::APPLICABLE_TYPE_USER, 'value' => 'test', 'mount_id' => $id]], $mounts[0]['applicable']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAdminMounts() {
|
||||||
|
$id1 = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->addMount('/test2', 'foo2', 'bar2', 100, DBConfigService::MOUNT_TYPE_PERSONAl);
|
||||||
|
|
||||||
|
$mounts = $this->dbConfig->getAdminMounts();
|
||||||
|
$this->assertCount(1, $mounts);
|
||||||
|
$this->assertEquals($id1, $mounts[0]['mount_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAdminMountsFor() {
|
||||||
|
$id1 = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->addMount('/test2', 'foo2', 'bar2', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$id3 = $this->addMount('/test3', 'foo3', 'bar3', 100, DBConfigService::MOUNT_TYPE_PERSONAl);
|
||||||
|
|
||||||
|
$this->dbConfig->addApplicable($id1, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->dbConfig->addApplicable($id3, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
|
||||||
|
$mounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->assertCount(1, $mounts);
|
||||||
|
$this->assertEquals($id1, $mounts[0]['mount_id']);
|
||||||
|
$this->assertEquals([['type' => DBConfigService::APPLICABLE_TYPE_USER, 'value' => 'test', 'mount_id' => $id1]], $mounts[0]['applicable']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetUserMountsFor() {
|
||||||
|
$id1 = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
$this->addMount('/test2', 'foo2', 'bar2', 100, DBConfigService::MOUNT_TYPE_PERSONAl);
|
||||||
|
$id3 = $this->addMount('/test3', 'foo3', 'bar3', 100, DBConfigService::MOUNT_TYPE_PERSONAl);
|
||||||
|
|
||||||
|
$this->dbConfig->addApplicable($id1, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->dbConfig->addApplicable($id3, DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
|
||||||
|
$mounts = $this->dbConfig->getUserMountsFor(DBConfigService::APPLICABLE_TYPE_USER, 'test');
|
||||||
|
$this->assertCount(1, $mounts);
|
||||||
|
$this->assertEquals($id3, $mounts[0]['mount_id']);
|
||||||
|
$this->assertEquals([['type' => DBConfigService::APPLICABLE_TYPE_USER, 'value' => 'test', 'mount_id' => $id3]], $mounts[0]['applicable']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAdminMountsForGlobal() {
|
||||||
|
$id1 = $this->addMount('/test', 'foo', 'bar', 100, DBConfigService::MOUNT_TYPE_ADMIN);
|
||||||
|
|
||||||
|
$this->dbConfig->addApplicable($id1, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
|
|
||||||
|
$mounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
|
||||||
|
$this->assertCount(1, $mounts);
|
||||||
|
$this->assertEquals($id1, $mounts[0]['mount_id']);
|
||||||
|
$this->assertEquals([['type' => DBConfigService::APPLICABLE_TYPE_GLOBAL, 'value' => null, 'mount_id' => $id1]], $mounts[0]['applicable']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,14 +23,18 @@ namespace OCA\Files_external\Tests\Service;
|
||||||
|
|
||||||
use \OC\Files\Filesystem;
|
use \OC\Files\Filesystem;
|
||||||
|
|
||||||
|
use OCA\Files_External\Service\DBConfigService;
|
||||||
use \OCA\Files_external\Service\GlobalStoragesService;
|
use \OCA\Files_external\Service\GlobalStoragesService;
|
||||||
use \OCA\Files_external\NotFoundException;
|
use \OCA\Files_external\NotFoundException;
|
||||||
use \OCA\Files_external\Lib\StorageConfig;
|
use \OCA\Files_external\Lib\StorageConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DB
|
||||||
|
*/
|
||||||
class GlobalStoragesServiceTest extends StoragesServiceTest {
|
class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->service = new GlobalStoragesService($this->backendService);
|
$this->service = new GlobalStoragesService($this->backendService, $this->dbConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
|
@ -39,7 +43,7 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function makeTestStorageData() {
|
protected function makeTestStorageData() {
|
||||||
return $this->makeStorageConfig([
|
return $this->makeStorageConfig([
|
||||||
'mountPoint' => 'mountpoint',
|
'mountPoint' => 'mountpoint',
|
||||||
'backendIdentifier' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
'backendIdentifier' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
||||||
'authMechanismIdentifier' => 'identifier:\Auth\Mechanism',
|
'authMechanismIdentifier' => 'identifier:\Auth\Mechanism',
|
||||||
|
@ -133,10 +137,9 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
$storage = $this->makeStorageConfig($storageParams);
|
$storage = $this->makeStorageConfig($storageParams);
|
||||||
$newStorage = $this->service->addStorage($storage);
|
$newStorage = $this->service->addStorage($storage);
|
||||||
|
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
$baseId = $newStorage->getId();
|
||||||
|
|
||||||
|
$newStorage = $this->service->getStorage($baseId);
|
||||||
$newStorage = $this->service->getStorage(1);
|
|
||||||
|
|
||||||
$this->assertEquals($storage->getMountPoint(), $newStorage->getMountPoint());
|
$this->assertEquals($storage->getMountPoint(), $newStorage->getMountPoint());
|
||||||
$this->assertEquals($storage->getBackend(), $newStorage->getBackend());
|
$this->assertEquals($storage->getBackend(), $newStorage->getBackend());
|
||||||
|
@ -145,12 +148,10 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
$this->assertEquals($storage->getApplicableUsers(), $newStorage->getApplicableUsers());
|
$this->assertEquals($storage->getApplicableUsers(), $newStorage->getApplicableUsers());
|
||||||
$this->assertEquals($storage->getApplicableGroups(), $newStorage->getApplicableGroups());
|
$this->assertEquals($storage->getApplicableGroups(), $newStorage->getApplicableGroups());
|
||||||
$this->assertEquals($storage->getPriority(), $newStorage->getPriority());
|
$this->assertEquals($storage->getPriority(), $newStorage->getPriority());
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
|
||||||
$this->assertEquals(0, $newStorage->getStatus());
|
$this->assertEquals(0, $newStorage->getStatus());
|
||||||
|
|
||||||
// next one gets id 2
|
|
||||||
$nextStorage = $this->service->addStorage($storage);
|
$nextStorage = $this->service->addStorage($storage);
|
||||||
$this->assertEquals(2, $nextStorage->getId());
|
$this->assertEquals($baseId + 1, $nextStorage->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,19 +174,18 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$newStorage = $this->service->addStorage($storage);
|
$newStorage = $this->service->addStorage($storage);
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
$id = $newStorage->getId();
|
||||||
|
|
||||||
$updatedStorage->setId(1);
|
$updatedStorage->setId($id);
|
||||||
|
|
||||||
$this->service->updateStorage($updatedStorage);
|
$this->service->updateStorage($updatedStorage);
|
||||||
$newStorage = $this->service->getStorage(1);
|
$newStorage = $this->service->getStorage($id);
|
||||||
|
|
||||||
$this->assertEquals($updatedStorage->getMountPoint(), $newStorage->getMountPoint());
|
$this->assertEquals($updatedStorage->getMountPoint(), $newStorage->getMountPoint());
|
||||||
$this->assertEquals($updatedStorage->getBackendOptions()['password'], $newStorage->getBackendOptions()['password']);
|
$this->assertEquals($updatedStorage->getBackendOptions()['password'], $newStorage->getBackendOptions()['password']);
|
||||||
$this->assertEquals($updatedStorage->getApplicableUsers(), $newStorage->getApplicableUsers());
|
$this->assertEquals($updatedStorage->getApplicableUsers(), $newStorage->getApplicableUsers());
|
||||||
$this->assertEquals($updatedStorage->getApplicableGroups(), $newStorage->getApplicableGroups());
|
$this->assertEquals($updatedStorage->getApplicableGroups(), $newStorage->getApplicableGroups());
|
||||||
$this->assertEquals($updatedStorage->getPriority(), $newStorage->getPriority());
|
$this->assertEquals($updatedStorage->getPriority(), $newStorage->getPriority());
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
|
||||||
$this->assertEquals(0, $newStorage->getStatus());
|
$this->assertEquals(0, $newStorage->getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +442,7 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
$sourceApplicableGroups,
|
$sourceApplicableGroups,
|
||||||
$updatedApplicableUsers,
|
$updatedApplicableUsers,
|
||||||
$updatedApplicableGroups,
|
$updatedApplicableGroups,
|
||||||
$expectedCalls) {
|
$expectedCalls) {
|
||||||
|
|
||||||
$storage = $this->makeTestStorageData();
|
$storage = $this->makeTestStorageData();
|
||||||
$storage->setApplicableUsers($sourceApplicableUsers);
|
$storage->setApplicableUsers($sourceApplicableUsers);
|
||||||
|
@ -601,7 +601,7 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
public function testHooksDeleteStorage(
|
public function testHooksDeleteStorage(
|
||||||
$sourceApplicableUsers,
|
$sourceApplicableUsers,
|
||||||
$sourceApplicableGroups,
|
$sourceApplicableGroups,
|
||||||
$expectedCalls) {
|
$expectedCalls) {
|
||||||
|
|
||||||
$storage = $this->makeTestStorageData();
|
$storage = $this->makeTestStorageData();
|
||||||
$storage->setApplicableUsers($sourceApplicableUsers);
|
$storage->setApplicableUsers($sourceApplicableUsers);
|
||||||
|
@ -626,321 +626,4 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure it uses the correct format when reading/writing
|
|
||||||
* the legacy config
|
|
||||||
*/
|
|
||||||
public function testLegacyConfigConversionApplicableAll() {
|
|
||||||
$configFile = $this->dataDir . '/mount.json';
|
|
||||||
|
|
||||||
$storage = $this->makeTestStorageData();
|
|
||||||
$storage = $this->service->addStorage($storage);
|
|
||||||
|
|
||||||
$json = json_decode(file_get_contents($configFile), true);
|
|
||||||
|
|
||||||
$this->assertCount(1, $json);
|
|
||||||
|
|
||||||
$this->assertEquals([\OC_Mount_Config::MOUNT_TYPE_USER], array_keys($json));
|
|
||||||
$this->assertEquals(['all'], array_keys($json[\OC_Mount_config::MOUNT_TYPE_USER]));
|
|
||||||
|
|
||||||
$mountPointData = $json[\OC_Mount_config::MOUNT_TYPE_USER]['all'];
|
|
||||||
$this->assertEquals(['/$user/files/mountpoint'], array_keys($mountPointData));
|
|
||||||
|
|
||||||
$mountPointOptions = current($mountPointData);
|
|
||||||
$this->assertEquals(1, $mountPointOptions['id']);
|
|
||||||
$this->assertEquals('identifier:\OCA\Files_External\Lib\Backend\SMB', $mountPointOptions['backend']);
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $mountPointOptions['authMechanism']);
|
|
||||||
$this->assertEquals(15, $mountPointOptions['priority']);
|
|
||||||
$this->assertEquals(false, $mountPointOptions['mountOptions']['preview']);
|
|
||||||
|
|
||||||
$backendOptions = $mountPointOptions['options'];
|
|
||||||
$this->assertEquals('value1', $backendOptions['option1']);
|
|
||||||
$this->assertEquals('value2', $backendOptions['option2']);
|
|
||||||
$this->assertEquals('', $backendOptions['password']);
|
|
||||||
$this->assertNotEmpty($backendOptions['password_encrypted']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure it uses the correct format when reading/writing
|
|
||||||
* the legacy config
|
|
||||||
*/
|
|
||||||
public function testLegacyConfigConversionApplicableUserAndGroup() {
|
|
||||||
$configFile = $this->dataDir . '/mount.json';
|
|
||||||
|
|
||||||
$storage = $this->makeTestStorageData();
|
|
||||||
$storage->setApplicableUsers(['user1', 'user2']);
|
|
||||||
$storage->setApplicableGroups(['group1', 'group2']);
|
|
||||||
|
|
||||||
$storage = $this->service->addStorage($storage);
|
|
||||||
|
|
||||||
$json = json_decode(file_get_contents($configFile), true);
|
|
||||||
|
|
||||||
$this->assertCount(2, $json);
|
|
||||||
|
|
||||||
$this->assertTrue(isset($json[\OC_Mount_Config::MOUNT_TYPE_USER]));
|
|
||||||
$this->assertTrue(isset($json[\OC_Mount_Config::MOUNT_TYPE_GROUP]));
|
|
||||||
$this->assertEquals(['user1', 'user2'], array_keys($json[\OC_Mount_config::MOUNT_TYPE_USER]));
|
|
||||||
$this->assertEquals(['group1', 'group2'], array_keys($json[\OC_Mount_config::MOUNT_TYPE_GROUP]));
|
|
||||||
|
|
||||||
// check that all options are the same for both users and both groups
|
|
||||||
foreach ($json[\OC_Mount_Config::MOUNT_TYPE_USER] as $mountPointData) {
|
|
||||||
$this->assertEquals(['/$user/files/mountpoint'], array_keys($mountPointData));
|
|
||||||
|
|
||||||
$mountPointOptions = current($mountPointData);
|
|
||||||
|
|
||||||
$this->assertEquals(1, $mountPointOptions['id']);
|
|
||||||
$this->assertEquals('identifier:\OCA\Files_External\Lib\Backend\SMB', $mountPointOptions['backend']);
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $mountPointOptions['authMechanism']);
|
|
||||||
$this->assertEquals(15, $mountPointOptions['priority']);
|
|
||||||
$this->assertEquals(false, $mountPointOptions['mountOptions']['preview']);
|
|
||||||
|
|
||||||
$backendOptions = $mountPointOptions['options'];
|
|
||||||
$this->assertEquals('value1', $backendOptions['option1']);
|
|
||||||
$this->assertEquals('value2', $backendOptions['option2']);
|
|
||||||
$this->assertEquals('', $backendOptions['password']);
|
|
||||||
$this->assertNotEmpty($backendOptions['password_encrypted']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($json[\OC_Mount_Config::MOUNT_TYPE_GROUP] as $mountPointData) {
|
|
||||||
$this->assertEquals(['/$user/files/mountpoint'], array_keys($mountPointData));
|
|
||||||
|
|
||||||
$mountPointOptions = current($mountPointData);
|
|
||||||
|
|
||||||
$this->assertEquals(1, $mountPointOptions['id']);
|
|
||||||
$this->assertEquals('identifier:\OCA\Files_External\Lib\Backend\SMB', $mountPointOptions['backend']);
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $mountPointOptions['authMechanism']);
|
|
||||||
$this->assertEquals(15, $mountPointOptions['priority']);
|
|
||||||
$this->assertEquals(false, $mountPointOptions['mountOptions']['preview']);
|
|
||||||
|
|
||||||
$backendOptions = $mountPointOptions['options'];
|
|
||||||
$this->assertEquals('value1', $backendOptions['option1']);
|
|
||||||
$this->assertEquals('value2', $backendOptions['option2']);
|
|
||||||
$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 . '/mount.json';
|
|
||||||
|
|
||||||
$legacyBackendOptions = [
|
|
||||||
'user' => 'someuser',
|
|
||||||
'password' => 'somepassword',
|
|
||||||
];
|
|
||||||
$legacyBackendOptions = \OC_Mount_Config::encryptPasswords($legacyBackendOptions);
|
|
||||||
|
|
||||||
$legacyConfig = [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => $legacyBackendOptions,
|
|
||||||
'mountOptions' => ['preview' => false],
|
|
||||||
];
|
|
||||||
// different mount options
|
|
||||||
$legacyConfig2 = [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => $legacyBackendOptions,
|
|
||||||
'mountOptions' => ['preview' => true],
|
|
||||||
];
|
|
||||||
|
|
||||||
$legacyBackendOptions2 = $legacyBackendOptions;
|
|
||||||
$legacyBackendOptions2 = ['user' => 'someuser2', 'password' => 'somepassword2'];
|
|
||||||
$legacyBackendOptions2 = \OC_Mount_Config::encryptPasswords($legacyBackendOptions2);
|
|
||||||
|
|
||||||
// different config
|
|
||||||
$legacyConfig3 = [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'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));
|
|
||||||
|
|
||||||
$this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB')
|
|
||||||
->expects($this->exactly(4))
|
|
||||||
->method('validateStorageDefinition');
|
|
||||||
$this->backendService->getAuthMechanism('identifier:\Auth\Mechanism')
|
|
||||||
->expects($this->exactly(4))
|
|
||||||
->method('validateStorageDefinition');
|
|
||||||
|
|
||||||
$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());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReadLegacyConfigNoAuthMechanism() {
|
|
||||||
$configFile = $this->dataDir . '/mount.json';
|
|
||||||
|
|
||||||
$json = [
|
|
||||||
'user' => [
|
|
||||||
'user1' => [
|
|
||||||
'/$user/files/somemount' => [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SFTP',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => [],
|
|
||||||
'mountOptions' => [],
|
|
||||||
],
|
|
||||||
'/$user/files/othermount' => [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SFTP',
|
|
||||||
// no authMechanism
|
|
||||||
'options' => [],
|
|
||||||
'mountOptions' => [],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
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('identifier:\OCA\Files_External\Lib\Backend\SFTP', $storage1->getBackend()->getIdentifier());
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $storage1->getAuthMechanism()->getIdentifier());
|
|
||||||
|
|
||||||
$this->assertEquals('/othermount', $storage2->getMountPoint());
|
|
||||||
$this->assertEquals('identifier:\OCA\Files_External\Lib\Backend\SFTP', $storage2->getBackend()->getIdentifier());
|
|
||||||
$this->assertEquals('identifier:\Other\Auth\Mechanism', $storage2->getAuthMechanism()->getIdentifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReadLegacyConfigClass() {
|
|
||||||
$configFile = $this->dataDir . '/mount.json';
|
|
||||||
|
|
||||||
$json = [
|
|
||||||
'user' => [
|
|
||||||
'user1' => [
|
|
||||||
'/$user/files/somemount' => [
|
|
||||||
'class' => 'identifier:\OCA\Files_External\Lib\Backend\SFTP',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => [],
|
|
||||||
'mountOptions' => [],
|
|
||||||
],
|
|
||||||
'/$user/files/othermount' => [
|
|
||||||
'class' => 'identifier:sftp_alias',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => [],
|
|
||||||
'mountOptions' => [],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
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('identifier:\OCA\Files_External\Lib\Backend\SFTP', $storage1->getBackend()->getIdentifier());
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $storage1->getAuthMechanism()->getIdentifier());
|
|
||||||
|
|
||||||
$this->assertEquals('/othermount', $storage2->getMountPoint());
|
|
||||||
$this->assertEquals('identifier:\OCA\Files_External\Lib\Backend\SFTP', $storage2->getBackend()->getIdentifier());
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $storage2->getAuthMechanism()->getIdentifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testReadEmptyMountPoint() {
|
|
||||||
$configFile = $this->dataDir . '/mount.json';
|
|
||||||
|
|
||||||
$json = [
|
|
||||||
'user' => [
|
|
||||||
'user1' => [
|
|
||||||
'/$user/files/' => [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SFTP',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => [],
|
|
||||||
'mountOptions' => [],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
file_put_contents($configFile, json_encode($json));
|
|
||||||
|
|
||||||
$allStorages = $this->service->getAllStorages();
|
|
||||||
|
|
||||||
$this->assertCount(1, $allStorages);
|
|
||||||
|
|
||||||
$storage1 = $allStorages[1];
|
|
||||||
|
|
||||||
$this->assertEquals('/', $storage1->getMountPoint());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,29 @@ use \OC\Files\Filesystem;
|
||||||
|
|
||||||
use \OCA\Files_external\NotFoundException;
|
use \OCA\Files_external\NotFoundException;
|
||||||
use \OCA\Files_external\Lib\StorageConfig;
|
use \OCA\Files_external\Lib\StorageConfig;
|
||||||
use \OCA\Files_External\Lib\BackendService;
|
use OCA\Files_External\Service\BackendService;
|
||||||
|
use OCA\Files_External\Service\DBConfigService;
|
||||||
|
use OCA\Files_external\Service\StoragesService;
|
||||||
|
|
||||||
|
class CleaningDBConfig extends DBConfigService {
|
||||||
|
private $mountIds = [];
|
||||||
|
|
||||||
|
public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
|
||||||
|
$id = parent::addMount($mountPoint, $storageBackend, $authBackend, $priority, $type); // TODO: Change the autogenerated stub
|
||||||
|
$this->mountIds[] = $id;
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clean() {
|
||||||
|
foreach ($this->mountIds as $id) {
|
||||||
|
$this->removeMount($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DB
|
||||||
|
*/
|
||||||
abstract class StoragesServiceTest extends \Test\TestCase {
|
abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +65,9 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
*/
|
*/
|
||||||
protected $dataDir;
|
protected $dataDir;
|
||||||
|
|
||||||
|
/** @var CleaningDBConfig */
|
||||||
|
protected $dbConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook calls
|
* Hook calls
|
||||||
*
|
*
|
||||||
|
@ -52,6 +76,8 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
protected static $hookCalls;
|
protected static $hookCalls;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
$this->dbConfig = new CleaningDBConfig(\OC::$server->getDatabaseConnection());
|
||||||
self::$hookCalls = array();
|
self::$hookCalls = array();
|
||||||
$config = \OC::$server->getConfig();
|
$config = \OC::$server->getConfig();
|
||||||
$this->dataDir = $config->getSystemValue(
|
$this->dataDir = $config->getSystemValue(
|
||||||
|
@ -63,8 +89,8 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
// prepare BackendService mock
|
// prepare BackendService mock
|
||||||
$this->backendService =
|
$this->backendService =
|
||||||
$this->getMockBuilder('\OCA\Files_External\Service\BackendService')
|
$this->getMockBuilder('\OCA\Files_External\Service\BackendService')
|
||||||
->disableOriginalConstructor()
|
->disableOriginalConstructor()
|
||||||
->getMock();
|
->getMock();
|
||||||
|
|
||||||
$authMechanisms = [
|
$authMechanisms = [
|
||||||
'identifier:\Auth\Mechanism' => $this->getAuthMechMock('null', '\Auth\Mechanism'),
|
'identifier:\Auth\Mechanism' => $this->getAuthMechMock('null', '\Auth\Mechanism'),
|
||||||
|
@ -72,14 +98,14 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
'identifier:\OCA\Files_External\Lib\Auth\NullMechanism' => $this->getAuthMechMock(),
|
'identifier:\OCA\Files_External\Lib\Auth\NullMechanism' => $this->getAuthMechMock(),
|
||||||
];
|
];
|
||||||
$this->backendService->method('getAuthMechanism')
|
$this->backendService->method('getAuthMechanism')
|
||||||
->will($this->returnCallback(function($class) use ($authMechanisms) {
|
->will($this->returnCallback(function ($class) use ($authMechanisms) {
|
||||||
if (isset($authMechanisms[$class])) {
|
if (isset($authMechanisms[$class])) {
|
||||||
return $authMechanisms[$class];
|
return $authMechanisms[$class];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}));
|
}));
|
||||||
$this->backendService->method('getAuthMechanismsByScheme')
|
$this->backendService->method('getAuthMechanismsByScheme')
|
||||||
->will($this->returnCallback(function($schemes) use ($authMechanisms) {
|
->will($this->returnCallback(function ($schemes) use ($authMechanisms) {
|
||||||
return array_filter($authMechanisms, function ($authMech) use ($schemes) {
|
return array_filter($authMechanisms, function ($authMech) use ($schemes) {
|
||||||
return in_array($authMech->getScheme(), $schemes, true);
|
return in_array($authMech->getScheme(), $schemes, true);
|
||||||
});
|
});
|
||||||
|
@ -96,7 +122,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
$backends['identifier:\OCA\Files_External\Lib\Backend\SFTP']->method('getLegacyAuthMechanism')
|
$backends['identifier:\OCA\Files_External\Lib\Backend\SFTP']->method('getLegacyAuthMechanism')
|
||||||
->willReturn($authMechanisms['identifier:\Other\Auth\Mechanism']);
|
->willReturn($authMechanisms['identifier:\Other\Auth\Mechanism']);
|
||||||
$this->backendService->method('getBackend')
|
$this->backendService->method('getBackend')
|
||||||
->will($this->returnCallback(function($backendClass) use ($backends) {
|
->will($this->returnCallback(function ($backendClass) use ($backends) {
|
||||||
if (isset($backends[$backendClass])) {
|
if (isset($backends[$backendClass])) {
|
||||||
return $backends[$backendClass];
|
return $backends[$backendClass];
|
||||||
}
|
}
|
||||||
|
@ -116,7 +142,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
|
|
||||||
$containerMock = $this->getMock('\OCP\AppFramework\IAppContainer');
|
$containerMock = $this->getMock('\OCP\AppFramework\IAppContainer');
|
||||||
$containerMock->method('query')
|
$containerMock->method('query')
|
||||||
->will($this->returnCallback(function($name) {
|
->will($this->returnCallback(function ($name) {
|
||||||
if ($name === 'OCA\Files_External\Service\BackendService') {
|
if ($name === 'OCA\Files_External\Service\BackendService') {
|
||||||
return $this->backendService;
|
return $this->backendService;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +158,9 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
\OC_Mount_Config::$skipTest = false;
|
\OC_Mount_Config::$skipTest = false;
|
||||||
self::$hookCalls = array();
|
self::$hookCalls = array();
|
||||||
|
if ($this->dbConfig) {
|
||||||
|
$this->dbConfig->clean();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getBackendMock($class = '\OCA\Files_External\Lib\Backend\SMB', $storageClass = '\OC\Files\Storage\SMB') {
|
protected function getBackendMock($class = '\OCA\Files_External\Lib\Backend\SMB', $storageClass = '\OC\Files\Storage\SMB') {
|
||||||
|
@ -141,7 +170,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
$backend->method('getStorageClass')
|
$backend->method('getStorageClass')
|
||||||
->willReturn($storageClass);
|
->willReturn($storageClass);
|
||||||
$backend->method('getIdentifier')
|
$backend->method('getIdentifier')
|
||||||
->willReturn('identifier:'.$class);
|
->willReturn('identifier:' . $class);
|
||||||
return $backend;
|
return $backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +181,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
$authMech->method('getScheme')
|
$authMech->method('getScheme')
|
||||||
->willReturn($scheme);
|
->willReturn($scheme);
|
||||||
$authMech->method('getIdentifier')
|
$authMech->method('getIdentifier')
|
||||||
->willReturn('identifier:'.$class);
|
->willReturn('identifier:' . $class);
|
||||||
|
|
||||||
return $authMech;
|
return $authMech;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +287,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
$storage->setBackendOptions($backendOptions);
|
$storage->setBackendOptions($backendOptions);
|
||||||
|
|
||||||
$newStorage = $this->service->addStorage($storage);
|
$newStorage = $this->service->addStorage($storage);
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
$id = $newStorage->getId();
|
||||||
|
|
||||||
// manually trigger storage entry because normally it happens on first
|
// manually trigger storage entry because normally it happens on first
|
||||||
// access, which isn't possible within this test
|
// access, which isn't possible within this test
|
||||||
|
@ -267,7 +296,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
// get numeric id for later check
|
// get numeric id for later check
|
||||||
$numericId = $storageCache->getNumericId();
|
$numericId = $storageCache->getNumericId();
|
||||||
|
|
||||||
$newStorage = $this->service->removeStorage(1);
|
$this->service->removeStorage($id);
|
||||||
|
|
||||||
$caught = false;
|
$caught = false;
|
||||||
try {
|
try {
|
||||||
|
@ -317,7 +346,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
|
||||||
$priority
|
$priority
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals('/'.$mountPoint, $storage->getMountPoint());
|
$this->assertEquals('/' . $mountPoint, $storage->getMountPoint());
|
||||||
$this->assertEquals($backend, $storage->getBackend());
|
$this->assertEquals($backend, $storage->getBackend());
|
||||||
$this->assertEquals($authMechanism, $storage->getAuthMechanism());
|
$this->assertEquals($authMechanism, $storage->getAuthMechanism());
|
||||||
$this->assertEquals($backendOptions, $storage->getBackendOptions());
|
$this->assertEquals($backendOptions, $storage->getBackendOptions());
|
||||||
|
|
|
@ -21,17 +21,33 @@
|
||||||
*/
|
*/
|
||||||
namespace OCA\Files_External\Tests\Service;
|
namespace OCA\Files_External\Tests\Service;
|
||||||
|
|
||||||
|
use OCA\Files_external\Service\StoragesService;
|
||||||
use \OCA\Files_External\Service\UserGlobalStoragesService;
|
use \OCA\Files_External\Service\UserGlobalStoragesService;
|
||||||
use \OCP\IGroupManager;
|
use \OCP\IGroupManager;
|
||||||
|
|
||||||
use \OCA\Files_External\Lib\StorageConfig;
|
use \OCA\Files_External\Lib\StorageConfig;
|
||||||
|
use OCP\IUser;
|
||||||
|
use Test\Traits\UserTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DB
|
||||||
|
*/
|
||||||
class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
||||||
|
use UserTrait;
|
||||||
|
|
||||||
|
/** @var \OCP\IGroupManager|\PHPUnit_Framework_MockObject_MockObject groupManager */
|
||||||
protected $groupManager;
|
protected $groupManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var StoragesService
|
||||||
|
*/
|
||||||
protected $globalStoragesService;
|
protected $globalStoragesService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var UserGlobalStoragesService
|
||||||
|
*/
|
||||||
|
protected $service;
|
||||||
|
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
const USER_ID = 'test_user';
|
const USER_ID = 'test_user';
|
||||||
|
@ -44,6 +60,7 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
||||||
$this->globalStoragesService = $this->service;
|
$this->globalStoragesService = $this->service;
|
||||||
|
|
||||||
$this->user = new \OC\User\User(self::USER_ID, null);
|
$this->user = new \OC\User\User(self::USER_ID, null);
|
||||||
|
/** @var \OCP\IUserSession|\PHPUnit_Framework_MockObject_MockObject $userSession */
|
||||||
$userSession = $this->getMock('\OCP\IUserSession');
|
$userSession = $this->getMock('\OCP\IUserSession');
|
||||||
$userSession
|
$userSession
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
|
@ -52,19 +69,28 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
||||||
|
|
||||||
$this->groupManager = $this->getMock('\OCP\IGroupManager');
|
$this->groupManager = $this->getMock('\OCP\IGroupManager');
|
||||||
$this->groupManager->method('isInGroup')
|
$this->groupManager->method('isInGroup')
|
||||||
->will($this->returnCallback(function($userId, $groupId) {
|
->will($this->returnCallback(function ($userId, $groupId) {
|
||||||
if ($userId === self::USER_ID) {
|
if ($userId === self::USER_ID) {
|
||||||
switch ($groupId) {
|
switch ($groupId) {
|
||||||
case self::GROUP_ID:
|
case self::GROUP_ID:
|
||||||
case self::GROUP_ID2:
|
case self::GROUP_ID2:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
|
$this->groupManager->method('getUserGroupIds')
|
||||||
|
->will($this->returnCallback(function (IUser $user) {
|
||||||
|
if ($user->getUID() === self::USER_ID) {
|
||||||
|
return [self::GROUP_ID, self::GROUP_ID2];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
$this->service = new UserGlobalStoragesService(
|
$this->service = new UserGlobalStoragesService(
|
||||||
$this->backendService,
|
$this->backendService,
|
||||||
|
$this->dbConfig,
|
||||||
$userSession,
|
$userSession,
|
||||||
$this->groupManager
|
$this->groupManager
|
||||||
);
|
);
|
||||||
|
@ -154,6 +180,13 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
||||||
$this->service->updateStorage($retrievedStorage);
|
$this->service->updateStorage($retrievedStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \DomainException
|
||||||
|
*/
|
||||||
|
public function testNonExistingStorage() {
|
||||||
|
parent::testNonExistingStorage();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \DomainException
|
* @expectedException \DomainException
|
||||||
* @dataProvider deleteStorageDataProvider
|
* @dataProvider deleteStorageDataProvider
|
||||||
|
@ -169,9 +202,16 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
||||||
$storage->setBackendOptions($backendOptions);
|
$storage->setBackendOptions($backendOptions);
|
||||||
|
|
||||||
$newStorage = $this->globalStoragesService->addStorage($storage);
|
$newStorage = $this->globalStoragesService->addStorage($storage);
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
$id = $newStorage->getId();
|
||||||
|
|
||||||
$this->service->removeStorage(1);
|
$this->service->removeStorage($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \DomainException
|
||||||
|
*/
|
||||||
|
public function testDeleteUnexistingStorage() {
|
||||||
|
parent::testDeleteUnexistingStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUniqueStoragesProvider() {
|
public function getUniqueStoragesProvider() {
|
||||||
|
|
|
@ -26,36 +26,33 @@ use \OC\Files\Filesystem;
|
||||||
use \OCA\Files_external\Service\UserStoragesService;
|
use \OCA\Files_external\Service\UserStoragesService;
|
||||||
use \OCA\Files_external\NotFoundException;
|
use \OCA\Files_external\NotFoundException;
|
||||||
use \OCA\Files_external\Lib\StorageConfig;
|
use \OCA\Files_external\Lib\StorageConfig;
|
||||||
|
use Test\Traits\UserTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DB
|
||||||
|
*/
|
||||||
class UserStoragesServiceTest extends StoragesServiceTest {
|
class UserStoragesServiceTest extends StoragesServiceTest {
|
||||||
|
use UserTrait;
|
||||||
|
|
||||||
|
private $user;
|
||||||
|
|
||||||
|
private $userId;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$userManager = \OC::$server->getUserManager();
|
|
||||||
|
|
||||||
$this->userId = $this->getUniqueID('user_');
|
$this->userId = $this->getUniqueID('user_');
|
||||||
$this->user = $userManager->createUser(
|
$this->createUser($this->userId, $this->userId);
|
||||||
$this->userId,
|
$this->user = \OC::$server->getUserManager()->get($this->userId);
|
||||||
$this->userId
|
|
||||||
);
|
|
||||||
|
|
||||||
|
/** @var \OCP\IUserSession|\PHPUnit_Framework_MockObject_MockObject $userSession */
|
||||||
$userSession = $this->getMock('\OCP\IUserSession');
|
$userSession = $this->getMock('\OCP\IUserSession');
|
||||||
$userSession
|
$userSession
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('getUser')
|
->method('getUser')
|
||||||
->will($this->returnValue($this->user));
|
->will($this->returnValue($this->user));
|
||||||
|
|
||||||
$this->service = new UserStoragesService($this->backendService, $userSession);
|
$this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession);
|
||||||
|
|
||||||
// create home folder
|
|
||||||
mkdir($this->dataDir . '/' . $this->userId . '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tearDown() {
|
|
||||||
@unlink($this->dataDir . '/' . $this->userId . '/mount.json');
|
|
||||||
$this->user->delete();
|
|
||||||
parent::tearDown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function makeTestStorageData() {
|
private function makeTestStorageData() {
|
||||||
|
@ -79,15 +76,14 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
||||||
|
|
||||||
$newStorage = $this->service->addStorage($storage);
|
$newStorage = $this->service->addStorage($storage);
|
||||||
|
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
$id = $newStorage->getId();
|
||||||
|
|
||||||
$newStorage = $this->service->getStorage(1);
|
$newStorage = $this->service->getStorage($id);
|
||||||
|
|
||||||
$this->assertEquals($storage->getMountPoint(), $newStorage->getMountPoint());
|
$this->assertEquals($storage->getMountPoint(), $newStorage->getMountPoint());
|
||||||
$this->assertEquals($storage->getBackend(), $newStorage->getBackend());
|
$this->assertEquals($storage->getBackend(), $newStorage->getBackend());
|
||||||
$this->assertEquals($storage->getAuthMechanism(), $newStorage->getAuthMechanism());
|
$this->assertEquals($storage->getAuthMechanism(), $newStorage->getAuthMechanism());
|
||||||
$this->assertEquals($storage->getBackendOptions(), $newStorage->getBackendOptions());
|
$this->assertEquals($storage->getBackendOptions(), $newStorage->getBackendOptions());
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
|
||||||
$this->assertEquals(0, $newStorage->getStatus());
|
$this->assertEquals(0, $newStorage->getStatus());
|
||||||
|
|
||||||
// hook called once for user
|
// hook called once for user
|
||||||
|
@ -99,9 +95,8 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
||||||
$this->userId
|
$this->userId
|
||||||
);
|
);
|
||||||
|
|
||||||
// next one gets id 2
|
|
||||||
$nextStorage = $this->service->addStorage($storage);
|
$nextStorage = $this->service->addStorage($storage);
|
||||||
$this->assertEquals(2, $nextStorage->getId());
|
$this->assertEquals($id + 1, $nextStorage->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateStorage() {
|
public function testUpdateStorage() {
|
||||||
|
@ -117,7 +112,6 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$newStorage = $this->service->addStorage($storage);
|
$newStorage = $this->service->addStorage($storage);
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
|
||||||
|
|
||||||
$backendOptions = $newStorage->getBackendOptions();
|
$backendOptions = $newStorage->getBackendOptions();
|
||||||
$backendOptions['password'] = 'anotherPassword';
|
$backendOptions['password'] = 'anotherPassword';
|
||||||
|
@ -131,7 +125,6 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
||||||
// these attributes are unused for user storages
|
// these attributes are unused for user storages
|
||||||
$this->assertEmpty($newStorage->getApplicableUsers());
|
$this->assertEmpty($newStorage->getApplicableUsers());
|
||||||
$this->assertEmpty($newStorage->getApplicableGroups());
|
$this->assertEmpty($newStorage->getApplicableGroups());
|
||||||
$this->assertEquals(1, $newStorage->getId());
|
|
||||||
$this->assertEquals(0, $newStorage->getStatus());
|
$this->assertEquals(0, $newStorage->getStatus());
|
||||||
|
|
||||||
// no hook calls
|
// no hook calls
|
||||||
|
@ -181,89 +174,4 @@ class UserStoragesServiceTest extends StoragesServiceTest {
|
||||||
$this->userId
|
$this->userId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure it uses the correct format when reading/writing
|
|
||||||
* the legacy config
|
|
||||||
*/
|
|
||||||
public function testLegacyConfigConversion() {
|
|
||||||
$configFile = $this->dataDir . '/' . $this->userId . '/mount.json';
|
|
||||||
|
|
||||||
$storage = $this->makeTestStorageData();
|
|
||||||
$storage = $this->service->addStorage($storage);
|
|
||||||
|
|
||||||
$json = json_decode(file_get_contents($configFile), true);
|
|
||||||
|
|
||||||
$this->assertCount(1, $json);
|
|
||||||
|
|
||||||
$this->assertEquals([\OC_Mount_Config::MOUNT_TYPE_USER], array_keys($json));
|
|
||||||
$this->assertEquals([$this->userId], array_keys($json[\OC_Mount_config::MOUNT_TYPE_USER]));
|
|
||||||
|
|
||||||
$mountPointData = $json[\OC_Mount_config::MOUNT_TYPE_USER][$this->userId];
|
|
||||||
$this->assertEquals(['/' . $this->userId . '/files/mountpoint'], array_keys($mountPointData));
|
|
||||||
|
|
||||||
$mountPointOptions = current($mountPointData);
|
|
||||||
$this->assertEquals(1, $mountPointOptions['id']);
|
|
||||||
$this->assertEquals('identifier:\OCA\Files_External\Lib\Backend\SMB', $mountPointOptions['backend']);
|
|
||||||
$this->assertEquals('identifier:\Auth\Mechanism', $mountPointOptions['authMechanism']);
|
|
||||||
$this->assertEquals(false, $mountPointOptions['mountOptions']['preview']);
|
|
||||||
|
|
||||||
$backendOptions = $mountPointOptions['options'];
|
|
||||||
$this->assertEquals('value1', $backendOptions['option1']);
|
|
||||||
$this->assertEquals('value2', $backendOptions['option2']);
|
|
||||||
$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 = [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'options' => $legacyBackendOptions,
|
|
||||||
'mountOptions' => ['preview' => false],
|
|
||||||
];
|
|
||||||
// different mount options
|
|
||||||
$legacyConfig2 = [
|
|
||||||
'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
|
||||||
'authMechanism' => 'identifier:\Auth\Mechanism',
|
|
||||||
'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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue