Merge pull request #11884 from owncloud/ext-appframework
Cleanup ext storage CRUD code, introduce storage config idremotes/origin/etag-endpoint
commit
e44ab2dcfe
@ -1,26 +0,0 @@ |
||||
<?php |
||||
|
||||
OCP\JSON::checkAppEnabled('files_external'); |
||||
OCP\JSON::callCheck(); |
||||
|
||||
if ($_POST['isPersonal'] == 'true') { |
||||
OCP\JSON::checkLoggedIn(); |
||||
$isPersonal = true; |
||||
} else { |
||||
OCP\JSON::checkAdminUser(); |
||||
$isPersonal = false; |
||||
} |
||||
|
||||
$mountPoint = (string)$_POST['mountPoint']; |
||||
$oldMountPoint = (string)$_POST['oldMountPoint']; |
||||
$class = (string)$_POST['class']; |
||||
$options = (array)$_POST['classOptions']; |
||||
$type = (string)$_POST['mountType']; |
||||
$applicable = (string)$_POST['applicable']; |
||||
|
||||
if ($oldMountPoint and $oldMountPoint !== $mountPoint) { |
||||
OC_Mount_Config::removeMountPoint($oldMountPoint, $type, $applicable, $isPersonal); |
||||
} |
||||
|
||||
$status = OC_Mount_Config::addMountPoint($mountPoint, $class, $options, $type, $applicable, $isPersonal); |
||||
OCP\JSON::success(array('data' => array('message' => $status))); |
@ -1,23 +0,0 @@ |
||||
<?php |
||||
|
||||
OCP\JSON::checkAppEnabled('files_external'); |
||||
OCP\JSON::callCheck(); |
||||
|
||||
if (!isset($_POST['isPersonal'])) |
||||
return; |
||||
if (!isset($_POST['mountPoint'])) |
||||
return; |
||||
if (!isset($_POST['mountType'])) |
||||
return; |
||||
if (!isset($_POST['applicable'])) |
||||
return; |
||||
|
||||
if ($_POST['isPersonal'] == 'true') { |
||||
OCP\JSON::checkLoggedIn(); |
||||
$isPersonal = true; |
||||
} else { |
||||
OCP\JSON::checkAdminUser(); |
||||
$isPersonal = false; |
||||
} |
||||
|
||||
OC_Mount_Config::removeMountPoint((string)$_POST['mountPoint'], (string)$_POST['mountType'], (string)$_POST['applicable'], $isPersonal); |
@ -0,0 +1,156 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud - files_external |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. See the COPYING file. |
||||
* |
||||
* @author Vincent Petry <pvince81@owncloud.com> |
||||
* @copyright Vincent Petry 2015 |
||||
*/ |
||||
|
||||
namespace OCA\Files_External\Controller; |
||||
|
||||
|
||||
use \OCP\IConfig; |
||||
use \OCP\IUserSession; |
||||
use \OCP\IRequest; |
||||
use \OCP\IL10N; |
||||
use \OCP\AppFramework\Http\DataResponse; |
||||
use \OCP\AppFramework\Controller; |
||||
use \OCP\AppFramework\Http; |
||||
use \OCA\Files_external\Service\GlobalStoragesService; |
||||
use \OCA\Files_external\NotFoundException; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
/** |
||||
* Global storages controller |
||||
*/ |
||||
class GlobalStoragesController extends StoragesController { |
||||
/** |
||||
* Creates a new global storages controller. |
||||
* |
||||
* @param string $AppName application name |
||||
* @param IRequest $request request object |
||||
* @param IL10N $l10n l10n service |
||||
* @param GlobalStoragesService $globalStoragesService storage service |
||||
*/ |
||||
public function __construct( |
||||
$AppName, |
||||
IRequest $request, |
||||
IL10N $l10n, |
||||
GlobalStoragesService $globalStoragesService |
||||
) { |
||||
parent::__construct( |
||||
$AppName, |
||||
$request, |
||||
$l10n, |
||||
$globalStoragesService |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Create an external storage entry. |
||||
* |
||||
* @param string $mountPoint storage mount point |
||||
* @param string $backendClass backend class name |
||||
* @param array $backendOptions backend-specific options |
||||
* @param array $mountOptions mount-specific options |
||||
* @param array $applicableUsers users for which to mount the storage |
||||
* @param array $applicableGroups groups for which to mount the storage |
||||
* @param int $priority priority |
||||
* |
||||
* @return DataResponse |
||||
*/ |
||||
public function create( |
||||
$mountPoint, |
||||
$backendClass, |
||||
$backendOptions, |
||||
$mountOptions, |
||||
$applicableUsers, |
||||
$applicableGroups, |
||||
$priority |
||||
) { |
||||
$newStorage = new StorageConfig(); |
||||
$newStorage->setMountPoint($mountPoint); |
||||
$newStorage->setBackendClass($backendClass); |
||||
$newStorage->setBackendOptions($backendOptions); |
||||
$newStorage->setMountOptions($mountOptions); |
||||
$newStorage->setApplicableUsers($applicableUsers); |
||||
$newStorage->setApplicableGroups($applicableGroups); |
||||
$newStorage->setPriority($priority); |
||||
|
||||
$response = $this->validate($newStorage); |
||||
if (!empty($response)) { |
||||
return $response; |
||||
} |
||||
|
||||
$newStorage = $this->service->addStorage($newStorage); |
||||
|
||||
$this->updateStorageStatus($newStorage); |
||||
|
||||
return new DataResponse( |
||||
$newStorage, |
||||
Http::STATUS_CREATED |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Update an external storage entry. |
||||
* |
||||
* @param int $id storage id |
||||
* @param string $mountPoint storage mount point |
||||
* @param string $backendClass backend class name |
||||
* @param array $backendOptions backend-specific options |
||||
* @param array $mountOptions mount-specific options |
||||
* @param array $applicableUsers users for which to mount the storage |
||||
* @param array $applicableGroups groups for which to mount the storage |
||||
* @param int $priority priority |
||||
* |
||||
* @return DataResponse |
||||
*/ |
||||
public function update( |
||||
$id, |
||||
$mountPoint, |
||||
$backendClass, |
||||
$backendOptions, |
||||
$mountOptions, |
||||
$applicableUsers, |
||||
$applicableGroups, |
||||
$priority |
||||
) { |
||||
$storage = new StorageConfig($id); |
||||
$storage->setMountPoint($mountPoint); |
||||
$storage->setBackendClass($backendClass); |
||||
$storage->setBackendOptions($backendOptions); |
||||
$storage->setMountOptions($mountOptions); |
||||
$storage->setApplicableUsers($applicableUsers); |
||||
$storage->setApplicableGroups($applicableGroups); |
||||
$storage->setPriority($priority); |
||||
|
||||
$response = $this->validate($storage); |
||||
if (!empty($response)) { |
||||
return $response; |
||||
} |
||||
|
||||
try { |
||||
$storage = $this->service->updateStorage($storage); |
||||
} catch (NotFoundException $e) { |
||||
return new DataResponse( |
||||
[ |
||||
'message' => (string)$this->l10n->t('Storage with id "%i" not found', array($id)) |
||||
], |
||||
Http::STATUS_NOT_FOUND |
||||
); |
||||
} |
||||
|
||||
$this->updateStorageStatus($storage); |
||||
|
||||
return new DataResponse( |
||||
$storage, |
||||
Http::STATUS_OK |
||||
); |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,167 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud - files_external |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. See the COPYING file. |
||||
* |
||||
* @author Vincent Petry <pvince81@owncloud.com> |
||||
* @copyright Vincent Petry 2014 |
||||
*/ |
||||
|
||||
namespace OCA\Files_External\Controller; |
||||
|
||||
|
||||
use \OCP\IConfig; |
||||
use \OCP\IUserSession; |
||||
use \OCP\IRequest; |
||||
use \OCP\IL10N; |
||||
use \OCP\AppFramework\Http\DataResponse; |
||||
use \OCP\AppFramework\Controller; |
||||
use \OCP\AppFramework\Http; |
||||
use \OCA\Files_external\Service\StoragesService; |
||||
use \OCA\Files_external\NotFoundException; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
/** |
||||
* Base class for storages controllers |
||||
*/ |
||||
abstract class StoragesController extends Controller { |
||||
|
||||
/** |
||||
* L10N service |
||||
* |
||||
* @var IL10N |
||||
*/ |
||||
protected $l10n; |
||||
|
||||
/** |
||||
* Storages service |
||||
* |
||||
* @var StoragesService |
||||
*/ |
||||
protected $service; |
||||
|
||||
/** |
||||
* Creates a new storages controller. |
||||
* |
||||
* @param string $AppName application name |
||||
* @param IRequest $request request object |
||||
* @param IL10N $l10n l10n service |
||||
* @param StoragesService $storagesService storage service |
||||
*/ |
||||
public function __construct( |
||||
$AppName, |
||||
IRequest $request, |
||||
IL10N $l10n, |
||||
StoragesService $storagesService |
||||
) { |
||||
parent::__construct($AppName, $request); |
||||
$this->l10n = $l10n; |
||||
$this->service = $storagesService; |
||||
} |
||||
|
||||
/** |
||||
* Validate storage config |
||||
* |
||||
* @param StorageConfig $storage storage config |
||||
* |
||||
* @return DataResponse|null returns response in case of validation error |
||||
*/ |
||||
protected function validate(StorageConfig $storage) { |
||||
$mountPoint = $storage->getMountPoint(); |
||||
if ($mountPoint === '' || $mountPoint === '/') { |
||||
return new DataResponse( |
||||
array( |
||||
'message' => (string)$this->l10n->t('Invalid mount point') |
||||
), |
||||
Http::STATUS_UNPROCESSABLE_ENTITY |
||||
); |
||||
} |
||||
|
||||
// TODO: validate that other attrs are set |
||||
|
||||
$backends = \OC_Mount_Config::getBackends(); |
||||
if (!isset($backends[$storage->getBackendClass()])) { |
||||
// invalid backend |
||||
return new DataResponse( |
||||
array( |
||||
'message' => (string)$this->l10n->t('Invalid storage backend "%s"', array($storage->getBackendClass())) |
||||
), |
||||
Http::STATUS_UNPROCESSABLE_ENTITY |
||||
); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Check whether the given storage is available / valid. |
||||
* |
||||
* Note that this operation can be time consuming depending |
||||
* on whether the remote storage is available or not. |
||||
* |
||||
* @param StorageConfig $storage storage configuration |
||||
*/ |
||||
protected function updateStorageStatus(StorageConfig &$storage) { |
||||
// update status (can be time-consuming) |
||||
$storage->setStatus( |
||||
\OC_Mount_Config::getBackendStatus( |
||||
$storage->getBackendClass(), |
||||
$storage->getBackendOptions(), |
||||
false |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Get an external storage entry. |
||||
* |
||||
* @param int $id storage id |
||||
* |
||||
* @return DataResponse |
||||
*/ |
||||
public function show($id) { |
||||
try { |
||||
$storage = $this->service->getStorage($id); |
||||
|
||||
$this->updateStorageStatus($storage); |
||||
} catch (NotFoundException $e) { |
||||
return new DataResponse( |
||||
[ |
||||
'message' => (string)$this->l10n->t('Storage with id "%i" not found', array($id)) |
||||
], |
||||
Http::STATUS_NOT_FOUND |
||||
); |
||||
} |
||||
|
||||
return new DataResponse( |
||||
$storage, |
||||
Http::STATUS_OK |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Deletes the storage with the given id. |
||||
* |
||||
* @param int $id storage id |
||||
* |
||||
* @return DataResponse |
||||
*/ |
||||
public function destroy($id) { |
||||
try { |
||||
$this->service->removeStorage($id); |
||||
} catch (NotFoundException $e) { |
||||
return new DataResponse( |
||||
[ |
||||
'message' => (string)$this->l10n->t('Storage with id "%i" not found', array($id)) |
||||
], |
||||
Http::STATUS_NOT_FOUND |
||||
); |
||||
} |
||||
|
||||
return new DataResponse([], Http::STATUS_NO_CONTENT); |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,191 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud - files_external |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. See the COPYING file. |
||||
* |
||||
* @author Vincent Petry <pvince81@owncloud.com> |
||||
* @copyright Vincent Petry 2015 |
||||
*/ |
||||
|
||||
namespace OCA\Files_External\Controller; |
||||
|
||||
|
||||
use \OCP\IConfig; |
||||
use \OCP\IUserSession; |
||||
use \OCP\IRequest; |
||||
use \OCP\IL10N; |
||||
use \OCP\AppFramework\Http\DataResponse; |
||||
use \OCP\AppFramework\Controller; |
||||
use \OCP\AppFramework\Http; |
||||
use \OCA\Files_external\Service\UserStoragesService; |
||||
use \OCA\Files_external\NotFoundException; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
/** |
||||
* User storages controller |
||||
*/ |
||||
class UserStoragesController extends StoragesController { |
||||
/** |
||||
* Creates a new user storages controller. |
||||
* |
||||
* @param string $AppName application name |
||||
* @param IRequest $request request object |
||||
* @param IL10N $l10n l10n service |
||||
* @param UserStoragesService $userStoragesService storage service |
||||
*/ |
||||
public function __construct( |
||||
$AppName, |
||||
IRequest $request, |
||||
IL10N $l10n, |
||||
UserStoragesService $userStoragesService |
||||
) { |
||||
parent::__construct( |
||||
$AppName, |
||||
$request, |
||||
$l10n, |
||||
$userStoragesService |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Validate storage config |
||||
* |
||||
* @param StorageConfig $storage storage config |
||||
* |
||||
* @return DataResponse|null returns response in case of validation error |
||||
*/ |
||||
protected function validate(StorageConfig $storage) { |
||||
$result = parent::validate($storage); |
||||
|
||||
if ($result != null) { |
||||
return $result; |
||||
} |
||||
|
||||
// Verify that the mount point applies for the current user |
||||
// Prevent non-admin users from mounting local storage and other disabled backends |
||||
$allowedBackends = \OC_Mount_Config::getPersonalBackends(); |
||||
if (!isset($allowedBackends[$storage->getBackendClass()])) { |
||||
return new DataResponse( |
||||
array( |
||||
'message' => (string)$this->l10n->t('Invalid storage backend "%s"', array($storage->getBackendClass())) |
||||
), |
||||
Http::STATUS_UNPROCESSABLE_ENTITY |
||||
); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Return storage |
||||
* |
||||
* @NoAdminRequired |
||||
* |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function show($id) { |
||||
return parent::show($id); |
||||
} |
||||
|
||||
/** |
||||
* Create an external storage entry. |
||||
* |
||||
* @param string $mountPoint storage mount point |
||||
* @param string $backendClass backend class name |
||||
* @param array $backendOptions backend-specific options |
||||
* @param array $mountOptions backend-specific mount options |
||||
* |
||||
* @return DataResponse |
||||
* |
||||
* @NoAdminRequired |
||||
*/ |
||||
public function create( |
||||
$mountPoint, |
||||
$backendClass, |
||||
$backendOptions, |
||||
$mountOptions |
||||
) { |
||||
$newStorage = new StorageConfig(); |
||||
$newStorage->setMountPoint($mountPoint); |
||||
$newStorage->setBackendClass($backendClass); |
||||
$newStorage->setBackendOptions($backendOptions); |
||||
$newStorage->setMountOptions($mountOptions); |
||||
|
||||
$response = $this->validate($newStorage); |
||||
if (!empty($response)) { |
||||
return $response; |
||||
} |
||||
|
||||
$newStorage = $this->service->addStorage($newStorage); |
||||
$this->updateStorageStatus($newStorage); |
||||
|
||||
return new DataResponse( |
||||
$newStorage, |
||||
Http::STATUS_CREATED |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Update an external storage entry. |
||||
* |
||||
* @param int $id storage id |
||||
* @param string $mountPoint storage mount point |
||||
* @param string $backendClass backend class name |
||||
* @param array $backendOptions backend-specific options |
||||
* @param array $mountOptions backend-specific mount options |
||||
* |
||||
* @return DataResponse |
||||
* |
||||
* @NoAdminRequired |
||||
*/ |
||||
public function update( |
||||
$id, |
||||
$mountPoint, |
||||
$backendClass, |
||||
$backendOptions, |
||||
$mountOptions |
||||
) { |
||||
$storage = new StorageConfig($id); |
||||
$storage->setMountPoint($mountPoint); |
||||
$storage->setBackendClass($backendClass); |
||||
$storage->setBackendOptions($backendOptions); |
||||
$storage->setMountOptions($mountOptions); |
||||
|
||||
$response = $this->validate($storage); |
||||
if (!empty($response)) { |
||||
return $response; |
||||
} |
||||
|
||||
try { |
||||
$storage = $this->service->updateStorage($storage); |
||||
} catch (NotFoundException $e) { |
||||
return new DataResponse( |
||||
[ |
||||
'message' => (string)$this->l10n->t('Storage with id "%i" not found', array($id)) |
||||
], |
||||
Http::STATUS_NOT_FOUND |
||||
); |
||||
} |
||||
|
||||
$this->updateStorageStatus($storage); |
||||
|
||||
return new DataResponse( |
||||
$storage, |
||||
Http::STATUS_OK |
||||
); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Delete storage |
||||
* |
||||
* @NoAdminRequired |
||||
* |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function destroy($id) { |
||||
return parent::destroy($id); |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
namespace OCA\Files_external; |
||||
|
||||
/** |
||||
* Storage is not found |
||||
*/ |
||||
class NotFoundException extends \Exception { |
||||
} |
@ -0,0 +1,292 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
namespace OCA\Files_external\Lib; |
||||
|
||||
/** |
||||
* External storage configuration |
||||
*/ |
||||
class StorageConfig implements \JsonSerializable { |
||||
|
||||
/** |
||||
* Storage config id |
||||
* |
||||
* @var int |
||||
*/ |
||||
private $id; |
||||
|
||||
/** |
||||
* Backend class name |
||||
* |
||||
* @var string |
||||
*/ |
||||
private $backendClass; |
||||
|
||||
/** |
||||
* Backend options |
||||
* |
||||
* @var array |
||||
*/ |
||||
private $backendOptions = []; |
||||
|
||||
/** |
||||
* Mount point path, relative to the user's "files" folder |
||||
* |
||||
* @var string |
||||
*/ |
||||
private $mountPoint; |
||||
|
||||
/** |
||||
* Storage status |
||||
* |
||||
* @var int |
||||
*/ |
||||
private $status; |
||||
|
||||
/** |
||||
* Priority |
||||
* |
||||
* @var int |
||||
*/ |
||||
private $priority; |
||||
|
||||
/** |
||||
* List of users who have access to this storage |
||||
* |
||||
* @var array |
||||
*/ |
||||
private $applicableUsers = []; |
||||
|
||||
/** |
||||
* List of groups that have access to this storage |
||||
* |
||||
* @var array |
||||
*/ |
||||
private $applicableGroups = []; |
||||
|
||||
/** |
||||
* Mount-specific options |
||||
* |
||||
* @var array |
||||
*/ |
||||
private $mountOptions = []; |
||||
|
||||
/** |
||||
* Creates a storage config |
||||
* |
||||
* @param int|null $id config id or null for a new config |
||||
*/ |
||||
public function __construct($id = null) { |
||||
$this->id = $id; |
||||
} |
||||
|
||||
/** |
||||
* Returns the configuration id |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function getId() { |
||||
return $this->id; |
||||
} |
||||
|
||||
/** |
||||
* Sets the configuration id |
||||
* |
||||
* @param int $id configuration id |
||||
*/ |
||||
public function setId($id) { |
||||
$this->id = $id; |
||||
} |
||||
|
||||
/** |
||||
* Returns mount point path relative to the user's |
||||
* "files" folder. |
||||
* |
||||
* @return string path |
||||
*/ |
||||
public function getMountPoint() { |
||||
return $this->mountPoint; |
||||
} |
||||
|
||||
/** |
||||
* Sets mount point path relative to the user's |
||||
* "files" folder. |
||||
* The path will be normalized. |
||||
* |
||||
* @param string $mountPoint path |
||||
*/ |
||||
public function setMountPoint($mountPoint) { |
||||
$this->mountPoint = \OC\Files\Filesystem::normalizePath($mountPoint); |
||||
} |
||||
|
||||
/** |
||||
* Returns the external storage backend class name |
||||
* |
||||
* @return string external storage backend class name |
||||
*/ |
||||
public function getBackendClass() { |
||||
return $this->backendClass; |
||||
} |
||||
|
||||
/** |
||||
* Sets the external storage backend class name |
||||
* |
||||
* @param string external storage backend class name |
||||
*/ |
||||
public function setBackendClass($backendClass) { |
||||
$this->backendClass = $backendClass; |
||||
} |
||||
|
||||
/** |
||||
* Returns the external storage backend-specific options |
||||
* |
||||
* @return array backend options |
||||
*/ |
||||
public function getBackendOptions() { |
||||
return $this->backendOptions; |
||||
} |
||||
|
||||
/** |
||||
* Sets the external storage backend-specific options |
||||
* |
||||
* @param array $backendOptions backend options |
||||
*/ |
||||
public function setBackendOptions($backendOptions) { |
||||
$this->backendOptions = $backendOptions; |
||||
} |
||||
|
||||
/** |
||||
* Returns the mount priority |
||||
* |
||||
* @return int priority |
||||
*/ |
||||
public function getPriority() { |
||||
return $this->priority; |
||||
} |
||||
|
||||
/** |
||||
* Sets the mount priotity |
||||
* |
||||
* @param int $priority priority |
||||
*/ |
||||
public function setPriority($priority) { |
||||
$this->priority = $priority; |
||||
} |
||||
|
||||
/** |
||||
* Returns the users for which to mount this storage |
||||
* |
||||
* @return array applicable users |
||||
*/ |
||||
public function getApplicableUsers() { |
||||
return $this->applicableUsers; |
||||
} |
||||
|
||||
/** |
||||
* Sets the users for which to mount this storage |
||||
* |
||||
* @param array|null $applicableUsers applicable users |
||||
*/ |
||||
public function setApplicableUsers($applicableUsers) { |
||||
if (is_null($applicableUsers)) { |
||||
$applicableUsers = []; |
||||
} |
||||
$this->applicableUsers = $applicableUsers; |
||||
} |
||||
|
||||
/** |
||||
* Returns the groups for which to mount this storage |
||||
* |
||||
* @return array applicable groups |
||||
*/ |
||||
public function getApplicableGroups() { |
||||
return $this->applicableGroups; |
||||
} |
||||
|
||||
/** |
||||
* Sets the groups for which to mount this storage |
||||
* |
||||
* @param array|null $applicableGroups applicable groups |
||||
*/ |
||||
public function setApplicableGroups($applicableGroups) { |
||||
if (is_null($applicableGroups)) { |
||||
$applicableGroups = []; |
||||
} |
||||
$this->applicableGroups = $applicableGroups; |
||||
} |
||||
|
||||
/** |
||||
* Returns the mount-specific options |
||||
* |
||||
* @return array mount specific options |
||||
*/ |
||||
public function getMountOptions() { |
||||
return $this->mountOptions; |
||||
} |
||||
|
||||
/** |
||||
* Sets the mount-specific options |
||||
* |
||||
* @param array $mountOptions applicable groups |
||||
*/ |
||||
public function setMountOptions($mountOptions) { |
||||
if (is_null($mountOptions)) { |
||||
$mountOptions = []; |
||||
} |
||||
$this->mountOptions = $mountOptions; |
||||
} |
||||
|
||||
/** |
||||
* Sets the storage status, whether the config worked last time |
||||
* |
||||
* @return int $status status |
||||
*/ |
||||
public function getStatus() { |
||||
return $this->status; |
||||
} |
||||
|
||||
/** |
||||
* Sets the storage status, whether the config worked last time |
||||
* |
||||
* @param int $status status |
||||
*/ |
||||
public function setStatus($status) { |
||||
$this->status = $status; |
||||
} |
||||
|
||||
/** |
||||
* Serialize config to JSON |
||||
* |
||||
* @return array |
||||
*/ |
||||
public function jsonSerialize() { |
||||
$result = []; |
||||
if (!is_null($this->id)) { |
||||
$result['id'] = $this->id; |
||||
} |
||||
$result['mountPoint'] = $this->mountPoint; |
||||
$result['backendClass'] = $this->backendClass; |
||||
$result['backendOptions'] = $this->backendOptions; |
||||
if (!is_null($this->priority)) { |
||||
$result['priority'] = $this->priority; |
||||
} |
||||
if (!empty($this->applicableUsers)) { |
||||
$result['applicableUsers'] = $this->applicableUsers; |
||||
} |
||||
if (!empty($this->applicableGroups)) { |
||||
$result['applicableGroups'] = $this->applicableGroups; |
||||
} |
||||
if (!empty($this->mountOptions)) { |
||||
$result['mountOptions'] = $this->mountOptions; |
||||
} |
||||
if (!is_null($this->status)) { |
||||
$result['status'] = $this->status; |
||||
} |
||||
return $result; |
||||
} |
||||
} |
@ -0,0 +1,191 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
namespace OCA\Files_external\Service; |
||||
|
||||
use \OCP\IUserSession; |
||||
use \OC\Files\Filesystem; |
||||
|
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
use \OCA\Files_external\NotFoundException; |
||||
|
||||
/** |
||||
* Service class to manage global external storages |
||||
*/ |
||||
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); |
||||
} |
||||
|
||||
\OC_Mount_Config::writeData(null, $mountPoints); |
||||
} |
||||
|
||||
/** |
||||
* Triggers $signal for all applicable users of the given |
||||
* storage |
||||
* |
||||
* @param StorageConfig $storage storage data |
||||
* @param string $signal signal to trigger |
||||
*/ |
||||
protected function triggerHooks(StorageConfig $storage, $signal) { |
||||
$applicableUsers = $storage->getApplicableUsers(); |
||||
$applicableGroups = $storage->getApplicableGroups(); |
||||
if (empty($applicableUsers) && empty($applicableGroups)) { |
||||
// raise for user "all" |
||||
$this->triggerApplicableHooks( |
||||
$signal, |
||||
$storage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
['all'] |
||||
); |
||||
return; |
||||
} |
||||
|
||||
$this->triggerApplicableHooks( |
||||
$signal, |
||||
$storage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$applicableUsers |
||||
); |
||||
$this->triggerApplicableHooks( |
||||
$signal, |
||||
$storage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
$applicableGroups |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Triggers signal_create_mount or signal_delete_mount to |
||||
* accomodate for additions/deletions in applicableUsers |
||||
* and applicableGroups fields. |
||||
* |
||||
* @param StorageConfig $oldStorage old storage config |
||||
* @param StorageConfig $newStorage new storage config |
||||
*/ |
||||
protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) { |
||||
// if mount point changed, it's like a deletion + creation |
||||
if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) { |
||||
$this->triggerHooks($oldStorage, Filesystem::signal_delete_mount); |
||||
$this->triggerHooks($newStorage, Filesystem::signal_create_mount); |
||||
return; |
||||
} |
||||
|
||||
$userAdditions = array_diff($newStorage->getApplicableUsers(), $oldStorage->getApplicableUsers()); |
||||
$userDeletions = array_diff($oldStorage->getApplicableUsers(), $newStorage->getApplicableUsers()); |
||||
$groupAdditions = array_diff($newStorage->getApplicableGroups(), $oldStorage->getApplicableGroups()); |
||||
$groupDeletions = array_diff($oldStorage->getApplicableGroups(), $newStorage->getApplicableGroups()); |
||||
|
||||
// if no applicable were set, raise a signal for "all" |
||||
if (empty($oldStorage->getApplicableUsers()) && empty($oldStorage->getApplicableGroups())) { |
||||
$this->triggerApplicableHooks( |
||||
Filesystem::signal_delete_mount, |
||||
$oldStorage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
['all'] |
||||
); |
||||
} |
||||
|
||||
// trigger delete for removed users |
||||
$this->triggerApplicableHooks( |
||||
Filesystem::signal_delete_mount, |
||||
$oldStorage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$userDeletions |
||||
); |
||||
|
||||
// trigger delete for removed groups |
||||
$this->triggerApplicableHooks( |
||||
Filesystem::signal_delete_mount, |
||||
$oldStorage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
$groupDeletions |
||||
); |
||||
|
||||
// and now add the new users |
||||
$this->triggerApplicableHooks( |
||||
Filesystem::signal_create_mount, |
||||
$newStorage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$userAdditions |
||||
); |
||||
|
||||
// and now add the new groups |
||||
$this->triggerApplicableHooks( |
||||
Filesystem::signal_create_mount, |
||||
$newStorage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
$groupAdditions |
||||
); |
||||
|
||||
// if no applicable, raise a signal for "all" |
||||
if (empty($newStorage->getApplicableUsers()) && empty($newStorage->getApplicableGroups())) { |
||||
$this->triggerApplicableHooks( |
||||
Filesystem::signal_create_mount, |
||||
$newStorage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
['all'] |
||||
); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,389 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
namespace OCA\Files_external\Service; |
||||
|
||||
use \OCP\IUserSession; |
||||
use \OC\Files\Filesystem; |
||||
|
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
use \OCA\Files_external\NotFoundException; |
||||
|
||||
/** |
||||
* Service class to manage external storages |
||||
*/ |
||||
abstract class StoragesService { |
||||
|
||||
/** |
||||
* Read legacy config data |
||||
* |
||||
* @return array list of mount configs |
||||
*/ |
||||
protected function readLegacyConfig() { |
||||
// read global config |
||||
return \OC_Mount_Config::readData(); |
||||
} |
||||
|
||||
/** |
||||
* Copy legacy storage options into the given storage config object. |
||||
* |
||||
* @param StorageConfig $storageConfig storage config to populate |
||||
* @param string $mountType mount type |
||||
* @param string $applicable applicable user or group |
||||
* @param array $storageOptions legacy storage options |
||||
* |
||||
* @return StorageConfig populated storage config |
||||
*/ |
||||
protected function populateStorageConfigWithLegacyOptions( |
||||
&$storageConfig, |
||||
$mountType, |
||||
$applicable, |
||||
$storageOptions |
||||
) { |
||||
$storageConfig->setBackendClass($storageOptions['class']); |
||||
$storageConfig->setBackendOptions($storageOptions['options']); |
||||
if (isset($storageOptions['mountOptions'])) { |
||||
$storageConfig->setMountOptions($storageOptions['mountOptions']); |
||||
} |
||||
if (isset($storageOptions['priority'])) { |
||||
$storageConfig->setPriority($storageOptions['priority']); |
||||
} |
||||
|
||||
if ($mountType === \OC_Mount_Config::MOUNT_TYPE_USER) { |
||||
$applicableUsers = $storageConfig->getApplicableUsers(); |
||||
if ($applicable !== 'all') { |
||||
$applicableUsers[] = $applicable; |
||||
$storageConfig->setApplicableUsers($applicableUsers); |
||||
} |
||||
} else if ($mountType === \OC_Mount_Config::MOUNT_TYPE_GROUP) { |
||||
$applicableGroups = $storageConfig->getApplicableGroups(); |
||||
$applicableGroups[] = $applicable; |
||||
$storageConfig->setApplicableGroups($applicableGroups); |
||||
} |
||||
return $storageConfig; |
||||
} |
||||
|
||||
/** |
||||
* Read the external storages config |
||||
* |
||||
* @return array map of storage id to storage config |
||||
*/ |
||||
protected function readConfig() { |
||||
$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 class name |
||||
* - "options": backend-specific options |
||||
* - "mountOptions": mount-specific options (ex: disable previews, scanner, etc) |
||||
*/ |
||||
|
||||
// group by storage id |
||||
$storages = []; |
||||
|
||||
// for storages without id (legacy), group by config hash for |
||||
// later processing |
||||
$storagesWithConfigHash = []; |
||||
|
||||
foreach ($mountPoints as $mountType => $applicables) { |
||||
foreach ($applicables as $applicable => $mountPaths) { |
||||
foreach ($mountPaths as $rootMountPath => $storageOptions) { |
||||
$currentStorage = null; |
||||
|
||||
/** |
||||
* Flag whether the config that was read already has an id. |
||||
* If not, it will use a config hash instead and generate |
||||
* a proper id later |
||||
* |
||||
* @var boolean |
||||
*/ |
||||
$hasId = false; |
||||
|
||||
// the root mount point is in the format "/$user/files/the/mount/point" |
||||
// we remove the "/$user/files" prefix |
||||
$parts = explode('/', trim($rootMountPath, '/'), 3); |
||||
if (count($parts) < 3) { |
||||
// something went wrong, skip |
||||
\OCP\Util::writeLog( |
||||
'files_external', |
||||
'Could not parse mount point "' . $rootMountPath . '"', |
||||
\OCP\Util::ERROR |
||||
); |
||||
continue; |
||||
} |
||||
|
||||
$relativeMountPath = $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['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); |
||||
} |
||||
|
||||
$this->populateStorageConfigWithLegacyOptions( |
||||
$currentStorage, |
||||
$mountType, |
||||
$applicable, |
||||
$storageOptions |
||||
); |
||||
|
||||
if ($hasId) { |
||||
$storages[$configId] = $currentStorage; |
||||
} else { |
||||
$storagesWithConfigHash[$configId] = $currentStorage; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// process storages with config hash, they must get a real id |
||||
if (!empty($storagesWithConfigHash)) { |
||||
$nextId = $this->generateNextId($storages); |
||||
foreach ($storagesWithConfigHash as $storage) { |
||||
$storage->setId($nextId); |
||||
$storages[$nextId] = $storage; |
||||
$nextId++; |
||||
} |
||||
|
||||
// re-save the config with the generated ids |
||||
$this->writeConfig($storages); |
||||
} |
||||
|
||||
return $storages; |
||||
} |
||||
|
||||
/** |
||||
* 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(), |
||||
'class' => $storageConfig->getBackendClass(), |
||||
'options' => $storageConfig->getBackendOptions(), |
||||
]; |
||||
|
||||
if (!is_null($storageConfig->getPriority())) { |
||||
$options['priority'] = $storageConfig->getPriority(); |
||||
} |
||||
if (!empty($storageConfig->getMountOptions())) { |
||||
$options['mountOptions'] = $storageConfig->getMountOptions(); |
||||
} |
||||
|
||||
$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 |
||||
* |
||||
* @param int $id storage id |
||||
* |
||||
* @return StorageConfig |
||||
* @throws NotFoundException if the storage with the given id was not found |
||||
*/ |
||||
public function getStorage($id) { |
||||
$allStorages = $this->readConfig(); |
||||
|
||||
if (!isset($allStorages[$id])) { |
||||
throw new NotFoundException('Storage with id "' . $id . '" not found'); |
||||
} |
||||
|
||||
return $allStorages[$id]; |
||||
} |
||||
|
||||
/** |
||||
* Gets all storages |
||||
* |
||||
* @return array array of storage configs |
||||
*/ |
||||
public function getAllStorages() { |
||||
return $this->readConfig(); |
||||
} |
||||
|
||||
/** |
||||
* Add new storage to the configuration |
||||
* |
||||
* @param array $newStorage storage attributes |
||||
* |
||||
* @return StorageConfig storage config, with added id |
||||
*/ |
||||
public function addStorage(StorageConfig $newStorage) { |
||||
$allStorages = $this->readConfig(); |
||||
|
||||
$configId = $this->generateNextId($allStorages); |
||||
$newStorage->setId($configId); |
||||
|
||||
// add new storage |
||||
$allStorages[$configId] = $newStorage; |
||||
|
||||
$this->writeConfig($allStorages); |
||||
|
||||
$this->triggerHooks($newStorage, Filesystem::signal_create_mount); |
||||
|
||||
$newStorage->setStatus(\OC_Mount_Config::STATUS_SUCCESS); |
||||
return $newStorage; |
||||
} |
||||
|
||||
/** |
||||
* Triggers the given hook signal for all the applicables given |
||||
* |
||||
* @param string $signal signal |
||||
* @param string $mountPoint hook mount pount param |
||||
* @param string $mountType hook mount type param |
||||
* @param array $applicableArray array of applicable users/groups for which to trigger the hook |
||||
*/ |
||||
protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray) { |
||||
foreach ($applicableArray as $applicable) { |
||||
\OC_Hook::emit( |
||||
Filesystem::CLASSNAME, |
||||
$signal, |
||||
[ |
||||
Filesystem::signal_param_path => $mountPoint, |
||||
Filesystem::signal_param_mount_type => $mountType, |
||||
Filesystem::signal_param_users => $applicable, |
||||
] |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Triggers $signal for all applicable users of the given |
||||
* storage |
||||
* |
||||
* @param StorageConfig $storage storage data |
||||
* @param string $signal signal to trigger |
||||
*/ |
||||
abstract protected function triggerHooks(StorageConfig $storage, $signal); |
||||
|
||||
/** |
||||
* Triggers signal_create_mount or signal_delete_mount to |
||||
* accomodate for additions/deletions in applicableUsers |
||||
* and applicableGroups fields. |
||||
* |
||||
* @param StorageConfig $oldStorage old storage data |
||||
* @param StorageConfig $newStorage new storage data |
||||
*/ |
||||
abstract protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage); |
||||
|
||||
/** |
||||
* Update storage to the configuration |
||||
* |
||||
* @param StorageConfig $updatedStorage storage attributes |
||||
* |
||||
* @return StorageConfig storage config |
||||
* @throws NotFoundException if the given storage does not exist in the config |
||||
*/ |
||||
public function updateStorage(StorageConfig $updatedStorage) { |
||||
$allStorages = $this->readConfig(); |
||||
|
||||
$id = $updatedStorage->getId(); |
||||
if (!isset($allStorages[$id])) { |
||||
throw new NotFoundException('Storage with id "' . $id . '" not found'); |
||||
} |
||||
|
||||
$oldStorage = $allStorages[$id]; |
||||
$allStorages[$id] = $updatedStorage; |
||||
|
||||
$this->writeConfig($allStorages); |
||||
|
||||
$this->triggerChangeHooks($oldStorage, $updatedStorage); |
||||
|
||||
return $this->getStorage($id); |
||||
} |
||||
|
||||
/** |
||||
* Delete the storage with the given id. |
||||
* |
||||
* @param int $id storage id |
||||
* |
||||
* @throws NotFoundException if no storage was found with the given id |
||||
*/ |
||||
public function removeStorage($id) { |
||||
$allStorages = $this->readConfig(); |
||||
|
||||
if (!isset($allStorages[$id])) { |
||||
throw new NotFoundException('Storage with id "' . $id . '" not found'); |
||||
} |
||||
|
||||
$deletedStorage = $allStorages[$id]; |
||||
unset($allStorages[$id]); |
||||
|
||||
$this->writeConfig($allStorages); |
||||
|
||||
$this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount); |
||||
} |
||||
|
||||
/** |
||||
* 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); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,150 @@ |
||||
<?php |
||||
/** |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. |
||||
* See the COPYING-README file. |
||||
*/ |
||||
|
||||
namespace OCA\Files_external\Service; |
||||
|
||||
use \OCP\IUserSession; |
||||
use \OC\Files\Filesystem; |
||||
|
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
use \OCA\Files_external\NotFoundException; |
||||
|
||||
/** |
||||
* Service class to manage user external storages |
||||
* (aka personal storages) |
||||
*/ |
||||
class UserStoragesService extends StoragesService { |
||||
|
||||
/** |
||||
* User session |
||||
* |
||||
* @var IUserSession |
||||
*/ |
||||
private $userSession; |
||||
|
||||
/** |
||||
* Create a user storages service |
||||
* |
||||
* @param IUserSession $userSession user session |
||||
*/ |
||||
public function __construct( |
||||
IUserSession $userSession |
||||
) { |
||||
$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); |
||||
} |
||||
|
||||
/** |
||||
* Read the external storages config |
||||
* |
||||
* @return array map of storage id to storage config |
||||
*/ |
||||
protected function readConfig() { |
||||
$user = $this->userSession->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->userSession->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); |
||||
} |
||||
|
||||
\OC_Mount_Config::writeData($user, $mountPoints); |
||||
} |
||||
|
||||
/** |
||||
* Triggers $signal for all applicable users of the given |
||||
* storage |
||||
* |
||||
* @param StorageConfig $storage storage data |
||||
* @param string $signal signal to trigger |
||||
*/ |
||||
protected function triggerHooks(StorageConfig $storage, $signal) { |
||||
$user = $this->userSession->getUser()->getUID(); |
||||
|
||||
// trigger hook for the current user |
||||
$this->triggerApplicableHooks( |
||||
$signal, |
||||
$storage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
[$user] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Triggers signal_create_mount or signal_delete_mount to |
||||
* accomodate for additions/deletions in applicableUsers |
||||
* and applicableGroups fields. |
||||
* |
||||
* @param StorageConfig $oldStorage old storage data |
||||
* @param StorageConfig $newStorage new storage data |
||||
*/ |
||||
protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) { |
||||
// if mount point changed, it's like a deletion + creation |
||||
if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) { |
||||
$this->triggerHooks($oldStorage, Filesystem::signal_delete_mount); |
||||
$this->triggerHooks($newStorage, Filesystem::signal_create_mount); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_external\Tests\Controller; |
||||
|
||||
use \OCA\Files_external\Controller\GlobalStoragesController; |
||||
use \OCA\Files_external\Service\GlobalStoragesService; |
||||
use \OCP\AppFramework\Http; |
||||
use \OCA\Files_external\NotFoundException; |
||||
|
||||
class GlobalStoragesControllerTest extends StoragesControllerTest { |
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->service = $this->getMock('\OCA\Files_external\Service\GlobalStoragesService'); |
||||
|
||||
$this->controller = new GlobalStoragesController( |
||||
'files_external', |
||||
$this->getMock('\OCP\IRequest'), |
||||
$this->getMock('\OCP\IL10N'), |
||||
$this->service |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,225 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_external\Tests\Controller; |
||||
|
||||
use \OCP\AppFramework\Http; |
||||
|
||||
use \OCA\Files_external\Controller\GlobalStoragesController; |
||||
use \OCA\Files_external\Service\GlobalStoragesService; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
use \OCA\Files_external\NotFoundException; |
||||
|
||||
abstract class StoragesControllerTest extends \Test\TestCase { |
||||
|
||||
/** |
||||
* @var GlobalStoragesController |
||||
*/ |
||||
protected $controller; |
||||
|
||||
/** |
||||
* @var GlobalStoragesService |
||||
*/ |
||||
protected $service; |
||||
|
||||
public function setUp() { |
||||
\OC_Mount_Config::$skipTest = true; |
||||
} |
||||
|
||||
public function tearDown() { |
||||
\OC_Mount_Config::$skipTest = false; |
||||
} |
||||
|
||||
public function testAddStorage() { |
||||
$storageConfig = new StorageConfig(1); |
||||
$storageConfig->setMountPoint('mount'); |
||||
|
||||
$this->service->expects($this->once()) |
||||
->method('addStorage') |
||||
->will($this->returnValue($storageConfig)); |
||||
|
||||
$response = $this->controller->create( |
||||
'mount', |
||||
'\OC\Files\Storage\SMB', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$data = $response->getData(); |
||||
$this->assertEquals($storageConfig, $data); |
||||
$this->assertEquals(Http::STATUS_CREATED, $response->getStatus()); |
||||
} |
||||
|
||||
public function testUpdateStorage() { |
||||
$storageConfig = new StorageConfig(1); |
||||
$storageConfig->setMountPoint('mount'); |
||||
|
||||
$this->service->expects($this->once()) |
||||
->method('updateStorage') |
||||
->will($this->returnValue($storageConfig)); |
||||
|
||||
$response = $this->controller->update( |
||||
1, |
||||
'mount', |
||||
'\OC\Files\Storage\SMB', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$data = $response->getData(); |
||||
$this->assertEquals($storageConfig, $data); |
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus()); |
||||
} |
||||
|
||||
function mountPointNamesProvider() { |
||||
return array( |
||||
array(''), |
||||
array('/'), |
||||
array('//'), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider mountPointNamesProvider |
||||
*/ |
||||
public function testAddOrUpdateStorageInvalidMountPoint($mountPoint) { |
||||
$this->service->expects($this->never()) |
||||
->method('addStorage'); |
||||
$this->service->expects($this->never()) |
||||
->method('updateStorage'); |
||||
|
||||
$response = $this->controller->create( |
||||
$mountPoint, |
||||
'\OC\Files\Storage\SMB', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); |
||||
|
||||
$response = $this->controller->update( |
||||
1, |
||||
$mountPoint, |
||||
'\OC\Files\Storage\SMB', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); |
||||
} |
||||
|
||||
public function testAddOrUpdateStorageInvalidBackend() { |
||||
$this->service->expects($this->never()) |
||||
->method('addStorage'); |
||||
$this->service->expects($this->never()) |
||||
->method('updateStorage'); |
||||
|
||||
$response = $this->controller->create( |
||||
'mount', |
||||
'\OC\Files\Storage\InvalidStorage', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); |
||||
|
||||
$response = $this->controller->update( |
||||
1, |
||||
'mount', |
||||
'\OC\Files\Storage\InvalidStorage', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); |
||||
} |
||||
|
||||
public function testUpdateStorageNonExisting() { |
||||
$this->service->expects($this->once()) |
||||
->method('updateStorage') |
||||
->will($this->throwException(new NotFoundException())); |
||||
|
||||
$response = $this->controller->update( |
||||
255, |
||||
'mount', |
||||
'\OC\Files\Storage\SMB', |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); |
||||
} |
||||
|
||||
public function testDeleteStorage() { |
||||
$this->service->expects($this->once()) |
||||
->method('removeStorage'); |
||||
|
||||
$response = $this->controller->destroy(1); |
||||
$this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus()); |
||||
} |
||||
|
||||
public function testDeleteStorageNonExisting() { |
||||
$this->service->expects($this->once()) |
||||
->method('removeStorage') |
||||
->will($this->throwException(new NotFoundException())); |
||||
|
||||
$response = $this->controller->destroy(255); |
||||
$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); |
||||
} |
||||
|
||||
public function testGetStorage() { |
||||
$storageConfig = new StorageConfig(1); |
||||
$storageConfig->setMountPoint('test'); |
||||
$storageConfig->setBackendClass('\OC\Files\Storage\SMB'); |
||||
$storageConfig->setBackendOptions(['user' => 'test', 'password', 'password123']); |
||||
$storageConfig->setMountOptions(['priority' => false]); |
||||
|
||||
$this->service->expects($this->once()) |
||||
->method('getStorage') |
||||
->with(1) |
||||
->will($this->returnValue($storageConfig)); |
||||
$response = $this->controller->show(1); |
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus()); |
||||
$this->assertEquals($storageConfig, $response->getData()); |
||||
} |
||||
} |
@ -0,0 +1,114 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_external\Tests\Controller; |
||||
|
||||
use \OCA\Files_external\Controller\UserStoragesController; |
||||
use \OCA\Files_external\Service\UserStoragesService; |
||||
use \OCP\AppFramework\Http; |
||||
use \OCA\Files_external\NotFoundException; |
||||
|
||||
class UserStoragesControllerTest extends StoragesControllerTest { |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
private $oldAllowedBackends; |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->service = $this->getMockBuilder('\OCA\Files_external\Service\UserStoragesService') |
||||
->disableOriginalConstructor() |
||||
->getMock(); |
||||
|
||||
$this->controller = new UserStoragesController( |
||||
'files_external', |
||||
$this->getMock('\OCP\IRequest'), |
||||
$this->getMock('\OCP\IL10N'), |
||||
$this->service |
||||
); |
||||
|
||||
$config = \OC::$server->getConfig(); |
||||
|
||||
$this->oldAllowedBackends = $config->getAppValue( |
||||
'files_external', |
||||
'user_mounting_backends', |
||||
'' |
||||
); |
||||
$config->setAppValue( |
||||
'files_external', |
||||
'user_mounting_backends', |
||||
'\OC\Files\Storage\SMB' |
||||
); |
||||
} |
||||
|
||||
public function tearDown() { |
||||
$config = \OC::$server->getConfig(); |
||||
$config->setAppValue( |
||||
'files_external', |
||||
'user_mounting_backends', |
||||
$this->oldAllowedBackends |
||||
); |
||||
parent::tearDown(); |
||||
} |
||||
|
||||
function disallowedBackendClassProvider() { |
||||
return array( |
||||
array('\OC\Files\Storage\Local'), |
||||
array('\OC\Files\Storage\FTP'), |
||||
); |
||||
} |
||||
/** |
||||
* @dataProvider disallowedBackendClassProvider |
||||
*/ |
||||
public function testAddOrUpdateStorageDisallowedBackend($backendClass) { |
||||
$this->service->expects($this->never()) |
||||
->method('addStorage'); |
||||
$this->service->expects($this->never()) |
||||
->method('updateStorage'); |
||||
|
||||
$response = $this->controller->create( |
||||
'mount', |
||||
$backendClass, |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); |
||||
|
||||
$response = $this->controller->update( |
||||
1, |
||||
'mount', |
||||
$backendClass, |
||||
array(), |
||||
[], |
||||
[], |
||||
[], |
||||
null |
||||
); |
||||
|
||||
$this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,167 @@ |
||||
/* |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 |
||||
* or later. |
||||
* |
||||
* See the COPYING-README file. |
||||
* |
||||
*/ |
||||
|
||||
describe('OCA.External.Settings tests', function() { |
||||
var clock; |
||||
var select2Stub; |
||||
var select2ApplicableUsers; |
||||
|
||||
beforeEach(function() { |
||||
clock = sinon.useFakeTimers(); |
||||
select2Stub = sinon.stub($.fn, 'select2', function(args) { |
||||
if (args === 'val') { |
||||
return select2ApplicableUsers; |
||||
} |
||||
return { |
||||
on: function() {} |
||||
}; |
||||
}); |
||||
|
||||
// view still requires an existing DOM table
|
||||
$('#testArea').append( |
||||
'<table id="externalStorage" data-admin="true">' + |
||||
'<thead></thead>' + |
||||
'<tbody>' + |
||||
'<tr id="addMountPoint" data-id="">' + |
||||
'<td class="status"></td>' + |
||||
'<td class="mountPoint"><input type="text" name="mountPoint"/></td>' + |
||||
'<td class="backend">' + |
||||
'<select class="selectBackend">' + |
||||
'<option disable selected>Add storage</option>' + |
||||
'<option value="\\OC\\TestBackend">Test Backend</option>' + |
||||
'<option value="\\OC\\AnotherTestBackend">Another Test Backend</option>' + |
||||
'</select>' + |
||||
'</td>' + |
||||
'<td class="configuration"></td>' + |
||||
'<td class="applicable">' + |
||||
'<input type="hidden" class="applicableUsers">' + |
||||
'</td>' + |
||||
'<td><img alt="Delete" title="Delete" class="svg action"/></td>' + |
||||
'</tr>' + |
||||
'</tbody>' + |
||||
'</table>' |
||||
); |
||||
// these are usually appended into the data attribute
|
||||
// within the DOM by the server template
|
||||
$('#externalStorage .selectBackend:first').data('configurations', { |
||||
'\\OC\\TestBackend': { |
||||
'backend': 'Test Backend Name', |
||||
'configuration': { |
||||
'field1': 'Display Name 1', |
||||
'field2': '&Display Name 2' |
||||
}, |
||||
'priority': 11 |
||||
}, |
||||
'\\OC\\AnotherTestBackend': { |
||||
'backend': 'Another Test Backend Name', |
||||
'configuration': { |
||||
'field1': 'Display Name 1', |
||||
'field2': '&Display Name 2' |
||||
}, |
||||
'priority': 12 |
||||
} |
||||
} |
||||
); |
||||
}); |
||||
afterEach(function() { |
||||
select2Stub.restore(); |
||||
clock.restore(); |
||||
}); |
||||
|
||||
describe('storage configuration', function() { |
||||
var view; |
||||
|
||||
function selectBackend(backendName) { |
||||
view.$el.find('.selectBackend:first').val('\\OC\\TestBackend').trigger('change'); |
||||
} |
||||
|
||||
beforeEach(function() { |
||||
var $el = $('#externalStorage'); |
||||
view = new OCA.External.Settings.MountConfigListView($el); |
||||
}); |
||||
afterEach(function() { |
||||
view = null; |
||||
}); |
||||
describe('selecting backend', function() { |
||||
it('populates the row and creates a new empty one', function() { |
||||
var $firstRow = view.$el.find('tr:first'); |
||||
selectBackend('\\OC\\TestBackend'); |
||||
expect($firstRow.find('.backend').text()).toEqual('Test Backend'); |
||||
expect($firstRow.find('.selectBackend').length).toEqual(0); |
||||
|
||||
// TODO: check "remove" button visibility
|
||||
|
||||
// the suggested mount point name
|
||||
expect($firstRow.find('[name=mountPoint]').val()).toEqual('TestBackend'); |
||||
|
||||
// TODO: check that the options have been created
|
||||
|
||||
// TODO: check select2 call on the ".applicableUsers" element
|
||||
|
||||
var $emptyRow = $firstRow.next('tr'); |
||||
expect($emptyRow.length).toEqual(1); |
||||
expect($emptyRow.find('.selectBackend').length).toEqual(1); |
||||
expect($emptyRow.find('.applicable select').length).toEqual(0); |
||||
|
||||
// TODO: check "remove" button visibility
|
||||
}); |
||||
// TODO: test with personal mounts (no applicable fields)
|
||||
// TODO: test suggested mount point logic
|
||||
}); |
||||
describe('saving storages', function() { |
||||
it('saves storage after editing config', function() { |
||||
var $tr = view.$el.find('tr:first'); |
||||
selectBackend('\\OC\\TestBackend'); |
||||
|
||||
var $field1 = $tr.find('input[data-parameter=field1]'); |
||||
expect($field1.length).toEqual(1); |
||||
$field1.val('test'); |
||||
$field1.trigger(new $.Event('keyup', {keyCode: 97})); |
||||
|
||||
clock.tick(4000); |
||||
|
||||
expect(fakeServer.requests.length).toEqual(1); |
||||
var request = fakeServer.requests[0]; |
||||
expect(request.url).toEqual(OC.webroot + '/index.php/apps/files_external/globalstorages'); |
||||
expect(OC.parseQueryString(request.requestBody)).toEqual({ |
||||
backendClass: '\\OC\\TestBackend', |
||||
'backendOptions[field1]': 'test', |
||||
'backendOptions[field2]': '', |
||||
mountPoint: 'TestBackend', |
||||
priority: '11' |
||||
}); |
||||
|
||||
// TODO: respond and check data-id
|
||||
}); |
||||
// TODO: tests with "applicableUsers" and "applicableGroups"
|
||||
// TODO: test with non-optional config parameters
|
||||
// TODO: test with missing mount point value
|
||||
// TODO: test with personal mounts (no applicable fields)
|
||||
// TODO: test save triggers: paste, keyup, checkbox
|
||||
// TODO: test "custom" field with addScript
|
||||
// TODO: status indicator
|
||||
}); |
||||
describe('update storage', function() { |
||||
// TODO
|
||||
}); |
||||
describe('delete storage', function() { |
||||
// TODO
|
||||
}); |
||||
describe('recheck storages', function() { |
||||
// TODO
|
||||
}); |
||||
}); |
||||
describe('applicable user list', function() { |
||||
// TODO: test select2 retrieval logic
|
||||
}); |
||||
describe('allow user mounts section', function() { |
||||
// TODO: test allowUserMounting section
|
||||
}); |
||||
}); |
@ -0,0 +1,815 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_external\Tests\Service; |
||||
|
||||
use \OC\Files\Filesystem; |
||||
|
||||
use \OCA\Files_external\Service\GlobalStoragesService; |
||||
use \OCA\Files_external\NotFoundException; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
class GlobalStoragesServiceTest extends StoragesServiceTest { |
||||
public function setUp() { |
||||
parent::setUp(); |
||||
$this->service = new GlobalStoragesService(); |
||||
} |
||||
|
||||
public function tearDown() { |
||||
@unlink($this->dataDir . '/mount.json'); |
||||
parent::tearDown(); |
||||
} |
||||
|
||||
protected function makeTestStorageData() { |
||||
return $this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'applicableUsers' => [], |
||||
'applicableGroups' => [], |
||||
'priority' => 15, |
||||
'mountOptions' => [ |
||||
'preview' => false, |
||||
] |
||||
]); |
||||
} |
||||
|
||||
function storageDataProvider() { |
||||
return [ |
||||
// all users |
||||
[ |
||||
$this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'applicableUsers' => [], |
||||
'applicableGroups' => [], |
||||
'priority' => 15, |
||||
]), |
||||
], |
||||
// some users |
||||
[ |
||||
$this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'applicableUsers' => ['user1', 'user2'], |
||||
'applicableGroups' => [], |
||||
'priority' => 15, |
||||
]), |
||||
], |
||||
// some groups |
||||
[ |
||||
$this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'applicableUsers' => [], |
||||
'applicableGroups' => ['group1', 'group2'], |
||||
'priority' => 15, |
||||
]), |
||||
], |
||||
// both users and groups |
||||
[ |
||||
$this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'applicableUsers' => ['user1', 'user2'], |
||||
'applicableGroups' => ['group1', 'group2'], |
||||
'priority' => 15, |
||||
]), |
||||
], |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider storageDataProvider |
||||
*/ |
||||
public function testAddStorage($storage) { |
||||
$newStorage = $this->service->addStorage($storage); |
||||
|
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
|
||||
|
||||
$newStorage = $this->service->getStorage(1); |
||||
|
||||
$this->assertEquals($storage->getMountPoint(), $newStorage->getMountPoint()); |
||||
$this->assertEquals($storage->getBackendClass(), $newStorage->getBackendClass()); |
||||
$this->assertEquals($storage->getBackendOptions(), $newStorage->getBackendOptions()); |
||||
$this->assertEquals($storage->getApplicableUsers(), $newStorage->getApplicableUsers()); |
||||
$this->assertEquals($storage->getApplicableGroups(), $newStorage->getApplicableGroups()); |
||||
$this->assertEquals($storage->getPriority(), $newStorage->getPriority()); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
$this->assertEquals(0, $newStorage->getStatus()); |
||||
|
||||
// next one gets id 2 |
||||
$nextStorage = $this->service->addStorage($storage); |
||||
$this->assertEquals(2, $nextStorage->getId()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider storageDataProvider |
||||
*/ |
||||
public function testUpdateStorage($updatedStorage) { |
||||
$storage = $this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'applicableUsers' => [], |
||||
'applicableGroups' => [], |
||||
'priority' => 15, |
||||
]); |
||||
|
||||
$newStorage = $this->service->addStorage($storage); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
|
||||
$updatedStorage->setId(1); |
||||
|
||||
$this->service->updateStorage($updatedStorage); |
||||
$newStorage = $this->service->getStorage(1); |
||||
|
||||
$this->assertEquals($updatedStorage->getMountPoint(), $newStorage->getMountPoint()); |
||||
$this->assertEquals($updatedStorage->getBackendOptions()['password'], $newStorage->getBackendOptions()['password']); |
||||
$this->assertEquals($updatedStorage->getApplicableUsers(), $newStorage->getApplicableUsers()); |
||||
$this->assertEquals($updatedStorage->getApplicableGroups(), $newStorage->getApplicableGroups()); |
||||
$this->assertEquals($updatedStorage->getPriority(), $newStorage->getPriority()); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
$this->assertEquals(0, $newStorage->getStatus()); |
||||
} |
||||
|
||||
function hooksAddStorageDataProvider() { |
||||
return [ |
||||
// applicable all |
||||
[ |
||||
[], |
||||
[], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'all' |
||||
], |
||||
], |
||||
], |
||||
// single user |
||||
[ |
||||
['user1'], |
||||
[], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
], |
||||
], |
||||
// single group |
||||
[ |
||||
[], |
||||
['group1'], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1', |
||||
], |
||||
], |
||||
], |
||||
// multiple users |
||||
[ |
||||
['user1', 'user2'], |
||||
[], |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
], |
||||
], |
||||
// multiple groups |
||||
[ |
||||
[], |
||||
['group1', 'group2'], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1' |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2' |
||||
], |
||||
], |
||||
], |
||||
// mixed groups and users |
||||
[ |
||||
['user1', 'user2'], |
||||
['group1', 'group2'], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1' |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2' |
||||
], |
||||
], |
||||
], |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider hooksAddStorageDataProvider |
||||
*/ |
||||
public function testHooksAddStorage($applicableUsers, $applicableGroups, $expectedCalls) { |
||||
$storage = $this->makeTestStorageData(); |
||||
$storage->setApplicableUsers($applicableUsers); |
||||
$storage->setApplicableGroups($applicableGroups); |
||||
$this->service->addStorage($storage); |
||||
|
||||
$this->assertCount(count($expectedCalls), self::$hookCalls); |
||||
|
||||
foreach ($expectedCalls as $index => $call) { |
||||
$this->assertHookCall( |
||||
self::$hookCalls[$index], |
||||
$call[0], |
||||
$storage->getMountPoint(), |
||||
$call[1], |
||||
$call[2] |
||||
); |
||||
} |
||||
} |
||||
|
||||
function hooksUpdateStorageDataProvider() { |
||||
return [ |
||||
[ |
||||
// nothing to multiple users and groups |
||||
[], |
||||
[], |
||||
['user1', 'user2'], |
||||
['group1', 'group2'], |
||||
// expected hook calls |
||||
[ |
||||
// delete the "all entry" |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'all', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1' |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2' |
||||
], |
||||
], |
||||
], |
||||
[ |
||||
// adding a user and a group |
||||
['user1'], |
||||
['group1'], |
||||
['user1', 'user2'], |
||||
['group1', 'group2'], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2' |
||||
], |
||||
], |
||||
], |
||||
[ |
||||
// removing a user and a group |
||||
['user1', 'user2'], |
||||
['group1', 'group2'], |
||||
['user1'], |
||||
['group1'], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2' |
||||
], |
||||
], |
||||
], |
||||
[ |
||||
// removing all |
||||
['user1'], |
||||
['group1'], |
||||
[], |
||||
[], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1' |
||||
], |
||||
// create the "all" entry |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'all' |
||||
], |
||||
], |
||||
], |
||||
[ |
||||
// no changes |
||||
['user1'], |
||||
['group1'], |
||||
['user1'], |
||||
['group1'], |
||||
// no hook calls |
||||
[] |
||||
] |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider hooksUpdateStorageDataProvider |
||||
*/ |
||||
public function testHooksUpdateStorage( |
||||
$sourceApplicableUsers, |
||||
$sourceApplicableGroups, |
||||
$updatedApplicableUsers, |
||||
$updatedApplicableGroups, |
||||
$expectedCalls) { |
||||
|
||||
$storage = $this->makeTestStorageData(); |
||||
$storage->setApplicableUsers($sourceApplicableUsers); |
||||
$storage->setApplicableGroups($sourceApplicableGroups); |
||||
$storage = $this->service->addStorage($storage); |
||||
|
||||
$storage->setapplicableUsers($updatedApplicableUsers); |
||||
$storage->setapplicableGroups($updatedApplicableGroups); |
||||
|
||||
// reset calls |
||||
self::$hookCalls = []; |
||||
|
||||
$this->service->updateStorage($storage); |
||||
|
||||
$this->assertCount(count($expectedCalls), self::$hookCalls); |
||||
|
||||
foreach ($expectedCalls as $index => $call) { |
||||
$this->assertHookCall( |
||||
self::$hookCalls[$index], |
||||
$call[0], |
||||
'/mountpoint', |
||||
$call[1], |
||||
$call[2] |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
*/ |
||||
public function testHooksRenameMountPoint() { |
||||
$storage = $this->makeTestStorageData(); |
||||
$storage->setApplicableUsers(['user1', 'user2']); |
||||
$storage->setApplicableGroups(['group1', 'group2']); |
||||
$storage = $this->service->addStorage($storage); |
||||
|
||||
$storage->setMountPoint('renamedMountpoint'); |
||||
|
||||
// reset calls |
||||
self::$hookCalls = []; |
||||
|
||||
$this->service->updateStorage($storage); |
||||
|
||||
$expectedCalls = [ |
||||
// deletes old mount |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
'/mountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
'/mountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
'/mountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
'/mountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2', |
||||
], |
||||
// creates new one |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
'/renamedMountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
'/renamedMountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
'/renamedMountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1', |
||||
], |
||||
[ |
||||
Filesystem::signal_create_mount, |
||||
'/renamedMountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2', |
||||
], |
||||
]; |
||||
|
||||
$this->assertCount(count($expectedCalls), self::$hookCalls); |
||||
|
||||
foreach ($expectedCalls as $index => $call) { |
||||
$this->assertHookCall( |
||||
self::$hookCalls[$index], |
||||
$call[0], |
||||
$call[1], |
||||
$call[2], |
||||
$call[3] |
||||
); |
||||
} |
||||
} |
||||
|
||||
function hooksDeleteStorageDataProvider() { |
||||
return [ |
||||
[ |
||||
['user1', 'user2'], |
||||
['group1', 'group2'], |
||||
// expected hook calls |
||||
[ |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user1', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'user2', |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group1' |
||||
], |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_GROUP, |
||||
'group2' |
||||
], |
||||
], |
||||
], |
||||
[ |
||||
// deleting "all" entry |
||||
[], |
||||
[], |
||||
[ |
||||
[ |
||||
Filesystem::signal_delete_mount, |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
'all', |
||||
], |
||||
], |
||||
], |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider hooksDeleteStorageDataProvider |
||||
*/ |
||||
public function testHooksDeleteStorage( |
||||
$sourceApplicableUsers, |
||||
$sourceApplicableGroups, |
||||
$expectedCalls) { |
||||
|
||||
$storage = $this->makeTestStorageData(); |
||||
$storage->setApplicableUsers($sourceApplicableUsers); |
||||
$storage->setApplicableGroups($sourceApplicableGroups); |
||||
$storage = $this->service->addStorage($storage); |
||||
|
||||
// reset calls |
||||
self::$hookCalls = []; |
||||
|
||||
$this->service->removeStorage($storage->getId()); |
||||
|
||||
$this->assertCount(count($expectedCalls), self::$hookCalls); |
||||
|
||||
foreach ($expectedCalls as $index => $call) { |
||||
$this->assertHookCall( |
||||
self::$hookCalls[$index], |
||||
$call[0], |
||||
'/mountpoint', |
||||
$call[1], |
||||
$call[2] |
||||
); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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('\OC\Files\Storage\SMB', $mountPointOptions['class']); |
||||
$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('\OC\Files\Storage\SMB', $mountPointOptions['class']); |
||||
$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('\OC\Files\Storage\SMB', $mountPointOptions['class']); |
||||
$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 = [ |
||||
'class' => '\OC\Files\Storage\SMB', |
||||
'options' => $legacyBackendOptions, |
||||
'mountOptions' => ['preview' => false], |
||||
]; |
||||
// different mount options |
||||
$legacyConfig2 = [ |
||||
'class' => '\OC\Files\Storage\SMB', |
||||
'options' => $legacyBackendOptions, |
||||
'mountOptions' => ['preview' => true], |
||||
]; |
||||
|
||||
$legacyBackendOptions2 = $legacyBackendOptions; |
||||
$legacyBackendOptions2 = ['user' => 'someuser2', 'password' => 'somepassword2']; |
||||
$legacyBackendOptions2 = \OC_Mount_Config::encryptPasswords($legacyBackendOptions2); |
||||
|
||||
// different config |
||||
$legacyConfig3 = [ |
||||
'class' => '\OC\Files\Storage\SMB', |
||||
'options' => $legacyBackendOptions2, |
||||
'mountOptions' => ['preview' => true], |
||||
]; |
||||
|
||||
$json = [ |
||||
'user' => [ |
||||
'user1' => [ |
||||
'/$user/files/somemount' => $legacyConfig, |
||||
], |
||||
// same config |
||||
'user2' => [ |
||||
'/$user/files/somemount' => $legacyConfig, |
||||
], |
||||
// different mountOptions |
||||
'user3' => [ |
||||
'/$user/files/somemount' => $legacyConfig2, |
||||
], |
||||
// different mount point |
||||
'user4' => [ |
||||
'/$user/files/anothermount' => $legacyConfig, |
||||
], |
||||
// different storage config |
||||
'user5' => [ |
||||
'/$user/files/somemount' => $legacyConfig3, |
||||
], |
||||
], |
||||
'group' => [ |
||||
'group1' => [ |
||||
// will get grouped with user configs |
||||
'/$user/files/somemount' => $legacyConfig, |
||||
], |
||||
], |
||||
]; |
||||
|
||||
file_put_contents($configFile, json_encode($json)); |
||||
|
||||
$allStorages = $this->service->getAllStorages(); |
||||
|
||||
$this->assertCount(4, $allStorages); |
||||
|
||||
$storage1 = $allStorages[1]; |
||||
$storage2 = $allStorages[2]; |
||||
$storage3 = $allStorages[3]; |
||||
$storage4 = $allStorages[4]; |
||||
|
||||
$this->assertEquals('/somemount', $storage1->getMountPoint()); |
||||
$this->assertEquals('someuser', $storage1->getBackendOptions()['user']); |
||||
$this->assertEquals('somepassword', $storage1->getBackendOptions()['password']); |
||||
$this->assertEquals(['user1', 'user2'], $storage1->getApplicableUsers()); |
||||
$this->assertEquals(['group1'], $storage1->getApplicableGroups()); |
||||
$this->assertEquals(['preview' => false], $storage1->getMountOptions()); |
||||
|
||||
$this->assertEquals('/somemount', $storage2->getMountPoint()); |
||||
$this->assertEquals('someuser', $storage2->getBackendOptions()['user']); |
||||
$this->assertEquals('somepassword', $storage2->getBackendOptions()['password']); |
||||
$this->assertEquals(['user3'], $storage2->getApplicableUsers()); |
||||
$this->assertEquals([], $storage2->getApplicableGroups()); |
||||
$this->assertEquals(['preview' => true], $storage2->getMountOptions()); |
||||
|
||||
$this->assertEquals('/anothermount', $storage3->getMountPoint()); |
||||
$this->assertEquals('someuser', $storage3->getBackendOptions()['user']); |
||||
$this->assertEquals('somepassword', $storage3->getBackendOptions()['password']); |
||||
$this->assertEquals(['user4'], $storage3->getApplicableUsers()); |
||||
$this->assertEquals([], $storage3->getApplicableGroups()); |
||||
$this->assertEquals(['preview' => false], $storage3->getMountOptions()); |
||||
|
||||
$this->assertEquals('/somemount', $storage4->getMountPoint()); |
||||
$this->assertEquals('someuser2', $storage4->getBackendOptions()['user']); |
||||
$this->assertEquals('somepassword2', $storage4->getBackendOptions()['password']); |
||||
$this->assertEquals(['user5'], $storage4->getApplicableUsers()); |
||||
$this->assertEquals([], $storage4->getApplicableGroups()); |
||||
$this->assertEquals(['preview' => true], $storage4->getMountOptions()); |
||||
} |
||||
} |
@ -0,0 +1,183 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_external\Tests\Service; |
||||
|
||||
use \OC\Files\Filesystem; |
||||
|
||||
use \OCA\Files_external\NotFoundException; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
abstract class StoragesServiceTest extends \Test\TestCase { |
||||
|
||||
/** |
||||
* @var StoragesService |
||||
*/ |
||||
protected $service; |
||||
|
||||
/** |
||||
* Data directory |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $dataDir; |
||||
|
||||
/** |
||||
* Hook calls |
||||
* |
||||
* @var array |
||||
*/ |
||||
protected static $hookCalls; |
||||
|
||||
public function setUp() { |
||||
self::$hookCalls = array(); |
||||
$config = \OC::$server->getConfig(); |
||||
$this->dataDir = $config->getSystemValue( |
||||
'datadirectory', |
||||
\OC::$SERVERROOT . '/data/' |
||||
); |
||||
\OC_Mount_Config::$skipTest = true; |
||||
|
||||
\OCP\Util::connectHook( |
||||
Filesystem::CLASSNAME, |
||||
Filesystem::signal_create_mount, |
||||
get_class($this), 'createHookCallback'); |
||||
\OCP\Util::connectHook( |
||||
Filesystem::CLASSNAME, |
||||
Filesystem::signal_delete_mount, |
||||
get_class($this), 'deleteHookCallback'); |
||||
|
||||
} |
||||
|
||||
public function tearDown() { |
||||
\OC_Mount_Config::$skipTest = false; |
||||
self::$hookCalls = array(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a StorageConfig instance based on array data |
||||
* |
||||
* @param array data |
||||
* |
||||
* @return StorageConfig storage config instance |
||||
*/ |
||||
protected function makeStorageConfig($data) { |
||||
$storage = new StorageConfig(); |
||||
if (isset($data['id'])) { |
||||
$storage->setId($data['id']); |
||||
} |
||||
$storage->setMountPoint($data['mountPoint']); |
||||
$storage->setBackendClass($data['backendClass']); |
||||
$storage->setBackendOptions($data['backendOptions']); |
||||
if (isset($data['applicableUsers'])) { |
||||
$storage->setApplicableUsers($data['applicableUsers']); |
||||
} |
||||
if (isset($data['applicableGroups'])) { |
||||
$storage->setApplicableGroups($data['applicableGroups']); |
||||
} |
||||
if (isset($data['priority'])) { |
||||
$storage->setPriority($data['priority']); |
||||
} |
||||
if (isset($data['mountOptions'])) { |
||||
$storage->setMountOptions($data['mountOptions']); |
||||
} |
||||
return $storage; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @expectedException \OCA\Files_external\NotFoundException |
||||
*/ |
||||
public function testNonExistingStorage() { |
||||
$storage = new StorageConfig(255); |
||||
$storage->setMountPoint('mountpoint'); |
||||
$storage->setBackendClass('\OC\Files\Storage\SMB'); |
||||
$this->service->updateStorage($storage); |
||||
} |
||||
|
||||
public function testDeleteStorage() { |
||||
$storage = new StorageConfig(255); |
||||
$storage->setMountPoint('mountpoint'); |
||||
$storage->setBackendClass('\OC\Files\Storage\SMB'); |
||||
$storage->setBackendOptions(['password' => 'testPassword']); |
||||
|
||||
$newStorage = $this->service->addStorage($storage); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
|
||||
$newStorage = $this->service->removeStorage(1); |
||||
|
||||
$caught = false; |
||||
try { |
||||
$this->service->getStorage(1); |
||||
} catch (NotFoundException $e) { |
||||
$caught = true; |
||||
} |
||||
|
||||
$this->assertTrue($caught); |
||||
} |
||||
|
||||
/** |
||||
* @expectedException \OCA\Files_external\NotFoundException |
||||
*/ |
||||
public function testDeleteUnexistingStorage() { |
||||
$this->service->removeStorage(255); |
||||
} |
||||
|
||||
public static function createHookCallback($params) { |
||||
self::$hookCalls[] = array( |
||||
'signal' => Filesystem::signal_create_mount, |
||||
'params' => $params |
||||
); |
||||
} |
||||
|
||||
public static function deleteHookCallback($params) { |
||||
self::$hookCalls[] = array( |
||||
'signal' => Filesystem::signal_delete_mount, |
||||
'params' => $params |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Asserts hook call |
||||
* |
||||
* @param array $callData hook call data to check |
||||
* @param string $signal signal name |
||||
* @param string $mountPath mount path |
||||
* @param string $mountType mount type |
||||
* @param string $applicable applicable users |
||||
*/ |
||||
protected function assertHookCall($callData, $signal, $mountPath, $mountType, $applicable) { |
||||
$this->assertEquals($signal, $callData['signal']); |
||||
$params = $callData['params']; |
||||
$this->assertEquals( |
||||
$mountPath, |
||||
$params[Filesystem::signal_param_path] |
||||
); |
||||
$this->assertEquals( |
||||
$mountType, |
||||
$params[Filesystem::signal_param_mount_type] |
||||
); |
||||
$this->assertEquals( |
||||
$applicable, |
||||
$params[Filesystem::signal_param_users] |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,254 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCA\Files_external\Tests\Service; |
||||
|
||||
use \OC\Files\Filesystem; |
||||
|
||||
use \OCA\Files_external\Service\UserStoragesService; |
||||
use \OCA\Files_external\NotFoundException; |
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
class UserStoragesServiceTest extends StoragesServiceTest { |
||||
|
||||
public function setUp() { |
||||
parent::setUp(); |
||||
|
||||
$this->userId = $this->getUniqueID('user_'); |
||||
|
||||
$this->user = new \OC\User\User($this->userId, null); |
||||
$userSession = $this->getMock('\OCP\IUserSession'); |
||||
$userSession |
||||
->expects($this->any()) |
||||
->method('getUser') |
||||
->will($this->returnValue($this->user)); |
||||
|
||||
$this->service = new UserStoragesService($userSession); |
||||
|
||||
// create home folder |
||||
mkdir($this->dataDir . '/' . $this->userId . '/'); |
||||
} |
||||
|
||||
public function tearDown() { |
||||
@unlink($this->dataDir . '/' . $this->userId . '/mount.json'); |
||||
parent::tearDown(); |
||||
} |
||||
|
||||
private function makeTestStorageData() { |
||||
return $this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
'mountOptions' => [ |
||||
'preview' => false, |
||||
] |
||||
]); |
||||
} |
||||
|
||||
public function testAddStorage() { |
||||
$storage = $this->makeTestStorageData(); |
||||
|
||||
$newStorage = $this->service->addStorage($storage); |
||||
|
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
|
||||
$newStorage = $this->service->getStorage(1); |
||||
|
||||
$this->assertEquals($storage->getMountPoint(), $newStorage->getMountPoint()); |
||||
$this->assertEquals($storage->getBackendClass(), $newStorage->getBackendClass()); |
||||
$this->assertEquals($storage->getBackendOptions(), $newStorage->getBackendOptions()); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
$this->assertEquals(0, $newStorage->getStatus()); |
||||
|
||||
// hook called once for user |
||||
$this->assertHookCall( |
||||
current(self::$hookCalls), |
||||
Filesystem::signal_create_mount, |
||||
$storage->getMountPoint(), |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$this->userId |
||||
); |
||||
|
||||
// next one gets id 2 |
||||
$nextStorage = $this->service->addStorage($storage); |
||||
$this->assertEquals(2, $nextStorage->getId()); |
||||
} |
||||
|
||||
public function testUpdateStorage() { |
||||
$storage = $this->makeStorageConfig([ |
||||
'mountPoint' => 'mountpoint', |
||||
'backendClass' => '\OC\Files\Storage\SMB', |
||||
'backendOptions' => [ |
||||
'option1' => 'value1', |
||||
'option2' => 'value2', |
||||
'password' => 'testPassword', |
||||
], |
||||
]); |
||||
|
||||
$newStorage = $this->service->addStorage($storage); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
|
||||
$backendOptions = $newStorage->getBackendOptions(); |
||||
$backendOptions['password'] = 'anotherPassword'; |
||||
$newStorage->setBackendOptions($backendOptions); |
||||
|
||||
self::$hookCalls = []; |
||||
|
||||
$newStorage = $this->service->updateStorage($newStorage); |
||||
|
||||
$this->assertEquals('anotherPassword', $newStorage->getBackendOptions()['password']); |
||||
// these attributes are unused for user storages |
||||
$this->assertEmpty($newStorage->getApplicableUsers()); |
||||
$this->assertEmpty($newStorage->getApplicableGroups()); |
||||
$this->assertEquals(1, $newStorage->getId()); |
||||
$this->assertEquals(0, $newStorage->getStatus()); |
||||
|
||||
// no hook calls |
||||
$this->assertEmpty(self::$hookCalls); |
||||
} |
||||
|
||||
public function testDeleteStorage() { |
||||
parent::testDeleteStorage(); |
||||
|
||||
// hook called once for user (first one was during test creation) |
||||
$this->assertHookCall( |
||||
self::$hookCalls[1], |
||||
Filesystem::signal_delete_mount, |
||||
'/mountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$this->userId |
||||
); |
||||
} |
||||
|
||||
public function testHooksRenameMountPoint() { |
||||
$storage = $this->makeTestStorageData(); |
||||
$storage = $this->service->addStorage($storage); |
||||
|
||||
$storage->setMountPoint('renamedMountpoint'); |
||||
|
||||
// reset calls |
||||
self::$hookCalls = []; |
||||
|
||||
$this->service->updateStorage($storage); |
||||
|
||||
// hook called twice |
||||
$this->assertHookCall( |
||||
self::$hookCalls[0], |
||||
Filesystem::signal_delete_mount, |
||||
'/mountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$this->userId |
||||
); |
||||
$this->assertHookCall( |
||||
self::$hookCalls[1], |
||||
Filesystem::signal_create_mount, |
||||
'/renamedMountpoint', |
||||
\OC_Mount_Config::MOUNT_TYPE_USER, |
||||
$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('\OC\Files\Storage\SMB', $mountPointOptions['class']); |
||||
$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 = [ |
||||
'class' => '\OC\Files\Storage\SMB', |
||||
'options' => $legacyBackendOptions, |
||||
'mountOptions' => ['preview' => false], |
||||
]; |
||||
// different mount options |
||||
$legacyConfig2 = [ |
||||
'class' => '\OC\Files\Storage\SMB', |
||||
'options' => $legacyBackendOptions, |
||||
'mountOptions' => ['preview' => true], |
||||
]; |
||||
|
||||
$json = ['user' => []]; |
||||
$json['user'][$this->userId] = [ |
||||
'/$user/files/somemount' => $legacyConfig, |
||||
'/$user/files/anothermount' => $legacyConfig2, |
||||
]; |
||||
|
||||
file_put_contents($configFile, json_encode($json)); |
||||
|
||||
$allStorages = $this->service->getAllStorages(); |
||||
|
||||
$this->assertCount(2, $allStorages); |
||||
|
||||
$storage1 = $allStorages[1]; |
||||
$storage2 = $allStorages[2]; |
||||
|
||||
$this->assertEquals('/somemount', $storage1->getMountPoint()); |
||||
$this->assertEquals('someuser', $storage1->getBackendOptions()['user']); |
||||
$this->assertEquals('somepassword', $storage1->getBackendOptions()['password']); |
||||
$this->assertEquals(['preview' => false], $storage1->getMountOptions()); |
||||
|
||||
$this->assertEquals('/anothermount', $storage2->getMountPoint()); |
||||
$this->assertEquals('someuser', $storage2->getBackendOptions()['user']); |
||||
$this->assertEquals('somepassword', $storage2->getBackendOptions()['password']); |
||||
$this->assertEquals(['preview' => true], $storage2->getMountOptions()); |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* @author Vincent Petry |
||||
* Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\Files_external\Tests; |
||||
|
||||
use \OCA\Files_external\Lib\StorageConfig; |
||||
|
||||
class StorageConfigTest extends \Test\TestCase { |
||||
|
||||
public function testJsonSerialization() { |
||||
$storageConfig = new StorageConfig(1); |
||||
$storageConfig->setMountPoint('test'); |
||||
$storageConfig->setBackendClass('\OC\Files\Storage\SMB'); |
||||
$storageConfig->setBackendOptions(['user' => 'test', 'password' => 'password123']); |
||||
$storageConfig->setPriority(128); |
||||
$storageConfig->setApplicableUsers(['user1', 'user2']); |
||||
$storageConfig->setApplicableGroups(['group1', 'group2']); |
||||
$storageConfig->setMountOptions(['preview' => false]); |
||||
|
||||
$json = $storageConfig->jsonSerialize(); |
||||
|
||||
$this->assertEquals(1, $json['id']); |
||||
$this->assertEquals('/test', $json['mountPoint']); |
||||
$this->assertEquals('\OC\Files\Storage\SMB', $json['backendClass']); |
||||
$this->assertEquals('test', $json['backendOptions']['user']); |
||||
$this->assertEquals('password123', $json['backendOptions']['password']); |
||||
$this->assertEquals(128, $json['priority']); |
||||
$this->assertEquals(['user1', 'user2'], $json['applicableUsers']); |
||||
$this->assertEquals(['group1', 'group2'], $json['applicableGroups']); |
||||
$this->assertEquals(['preview' => false], $json['mountOptions']); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue