Introduce UserGlobalStoragesService
UserGlobalStoragesService reads the global storage configuration, cherry-picking storages applicable to a user. Writing storages through this service is forbidden, on punishment of throwing an exception. Storage IDs may also be config hashes when retrieved from this service, as it is unable to update the storages with real IDs. As UserGlobalStoragesService and UserStoragesService share a bit of code relating to users, that has been split into UserTrait. UserTrait also allows for the user set to be overridden, rather than using the user from IUserSession. Config\ConfigAdapter has been reworked to use UserStoragesService and UserGlobalStoragesService instead of OC_Mount_Config::getAbsoluteMountPoints(), further reducing dependance on that horrible static class.
This commit is contained in:
parent
37beb58c6f
commit
a6a69ef1df
|
@ -2,6 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* @author Morris Jobke <hey@morrisjobke.de>
|
* @author Morris Jobke <hey@morrisjobke.de>
|
||||||
* @author Robin Appelman <icewind@owncloud.com>
|
* @author Robin Appelman <icewind@owncloud.com>
|
||||||
|
* @author Robin McCorkell <rmccorkell@owncloud.com>
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||||
* @license AGPL-3.0
|
* @license AGPL-3.0
|
||||||
|
@ -22,23 +23,67 @@
|
||||||
|
|
||||||
namespace OCA\Files_External\Config;
|
namespace OCA\Files_External\Config;
|
||||||
|
|
||||||
|
use OCP\Files\Storage;
|
||||||
use OC\Files\Mount\MountPoint;
|
use OC\Files\Mount\MountPoint;
|
||||||
use OCP\Files\Storage\IStorageFactory;
|
use OCP\Files\Storage\IStorageFactory;
|
||||||
use OCA\Files_External\Lib\PersonalMount;
|
use OCA\Files_External\Lib\PersonalMount;
|
||||||
use OCP\Files\Config\IMountProvider;
|
use OCP\Files\Config\IMountProvider;
|
||||||
use OCP\IUser;
|
use OCP\IUser;
|
||||||
use OCA\Files_external\Service\UserStoragesService;
|
use OCA\Files_external\Service\UserStoragesService;
|
||||||
|
use OCA\Files_External\Service\UserGlobalStoragesService;
|
||||||
|
use OCA\Files_External\Lib\StorageConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the old files_external config work with the new public mount config api
|
* Make the old files_external config work with the new public mount config api
|
||||||
*/
|
*/
|
||||||
class ConfigAdapter implements IMountProvider {
|
class ConfigAdapter implements IMountProvider {
|
||||||
|
|
||||||
|
/** @var UserStoragesService */
|
||||||
|
private $userStoragesService;
|
||||||
|
|
||||||
|
/** @var UserGlobalStoragesService */
|
||||||
|
private $userGlobalStoragesService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param UserStoragesService $userStoragesService
|
* @param UserStoragesService $userStoragesService
|
||||||
|
* @param UserGlobalStoragesService $userGlobalStoragesService
|
||||||
*/
|
*/
|
||||||
public function __construct(UserStoragesService $userStoragesService) {
|
public function __construct(
|
||||||
|
UserStoragesService $userStoragesService,
|
||||||
|
UserGlobalStoragesService $userGlobalStoragesService
|
||||||
|
) {
|
||||||
$this->userStoragesService = $userStoragesService;
|
$this->userStoragesService = $userStoragesService;
|
||||||
|
$this->userGlobalStoragesService = $userGlobalStoragesService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process storage ready for mounting
|
||||||
|
*
|
||||||
|
* @param StorageConfig $storage
|
||||||
|
*/
|
||||||
|
private function prepareStorageConfig(StorageConfig &$storage) {
|
||||||
|
$objectStore = $storage->getBackendOption('objectstore');
|
||||||
|
if ($objectStore) {
|
||||||
|
$objectClass = $objectStore['class'];
|
||||||
|
$storage->setBackendOption('objectstore', new $objectClass($objectStore));
|
||||||
|
}
|
||||||
|
|
||||||
|
$storage->getBackend()->manipulateStorageConfig($storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the storage implementation
|
||||||
|
*
|
||||||
|
* @param StorageConfig $storageConfig
|
||||||
|
* @return Storage
|
||||||
|
*/
|
||||||
|
private function constructStorage(StorageConfig $storageConfig) {
|
||||||
|
$class = $storageConfig->getBackend()->getStorageClass();
|
||||||
|
$storage = new $class($storageConfig->getBackendOptions());
|
||||||
|
|
||||||
|
$storage = $storageConfig->getBackend()->wrapStorage($storage);
|
||||||
|
|
||||||
|
return $storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,21 +94,44 @@ 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) {
|
||||||
$mountPoints = \OC_Mount_Config::getAbsoluteMountPoints($user->getUID());
|
$mounts = [];
|
||||||
$mounts = array();
|
|
||||||
foreach ($mountPoints as $mountPoint => $options) {
|
$this->userStoragesService->setUser($user);
|
||||||
if (isset($options['options']['objectstore'])) {
|
$this->userGlobalStoragesService->setUser($user);
|
||||||
$objectClass = $options['options']['objectstore']['class'];
|
|
||||||
$options['options']['objectstore'] = new $objectClass($options['options']['objectstore']);
|
foreach ($this->userGlobalStoragesService->getAllStorages() as $storage) {
|
||||||
}
|
$this->prepareStorageConfig($storage);
|
||||||
$mountOptions = isset($options['mountOptions']) ? $options['mountOptions'] : [];
|
$impl = $this->constructStorage($storage);
|
||||||
if (isset($options['personal']) && $options['personal']) {
|
|
||||||
$mount = new PersonalMount($this->userStoragesService, $options['id'], $options['class'], $mountPoint, $options['options'], $loader, $mountOptions);
|
$mount = new MountPoint(
|
||||||
$mounts[] = $mount;
|
$impl,
|
||||||
} else {
|
'/'.$user->getUID().'/files' . $storage->getMountPoint(),
|
||||||
$mounts[] = new MountPoint($options['class'], $mountPoint, $options['options'], $loader, $mountOptions);
|
null,
|
||||||
}
|
$loader,
|
||||||
|
$storage->getMountOptions()
|
||||||
|
);
|
||||||
|
$mounts[$storage->getMountPoint()] = $mount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($this->userStoragesService->getAllStorages() as $storage) {
|
||||||
|
$this->prepareStorageConfig($storage);
|
||||||
|
$impl = $this->constructStorage($storage);
|
||||||
|
|
||||||
|
$mount = new PersonalMount(
|
||||||
|
$this->userStoragesService,
|
||||||
|
$storage->getId(),
|
||||||
|
$impl,
|
||||||
|
'/'.$user->getUID().'/files' . $storage->getMountPoint(),
|
||||||
|
null,
|
||||||
|
$loader,
|
||||||
|
$storage->getMountOptions()
|
||||||
|
);
|
||||||
|
$mounts[$storage->getMountPoint()] = $mount;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->userStoragesService->resetUser();
|
||||||
|
$this->userGlobalStoragesService->resetUser();
|
||||||
|
|
||||||
return $mounts;
|
return $mounts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ class GlobalStoragesService extends StoragesService {
|
||||||
$storageConfig->setBackendOptions($oldBackendOptions);
|
$storageConfig->setBackendOptions($oldBackendOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
\OC_Mount_Config::writeData(null, $mountPoints);
|
$this->writeLegacyConfig($mountPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -55,6 +55,16 @@ abstract class StoragesService {
|
||||||
return \OC_Mount_Config::readData();
|
return \OC_Mount_Config::readData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write legacy config data
|
||||||
|
*
|
||||||
|
* @param array $mountPoints
|
||||||
|
*/
|
||||||
|
protected function writeLegacyConfig(array $mountPoints) {
|
||||||
|
// write global config
|
||||||
|
\OC_Mount_Config::writeData(null, $mountPoints);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy legacy storage options into the given storage config object.
|
* Copy legacy storage options into the given storage config object.
|
||||||
*
|
*
|
||||||
|
@ -202,20 +212,30 @@ abstract class StoragesService {
|
||||||
|
|
||||||
// process storages with config hash, they must get a real id
|
// process storages with config hash, they must get a real id
|
||||||
if (!empty($storagesWithConfigHash)) {
|
if (!empty($storagesWithConfigHash)) {
|
||||||
$nextId = $this->generateNextId($storages);
|
$this->setRealStorageIds($storages, $storagesWithConfigHash);
|
||||||
foreach ($storagesWithConfigHash as $storage) {
|
|
||||||
$storage->setId($nextId);
|
|
||||||
$storages[$nextId] = $storage;
|
|
||||||
$nextId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-save the config with the generated ids
|
|
||||||
$this->writeConfig($storages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $storages;
|
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
|
* Add mount point into the messy mount point structure
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin McCorkell <rmccorkell@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\Service\GlobalStoragesService;
|
||||||
|
use \OCA\Files_External\Service\BackendService;
|
||||||
|
use \OCP\IUserSession;
|
||||||
|
use \OCP\IGroupManager;
|
||||||
|
use \OCA\Files_External\Service\UserTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service class to read global storages applicable to the user
|
||||||
|
* Read-only access available, attempting to write will throw DomainException
|
||||||
|
*/
|
||||||
|
class UserGlobalStoragesService extends GlobalStoragesService {
|
||||||
|
|
||||||
|
use UserTrait;
|
||||||
|
|
||||||
|
/** @var IGroupManager */
|
||||||
|
protected $groupManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BackendService $backendService
|
||||||
|
* @param IUserSession $userSession
|
||||||
|
* @param IGroupManager $groupManager
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
BackendService $backendService,
|
||||||
|
IUserSession $userSession,
|
||||||
|
IGroupManager $groupManager
|
||||||
|
) {
|
||||||
|
parent::__construct($backendService);
|
||||||
|
$this->userSession = $userSession;
|
||||||
|
$this->groupManager = $groupManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
// as a read-only view, storage IDs don't need to be real
|
||||||
|
foreach ($storagesWithConfigHash as $storage) {
|
||||||
|
$storages[$storage->getId()] = $storage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read legacy config data
|
||||||
|
*
|
||||||
|
* @return array list of mount configs
|
||||||
|
*/
|
||||||
|
protected function readLegacyConfig() {
|
||||||
|
// read global config
|
||||||
|
$data = parent::readLegacyConfig();
|
||||||
|
$userId = $this->getUser()->getUID();
|
||||||
|
|
||||||
|
if (isset($data[\OC_Mount_Config::MOUNT_TYPE_USER])) {
|
||||||
|
$data[\OC_Mount_Config::MOUNT_TYPE_USER] = array_filter(
|
||||||
|
$data[\OC_Mount_Config::MOUNT_TYPE_USER], function($key) use ($userId) {
|
||||||
|
return (strtolower($key) === strtolower($userId) || $key === 'all');
|
||||||
|
}, ARRAY_FILTER_USE_KEY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data[\OC_Mount_Config::MOUNT_TYPE_GROUP])) {
|
||||||
|
$data[\OC_Mount_Config::MOUNT_TYPE_GROUP] = array_filter(
|
||||||
|
$data[\OC_Mount_Config::MOUNT_TYPE_GROUP], function($key) use ($userId) {
|
||||||
|
return ($this->groupManager->isInGroup($userId, $key));
|
||||||
|
}, ARRAY_FILTER_USE_KEY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write legacy config data
|
||||||
|
*
|
||||||
|
* @param array $mountPoints
|
||||||
|
*/
|
||||||
|
protected function writeLegacyConfig(array $mountPoints) {
|
||||||
|
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ use \OC\Files\Filesystem;
|
||||||
use \OCA\Files_external\Lib\StorageConfig;
|
use \OCA\Files_external\Lib\StorageConfig;
|
||||||
use \OCA\Files_external\NotFoundException;
|
use \OCA\Files_external\NotFoundException;
|
||||||
use \OCA\Files_External\Service\BackendService;
|
use \OCA\Files_External\Service\BackendService;
|
||||||
|
use \OCA\Files_External\Service\UserTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service class to manage user external storages
|
* Service class to manage user external storages
|
||||||
|
@ -34,12 +35,7 @@ use \OCA\Files_External\Service\BackendService;
|
||||||
*/
|
*/
|
||||||
class UserStoragesService extends StoragesService {
|
class UserStoragesService extends StoragesService {
|
||||||
|
|
||||||
/**
|
use UserTrait;
|
||||||
* User session
|
|
||||||
*
|
|
||||||
* @var IUserSession
|
|
||||||
*/
|
|
||||||
private $userSession;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a user storages service
|
* Create a user storages service
|
||||||
|
@ -62,17 +58,28 @@ class UserStoragesService extends StoragesService {
|
||||||
*/
|
*/
|
||||||
protected function readLegacyConfig() {
|
protected function readLegacyConfig() {
|
||||||
// read user config
|
// read user config
|
||||||
$user = $this->userSession->getUser()->getUID();
|
$user = $this->getUser()->getUID();
|
||||||
return \OC_Mount_Config::readData($user);
|
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
|
* Read the external storages config
|
||||||
*
|
*
|
||||||
* @return array map of storage id to storage config
|
* @return array map of storage id to storage config
|
||||||
*/
|
*/
|
||||||
protected function readConfig() {
|
protected function readConfig() {
|
||||||
$user = $this->userSession->getUser()->getUID();
|
$user = $this->getUser()->getUID();
|
||||||
// TODO: in the future don't rely on the global config reading code
|
// TODO: in the future don't rely on the global config reading code
|
||||||
$storages = parent::readConfig();
|
$storages = parent::readConfig();
|
||||||
|
|
||||||
|
@ -99,7 +106,7 @@ class UserStoragesService extends StoragesService {
|
||||||
* @param array $storages map of storage id to storage config
|
* @param array $storages map of storage id to storage config
|
||||||
*/
|
*/
|
||||||
public function writeConfig($storages) {
|
public function writeConfig($storages) {
|
||||||
$user = $this->userSession->getUser()->getUID();
|
$user = $this->getUser()->getUID();
|
||||||
|
|
||||||
// let the horror begin
|
// let the horror begin
|
||||||
$mountPoints = [];
|
$mountPoints = [];
|
||||||
|
@ -127,7 +134,7 @@ class UserStoragesService extends StoragesService {
|
||||||
$storageConfig->setBackendOptions($oldBackendOptions);
|
$storageConfig->setBackendOptions($oldBackendOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
\OC_Mount_Config::writeData($user, $mountPoints);
|
$this->writeLegacyConfig($mountPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,7 +145,7 @@ class UserStoragesService extends StoragesService {
|
||||||
* @param string $signal signal to trigger
|
* @param string $signal signal to trigger
|
||||||
*/
|
*/
|
||||||
protected function triggerHooks(StorageConfig $storage, $signal) {
|
protected function triggerHooks(StorageConfig $storage, $signal) {
|
||||||
$user = $this->userSession->getUser()->getUID();
|
$user = $this->getUser()->getUID();
|
||||||
|
|
||||||
// trigger hook for the current user
|
// trigger hook for the current user
|
||||||
$this->triggerApplicableHooks(
|
$this->triggerApplicableHooks(
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Robin McCorkell <rmccorkell@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;
|
||||||
|
use \OCP\IUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trait for getting user information in a service
|
||||||
|
*/
|
||||||
|
trait UserTrait {
|
||||||
|
|
||||||
|
/** @var IUserSession */
|
||||||
|
protected $userSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User override
|
||||||
|
*
|
||||||
|
* @var IUser|null
|
||||||
|
*/
|
||||||
|
private $user = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return IUser|null
|
||||||
|
*/
|
||||||
|
protected function getUser() {
|
||||||
|
if ($this->user) {
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
return $this->userSession->getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the user from the session
|
||||||
|
* Unset with ->resetUser() when finished!
|
||||||
|
*
|
||||||
|
* @param IUser
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setUser(IUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the user override
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function resetUser() {
|
||||||
|
$this->user = null;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue