files_external: allow to register config handlers for flexible placeholders
* BackendService (directly accessable via \OC_Server) offers registerConfigHandler * SimpleSubstitutionTrait brings reusable logic for simple string replacments * internal $user replacement mechanism was migrated Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
parent
a80bae398a
commit
a26bcd8e8f
9 changed files with 423 additions and 33 deletions
|
@ -29,6 +29,7 @@
|
|||
|
||||
namespace OCA\Files_External\AppInfo;
|
||||
|
||||
use OCA\Files_External\Config\UserPlaceholderHandler;
|
||||
use OCA\Files_External\Lib\Auth\PublicKey\RSAPrivateKey;
|
||||
use OCA\Files_External\Lib\Auth\SMB\KerberosAuth;
|
||||
use \OCP\AppFramework\App;
|
||||
|
@ -67,7 +68,12 @@ use OCP\Files\Config\IUserMountCache;
|
|||
*/
|
||||
class Application extends App implements IBackendProvider, IAuthMechanismProvider {
|
||||
|
||||
public function __construct(array $urlParams = array()) {
|
||||
/**
|
||||
* Application constructor.
|
||||
*
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function __construct(array $urlParams = []) {
|
||||
parent::__construct('files_external', $urlParams);
|
||||
|
||||
$container = $this->getContainer();
|
||||
|
@ -76,9 +82,13 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide
|
|||
return $c->getServer()->query('UserMountCache');
|
||||
});
|
||||
|
||||
/** @var BackendService $backendService */
|
||||
$backendService = $container->query(BackendService::class);
|
||||
$backendService->registerBackendProvider($this);
|
||||
$backendService->registerAuthMechanismProvider($this);
|
||||
$backendService->registerConfigHandler('user', function() use ($container) {
|
||||
return $container->query(UserPlaceholderHandler::class);
|
||||
});
|
||||
|
||||
// force-load auth mechanisms since some will register hooks
|
||||
// TODO: obsolete these and use the TokenProvider to get the user's password from the session
|
||||
|
|
|
@ -29,7 +29,6 @@ namespace OCA\Files_External\Config;
|
|||
use OC\Files\Storage\Wrapper\Availability;
|
||||
use OCA\Files_External\Migration\StorageMigrator;
|
||||
use OCP\Files\Storage;
|
||||
use OC\Files\Mount\MountPoint;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCA\Files_External\Lib\PersonalMount;
|
||||
use OCP\Files\Config\IMountProvider;
|
||||
|
@ -73,12 +72,11 @@ class ConfigAdapter implements IMountProvider {
|
|||
*
|
||||
* @param StorageConfig $storage
|
||||
* @param IUser $user
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
private function prepareStorageConfig(StorageConfig &$storage, IUser $user) {
|
||||
foreach ($storage->getBackendOptions() as $option => $value) {
|
||||
$storage->setBackendOption($option, \OC_Mount_Config::setUserVars(
|
||||
$user->getUID(), $value
|
||||
));
|
||||
$storage->setBackendOption($option, \OC_Mount_Config::substitutePlaceholdersInConfig($value));
|
||||
}
|
||||
|
||||
$objectStore = $storage->getBackendOption('objectstore');
|
||||
|
|
39
apps/files_external/lib/Config/IConfigHandler.php
Normal file
39
apps/files_external/lib/Config/IConfigHandler.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Files_External\Config;
|
||||
|
||||
/**
|
||||
* Interface IConfigHandler
|
||||
*
|
||||
* @package OCA\Files_External\Config
|
||||
* @since 16.0.0
|
||||
*/
|
||||
interface IConfigHandler {
|
||||
/**
|
||||
* @param mixed $optionValue
|
||||
* @return mixed the same type as $optionValue
|
||||
* @since 16.0.0
|
||||
*/
|
||||
public function handle($optionValue);
|
||||
}
|
86
apps/files_external/lib/Config/SimpleSubstitutionTrait.php
Normal file
86
apps/files_external/lib/Config/SimpleSubstitutionTrait.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Files_External\Config;
|
||||
|
||||
/**
|
||||
* Trait SimpleSubstitutionTrait
|
||||
*
|
||||
* @package OCA\Files_External\Config
|
||||
* @since 16.0.0
|
||||
*/
|
||||
trait SimpleSubstitutionTrait {
|
||||
/**
|
||||
* @var string the placeholder without @ prefix
|
||||
* @since 16.0.0
|
||||
*/
|
||||
private $placeholder;
|
||||
|
||||
/** @var string */
|
||||
protected $sanitizedPlaceholder;
|
||||
|
||||
/**
|
||||
* @param mixed $optionValue
|
||||
* @param string $replacement
|
||||
* @return mixed
|
||||
* @since 16.0.0
|
||||
*/
|
||||
private function processInput($optionValue, string $replacement) {
|
||||
$this->checkPlaceholder();
|
||||
if (is_array($optionValue)) {
|
||||
foreach ($optionValue as &$value) {
|
||||
$value = $this->substituteIfString($value, $replacement);
|
||||
}
|
||||
} else {
|
||||
$optionValue = $this->substituteIfString($optionValue, $replacement);
|
||||
}
|
||||
return $optionValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function checkPlaceholder(): void {
|
||||
$this->sanitizedPlaceholder = trim(strtolower($this->placeholder));
|
||||
if(!(bool)\preg_match('/^[a-z0-9]*$/', $this->sanitizedPlaceholder)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Invalid placeholder %s, only [a-z0-9] are allowed', $this->sanitizedPlaceholder
|
||||
));
|
||||
}
|
||||
if($this->sanitizedPlaceholder === '') {
|
||||
throw new \RuntimeException('Invalid empty placeholder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param string $replacement
|
||||
* @return mixed
|
||||
*/
|
||||
protected function substituteIfString($value, string $replacement) {
|
||||
if(is_string($value)) {
|
||||
return str_ireplace('$' . $this->sanitizedPlaceholder, $replacement, $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
53
apps/files_external/lib/Config/UserPlaceholderHandler.php
Normal file
53
apps/files_external/lib/Config/UserPlaceholderHandler.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Files_External\Config;
|
||||
|
||||
use OCP\IUserSession;
|
||||
|
||||
class UserPlaceholderHandler implements IConfigHandler {
|
||||
use SimpleSubstitutionTrait;
|
||||
|
||||
/** @var IUserSession */
|
||||
private $session;
|
||||
|
||||
public function __construct(IUserSession $session) {
|
||||
$this->session = $session;
|
||||
$this->placeholder = 'user';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $optionValue
|
||||
* @return mixed the same type as $optionValue
|
||||
* @since 16.0.0
|
||||
*/
|
||||
public function handle($optionValue) {
|
||||
$user = $this->session->getUser();
|
||||
if($user === null) {
|
||||
return $optionValue;
|
||||
}
|
||||
$uid = $user->getUID();
|
||||
|
||||
return $this->processInput($optionValue, $uid);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
namespace OCA\Files_External\Service;
|
||||
|
||||
use OCA\Files_External\Config\IConfigHandler;
|
||||
use \OCP\IConfig;
|
||||
|
||||
use \OCA\Files_External\Lib\Backend\Backend;
|
||||
|
@ -67,6 +68,11 @@ class BackendService {
|
|||
/** @var IAuthMechanismProvider[] */
|
||||
private $authMechanismProviders = [];
|
||||
|
||||
/** @var callable[] */
|
||||
private $configHandlerLoaders = [];
|
||||
|
||||
private $configHandlers = [];
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
*/
|
||||
|
@ -280,4 +286,66 @@ class BackendService {
|
|||
protected function isAllowedAuthMechanism(AuthMechanism $authMechanism) {
|
||||
return true; // not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* registers a configuration handler
|
||||
*
|
||||
* The function of the provided $placeholder is mostly to act a sorting
|
||||
* criteria, so longer placeholders are replaced first. This avoids
|
||||
* "@user" overwriting parts of "@userMail" and "@userLang", for example.
|
||||
* The provided value should not contain the @ prefix, only a-z0-9 are
|
||||
* allowed. Upper case letters are lower cased, the replacement is case-
|
||||
* insensitive.
|
||||
*
|
||||
* The configHandlerLoader should just instantiate the handler on demand.
|
||||
* For now all handlers are instantiated when a mount is loaded, independent
|
||||
* of whether the placeholder is present or not. This may change in future.
|
||||
*
|
||||
* @since 16.0.0
|
||||
*/
|
||||
public function registerConfigHandler(string $placeholder, callable $configHandlerLoader) {
|
||||
$placeholder = trim(strtolower($placeholder));
|
||||
if(!(bool)\preg_match('/^[a-z0-9]*$/', $placeholder)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Invalid placeholder %s, only [a-z0-9] are allowed', $placeholder
|
||||
));
|
||||
}
|
||||
if($placeholder === '') {
|
||||
throw new \RuntimeException('Invalid empty placeholder');
|
||||
}
|
||||
if(isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) {
|
||||
throw new \RuntimeException(sprintf('A handler is already registered for %s', $placeholder));
|
||||
}
|
||||
$this->configHandlerLoaders[$placeholder] = $configHandlerLoader;
|
||||
}
|
||||
|
||||
protected function loadConfigHandlers():void {
|
||||
$newLoaded = false;
|
||||
foreach ($this->configHandlerLoaders as $placeholder => $loader) {
|
||||
$handler = $loader();
|
||||
if(!$handler instanceof IConfigHandler) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Handler for %s is not an instance of IConfigHandler', $placeholder
|
||||
));
|
||||
}
|
||||
$this->configHandlers[] = $handler;
|
||||
$newLoaded = true;
|
||||
}
|
||||
$this->configHandlerLoaders = [];
|
||||
if($newLoaded) {
|
||||
// ensure those with longest placeholders come first,
|
||||
// to avoid substring matches
|
||||
uksort($this->configHandlers, function ($phA, $phB) {
|
||||
return strlen($phB) <=> strlen($phA);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 16.0.0
|
||||
*/
|
||||
public function getConfigHandlers() {
|
||||
$this->loadConfigHandlers();
|
||||
return $this->configHandlers;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
use OCA\Files_External\Config\IConfigHandler;
|
||||
use OCA\Files_External\Config\UserPlaceholderHandler;
|
||||
use phpseclib\Crypt\AES;
|
||||
use \OCA\Files_External\AppInfo\Application;
|
||||
use \OCA\Files_External\Lib\Backend\LegacyBackend;
|
||||
|
@ -104,7 +106,7 @@ class OC_Mount_Config {
|
|||
$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
|
||||
$mountEntry = self::prepareMountPointEntry($storage, false);
|
||||
foreach ($mountEntry['options'] as &$option) {
|
||||
$option = self::setUserVars($uid, $option);
|
||||
$option = self::substitutePlaceholdersInConfig($option);
|
||||
}
|
||||
$mountPoints[$mountPoint] = $mountEntry;
|
||||
}
|
||||
|
@ -113,7 +115,7 @@ class OC_Mount_Config {
|
|||
$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
|
||||
$mountEntry = self::prepareMountPointEntry($storage, true);
|
||||
foreach ($mountEntry['options'] as &$option) {
|
||||
$option = self::setUserVars($uid, $option);
|
||||
$option = self::substitutePlaceholdersInConfig($uid, $option);
|
||||
}
|
||||
$mountPoints[$mountPoint] = $mountEntry;
|
||||
}
|
||||
|
@ -199,18 +201,26 @@ class OC_Mount_Config {
|
|||
* @param string $user user value
|
||||
* @param string|array $input
|
||||
* @return string
|
||||
* @deprecated use self::substitutePlaceholdersInConfig($input)
|
||||
*/
|
||||
public static function setUserVars($user, $input) {
|
||||
if (is_array($input)) {
|
||||
foreach ($input as &$value) {
|
||||
if (is_string($value)) {
|
||||
$value = str_replace('$user', $user, $value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_string($input)) {
|
||||
$input = str_replace('$user', $user, $input);
|
||||
}
|
||||
$handler = self::$app->getContainer()->query(UserPlaceholderHandler::class);
|
||||
return $handler->handle($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $input
|
||||
* @return mixed
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
* @since 16.0.0
|
||||
*/
|
||||
public static function substitutePlaceholdersInConfig($input) {
|
||||
/** @var BackendService $backendService */
|
||||
$backendService = self::$app->getContainer()->query(BackendService::class);
|
||||
/** @var IConfigHandler[] $handlers */
|
||||
$handlers = $backendService->getConfigHandlers();
|
||||
foreach ($handlers as $handler) {
|
||||
$input = $handler->handle($input);
|
||||
}
|
||||
return $input;
|
||||
}
|
||||
|
@ -229,7 +239,7 @@ class OC_Mount_Config {
|
|||
return StorageNotAvailableException::STATUS_SUCCESS;
|
||||
}
|
||||
foreach ($options as &$option) {
|
||||
$option = self::setUserVars(OCP\User::getUser(), $option);
|
||||
$option = self::substitutePlaceholdersInConfig($option);
|
||||
}
|
||||
if (class_exists($class)) {
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\files_external\tests\Config;
|
||||
|
||||
use OCA\Files_External\Config\UserPlaceholderHandler;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
|
||||
class UserPlaceholderHandlerTest extends \Test\TestCase {
|
||||
/** @var IUser|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $user;
|
||||
|
||||
/** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $session;
|
||||
|
||||
/** @var UserPlaceholderHandler */
|
||||
protected $handler;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
$this->user->expects($this->any())
|
||||
->method('getUid')
|
||||
->willReturn('alice');
|
||||
$this->session = $this->createMock(IUserSession::class);
|
||||
|
||||
$this->handler = new UserPlaceholderHandler($this->session);
|
||||
}
|
||||
|
||||
protected function setUser() {
|
||||
$this->session->expects($this->any())
|
||||
->method('getUser')
|
||||
->willReturn($this->user);
|
||||
}
|
||||
|
||||
public function optionProvider() {
|
||||
return [
|
||||
['/foo/bar/$user/foobar', '/foo/bar/alice/foobar'],
|
||||
[['/foo/bar/$user/foobar'], ['/foo/bar/alice/foobar']],
|
||||
[['/FOO/BAR/$USER/FOOBAR'], ['/FOO/BAR/alice/FOOBAR']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider optionProvider
|
||||
*/
|
||||
public function testHandle($option, $expected) {
|
||||
$this->setUser();
|
||||
$this->assertSame($expected, $this->handler->handle($option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider optionProvider
|
||||
*/
|
||||
public function testHandleNoUser($option) {
|
||||
$this->assertSame($option, $this->handler->handle($option));
|
||||
}
|
||||
|
||||
}
|
|
@ -23,31 +23,27 @@
|
|||
*/
|
||||
namespace OCA\Files_External\Tests\Service;
|
||||
|
||||
use OCA\Files_External\Config\IConfigHandler;
|
||||
use OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use OCA\Files_External\Lib\Backend\Backend;
|
||||
use OCA\Files_External\Lib\Config\IAuthMechanismProvider;
|
||||
use OCA\Files_External\Lib\Config\IBackendProvider;
|
||||
use \OCA\Files_External\Service\BackendService;
|
||||
use OCA\Files_External\Service\BackendService;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
|
||||
class BackendServiceTest extends \Test\TestCase {
|
||||
|
||||
/** @var \OCP\IConfig */
|
||||
/** @var \OCP\IConfig|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $config;
|
||||
|
||||
/** @var \OCP\IL10N */
|
||||
protected $l10n;
|
||||
|
||||
protected function setUp() {
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->l10n = $this->createMock(IL10N::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return \OCA\Files_External\Lib\Backend\Backend
|
||||
* @return \OCA\Files_External\Lib\Backend\Backend|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected function getBackendMock($class) {
|
||||
$backend = $this->getMockBuilder(Backend::class)
|
||||
|
@ -61,7 +57,7 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return \OCA\Files_External\Lib\Auth\AuthMechanism
|
||||
* @return \OCA\Files_External\Lib\Auth\AuthMechanism|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected function getAuthMechanismMock($class) {
|
||||
$backend = $this->getMockBuilder(AuthMechanism::class)
|
||||
|
@ -73,10 +69,11 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testRegisterBackend() {
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
$service = new BackendService($this->config);
|
||||
|
||||
$backend = $this->getBackendMock('\Foo\Bar');
|
||||
|
||||
/** @var \OCA\Files_External\Lib\Backend\Backend|\PHPUnit_Framework_MockObject_MockObject $backendAlias */
|
||||
$backendAlias = $this->getMockBuilder(Backend::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
@ -100,11 +97,12 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testBackendProvider() {
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
$service = new BackendService($this->config);
|
||||
|
||||
$backend1 = $this->getBackendMock('\Foo\Bar');
|
||||
$backend2 = $this->getBackendMock('\Bar\Foo');
|
||||
|
||||
/** @var IBackendProvider|\PHPUnit_Framework_MockObject_MockObject $providerMock */
|
||||
$providerMock = $this->createMock(IBackendProvider::class);
|
||||
$providerMock->expects($this->once())
|
||||
->method('getBackends')
|
||||
|
@ -118,11 +116,12 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testAuthMechanismProvider() {
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
$service = new BackendService($this->config);
|
||||
|
||||
$backend1 = $this->getAuthMechanismMock('\Foo\Bar');
|
||||
$backend2 = $this->getAuthMechanismMock('\Bar\Foo');
|
||||
|
||||
/** @var IAuthMechanismProvider|\PHPUnit_Framework_MockObject_MockObject $providerMock */
|
||||
$providerMock = $this->createMock(IAuthMechanismProvider::class);
|
||||
$providerMock->expects($this->once())
|
||||
->method('getAuthMechanisms')
|
||||
|
@ -136,18 +135,20 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testMultipleBackendProviders() {
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
$service = new BackendService($this->config);
|
||||
|
||||
$backend1a = $this->getBackendMock('\Foo\Bar');
|
||||
$backend1b = $this->getBackendMock('\Bar\Foo');
|
||||
|
||||
$backend2 = $this->getBackendMock('\Dead\Beef');
|
||||
|
||||
/** @var IBackendProvider|\PHPUnit_Framework_MockObject_MockObject $provider1Mock */
|
||||
$provider1Mock = $this->createMock(IBackendProvider::class);
|
||||
$provider1Mock->expects($this->once())
|
||||
->method('getBackends')
|
||||
->willReturn([$backend1a, $backend1b]);
|
||||
$service->registerBackendProvider($provider1Mock);
|
||||
/** @var IBackendProvider|\PHPUnit_Framework_MockObject_MockObject $provider2Mock */
|
||||
$provider2Mock = $this->createMock(IBackendProvider::class);
|
||||
$provider2Mock->expects($this->once())
|
||||
->method('getBackends')
|
||||
|
@ -169,7 +170,7 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
['files_external', 'user_mounting_backends', '', 'identifier:\User\Mount\Allowed,identifier_alias']
|
||||
]));
|
||||
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
$service = new BackendService($this->config);
|
||||
|
||||
$backendAllowed = $this->getBackendMock('\User\Mount\Allowed');
|
||||
$backendAllowed->expects($this->never())
|
||||
|
@ -193,7 +194,7 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testGetAvailableBackends() {
|
||||
$service = new BackendService($this->config, $this->l10n);
|
||||
$service = new BackendService($this->config);
|
||||
|
||||
$backendAvailable = $this->getBackendMock('\Backend\Available');
|
||||
$backendAvailable->expects($this->once())
|
||||
|
@ -216,5 +217,49 @@ class BackendServiceTest extends \Test\TestCase {
|
|||
$this->assertArrayNotHasKey('identifier:\Backend\NotAvailable', $availableBackends);
|
||||
}
|
||||
|
||||
public function invalidConfigPlaceholderProvider() {
|
||||
return [
|
||||
[['@user']],
|
||||
[['hællo']],
|
||||
[['spa ce']],
|
||||
[['yo\o']],
|
||||
[['<script>…</script>']],
|
||||
[['xxyoloxx', 'invÆlid']],
|
||||
[['tautology', 'tautology']],
|
||||
[['tautology2', 'TAUTOLOGY2']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidConfigPlaceholderProvider
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
public function testRegisterConfigHandlerInvalid(array $placeholders) {
|
||||
$service = new BackendService($this->config);
|
||||
$mock = $this->createMock(IConfigHandler::class);
|
||||
$cb = function () use ($mock) { return $mock; };
|
||||
foreach ($placeholders as $placeholder) {
|
||||
$service->registerConfigHandler($placeholder, $cb);
|
||||
}
|
||||
}
|
||||
|
||||
public function testConfigHandlers() {
|
||||
$service = new BackendService($this->config);
|
||||
$mock = $this->createMock(IConfigHandler::class);
|
||||
$mock->expects($this->exactly(3))
|
||||
->method('handle');
|
||||
$cb = function () use ($mock) { return $mock; };
|
||||
$service->registerConfigHandler('one', $cb);
|
||||
$service->registerConfigHandler('2', $cb);
|
||||
$service->registerConfigHandler('Three', $cb);
|
||||
|
||||
/** @var IConfigHandler[] $handlers */
|
||||
$handlers = $service->getConfigHandlers();
|
||||
|
||||
foreach ($handlers as $handler) {
|
||||
$handler->handle('Something');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue