2015-11-02 15:13:06 +03:00
|
|
|
<?php
|
|
|
|
/**
|
2016-07-21 17:49:16 +03:00
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
|
|
*
|
2019-12-03 21:57:53 +03:00
|
|
|
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
2016-07-21 17:49:16 +03:00
|
|
|
* @author Joas Schilling <coding@schilljs.com>
|
2019-12-03 21:57:53 +03:00
|
|
|
* @author Morris Jobke <hey@morrisjobke.de>
|
2016-07-21 19:13:36 +03:00
|
|
|
* @author Robin Appelman <robin@icewind.nl>
|
2016-05-26 20:56:05 +03:00
|
|
|
* @author Stefan Weil <sw@weilnetz.de>
|
2015-11-02 15:13:06 +03:00
|
|
|
*
|
|
|
|
* @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,
|
2019-12-03 21:57:53 +03:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
2015-11-02 15:13:06 +03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-05-13 12:22:28 +03:00
|
|
|
namespace OCA\Files_External\Service;
|
2015-11-02 15:13:06 +03:00
|
|
|
|
2016-05-13 12:56:47 +03:00
|
|
|
use OCA\Files_External\Lib\StorageConfig;
|
2018-04-25 16:22:28 +03:00
|
|
|
use OCP\ILogger;
|
2015-11-02 15:13:06 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
2020-04-10 11:35:09 +03:00
|
|
|
} elseif ($mountType === \OC_Mount_Config::MOUNT_TYPE_GROUP) {
|
2015-11-02 15:13:06 +03:00
|
|
|
$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
|
2018-04-20 15:35:37 +03:00
|
|
|
\OC::$server->getLogger()->error('Could not parse mount point "' . $rootMountPath . '"', ['app' => 'files_external']);
|
2015-11-02 15:13:06 +03:00
|
|
|
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) {
|
2016-03-30 14:27:12 +03:00
|
|
|
// don't die if a storage backend doesn't exist
|
2018-01-17 17:21:56 +03:00
|
|
|
\OC::$server->getLogger()->logException($e, [
|
|
|
|
'message' => 'Could not load storage.',
|
2018-04-25 16:22:28 +03:00
|
|
|
'level' => ILogger::ERROR,
|
2018-01-17 17:21:56 +03:00
|
|
|
'app' => 'files_external',
|
|
|
|
]);
|
2015-11-02 15:13:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert parameter values
|
|
|
|
foreach ($storages as $storage) {
|
|
|
|
$storage->getBackend()->validateStorageDefinition($storage);
|
|
|
|
$storage->getAuthMechanism()->validateStorageDefinition($storage);
|
|
|
|
}
|
|
|
|
return $storages;
|
|
|
|
}
|
|
|
|
}
|