Use storage id + appframework for ext storage CRUD
- Added StorageConfig class to replace ugly arrays - Implemented StorageService and StorageController for Global and User storages - Async status checking for storages (from Xenopathic) - Auto-generate id for external storage configs (not the same as storage_id) - Refactor JS classes for external storage settings, this mostly moves/encapsulated existing global event handlers into the MountConfigListView class. - Added some JS unit tests for the external storage UI
This commit is contained in:
parent
23cc3cc5f2
commit
ce94a998dd
|
@ -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);
|
|
@ -6,6 +6,8 @@
|
|||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
$app = new \OCA\Files_external\Appinfo\Application();
|
||||
|
||||
$l = \OC::$server->getL10N('files_external');
|
||||
|
||||
OC::$CLASSPATH['OC\Files\Storage\StreamWrapper'] = 'files_external/lib/streamwrapper.php';
|
||||
|
|
|
@ -12,12 +12,13 @@ use \OCA\Files_External\Controller\AjaxController;
|
|||
use \OCP\AppFramework\App;
|
||||
use \OCP\IContainer;
|
||||
|
||||
/**
|
||||
* @package OCA\Files_External\Appinfo
|
||||
*/
|
||||
/**
|
||||
* @package OCA\Files_External\Appinfo
|
||||
*/
|
||||
class Application extends App {
|
||||
public function __construct(array $urlParams=array()) {
|
||||
parent::__construct('files_external', $urlParams);
|
||||
|
||||
$container = $this->getContainer();
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,28 +22,30 @@
|
|||
|
||||
namespace OCA\Files_External\Appinfo;
|
||||
|
||||
/**
|
||||
* @var $this OC\Route\Router
|
||||
**/
|
||||
|
||||
$application = new Application();
|
||||
$application->registerRoutes(
|
||||
$this,
|
||||
array(
|
||||
'routes' => array(
|
||||
array(
|
||||
'name' => 'Ajax#getSshKeys',
|
||||
'url' => '/ajax/sftp_key.php',
|
||||
'verb' => 'POST',
|
||||
'requirements' => array()
|
||||
)
|
||||
)
|
||||
)
|
||||
$this,
|
||||
array(
|
||||
'resources' => array(
|
||||
'global_storages' => array('url' => '/globalstorages'),
|
||||
'user_storages' => array('url' => '/userstorages'),
|
||||
),
|
||||
'routes' => array(
|
||||
array(
|
||||
'name' => 'Ajax#getSshKeys',
|
||||
'url' => '/ajax/sftp_key.php',
|
||||
'verb' => 'POST',
|
||||
'requirements' => array()
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/** @var $this OC\Route\Router */
|
||||
|
||||
$this->create('files_external_add_mountpoint', 'ajax/addMountPoint.php')
|
||||
->actionInclude('files_external/ajax/addMountPoint.php');
|
||||
$this->create('files_external_remove_mountpoint', 'ajax/removeMountPoint.php')
|
||||
->actionInclude('files_external/ajax/removeMountPoint.php');
|
||||
|
||||
// TODO: move these to app framework
|
||||
$this->create('files_external_add_root_certificate', 'ajax/addRootCertificate.php')
|
||||
->actionInclude('files_external/ajax/addRootCertificate.php');
|
||||
$this->create('files_external_remove_root_certificate', 'ajax/removeRootCertificate.php')
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
<?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\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;
|
||||
|
||||
class GlobalStoragesController extends StoragesController {
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IConfig $config
|
||||
* @param GlobalStoragesService $globalStoragesService
|
||||
*/
|
||||
public function __construct(
|
||||
$AppName,
|
||||
IRequest $request,
|
||||
\OCP\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 $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,
|
||||
$applicableUsers,
|
||||
$applicableGroups,
|
||||
$priority
|
||||
) {
|
||||
$newStorage = new StorageConfig();
|
||||
$newStorage->setMountPoint($mountPoint);
|
||||
$newStorage->setBackendClass($backendClass);
|
||||
$newStorage->setBackendOptions($backendOptions);
|
||||
$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 $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,
|
||||
$applicableUsers,
|
||||
$applicableGroups,
|
||||
$priority
|
||||
) {
|
||||
$storage = new StorageConfig($id);
|
||||
$storage->setMountPoint($mountPoint);
|
||||
$storage->setBackendClass($backendClass);
|
||||
$storage->setBackendOptions($backendOptions);
|
||||
$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,157 @@
|
|||
<?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\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;
|
||||
|
||||
abstract class StoragesController extends Controller {
|
||||
|
||||
/**
|
||||
* @var \OCP\IL10N
|
||||
*/
|
||||
protected $l10n;
|
||||
|
||||
/**
|
||||
* @var StoragesService
|
||||
*/
|
||||
protected $service;
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IConfig $config
|
||||
* @param StoragesService $storagesService
|
||||
*/
|
||||
public function __construct(
|
||||
$AppName,
|
||||
IRequest $request,
|
||||
\OCP\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
|
||||
*/
|
||||
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,172 @@
|
|||
<?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\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;
|
||||
|
||||
class UserStoragesController extends StoragesController {
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IConfig $config
|
||||
* @param UserStoragesService $userStoragesService
|
||||
*/
|
||||
public function __construct(
|
||||
$AppName,
|
||||
IRequest $request,
|
||||
\OCP\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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
* @return DataResponse
|
||||
*
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function create(
|
||||
$mountPoint,
|
||||
$backendClass,
|
||||
$backendOptions
|
||||
) {
|
||||
$newStorage = new StorageConfig();
|
||||
$newStorage->setMountPoint($mountPoint);
|
||||
$newStorage->setBackendClass($backendClass);
|
||||
$newStorage->setBackendOptions($backendOptions);
|
||||
|
||||
$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
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function update(
|
||||
$id,
|
||||
$mountPoint,
|
||||
$backendClass,
|
||||
$backendOptions
|
||||
) {
|
||||
$storage = new StorageConfig($id);
|
||||
$storage->setMountPoint($mountPoint);
|
||||
$storage->setBackendClass($backendClass);
|
||||
$storage->setBackendOptions($backendOptions);
|
||||
|
||||
$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
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function destroy($id) {
|
||||
return parent::destroy($id);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ $(document).ready(function() {
|
|||
$(token).val(result.access_token);
|
||||
$(token_secret).val(result.access_token_secret);
|
||||
$(configured).val('true');
|
||||
OC.MountConfig.saveStorage(tr, function(status) {
|
||||
OCA.External.Settings.mountConfig.saveStorageConfig(tr, function(status) {
|
||||
if (status) {
|
||||
$(tr).find('.configuration input').attr('disabled', 'disabled');
|
||||
$(tr).find('.configuration').append('<span id="access" style="padding-left:0.5em;">'+t('files_external', 'Access granted')+'</span>');
|
||||
|
@ -93,7 +93,7 @@ $(document).ready(function() {
|
|||
$(configured).val('false');
|
||||
$(token).val(result.data.request_token);
|
||||
$(token_secret).val(result.data.request_token_secret);
|
||||
OC.MountConfig.saveStorage(tr, function() {
|
||||
OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() {
|
||||
window.location = result.data.url;
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -32,7 +32,7 @@ $(document).ready(function() {
|
|||
if (result && result.status == 'success') {
|
||||
$(token).val(result.data.token);
|
||||
$(configured).val('true');
|
||||
OC.MountConfig.saveStorage(tr, function(status) {
|
||||
OCA.External.Settings.mountConfig.saveStorageConfig(tr, function(status) {
|
||||
if (status) {
|
||||
$(tr).find('.configuration input').attr('disabled', 'disabled');
|
||||
$(tr).find('.configuration').append($('<span/>')
|
||||
|
@ -115,7 +115,7 @@ $(document).ready(function() {
|
|||
if (result && result.status == 'success') {
|
||||
$(configured).val('false');
|
||||
$(token).val('false');
|
||||
OC.MountConfig.saveStorage(tr, function(status) {
|
||||
OCA.External.Settings.mountConfig.saveStorageConfig(tr, function(status) {
|
||||
window.location = result.data.url;
|
||||
});
|
||||
} else {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,7 +42,7 @@ $(document).ready(function() {
|
|||
if (result && result.status === 'success') {
|
||||
$(config).find('[data-parameter="public_key"]').val(result.data.public_key);
|
||||
$(config).find('[data-parameter="private_key"]').val(result.data.private_key);
|
||||
OC.MountConfig.saveStorage(tr, function() {
|
||||
OCA.External.mountConfig.saveStorageConfig(tr, function() {
|
||||
// Nothing to do
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -32,6 +32,10 @@ class OC_Mount_Config {
|
|||
const MOUNT_TYPE_USER = 'user';
|
||||
const MOUNT_TYPE_PERSONAL = 'personal';
|
||||
|
||||
// getBackendStatus return types
|
||||
const STATUS_SUCCESS = 0;
|
||||
const STATUS_ERROR = 1;
|
||||
|
||||
// whether to skip backend test (for unit tests, as this static class is not mockable)
|
||||
public static $skipTest = false;
|
||||
|
||||
|
@ -143,15 +147,9 @@ class OC_Mount_Config {
|
|||
$mountPoints = array();
|
||||
|
||||
$datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
|
||||
$mount_file = \OC_Config::getValue("mount_file", $datadir . "/mount.json");
|
||||
|
||||
$backends = self::getBackends();
|
||||
|
||||
//move config file to it's new position
|
||||
if (is_file(\OC::$SERVERROOT . '/config/mount.json')) {
|
||||
rename(\OC::$SERVERROOT . '/config/mount.json', $mount_file);
|
||||
}
|
||||
|
||||
// Load system mount points
|
||||
$mountConfig = self::readData();
|
||||
|
||||
|
@ -349,6 +347,8 @@ class OC_Mount_Config {
|
|||
$mountPoint = substr($mountPoint, 13);
|
||||
|
||||
$config = array(
|
||||
'id' => (int) $mount['id'],
|
||||
'storage_id' => (int) $mount['storage_id'],
|
||||
'class' => $mount['class'],
|
||||
'mountpoint' => $mountPoint,
|
||||
'backend' => $backends[$mount['class']]['backend'],
|
||||
|
@ -383,6 +383,8 @@ class OC_Mount_Config {
|
|||
// Remove '/$user/files/' from mount point
|
||||
$mountPoint = substr($mountPoint, 13);
|
||||
$config = array(
|
||||
'id' => (int) $mount['id'],
|
||||
'storage_id' => (int) $mount['storage_id'],
|
||||
'class' => $mount['class'],
|
||||
'mountpoint' => $mountPoint,
|
||||
'backend' => $backends[$mount['class']]['backend'],
|
||||
|
@ -425,6 +427,8 @@ class OC_Mount_Config {
|
|||
}
|
||||
$mount['options'] = self::decryptPasswords($mount['options']);
|
||||
$personal[] = array(
|
||||
'id' => (int) $mount['id'],
|
||||
'storage_id' => (int) $mount['storage_id'],
|
||||
'class' => $mount['class'],
|
||||
// Remove '/uid/files/' from mount point
|
||||
'mountpoint' => substr($mountPoint, strlen($uid) + 8),
|
||||
|
@ -442,11 +446,11 @@ class OC_Mount_Config {
|
|||
*
|
||||
* @param string $class backend class name
|
||||
* @param array $options backend configuration options
|
||||
* @return bool true if the connection succeeded, false otherwise
|
||||
* @return int see self::STATUS_*
|
||||
*/
|
||||
private static function getBackendStatus($class, $options, $isPersonal) {
|
||||
public static function getBackendStatus($class, $options, $isPersonal) {
|
||||
if (self::$skipTest) {
|
||||
return true;
|
||||
return self::STATUS_SUCCESS;
|
||||
}
|
||||
foreach ($options as &$option) {
|
||||
$option = self::setUserVars(OCP\User::getUser(), $option);
|
||||
|
@ -454,13 +458,14 @@ class OC_Mount_Config {
|
|||
if (class_exists($class)) {
|
||||
try {
|
||||
$storage = new $class($options);
|
||||
return $storage->test($isPersonal);
|
||||
if ($storage->test($isPersonal)) {
|
||||
return self::STATUS_SUCCESS;
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
\OCP\Util::logException('files_external', $exception);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return self::STATUS_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -474,6 +479,8 @@ class OC_Mount_Config {
|
|||
* @param bool $isPersonal Personal or system mount point i.e. is this being called from the personal or admin page
|
||||
* @param int|null $priority Mount point priority, null for default
|
||||
* @return boolean
|
||||
*
|
||||
* @deprecated use StoragesService#addStorage() instead
|
||||
*/
|
||||
public static function addMountPoint($mountPoint,
|
||||
$class,
|
||||
|
@ -537,7 +544,7 @@ class OC_Mount_Config {
|
|||
self::writeData($isPersonal ? OCP\User::getUser() : null, $mountPoints);
|
||||
|
||||
$result = self::getBackendStatus($class, $classOptions, $isPersonal);
|
||||
if ($result && $isNew) {
|
||||
if ($result === self::STATUS_SUCCESS && $isNew) {
|
||||
\OC_Hook::emit(
|
||||
\OC\Files\Filesystem::CLASSNAME,
|
||||
\OC\Files\Filesystem::signal_create_mount,
|
||||
|
@ -558,6 +565,8 @@ class OC_Mount_Config {
|
|||
* @param string $applicable User or group to remove mount from
|
||||
* @param bool $isPersonal Personal or system mount point
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated use StoragesService#removeStorage() instead
|
||||
*/
|
||||
public static function removeMountPoint($mountPoint, $mountType, $applicable, $isPersonal = false) {
|
||||
// Verify that the mount point applies for the current user
|
||||
|
@ -622,13 +631,10 @@ class OC_Mount_Config {
|
|||
* @param string|null $user If not null, personal for $user, otherwise system
|
||||
* @return array
|
||||
*/
|
||||
private static function readData($user = null) {
|
||||
$parser = new \OC\ArrayParser();
|
||||
public static function readData($user = null) {
|
||||
if (isset($user)) {
|
||||
$phpFile = OC_User::getHome($user) . '/mount.php';
|
||||
$jsonFile = OC_User::getHome($user) . '/mount.json';
|
||||
} else {
|
||||
$phpFile = OC::$SERVERROOT . '/config/mount.php';
|
||||
$datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/');
|
||||
$jsonFile = \OC_Config::getValue('mount_file', $datadir . '/mount.json');
|
||||
}
|
||||
|
@ -637,11 +643,6 @@ class OC_Mount_Config {
|
|||
if (is_array($mountPoints)) {
|
||||
return $mountPoints;
|
||||
}
|
||||
} elseif (is_file($phpFile)) {
|
||||
$mountPoints = $parser->parsePHP(file_get_contents($phpFile));
|
||||
if (is_array($mountPoints)) {
|
||||
return $mountPoints;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
@ -652,7 +653,7 @@ class OC_Mount_Config {
|
|||
* @param string|null $user If not null, personal for $user, otherwise system
|
||||
* @param array $data Mount points
|
||||
*/
|
||||
private static function writeData($user, $data) {
|
||||
public static function writeData($user, $data) {
|
||||
if (isset($user)) {
|
||||
$file = OC_User::getHome($user) . '/mount.json';
|
||||
} else {
|
||||
|
@ -769,7 +770,7 @@ class OC_Mount_Config {
|
|||
* @param array $options mount options
|
||||
* @return array updated options
|
||||
*/
|
||||
private static function encryptPasswords($options) {
|
||||
public static function encryptPasswords($options) {
|
||||
if (isset($options['password'])) {
|
||||
$options['password_encrypted'] = self::encryptPassword($options['password']);
|
||||
// do not unset the password, we want to keep the keys order
|
||||
|
@ -785,7 +786,7 @@ class OC_Mount_Config {
|
|||
* @param array $options mount options
|
||||
* @return array updated options
|
||||
*/
|
||||
private static function decryptPasswords($options) {
|
||||
public static function decryptPasswords($options) {
|
||||
// note: legacy options might still have the unencrypted password in the "password" field
|
||||
if (isset($options['password_encrypted'])) {
|
||||
$options['password'] = self::decryptPassword($options['password_encrypted']);
|
||||
|
|
|
@ -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,243 @@
|
|||
<?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 {
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $backendClass;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $backendOptions = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $mountPoint;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $status;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $priority;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $applicableUsers = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $applicableGroups = [];
|
||||
|
||||
/**
|
||||
* @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 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 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 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
|
||||
*/
|
||||
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 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 applicable groups
|
||||
*/
|
||||
public function setApplicableGroups($applicableGroups) {
|
||||
if (is_null($applicableGroups)) {
|
||||
$applicableGroups = [];
|
||||
}
|
||||
$this->applicableGroups = $applicableGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (!is_null($this->status)) {
|
||||
$result['status'] = $this->status;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
<?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 string $user user or null for global config
|
||||
* @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 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);
|
||||
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,303 @@
|
|||
<?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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// group by storage id
|
||||
$storages = [];
|
||||
foreach ($mountPoints as $mountType => $applicables) {
|
||||
foreach ($applicables as $applicable => $mountPaths) {
|
||||
foreach ($mountPaths as $rootMountPath => $storageOptions) {
|
||||
// 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];
|
||||
|
||||
$configId = (int)$storageOptions['id'];
|
||||
if (isset($storages[$configId])) {
|
||||
$currentStorage = $storages[$configId];
|
||||
} else {
|
||||
$currentStorage = new StorageConfig($configId);
|
||||
$currentStorage->setMountPoint($relativeMountPath);
|
||||
}
|
||||
|
||||
$currentStorage->setBackendClass($storageOptions['class']);
|
||||
$currentStorage->setBackendOptions($storageOptions['options']);
|
||||
if (isset($storageOptions['priority'])) {
|
||||
$currentStorage->setPriority($storageOptions['priority']);
|
||||
}
|
||||
|
||||
if ($mountType === \OC_Mount_Config::MOUNT_TYPE_USER) {
|
||||
$applicableUsers = $currentStorage->getApplicableUsers();
|
||||
if ($applicable !== 'all') {
|
||||
$applicableUsers[] = $applicable;
|
||||
$currentStorage->setApplicableUsers($applicableUsers);
|
||||
}
|
||||
} else if ($mountType === \OC_Mount_Config::MOUNT_TYPE_GROUP) {
|
||||
$applicableGroups = $currentStorage->getApplicableGroups();
|
||||
$applicableGroups[] = $applicable;
|
||||
$currentStorage->setApplicableGroups($applicableGroups);
|
||||
}
|
||||
$storages[$configId] = $currentStorage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// decrypt passwords
|
||||
foreach ($storages as &$storage) {
|
||||
$storage->setBackendOptions(
|
||||
\OC_Mount_Config::decryptPasswords(
|
||||
$storage->getBackendOptions()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
$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
|
||||
*
|
||||
* @return StorageConfig
|
||||
*/
|
||||
public function getStorage($id) {
|
||||
$allStorages = $this->readConfig();
|
||||
|
||||
if (!isset($allStorages[$id])) {
|
||||
throw new NotFoundException('Storage with id "' . $id . '" not found');
|
||||
}
|
||||
|
||||
return $allStorages[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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,142 @@
|
|||
<?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 {
|
||||
/**
|
||||
* @var IUserSession
|
||||
*/
|
||||
private $userSession;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,12 +13,12 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $_['mounts'] = array_merge($_['mounts'], array('' => array())); ?>
|
||||
<?php $_['mounts'] = array_merge($_['mounts'], array('' => array('id' => ''))); ?>
|
||||
<?php foreach ($_['mounts'] as $mount): ?>
|
||||
<tr <?php print_unescaped(isset($mount['mountpoint']) ? 'class="'.OC_Util::sanitizeHTML($mount['class']).'"' : 'id="addMountPoint"'); ?>>
|
||||
<tr <?php print_unescaped(isset($mount['mountpoint']) ? 'class="'.OC_Util::sanitizeHTML($mount['class']).'"' : 'id="addMountPoint"'); ?> data-id="<?php p($mount['id']) ?>">
|
||||
<td class="status">
|
||||
<?php if (isset($mount['status'])): ?>
|
||||
<span class="<?php p(($mount['status']) ? 'success' : 'error'); ?>"></span>
|
||||
<span class="<?php p(($mount['status'] === \OC_Mount_Config::STATUS_SUCCESS) ? 'success' : 'error'); ?>"></span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="mountPoint"><input type="text" name="mountPoint"
|
||||
|
@ -28,7 +28,7 @@
|
|||
</td>
|
||||
<?php if (!isset($mount['mountpoint'])): ?>
|
||||
<td class="backend">
|
||||
<select id="selectBackend" data-configurations='<?php p(json_encode($_['backends'])); ?>'>
|
||||
<select id="selectBackend" class="selectBackend" data-configurations='<?php p(json_encode($_['backends'])); ?>'>
|
||||
<option value="" disabled selected
|
||||
style="display:none;"><?php p($l->t('Add storage')); ?></option>
|
||||
<?php foreach ($_['backends'] as $class => $backend): ?>
|
||||
|
|
|
@ -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,217 @@
|
|||
<?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']);
|
||||
|
||||
$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,112 @@
|
|||
<?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,164 @@
|
|||
/*
|
||||
* 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'
|
||||
}
|
||||
},
|
||||
'\\OC\\AnotherTestBackend': {
|
||||
'backend': 'Another Test Backend Name',
|
||||
'configuration': {
|
||||
'field1': 'Display Name 1',
|
||||
'field2': '&Display Name 2'
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
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'
|
||||
});
|
||||
|
||||
// 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,705 @@
|
|||
<?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,
|
||||
]);
|
||||
}
|
||||
|
||||
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']);
|
||||
|
||||
$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']);
|
||||
|
||||
$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']);
|
||||
|
||||
$backendOptions = $mountPointOptions['options'];
|
||||
$this->assertEquals('value1', $backendOptions['option1']);
|
||||
$this->assertEquals('value2', $backendOptions['option2']);
|
||||
$this->assertEquals('', $backendOptions['password']);
|
||||
$this->assertNotEmpty($backendOptions['password_encrypted']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
<?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']);
|
||||
}
|
||||
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,200 @@
|
|||
<?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',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
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']);
|
||||
|
||||
$backendOptions = $mountPointOptions['options'];
|
||||
$this->assertEquals('value1', $backendOptions['option1']);
|
||||
$this->assertEquals('value2', $backendOptions['option2']);
|
||||
$this->assertEquals('', $backendOptions['password']);
|
||||
$this->assertNotEmpty($backendOptions['password_encrypted']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?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']);
|
||||
|
||||
$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']);
|
||||
}
|
||||
|
||||
}
|
|
@ -123,6 +123,9 @@ window.isPhantom = /phantom/i.test(navigator.userAgent);
|
|||
|
||||
// reset plugins
|
||||
OC.Plugins._plugins = [];
|
||||
|
||||
// dummy select2 (which isn't loaded during the tests)
|
||||
$.fn.select2 = function() {};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
|
@ -131,6 +134,8 @@ window.isPhantom = /phantom/i.test(navigator.userAgent);
|
|||
fakeServer.restore();
|
||||
|
||||
$testArea.remove();
|
||||
|
||||
delete($.fn.select2);
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
@ -64,7 +64,8 @@ module.exports = function(config) {
|
|||
// only test these files, others are not ready and mess
|
||||
// up with the global namespace/classes/state
|
||||
'apps/files_external/js/app.js',
|
||||
'apps/files_external/js/mountsfilelist.js'
|
||||
'apps/files_external/js/mountsfilelist.js',
|
||||
'apps/files_external/js/settings.js'
|
||||
],
|
||||
testFiles: ['apps/files_external/tests/js/*.js']
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue