@@ -0,0 +1,136 @@ | |||
<?php | |||
/** | |||
* @author Björn Schießle <schiessle@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\Federation\API; | |||
use OC\BackgroundJob\JobList; | |||
use OCA\Federation\DbHandler; | |||
use OCA\Federation\TrustedServers; | |||
use OCP\AppFramework\Http; | |||
use OCP\IRequest; | |||
use OCP\Security\ISecureRandom; | |||
use OCP\Security\StringUtils; | |||
/** | |||
* Class OCSAuthAPI | |||
* | |||
* OCS API end-points to exchange shared secret between two connected ownClouds | |||
* | |||
* @package OCA\Federation\API | |||
*/ | |||
class OCSAuthAPI { | |||
/** @var IRequest */ | |||
private $request; | |||
/** @var ISecureRandom */ | |||
private $secureRandom; | |||
/** @var JobList */ | |||
private $jobList; | |||
/** @var TrustedServers */ | |||
private $trustedServers; | |||
/** @var DbHandler */ | |||
private $dbHandler; | |||
/** | |||
* AuthController constructor. | |||
* | |||
* @param IRequest $request | |||
* @param ISecureRandom $secureRandom | |||
* @param JobList $jobList | |||
* @param TrustedServers $trustedServers | |||
* @param DbHandler $dbHandler | |||
*/ | |||
public function __construct( | |||
IRequest $request, | |||
ISecureRandom $secureRandom, | |||
JobList $jobList, | |||
TrustedServers $trustedServers, | |||
DbHandler $dbHandler | |||
) { | |||
$this->request = $request; | |||
$this->secureRandom = $secureRandom; | |||
$this->jobList = $jobList; | |||
$this->trustedServers = $trustedServers; | |||
$this->dbHandler = $dbHandler; | |||
} | |||
/** | |||
* request received to ask remote server for a shared secret | |||
* | |||
* @return \OC_OCS_Result | |||
*/ | |||
public function requestSharedSecret() { | |||
$url = $this->request->getParam('url'); | |||
$token = $this->request->getParam('token'); | |||
if ($this->trustedServers->isTrustedServer($url) === false) { | |||
return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN); | |||
} | |||
$this->jobList->add( | |||
'OCA\Federation\BackgroundJob\GetSharedSecret', | |||
[ | |||
'url' => $url, | |||
'token' => $token, | |||
] | |||
); | |||
return new \OC_OCS_Result(null, Http::STATUS_OK); | |||
} | |||
/** | |||
* create shared secret and return it | |||
* | |||
* @return \OC_OCS_Result | |||
*/ | |||
public function getSharedSecret() { | |||
$url = $this->request->getParam('url'); | |||
$token = $this->request->getParam('token'); | |||
if ( | |||
$this->trustedServers->isTrustedServer($url) === false | |||
|| $this->isValidToken($url, $token) === false | |||
) { | |||
return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN); | |||
} | |||
$sharedSecret = $this->secureRandom->getMediumStrengthGenerator()->generate(32); | |||
$this->trustedServers->addSharedSecret($url, $sharedSecret); | |||
return new \OC_OCS_Result(['sharedSecret' => $sharedSecret], Http::STATUS_OK); | |||
} | |||
protected function isValidToken($url, $token) { | |||
$storedToken = $this->dbHandler->getToken($url); | |||
return StringUtils::equals($storedToken, $token); | |||
} | |||
} |
@@ -21,13 +21,15 @@ | |||
namespace OCA\Federation\AppInfo; | |||
use OCA\Federation\API\OCSAuthAPI; | |||
use OCA\Federation\Controller\AuthController; | |||
use OCA\Federation\Controller\SettingsController; | |||
use OCA\Federation\DbHandler; | |||
use OCA\Federation\Middleware\AddServerMiddleware; | |||
use OCA\Federation\TrustedServers; | |||
use OCP\API; | |||
use OCP\App; | |||
use OCP\AppFramework\IAppContainer; | |||
use OCP\IAppConfig; | |||
class Application extends \OCP\AppFramework\App { | |||
@@ -38,7 +40,6 @@ class Application extends \OCP\AppFramework\App { | |||
parent::__construct('federation', $urlParams); | |||
$this->registerService(); | |||
$this->registerMiddleware(); | |||
} | |||
/** | |||
@@ -70,7 +71,9 @@ class Application extends \OCP\AppFramework\App { | |||
return new TrustedServers( | |||
$c->query('DbHandler'), | |||
\OC::$server->getHTTPClientService(), | |||
\OC::$server->getLogger() | |||
\OC::$server->getLogger(), | |||
\OC::$server->getJobList(), | |||
\OC::$server->getSecureRandom() | |||
); | |||
}); | |||
@@ -83,10 +86,57 @@ class Application extends \OCP\AppFramework\App { | |||
$c->query('TrustedServers') | |||
); | |||
}); | |||
$container->registerService('AuthController', function (IAppContainer $c) { | |||
$server = $c->getServer(); | |||
return new AuthController( | |||
$c->getAppName(), | |||
$server->getRequest(), | |||
$server->getSecureRandom(), | |||
$server->getJobList(), | |||
$c->query('TrustedServers'), | |||
$c->query('DbHandler') | |||
); | |||
}); | |||
} | |||
private function registerMiddleware() { | |||
$container = $this->getContainer(); | |||
$container->registerMiddleware('addServerMiddleware'); | |||
} | |||
/** | |||
* register OCS API Calls | |||
*/ | |||
public function registerOCSApi() { | |||
$container = $this->getContainer(); | |||
$server = $container->getServer(); | |||
$auth = new OCSAuthAPI( | |||
$server->getRequest(), | |||
$server->getSecureRandom(), | |||
$server->getJobList(), | |||
$container->query('TrustedServers'), | |||
$container->query('DbHandler') | |||
); | |||
API::register('get', | |||
'/apps/federation/api/v1/shared-secret', | |||
array($auth, 'getSharedSecret'), | |||
'federation', | |||
API::GUEST_AUTH | |||
); | |||
API::register('post', | |||
'/apps/federation/api/v1/request-shared-secret', | |||
array($auth, 'requestSharedSecret'), | |||
'federation', | |||
API::GUEST_AUTH | |||
); | |||
} | |||
} |
@@ -28,7 +28,27 @@ | |||
<default></default> | |||
<notnull>true</notnull> | |||
<length>32</length> | |||
<comments>md5 hash of the url</comments> | |||
<comments>md5 hash of the url without the protocol</comments> | |||
</field> | |||
<field> | |||
<name>token</name> | |||
<type>text</type> | |||
<length>128</length> | |||
<comments>toke used to exchange the shared secret</comments> | |||
</field> | |||
<field> | |||
<name>shared_secret</name> | |||
<type>text</type> | |||
<length>256</length> | |||
<comments>shared secret used to authenticate</comments> | |||
</field> | |||
<field> | |||
<name>status</name> | |||
<type>integer</type> | |||
<length>4</length> | |||
<notnull>true</notnull> | |||
<default>2</default> | |||
<comments>current status of the connection</comments> | |||
</field> | |||
<index> | |||
<name>url_hash</name> |
@@ -19,17 +19,24 @@ | |||
* | |||
*/ | |||
return [ | |||
'routes' => [ | |||
[ | |||
'name' => 'Settings#addServer', | |||
'url' => '/trusted-servers', | |||
'verb' => 'POST' | |||
], | |||
[ | |||
'name' => 'Settings#removeServer', | |||
'url' => '/trusted-servers/{id}', | |||
'verb' => 'DELETE' | |||
], | |||
] | |||
]; | |||
$application = new \OCA\Federation\AppInfo\Application(); | |||
$application->registerRoutes( | |||
$this, | |||
[ | |||
'routes' => [ | |||
[ | |||
'name' => 'Settings#addServer', | |||
'url' => '/trusted-servers', | |||
'verb' => 'POST' | |||
], | |||
[ | |||
'name' => 'Settings#removeServer', | |||
'url' => '/trusted-servers/{id}', | |||
'verb' => 'DELETE' | |||
], | |||
] | |||
] | |||
); | |||
$application->registerOCSApi(); |
@@ -0,0 +1,155 @@ | |||
<?php | |||
/** | |||
* @author Björn Schießle <schiessle@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\Federation\BackgroundJob; | |||
use OC\BackgroundJob\QueuedJob; | |||
use OCA\Federation\DbHandler; | |||
use OCA\Federation\TrustedServers; | |||
use OCP\AppFramework\Http; | |||
use OCP\BackgroundJob\IJobList; | |||
use OCP\Http\Client\IClient; | |||
use OCP\ILogger; | |||
use OCP\IURLGenerator; | |||
/** | |||
* Class GetSharedSecret | |||
* | |||
* request shared secret from remote ownCloud | |||
* | |||
* @package OCA\Federation\Backgroundjob | |||
*/ | |||
class GetSharedSecret extends QueuedJob{ | |||
/** @var IClient */ | |||
private $httpClient; | |||
/** @var IJobList */ | |||
private $jobList; | |||
/** @var IURLGenerator */ | |||
private $urlGenerator; | |||
/** @var TrustedServers */ | |||
private $trustedServers; | |||
/** @var ILogger */ | |||
private $logger; | |||
private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json'; | |||
/** | |||
* RequestSharedSecret constructor. | |||
* | |||
* @param IClient $httpClient | |||
* @param IURLGenerator $urlGenerator | |||
* @param IJobList $jobList | |||
* @param TrustedServers $trustedServers | |||
* @param ILogger $logger | |||
*/ | |||
public function __construct( | |||
IClient $httpClient = null, | |||
IURLGenerator $urlGenerator = null, | |||
IJobList $jobList = null, | |||
TrustedServers $trustedServers = null, | |||
ILogger $logger = null | |||
) { | |||
$this->logger = $logger ? $logger : \OC::$server->getLogger(); | |||
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient(); | |||
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList(); | |||
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator(); | |||
if ($trustedServers) { | |||
$this->trustedServers = $trustedServers; | |||
} else { | |||
$this->trustedServers = new TrustedServers( | |||
new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')), | |||
\OC::$server->getHTTPClientService(), | |||
\OC::$server->getLogger(), | |||
$this->jobList, | |||
\OC::$server->getSecureRandom() | |||
); | |||
} | |||
} | |||
/** | |||
* run the job, then remove it from the joblist | |||
* | |||
* @param JobList $jobList | |||
* @param ILogger $logger | |||
*/ | |||
public function execute($jobList, ILogger $logger = null) { | |||
$jobList->remove($this, $this->argument); | |||
$target = $this->argument['url']; | |||
// only execute if target is still in the list of trusted domains | |||
if ($this->trustedServers->isTrustedServer($target)) { | |||
parent::execute($jobList, $logger); | |||
} | |||
} | |||
protected function run($argument) { | |||
$target = $argument['url']; | |||
$source = $this->urlGenerator->getAbsoluteURL('/'); | |||
$source = rtrim($source, '/'); | |||
$token = $argument['token']; | |||
$result = $this->httpClient->get( | |||
$target . $this->endPoint, | |||
[ | |||
'query' => | |||
[ | |||
'url' => $source, | |||
'token' => $token | |||
], | |||
'timeout' => 3, | |||
'connect_timeout' => 3, | |||
] | |||
); | |||
$status = $result->getStatusCode(); | |||
// if we received a unexpected response we try again later | |||
if ( | |||
$status !== Http::STATUS_OK | |||
&& $status !== Http::STATUS_FORBIDDEN | |||
) { | |||
$this->jobList->add( | |||
'OCA\Federation\Backgroundjob\RequestSharedSecret', | |||
$argument | |||
); | |||
} elseif ($status === Http::STATUS_OK) { | |||
$body = $result->getBody(); | |||
$result = json_decode($body, true); | |||
if (isset($result['ocs']['data']['sharedSecret'])) { | |||
$this->trustedServers->addSharedSecret( | |||
$target, | |||
$result['ocs']['data']['sharedSecret'] | |||
); | |||
} else { | |||
$this->logger->error( | |||
'remote server "' . $target . '"" does not return a valid shared secret', | |||
['app' => 'federation'] | |||
); | |||
$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,134 @@ | |||
<?php | |||
/** | |||
* @author Björn Schießle <schiessle@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\Federation\BackgroundJob; | |||
use OC\BackgroundJob\QueuedJob; | |||
use OCA\Federation\DbHandler; | |||
use OCA\Federation\TrustedServers; | |||
use OCP\AppFramework\Http; | |||
use OCP\BackgroundJob\IJobList; | |||
use OCP\Http\Client\IClient; | |||
use OCP\ILogger; | |||
use OCP\IURLGenerator; | |||
/** | |||
* Class RequestSharedSecret | |||
* | |||
* Ask remote ownCloud to request a sharedSecret from this server | |||
* | |||
* @package OCA\Federation\Backgroundjob | |||
*/ | |||
class RequestSharedSecret extends QueuedJob { | |||
/** @var IClient */ | |||
private $httpClient; | |||
/** @var IJobList */ | |||
private $jobList; | |||
/** @var IURLGenerator */ | |||
private $urlGenerator; | |||
private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json'; | |||
/** | |||
* RequestSharedSecret constructor. | |||
* | |||
* @param IClient $httpClient | |||
* @param IURLGenerator $urlGenerator | |||
* @param IJobList $jobList | |||
* @param TrustedServers $trustedServers | |||
*/ | |||
public function __construct( | |||
IClient $httpClient = null, | |||
IURLGenerator $urlGenerator = null, | |||
IJobList $jobList = null, | |||
TrustedServers $trustedServers = null | |||
) { | |||
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient(); | |||
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList(); | |||
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator(); | |||
if ($trustedServers) { | |||
$this->trustedServers = $trustedServers; | |||
} else { | |||
$this->trustedServers = new TrustedServers( | |||
new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation')), | |||
\OC::$server->getHTTPClientService(), | |||
\OC::$server->getLogger(), | |||
$this->jobList, | |||
\OC::$server->getSecureRandom() | |||
); | |||
} | |||
} | |||
/** | |||
* run the job, then remove it from the joblist | |||
* | |||
* @param JobList $jobList | |||
* @param ILogger $logger | |||
*/ | |||
public function execute($jobList, ILogger $logger = null) { | |||
$jobList->remove($this, $this->argument); | |||
$target = $this->argument['url']; | |||
// only execute if target is still in the list of trusted domains | |||
if ($this->trustedServers->isTrustedServer($target)) { | |||
parent::execute($jobList, $logger); | |||
} | |||
} | |||
protected function run($argument) { | |||
$target = $argument['url']; | |||
$source = $this->urlGenerator->getAbsoluteURL('/'); | |||
$source = rtrim($source, '/'); | |||
$token = $argument['token']; | |||
$result = $this->httpClient->post( | |||
$target . $this->endPoint, | |||
[ | |||
'body' => [ | |||
'url' => $source, | |||
'token' => $token, | |||
], | |||
'timeout' => 3, | |||
'connect_timeout' => 3, | |||
] | |||
); | |||
$status = $result->getStatusCode(); | |||
// if we received a unexpected response we try again later | |||
if ( | |||
$status !== Http::STATUS_OK | |||
&& $status !== Http::STATUS_FORBIDDEN | |||
) { | |||
$this->jobList->add( | |||
'OCA\Federation\BackgroundJob\RequestSharedSecret', | |||
$argument | |||
); | |||
} | |||
} | |||
} |
@@ -23,10 +23,19 @@ | |||
namespace OCA\Federation; | |||
use OC\Files\Filesystem; | |||
use OC\HintException; | |||
use OCP\IDBConnection; | |||
use OCP\IL10N; | |||
/** | |||
* Class DbHandler | |||
* | |||
* handles all database calls for the federation app | |||
* | |||
* @group DB | |||
* @package OCA\Federation | |||
*/ | |||
class DbHandler { | |||
/** @var IDBConnection */ | |||
@@ -53,12 +62,12 @@ class DbHandler { | |||
/** | |||
* add server to the list of trusted ownCloud servers | |||
* | |||
* @param $url | |||
* @param string $url | |||
* @return int | |||
* @throws HintException | |||
*/ | |||
public function add($url) { | |||
$hash = md5($url); | |||
public function addServer($url) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->insert($this->dbTable) | |||
->values( | |||
@@ -73,14 +82,7 @@ class DbHandler { | |||
$result = $query->execute(); | |||
if ($result) { | |||
$id = $this->connection->lastInsertId(); | |||
// Fallback, if lastInterId() doesn't work we need to perform a select | |||
// to get the ID (seems to happen sometimes on Oracle) | |||
if (!$id) { | |||
$server = $this->get($url); | |||
$id = $server['id']; | |||
} | |||
return $id; | |||
return $this->connection->lastInsertId($this->dbTable); | |||
} else { | |||
$message = 'Internal failure, Could not add ownCloud as trusted server: ' . $url; | |||
$message_t = $this->l->t('Could not add server'); | |||
@@ -93,7 +95,7 @@ class DbHandler { | |||
* | |||
* @param int $id | |||
*/ | |||
public function remove($id) { | |||
public function removeServer($id) { | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->delete($this->dbTable) | |||
->where($query->expr()->eq('id', $query->createParameter('id'))) | |||
@@ -101,27 +103,12 @@ class DbHandler { | |||
$query->execute(); | |||
} | |||
/** | |||
* get trusted server from database | |||
* | |||
* @param $url | |||
* @return mixed | |||
*/ | |||
public function get($url) { | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->select('url', 'id')->from($this->dbTable) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', md5($url)); | |||
return $query->execute()->fetch(); | |||
} | |||
/** | |||
* get all trusted servers | |||
* | |||
* @return array | |||
*/ | |||
public function getAll() { | |||
public function getAllServer() { | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->select('url', 'id')->from($this->dbTable); | |||
$result = $query->execute()->fetchAll(); | |||
@@ -134,14 +121,149 @@ class DbHandler { | |||
* @param string $url | |||
* @return bool | |||
*/ | |||
public function exists($url) { | |||
public function serverExists($url) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->select('url')->from($this->dbTable) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', md5($url)); | |||
->setParameter('url_hash', $hash); | |||
$result = $query->execute()->fetchAll(); | |||
return !empty($result); | |||
} | |||
/** | |||
* write token to database. Token is used to exchange the secret | |||
* | |||
* @param string $url | |||
* @param string $token | |||
*/ | |||
public function addToken($url, $token) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->update($this->dbTable) | |||
->set('token', $query->createParameter('token')) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', $hash) | |||
->setParameter('token', $token); | |||
$query->execute(); | |||
} | |||
/** | |||
* get token stored in database | |||
* | |||
* @param string $url | |||
* @return string | |||
*/ | |||
public function getToken($url) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->select('token')->from($this->dbTable) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', $hash); | |||
$result = $query->execute()->fetch(); | |||
return $result['token']; | |||
} | |||
/** | |||
* add shared Secret to database | |||
* | |||
* @param string $url | |||
* @param string $sharedSecret | |||
*/ | |||
public function addSharedSecret($url, $sharedSecret) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->update($this->dbTable) | |||
->set('shared_secret', $query->createParameter('sharedSecret')) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', $hash) | |||
->setParameter('sharedSecret', $sharedSecret); | |||
$query->execute(); | |||
} | |||
/** | |||
* get shared secret from database | |||
* | |||
* @param string $url | |||
* @return string | |||
*/ | |||
public function getSharedSecret($url) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->select('shared_secret')->from($this->dbTable) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', $hash); | |||
$result = $query->execute()->fetch(); | |||
return $result['shared_secret']; | |||
} | |||
/** | |||
* set server status | |||
* | |||
* @param string $url | |||
* @param int $status | |||
*/ | |||
public function setServerStatus($url, $status) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->update($this->dbTable) | |||
->set('status', $query->createParameter('status')) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', $hash) | |||
->setParameter('status', $status); | |||
$query->execute(); | |||
} | |||
/** | |||
* get server status | |||
* | |||
* @param string $url | |||
* @return int | |||
*/ | |||
public function getServerStatus($url) { | |||
$hash = $this->hash($url); | |||
$query = $this->connection->getQueryBuilder(); | |||
$query->select('status')->from($this->dbTable) | |||
->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) | |||
->setParameter('url_hash', $hash); | |||
$result = $query->execute()->fetch(); | |||
return $result['status']; | |||
} | |||
/** | |||
* create hash from URL | |||
* | |||
* @param string $url | |||
* @return string | |||
*/ | |||
protected function hash($url) { | |||
$normalized = $this->normalizeUrl($url); | |||
return md5($normalized); | |||
} | |||
/** | |||
* normalize URL, used to create the md5 hash | |||
* | |||
* @param string $url | |||
* @return string | |||
*/ | |||
protected function normalizeUrl($url) { | |||
$normalized = $url; | |||
if (strpos($url, 'https://') === 0) { | |||
$normalized = substr($url, strlen('https://')); | |||
} else if (strpos($url, 'http://') === 0) { | |||
$normalized = substr($url, strlen('http://')); | |||
} | |||
$normalized = Filesystem::normalizePath($normalized); | |||
$normalized = trim($normalized, '/'); | |||
return $normalized; | |||
} | |||
} |
@@ -22,15 +22,21 @@ | |||
namespace OCA\Federation; | |||
use OC\Files\Filesystem; | |||
use OCP\AppFramework\Http; | |||
use OCP\BackgroundJob\IJobList; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\IDBConnection; | |||
use OCP\ILogger; | |||
use OCP\Security\ISecureRandom; | |||
class TrustedServers { | |||
/** after a user list was exchanged at least once successfully */ | |||
const STATUS_OK = 1; | |||
/** waiting for shared secret or initial user list exchange */ | |||
const STATUS_PENDING = 2; | |||
/** something went wrong, misconfigured server, software bug,... user interaction needed */ | |||
const STATUS_FAILURE = 3; | |||
/** @var dbHandler */ | |||
private $dbHandler; | |||
@@ -40,21 +46,31 @@ class TrustedServers { | |||
/** @var ILogger */ | |||
private $logger; | |||
private $dbTable = 'trusted_servers'; | |||
/** @var IJobList */ | |||
private $jobList; | |||
/** @var ISecureRandom */ | |||
private $secureRandom; | |||
/** | |||
* @param DbHandler $dbHandler | |||
* @param IClientService $httpClientService | |||
* @param ILogger $logger | |||
* @param IJobList $jobList | |||
* @param ISecureRandom $secureRandom | |||
*/ | |||
public function __construct( | |||
DbHandler $dbHandler, | |||
IClientService $httpClientService, | |||
ILogger $logger | |||
ILogger $logger, | |||
IJobList $jobList, | |||
ISecureRandom $secureRandom | |||
) { | |||
$this->dbHandler = $dbHandler; | |||
$this->httpClientService = $httpClientService; | |||
$this->logger = $logger; | |||
$this->jobList = $jobList; | |||
$this->secureRandom = $secureRandom; | |||
} | |||
/** | |||
@@ -64,7 +80,41 @@ class TrustedServers { | |||
* @return int server id | |||
*/ | |||
public function addServer($url) { | |||
return $this->dbHandler->add($this->normalizeUrl($url)); | |||
$url = $this->updateProtocol($url); | |||
$result = $this->dbHandler->addServer($url); | |||
if ($result) { | |||
$token = $this->secureRandom->getMediumStrengthGenerator()->generate(16); | |||
$this->dbHandler->addToken($url, $token); | |||
$this->jobList->add( | |||
'OCA\Federation\BackgroundJob\RequestSharedSecret', | |||
[ | |||
'url' => $url, | |||
'token' => $token | |||
] | |||
); | |||
} | |||
return $result; | |||
} | |||
/** | |||
* get shared secret for the given server | |||
* | |||
* @param string $url | |||
* @return string | |||
*/ | |||
public function getSharedSecret($url) { | |||
return $this->dbHandler->getSharedSecret($url); | |||
} | |||
/** | |||
* add shared secret for the given server | |||
* | |||
* @param string $url | |||
* @param $sharedSecret | |||
*/ | |||
public function addSharedSecret($url, $sharedSecret) { | |||
$this->dbHandler->addSharedSecret($url, $sharedSecret); | |||
} | |||
/** | |||
@@ -73,7 +123,7 @@ class TrustedServers { | |||
* @param int $id | |||
*/ | |||
public function removeServer($id) { | |||
$this->dbHandler->remove($id); | |||
$this->dbHandler->removeServer($id); | |||
} | |||
/** | |||
@@ -82,7 +132,7 @@ class TrustedServers { | |||
* @return array | |||
*/ | |||
public function getServers() { | |||
return $this->dbHandler->getAll(); | |||
return $this->dbHandler->getAllServer(); | |||
} | |||
/** | |||
@@ -92,7 +142,25 @@ class TrustedServers { | |||
* @return bool | |||
*/ | |||
public function isTrustedServer($url) { | |||
return $this->dbHandler->exists($this->normalizeUrl($url)); | |||
return $this->dbHandler->serverExists($url); | |||
} | |||
/** | |||
* set server status | |||
* | |||
* @param string $url | |||
* @param int $status | |||
*/ | |||
public function setServerStatus($url, $status) { | |||
$this->dbHandler->setServerStatus($url, $status); | |||
} | |||
/** | |||
* @param string $url | |||
* @return int | |||
*/ | |||
public function getServerStatus($url) { | |||
return $this->dbHandler->getServerStatus($url); | |||
} | |||
/** | |||
@@ -137,24 +205,21 @@ class TrustedServers { | |||
} | |||
/** | |||
* normalize URL | |||
* check if the URL contain a protocol, if not add https | |||
* | |||
* @param string $url | |||
* @return string | |||
*/ | |||
protected function normalizeUrl($url) { | |||
protected function updateProtocol($url) { | |||
if ( | |||
strpos($url, 'https://') === 0 | |||
|| strpos($url, 'http://') === 0 | |||
) { | |||
$normalized = $url; | |||
return $url; | |||
if (strpos($url, 'https://') === 0) { | |||
$normalized = substr($url, strlen('https://')); | |||
} else if (strpos($url, 'http://') === 0) { | |||
$normalized = substr($url, strlen('http://')); | |||
} | |||
$normalized = Filesystem::normalizePath($normalized); | |||
$normalized = trim($normalized, '/'); | |||
return $normalized; | |||
return 'https://' . $url; | |||
} | |||
} |
@@ -31,7 +31,9 @@ $dbHandler = new \OCA\Federation\DbHandler( | |||
$trustedServers = new \OCA\Federation\TrustedServers( | |||
$dbHandler, | |||
\OC::$server->getHTTPClientService(), | |||
\OC::$server->getLogger() | |||
\OC::$server->getLogger(), | |||
\OC::$server->getJobList(), | |||
\OC::$server->getSecureRandom() | |||
); | |||
$template->assign('trustedServers', $trustedServers->getServers()); |
@@ -0,0 +1,184 @@ | |||
<?php | |||
/** | |||
* @author Björn Schießle <schiessle@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OCA\Federation\Tests\API; | |||
use OC\BackgroundJob\JobList; | |||
use OCA\Federation\API\OCSAuthAPI; | |||
use OCA\Federation\DbHandler; | |||
use OCA\Federation\TrustedServers; | |||
use OCP\AppFramework\Http; | |||
use OCP\IRequest; | |||
use OCP\Security\ISecureRandom; | |||
use Test\TestCase; | |||
class OCSAuthAPITest extends TestCase { | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | IRequest */ | |||
private $request; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | ISecureRandom */ | |||
private $secureRandom; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | JobList */ | |||
private $jobList; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers */ | |||
private $trustedServers; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */ | |||
private $dbHandler; | |||
/** @var OCSAuthApi */ | |||
private $ocsAuthApi; | |||
public function setUp() { | |||
parent::setUp(); | |||
$this->request = $this->getMock('OCP\IRequest'); | |||
$this->secureRandom = $this->getMock('OCP\Security\ISecureRandom'); | |||
$this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->jobList = $this->getMockBuilder('OC\BackgroundJob\JobList') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->ocsAuthApi = new OCSAuthAPI( | |||
$this->request, | |||
$this->secureRandom, | |||
$this->jobList, | |||
$this->trustedServers, | |||
$this->dbHandler | |||
); | |||
} | |||
/** | |||
* @dataProvider dataTestRequestSharedSecret | |||
* | |||
* @param string $token | |||
* @param string $localToken | |||
* @param bool $isTrustedServer | |||
* @param int $expected | |||
*/ | |||
public function testRequestSharedSecret($token, $localToken, $isTrustedServer, $expected) { | |||
$url = 'url'; | |||
$this->request->expects($this->at(0))->method('getParam')->with('url')->willReturn($url); | |||
$this->request->expects($this->at(1))->method('getParam')->with('token')->willReturn($token); | |||
$this->trustedServers | |||
->expects($this->once()) | |||
->method('isTrustedServer')->with($url)->willReturn($isTrustedServer); | |||
$this->dbHandler->expects($this->any()) | |||
->method('getToken')->with($url)->willReturn($localToken); | |||
if ($expected === Http::STATUS_OK) { | |||
$this->jobList->expects($this->once())->method('add') | |||
->with('OCA\Federation\BackgroundJob\GetSharedSecret', ['url' => $url, 'token' => $token]); | |||
} else { | |||
$this->jobList->expects($this->never())->method('add'); | |||
} | |||
$result = $this->ocsAuthApi->requestSharedSecret(); | |||
$this->assertSame($expected, $result->getStatusCode()); | |||
} | |||
public function dataTestRequestSharedSecret() { | |||
return [ | |||
['token2', 'token1', true, Http::STATUS_OK], | |||
['token1', 'token2', false, Http::STATUS_FORBIDDEN], | |||
['token1', 'token2', true, Http::STATUS_FORBIDDEN], | |||
]; | |||
} | |||
/** | |||
* @dataProvider dataTestGetSharedSecret | |||
* | |||
* @param bool $isTrustedServer | |||
* @param bool $isValidToken | |||
* @param int $expected | |||
*/ | |||
public function testGetSharedSecret($isTrustedServer, $isValidToken, $expected) { | |||
$url = 'url'; | |||
$token = 'token'; | |||
$this->request->expects($this->at(0))->method('getParam')->with('url')->willReturn($url); | |||
$this->request->expects($this->at(1))->method('getParam')->with('token')->willReturn($token); | |||
/** @var OCSAuthAPI | \PHPUnit_Framework_MockObject_MockObject $ocsAuthApi */ | |||
$ocsAuthApi = $this->getMockBuilder('OCA\Federation\API\OCSAuthAPI') | |||
->setConstructorArgs( | |||
[ | |||
$this->request, | |||
$this->secureRandom, | |||
$this->jobList, | |||
$this->trustedServers, | |||
$this->dbHandler | |||
] | |||
)->setMethods(['isValidToken'])->getMock(); | |||
$this->trustedServers | |||
->expects($this->any()) | |||
->method('isTrustedServer')->with($url)->willReturn($isTrustedServer); | |||
$ocsAuthApi->expects($this->any()) | |||
->method('isValidToken')->with($url, $token)->willReturn($isValidToken); | |||
if($expected === Http::STATUS_OK) { | |||
$this->secureRandom->expects($this->once())->method('getMediumStrengthGenerator') | |||
->willReturn($this->secureRandom); | |||
$this->secureRandom->expects($this->once())->method('generate')->with(32) | |||
->willReturn('secret'); | |||
$this->trustedServers->expects($this->once()) | |||
->method('addSharedSecret')->willReturn($url, 'secret'); | |||
$this->dbHandler->expects($this->once()) | |||
->method('addToken')->with($url, ''); | |||
} else { | |||
$this->secureRandom->expects($this->never())->method('getMediumStrengthGenerator'); | |||
$this->secureRandom->expects($this->never())->method('generate'); | |||
$this->trustedServers->expects($this->never())->method('addSharedSecret'); | |||
$this->dbHandler->expects($this->never())->method('addToken'); | |||
} | |||
$result = $ocsAuthApi->getSharedSecret(); | |||
$this->assertSame($expected, $result->getStatusCode()); | |||
if ($expected === Http::STATUS_OK) { | |||
$data = $result->getData(); | |||
$this->assertSame('secret', $data['sharedSecret']); | |||
} | |||
} | |||
public function dataTestGetSharedSecret() { | |||
return [ | |||
[true, true, Http::STATUS_OK], | |||
[false, true, Http::STATUS_FORBIDDEN], | |||
[true, false, Http::STATUS_FORBIDDEN], | |||
[false, false, Http::STATUS_FORBIDDEN], | |||
]; | |||
} | |||
} |
@@ -27,6 +27,9 @@ use OCA\Federation\DbHandler; | |||
use OCP\IDBConnection; | |||
use Test\TestCase; | |||
/** | |||
* @group DB | |||
*/ | |||
class DbHandlerTest extends TestCase { | |||
/** @var DbHandler */ | |||
@@ -63,8 +66,8 @@ class DbHandlerTest extends TestCase { | |||
$query->execute(); | |||
} | |||
public function testAdd() { | |||
$id = $this->dbHandler->add('server1'); | |||
public function testAddServer() { | |||
$id = $this->dbHandler->addServer('server1'); | |||
$query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); | |||
$result = $query->execute()->fetchAll(); | |||
@@ -74,8 +77,8 @@ class DbHandlerTest extends TestCase { | |||
} | |||
public function testRemove() { | |||
$id1 = $this->dbHandler->add('server1'); | |||
$id2 = $this->dbHandler->add('server2'); | |||
$id1 = $this->dbHandler->addServer('server1'); | |||
$id2 = $this->dbHandler->addServer('server2'); | |||
$query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); | |||
$result = $query->execute()->fetchAll(); | |||
@@ -85,7 +88,7 @@ class DbHandlerTest extends TestCase { | |||
$this->assertSame($id1, $result[0]['id']); | |||
$this->assertSame($id2, $result[1]['id']); | |||
$this->dbHandler->remove($id2); | |||
$this->dbHandler->removeServer($id2); | |||
$query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable); | |||
$result = $query->execute()->fetchAll(); | |||
$this->assertSame(1, count($result)); | |||
@@ -94,10 +97,10 @@ class DbHandlerTest extends TestCase { | |||
} | |||
public function testGetAll() { | |||
$id1 = $this->dbHandler->add('server1'); | |||
$id2 = $this->dbHandler->add('server2'); | |||
$id1 = $this->dbHandler->addServer('server1'); | |||
$id2 = $this->dbHandler->addServer('server2'); | |||
$result = $this->dbHandler->getAll(); | |||
$result = $this->dbHandler->getAllServer(); | |||
$this->assertSame(2, count($result)); | |||
$this->assertSame('server1', $result[0]['url']); | |||
$this->assertSame('server2', $result[1]['url']); | |||
@@ -113,9 +116,9 @@ class DbHandlerTest extends TestCase { | |||
* @param bool $expected | |||
*/ | |||
public function testExists($serverInTable, $checkForServer, $expected) { | |||
$this->dbHandler->add($serverInTable); | |||
$this->dbHandler->addServer($serverInTable); | |||
$this->assertSame($expected, | |||
$this->dbHandler->exists($checkForServer) | |||
$this->dbHandler->serverExists($checkForServer) | |||
); | |||
} | |||
@@ -127,4 +130,26 @@ class DbHandlerTest extends TestCase { | |||
]; | |||
} | |||
/** | |||
* @dataProvider dataTestNormalizeUrl | |||
* | |||
* @param string $url | |||
* @param string $expected | |||
*/ | |||
public function testNormalizeUrl($url, $expected) { | |||
$this->assertSame($expected, | |||
$this->invokePrivate($this->dbHandler, 'normalizeUrl', [$url]) | |||
); | |||
} | |||
public function dataTestNormalizeUrl() { | |||
return [ | |||
['owncloud.org', 'owncloud.org'], | |||
['http://owncloud.org', 'owncloud.org'], | |||
['https://owncloud.org', 'owncloud.org'], | |||
['https://owncloud.org//mycloud', 'owncloud.org/mycloud'], | |||
['https://owncloud.org/mycloud/', 'owncloud.org/mycloud'], | |||
]; | |||
} | |||
} |
@@ -25,11 +25,13 @@ namespace OCA\Federation\Tests\lib; | |||
use OCA\Federation\DbHandler; | |||
use OCA\Federation\TrustedServers; | |||
use OCP\BackgroundJob\IJobList; | |||
use OCP\Http\Client\IClient; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\Http\Client\IResponse; | |||
use OCP\IDBConnection; | |||
use OCP\IConfig; | |||
use OCP\ILogger; | |||
use OCP\Security\ISecureRandom; | |||
use Test\TestCase; | |||
class TrustedServersTest extends TestCase { | |||
@@ -52,6 +54,15 @@ class TrustedServersTest extends TestCase { | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */ | |||
private $logger; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | IJobList */ | |||
private $jobList; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | ISecureRandom */ | |||
private $secureRandom; | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | IConfig */ | |||
private $config; | |||
public function setUp() { | |||
parent::setUp(); | |||
@@ -61,45 +72,79 @@ class TrustedServersTest extends TestCase { | |||
$this->httpClient = $this->getMock('OCP\Http\Client\IClient'); | |||
$this->response = $this->getMock('OCP\Http\Client\IResponse'); | |||
$this->logger = $this->getMock('OCP\ILogger'); | |||
$this->jobList = $this->getMock('OCP\BackgroundJob\IJobList'); | |||
$this->secureRandom = $this->getMock('OCP\Security\ISecureRandom'); | |||
$this->config = $this->getMock('OCP\IConfig'); | |||
$this->trustedServers = new TrustedServers( | |||
$this->dbHandler, | |||
$this->httpClientService, | |||
$this->logger | |||
$this->logger, | |||
$this->jobList, | |||
$this->secureRandom, | |||
$this->config | |||
); | |||
} | |||
public function testAddServer() { | |||
/** | |||
* @dataProvider dataTestAddServer | |||
* | |||
* @param bool $success | |||
*/ | |||
public function testAddServer($success) { | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ | |||
$trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') | |||
->setConstructorArgs( | |||
[ | |||
$this->dbHandler, | |||
$this->httpClientService, | |||
$this->logger | |||
$this->logger, | |||
$this->jobList, | |||
$this->secureRandom, | |||
$this->config | |||
] | |||
) | |||
->setMethods(['normalizeUrl']) | |||
->setMethods(['normalizeUrl', 'updateProtocol']) | |||
->getMock(); | |||
$trustedServers->expects($this->once())->method('normalizeUrl') | |||
->with('url')->willReturn('normalized'); | |||
$this->dbHandler->expects($this->once())->method('add')->with('normalized') | |||
->willReturn(true); | |||
$trustedServers->expects($this->once())->method('updateProtocol') | |||
->with('url')->willReturn('https://url'); | |||
$this->dbHandler->expects($this->once())->method('addServer')->with('https://url') | |||
->willReturn($success); | |||
if ($success) { | |||
$this->secureRandom->expects($this->once())->method('getMediumStrengthGenerator') | |||
->willReturn($this->secureRandom); | |||
$this->secureRandom->expects($this->once())->method('generate') | |||
->willReturn('token'); | |||
$this->dbHandler->expects($this->once())->method('addToken')->with('https://url', 'token'); | |||
$this->jobList->expects($this->once())->method('add') | |||
->with('OCA\Federation\BackgroundJob\RequestSharedSecret', | |||
['url' => 'https://url', 'token' => 'token']); | |||
} else { | |||
$this->jobList->expects($this->never())->method('add'); | |||
} | |||
$this->assertTrue( | |||
$this->assertSame($success, | |||
$trustedServers->addServer('url') | |||
); | |||
} | |||
public function dataTestAddServer() { | |||
return [ | |||
[true], | |||
[false] | |||
]; | |||
} | |||
public function testRemoveServer() { | |||
$id = 42; | |||
$this->dbHandler->expects($this->once())->method('remove')->with($id); | |||
$this->dbHandler->expects($this->once())->method('removeServer')->with($id); | |||
$this->trustedServers->removeServer($id); | |||
} | |||
public function testGetServers() { | |||
$this->dbHandler->expects($this->once())->method('getAll')->willReturn(true); | |||
$this->dbHandler->expects($this->once())->method('getAllServer')->willReturn(true); | |||
$this->assertTrue( | |||
$this->trustedServers->getServers() | |||
@@ -108,24 +153,11 @@ class TrustedServersTest extends TestCase { | |||
public function testIsTrustedServer() { | |||
/** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */ | |||
$trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers') | |||
->setConstructorArgs( | |||
[ | |||
$this->dbHandler, | |||
$this->httpClientService, | |||
$this->logger | |||
] | |||
) | |||
->setMethods(['normalizeUrl']) | |||
->getMock(); | |||
$trustedServers->expects($this->once())->method('normalizeUrl') | |||
->with('url')->willReturn('normalized'); | |||
$this->dbHandler->expects($this->once())->method('exists')->with('normalized') | |||
->willReturn(true); | |||
$this->dbHandler->expects($this->once())->method('serverExists')->with('url') | |||
->willReturn(true); | |||
$this->assertTrue( | |||
$trustedServers->isTrustedServer('url') | |||
$this->trustedServers->isTrustedServer('url') | |||
); | |||
} | |||
@@ -146,7 +178,10 @@ class TrustedServersTest extends TestCase { | |||
[ | |||
$this->dbHandler, | |||
$this->httpClientService, | |||
$this->logger | |||
$this->logger, | |||
$this->jobList, | |||
$this->secureRandom, | |||
$this->config | |||
] | |||
) | |||
->setMethods(['checkOwnCloudVersion']) | |||
@@ -192,7 +227,7 @@ class TrustedServersTest extends TestCase { | |||
->with('simulated exception', ['app' => 'federation']); | |||
$this->httpClient->expects($this->once())->method('get')->with($server . '/status.php') | |||
->willReturnCallback(function() { | |||
->willReturnCallback(function () { | |||
throw new \Exception('simulated exception'); | |||
}); | |||
@@ -221,24 +256,22 @@ class TrustedServersTest extends TestCase { | |||
} | |||
/** | |||
* @dataProvider dataTestNormalizeUrl | |||
* | |||
* @dataProvider dataTestUpdateProtocol | |||
* @param string $url | |||
* @param string $expected | |||
*/ | |||
public function testNormalizeUrl($url, $expected) { | |||
public function testUpdateProtocol($url, $expected) { | |||
$this->assertSame($expected, | |||
$this->invokePrivate($this->trustedServers, 'normalizeUrl', [$url]) | |||
$this->invokePrivate($this->trustedServers, 'updateProtocol', [$url]) | |||
); | |||
} | |||
public function dataTestNormalizeUrl() { | |||
public function dataTestUpdateProtocol() { | |||
return [ | |||
['owncloud.org', 'owncloud.org'], | |||
['http://owncloud.org', 'owncloud.org'], | |||
['https://owncloud.org', 'owncloud.org'], | |||
['https://owncloud.org//mycloud', 'owncloud.org/mycloud'], | |||
['https://owncloud.org/mycloud/', 'owncloud.org/mycloud'], | |||
['http://owncloud.org', 'http://owncloud.org'], | |||
['https://owncloud.org', 'https://owncloud.org'], | |||
['owncloud.org', 'https://owncloud.org'], | |||
['httpserver', 'https://httpserver'], | |||
]; | |||
} | |||
} |