summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--apps/federation/api/ocsauthapi.php145
-rw-r--r--apps/federation/appinfo/app.php25
-rw-r--r--apps/federation/appinfo/application.php130
-rw-r--r--apps/federation/appinfo/database.xml63
-rw-r--r--apps/federation/appinfo/info.xml14
-rw-r--r--apps/federation/appinfo/routes.php47
-rw-r--r--apps/federation/backgroundjob/getsharedsecret.php185
-rw-r--r--apps/federation/backgroundjob/requestsharedsecret.php164
-rw-r--r--apps/federation/controller/settingscontroller.php123
-rw-r--r--apps/federation/css/settings-admin.css26
-rw-r--r--apps/federation/js/settings-admin.js82
-rw-r--r--apps/federation/lib/dbhandler.php269
-rw-r--r--apps/federation/lib/trustedservers.php254
-rw-r--r--apps/federation/middleware/addservermiddleware.php71
-rw-r--r--apps/federation/settings/settings-admin.php43
-rw-r--r--apps/federation/templates/settings-admin.php40
-rw-r--r--apps/federation/tests/api/ocsauthapitest.php184
-rw-r--r--apps/federation/tests/backgroundjob/getsharedsecrettest.php190
-rw-r--r--apps/federation/tests/backgroundjob/requestsharedsecrettest.php169
-rw-r--r--apps/federation/tests/controller/settingscontrollertest.php166
-rw-r--r--apps/federation/tests/lib/dbhandlertest.php243
-rw-r--r--apps/federation/tests/lib/trustedserverstest.php344
-rw-r--r--apps/federation/tests/middleware/addservermiddlewaretest.php100
-rw-r--r--core/shipped.json3
-rw-r--r--settings/css/settings.css4
-rw-r--r--settings/templates/admin.php6
-rw-r--r--tests/enable_all.php2
28 files changed, 3086 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index 531e372e607..3fb848dbb44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
!/apps/dav
!/apps/files
!/apps/files_encryption
+!/apps/federation
!/apps/encryption
!/apps/encryption_dummy
!/apps/files_external
diff --git a/apps/federation/api/ocsauthapi.php b/apps/federation/api/ocsauthapi.php
new file mode 100644
index 00000000000..42d7113820d
--- /dev/null
+++ b/apps/federation/api/ocsauthapi.php
@@ -0,0 +1,145 @@
+<?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 OCA\Federation\DbHandler;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+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 IJobList */
+ private $jobList;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ /** @var DbHandler */
+ private $dbHandler;
+
+ /**
+ * OCSAuthAPI constructor.
+ *
+ * @param IRequest $request
+ * @param ISecureRandom $secureRandom
+ * @param IJobList $jobList
+ * @param TrustedServers $trustedServers
+ * @param DbHandler $dbHandler
+ */
+ public function __construct(
+ IRequest $request,
+ ISecureRandom $secureRandom,
+ IJobList $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);
+ }
+
+ // if both server initiated the exchange of the shared secret the greater
+ // token wins
+ $localToken = $this->dbHandler->getToken($url);
+ if (strcmp($localToken, $token) > 0) {
+ 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);
+ // reset token after the exchange of the shared secret was successful
+ $this->dbHandler->addToken($url, '');
+
+ 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);
+ }
+
+}
diff --git a/apps/federation/appinfo/app.php b/apps/federation/appinfo/app.php
new file mode 100644
index 00000000000..9ed00f23866
--- /dev/null
+++ b/apps/federation/appinfo/app.php
@@ -0,0 +1,25 @@
+<?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\AppInfo;
+
+$app = new Application();
+$app->registerSettings();
diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php
new file mode 100644
index 00000000000..350b140b4dd
--- /dev/null
+++ b/apps/federation/appinfo/application.php
@@ -0,0 +1,130 @@
+<?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\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;
+
+class Application extends \OCP\AppFramework\App {
+
+ /**
+ * @param array $urlParams
+ */
+ public function __construct($urlParams = array()) {
+ parent::__construct('federation', $urlParams);
+ $this->registerService();
+ $this->registerMiddleware();
+ }
+
+ /**
+ * register setting scripts
+ */
+ public function registerSettings() {
+ App::registerAdmin('federation', 'settings/settings-admin');
+ }
+
+ private function registerService() {
+ $container = $this->getContainer();
+
+ $container->registerService('addServerMiddleware', function(IAppContainer $c) {
+ return new AddServerMiddleware(
+ $c->getAppName(),
+ \OC::$server->getL10N($c->getAppName()),
+ \OC::$server->getLogger()
+ );
+ });
+
+ $container->registerService('DbHandler', function(IAppContainer $c) {
+ return new DbHandler(
+ \OC::$server->getDatabaseConnection(),
+ \OC::$server->getL10N($c->getAppName())
+ );
+ });
+
+ $container->registerService('TrustedServers', function(IAppContainer $c) {
+ return new TrustedServers(
+ $c->query('DbHandler'),
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getLogger(),
+ \OC::$server->getJobList(),
+ \OC::$server->getSecureRandom(),
+ \OC::$server->getConfig()
+ );
+ });
+
+ $container->registerService('SettingsController', function (IAppContainer $c) {
+ $server = $c->getServer();
+ return new SettingsController(
+ $c->getAppName(),
+ $server->getRequest(),
+ $server->getL10N($c->getAppName()),
+ $c->query('TrustedServers')
+ );
+ });
+ }
+
+ 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
+ );
+
+ }
+
+}
diff --git a/apps/federation/appinfo/database.xml b/apps/federation/appinfo/database.xml
new file mode 100644
index 00000000000..e0bb241918e
--- /dev/null
+++ b/apps/federation/appinfo/database.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<database>
+ <name>*dbname*</name>
+ <create>true</create>
+ <overwrite>false</overwrite>
+ <charset>utf8</charset>
+ <table>
+ <name>*dbprefix*trusted_servers</name>
+ <declaration>
+ <field>
+ <name>id</name>
+ <type>integer</type>
+ <default>0</default>
+ <notnull>true</notnull>
+ <autoincrement>1</autoincrement>
+ <length>4</length>
+ </field>
+ <field>
+ <name>url</name>
+ <type>text</type>
+ <notnull>true</notnull>
+ <length>512</length>
+ <comments>Url of trusted server</comments>
+ </field>
+ <field>
+ <name>url_hash</name>
+ <type>text</type>
+ <default></default>
+ <notnull>true</notnull>
+ <length>32</length>
+ <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>
+ <unique>true</unique>
+ <field>
+ <name>url_hash</name>
+ <sorting>ascending</sorting>
+ </field>
+ </index>
+ </declaration>
+ </table>
+</database>
diff --git a/apps/federation/appinfo/info.xml b/apps/federation/appinfo/info.xml
new file mode 100644
index 00000000000..53b2926ba53
--- /dev/null
+++ b/apps/federation/appinfo/info.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<info>
+ <id>federation</id>
+ <name>Federation</name>
+ <description>ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing.</description>
+ <licence>AGPL</licence>
+ <author>Bjoern Schiessle</author>
+ <version>0.0.1</version>
+ <namespace>Federation</namespace>
+ <category>other</category>
+ <dependencies>
+ <owncloud min-version="9.0" />
+ </dependencies>
+</info>
diff --git a/apps/federation/appinfo/routes.php b/apps/federation/appinfo/routes.php
new file mode 100644
index 00000000000..8c1629a4fc6
--- /dev/null
+++ b/apps/federation/appinfo/routes.php
@@ -0,0 +1,47 @@
+<?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/>
+ *
+ */
+
+$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'
+ ],
+ [
+ 'name' => 'Settings#autoAddServers',
+ 'url' => '/auto-add-servers',
+ 'verb' => 'POST'
+ ],
+ ]
+ ]
+);
+
+$application->registerOCSApi();
diff --git a/apps/federation/backgroundjob/getsharedsecret.php b/apps/federation/backgroundjob/getsharedsecret.php
new file mode 100644
index 00000000000..eb55fa2d6ab
--- /dev/null
+++ b/apps/federation/backgroundjob/getsharedsecret.php
@@ -0,0 +1,185 @@
+<?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 GuzzleHttp\Exception\ClientException;
+use OC\BackgroundJob\JobList;
+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 DbHandler */
+ private $dbHandler;
+
+ /** @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
+ * @param DbHandler $dbHandler
+ */
+ public function __construct(
+ IClient $httpClient = null,
+ IURLGenerator $urlGenerator = null,
+ IJobList $jobList = null,
+ TrustedServers $trustedServers = null,
+ ILogger $logger = null,
+ dbHandler $dbHandler = 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();
+ $this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
+ if ($trustedServers) {
+ $this->trustedServers = $trustedServers;
+ } else {
+ $this->trustedServers = new TrustedServers(
+ $this->dbHandler,
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getLogger(),
+ $this->jobList,
+ \OC::$server->getSecureRandom(),
+ \OC::$server->getConfig()
+ );
+ }
+ }
+
+ /**
+ * 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)) {
+ $this->parentExecute($jobList, $logger);
+ }
+ }
+
+ /**
+ * call execute() method of parent
+ *
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ protected function parentExecute($jobList, $logger) {
+ parent::execute($jobList, $logger);
+ }
+
+ protected function run($argument) {
+ $target = $argument['url'];
+ $source = $this->urlGenerator->getAbsoluteURL('/');
+ $source = rtrim($source, '/');
+ $token = $argument['token'];
+
+ try {
+ $result = $this->httpClient->get(
+ $target . $this->endPoint,
+ [
+ 'query' =>
+ [
+ 'url' => $source,
+ 'token' => $token
+ ],
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ );
+
+ $status = $result->getStatusCode();
+
+ } catch (ClientException $e) {
+ $status = $e->getCode();
+ }
+
+ // 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\GetSharedSecret',
+ $argument
+ );
+ } else {
+ // reset token if we received a valid response
+ $this->dbHandler->addToken($target, '');
+ }
+
+ if ($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);
+ }
+ }
+
+ }
+}
diff --git a/apps/federation/backgroundjob/requestsharedsecret.php b/apps/federation/backgroundjob/requestsharedsecret.php
new file mode 100644
index 00000000000..24d8adada11
--- /dev/null
+++ b/apps/federation/backgroundjob/requestsharedsecret.php
@@ -0,0 +1,164 @@
+<?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 GuzzleHttp\Exception\ClientException;
+use OC\BackgroundJob\JobList;
+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;
+
+ /** @var DbHandler */
+ private $dbHandler;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ 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
+ * @param DbHandler $dbHandler
+ */
+ public function __construct(
+ IClient $httpClient = null,
+ IURLGenerator $urlGenerator = null,
+ IJobList $jobList = null,
+ TrustedServers $trustedServers = null,
+ dbHandler $dbHandler = null
+ ) {
+ $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
+ $this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
+ $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
+ $this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
+ if ($trustedServers) {
+ $this->trustedServers = $trustedServers;
+ } else {
+ $this->trustedServers = new TrustedServers(
+ $this->dbHandler,
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getLogger(),
+ $this->jobList,
+ \OC::$server->getSecureRandom(),
+ \OC::$server->getConfig()
+ );
+ }
+ }
+
+
+ /**
+ * 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)) {
+ $this->parentExecute($jobList, $logger);
+ }
+ }
+
+ /**
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ protected function parentExecute($jobList, $logger) {
+ parent::execute($jobList, $logger);
+ }
+
+ protected function run($argument) {
+
+ $target = $argument['url'];
+ $source = $this->urlGenerator->getAbsoluteURL('/');
+ $source = rtrim($source, '/');
+ $token = $argument['token'];
+
+ try {
+ $result = $this->httpClient->post(
+ $target . $this->endPoint,
+ [
+ 'body' => [
+ 'url' => $source,
+ 'token' => $token,
+ ],
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ );
+
+ $status = $result->getStatusCode();
+
+ } catch (ClientException $e) {
+ $status = $e->getCode();
+ }
+
+ // 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
+ );
+ }
+
+ if ($status === Http::STATUS_FORBIDDEN) {
+ // clear token if remote server refuses to ask for shared secret
+ $this->dbHandler->addToken($target, '');
+ }
+
+ }
+}
diff --git a/apps/federation/controller/settingscontroller.php b/apps/federation/controller/settingscontroller.php
new file mode 100644
index 00000000000..2e28cd60cfa
--- /dev/null
+++ b/apps/federation/controller/settingscontroller.php
@@ -0,0 +1,123 @@
+<?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\Controller;
+
+use OC\HintException;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IConfig;
+use OCP\IL10N;
+use OCP\IRequest;
+
+
+class SettingsController extends Controller {
+
+ /** @var IL10N */
+ private $l;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ /**
+ * @param string $AppName
+ * @param IRequest $request
+ * @param IL10N $l10n
+ * @param TrustedServers $trustedServers
+ */
+ public function __construct($AppName,
+ IRequest $request,
+ IL10N $l10n,
+ TrustedServers $trustedServers
+ ) {
+ parent::__construct($AppName, $request);
+ $this->l = $l10n;
+ $this->trustedServers = $trustedServers;
+ }
+
+
+ /**
+ * add server to the list of trusted ownClouds
+ *
+ * @param string $url
+ * @return DataResponse
+ * @throws HintException
+ */
+ public function addServer($url) {
+ $this->checkServer($url);
+ $id = $this->trustedServers->addServer($url);
+
+ return new DataResponse(
+ [
+ 'url' => $url,
+ 'id' => $id,
+ 'message' => (string) $this->l->t('Server added to the list of trusted ownClouds')
+ ]
+ );
+ }
+
+ /**
+ * add server to the list of trusted ownClouds
+ *
+ * @param int $id
+ * @return DataResponse
+ */
+ public function removeServer($id) {
+ $this->trustedServers->removeServer($id);
+ return new DataResponse();
+ }
+
+ /**
+ * enable/disable to automatically add servers to the list of trusted servers
+ * once a federated share was created and accepted successfully
+ *
+ * @param bool $autoAddServers
+ */
+ public function autoAddServers($autoAddServers) {
+ $this->trustedServers->setAutoAddServers($autoAddServers);
+ }
+
+ /**
+ * check if the server should be added to the list of trusted servers or not
+ *
+ * @param string $url
+ * @return bool
+ * @throws HintException
+ */
+ protected function checkServer($url) {
+ if ($this->trustedServers->isTrustedServer($url) === true) {
+ $message = 'Server is already in the list of trusted servers.';
+ $hint = $this->l->t('Server is already in the list of trusted servers.');
+ throw new HintException($message, $hint);
+ }
+
+ if ($this->trustedServers->isOwnCloudServer($url) === false) {
+ $message = 'No ownCloud server found';
+ $hint = $this->l->t('No ownCloud server found');
+ throw new HintException($message, $hint);
+ }
+
+ return true;
+ }
+
+}
diff --git a/apps/federation/css/settings-admin.css b/apps/federation/css/settings-admin.css
new file mode 100644
index 00000000000..55b1dd64d15
--- /dev/null
+++ b/apps/federation/css/settings-admin.css
@@ -0,0 +1,26 @@
+#ocFederationSettings p {
+ padding-top: 10px;
+}
+
+#listOfTrustedServers li {
+ padding-top: 10px;
+ padding-left: 20px;
+}
+
+.removeTrustedServer {
+ display: none;
+ vertical-align:middle;
+ padding-left: 10px;
+}
+
+#ocFederationAddServerButton {
+ cursor: pointer;
+}
+
+#listOfTrustedServers li:hover {
+ cursor: pointer;
+}
+
+#listOfTrustedServers .status {
+ margin-right: 10px;
+}
diff --git a/apps/federation/js/settings-admin.js b/apps/federation/js/settings-admin.js
new file mode 100644
index 00000000000..7d531b39d8c
--- /dev/null
+++ b/apps/federation/js/settings-admin.js
@@ -0,0 +1,82 @@
+/**
+ * @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/>
+ *
+ */
+
+$(document).ready(function () {
+
+ // show input field to add a new trusted server
+ $("#ocFederationAddServer").on('click', function() {
+ $('#ocFederationAddServerButton').addClass('hidden');
+ $("#serverUrl").removeClass('hidden');
+ $("#serverUrl").focus();
+ });
+
+ // add new trusted server
+ $("#serverUrl").keyup(function (e) {
+ if (e.keyCode === 13) { // add server on "enter"
+ var url = $('#serverUrl').val();
+ OC.msg.startSaving('#ocFederationAddServer .msg');
+ $.post(
+ OC.generateUrl('/apps/federation/trusted-servers'),
+ {
+ url: url
+ }
+ ).done(function (data) {
+ $('#serverUrl').attr('value', '');
+ $('ul#listOfTrustedServers').prepend(
+ $('<li>')
+ .attr('id', data.id)
+ .attr('class', 'icon-delete')
+ .html('<span class="status indeterminate"></span>' + data.url)
+ );
+ OC.msg.finishedSuccess('#ocFederationAddServer .msg', data.message);
+ })
+ .fail(function (jqXHR) {
+ OC.msg.finishedError('#ocFederationAddServer .msg', JSON.parse(jqXHR.responseText).message);
+ });
+ } else if (e.keyCode === 27) { // hide input filed again in ESC
+ $('#ocFederationAddServerButton').toggleClass('hidden');
+ $("#serverUrl").toggleClass('hidden');
+ }
+ });
+
+ // remove trusted server from list
+ $( "#listOfTrustedServers" ).on('click', 'li', function() {
+ var id = $(this).attr('id');
+ var $this = $(this);
+ $.ajax({
+ url: OC.generateUrl('/apps/federation/trusted-servers/' + id),
+ type: 'DELETE',
+ success: function(response) {
+ $this.remove();
+ }
+ });
+
+ });
+
+ $("#ocFederationSettings #autoAddServers").change(function() {
+ $.post(
+ OC.generateUrl('/apps/federation/auto-add-servers'),
+ {
+ autoAddServers: $(this).is(":checked")
+ }
+ );
+ });
+
+});
diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php
new file mode 100644
index 00000000000..61ba5c87cfd
--- /dev/null
+++ b/apps/federation/lib/dbhandler.php
@@ -0,0 +1,269 @@
+<?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;
+
+
+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 */
+ private $connection;
+
+ /** @var IL10N */
+ private $l;
+
+ /** @var string */
+ private $dbTable = 'trusted_servers';
+
+ /**
+ * @param IDBConnection $connection
+ * @param IL10N $il10n
+ */
+ public function __construct(
+ IDBConnection $connection,
+ IL10N $il10n
+ ) {
+ $this->connection = $connection;
+ $this->IL10N = $il10n;
+ }
+
+ /**
+ * add server to the list of trusted ownCloud servers
+ *
+ * @param string $url
+ * @return int
+ * @throws HintException
+ */
+ public function addServer($url) {
+ $hash = $this->hash($url);
+ $query = $this->connection->getQueryBuilder();
+ $query->insert($this->dbTable)
+ ->values(
+ [
+ 'url' => $query->createParameter('url'),
+ 'url_hash' => $query->createParameter('url_hash'),
+ ]
+ )
+ ->setParameter('url', $url)
+ ->setParameter('url_hash', $hash);
+
+ $result = $query->execute();
+
+ if ($result) {
+ return (int)$this->connection->lastInsertId('*PREFIX*'.$this->dbTable);
+ } else {
+ $message = 'Internal failure, Could not add ownCloud as trusted server: ' . $url;
+ $message_t = $this->l->t('Could not add server');
+ throw new HintException($message, $message_t);
+ }
+ }
+
+ /**
+ * remove server from the list of trusted ownCloud servers
+ *
+ * @param int $id
+ */
+ public function removeServer($id) {
+ $query = $this->connection->getQueryBuilder();
+ $query->delete($this->dbTable)
+ ->where($query->expr()->eq('id', $query->createParameter('id')))
+ ->setParameter('id', $id);
+ $query->execute();
+ }
+
+ /**
+ * get all trusted servers
+ *
+ * @return array
+ */
+ public function getAllServer() {
+ $query = $this->connection->getQueryBuilder();
+ $query->select(['url', 'id', 'status'])->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ return $result;
+ }
+
+ /**
+ * check if server already exists in the database table
+ *
+ * @param string $url
+ * @return bool
+ */
+ 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', $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 (int)$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;
+ }
+
+}
diff --git a/apps/federation/lib/trustedservers.php b/apps/federation/lib/trustedservers.php
new file mode 100644
index 00000000000..96a29178076
--- /dev/null
+++ b/apps/federation/lib/trustedservers.php
@@ -0,0 +1,254 @@
+<?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;
+
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
+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;
+
+ /** @var IClientService */
+ private $httpClientService;
+
+ /** @var ILogger */
+ private $logger;
+
+ /** @var IJobList */
+ private $jobList;
+
+ /** @var ISecureRandom */
+ private $secureRandom;
+
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param DbHandler $dbHandler
+ * @param IClientService $httpClientService
+ * @param ILogger $logger
+ * @param IJobList $jobList
+ * @param ISecureRandom $secureRandom
+ * @param IConfig $config
+ */
+ public function __construct(
+ DbHandler $dbHandler,
+ IClientService $httpClientService,
+ ILogger $logger,
+ IJobList $jobList,
+ ISecureRandom $secureRandom,
+ IConfig $config
+ ) {
+ $this->dbHandler = $dbHandler;
+ $this->httpClientService = $httpClientService;
+ $this->logger = $logger;
+ $this->jobList = $jobList;
+ $this->secureRandom = $secureRandom;
+ $this->config = $config;
+ }
+
+ /**
+ * add server to the list of trusted ownCloud servers
+ *
+ * @param $url
+ * @return int server id
+ */
+ public function addServer($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;
+ }
+
+ /**
+ * enable/disable to automatically add servers to the list of trusted servers
+ * once a federated share was created and accepted successfully
+ *
+ * @param bool $status
+ */
+ public function setAutoAddServers($status) {
+ $value = $status ? '1' : '0';
+ $this->config->setAppValue('federation', 'autoAddServers', $value);
+ }
+
+ /**
+ * return if we automatically add servers to the list of trusted servers
+ * once a federated share was created and accepted successfully
+ *
+ * @return bool
+ */
+ public function getAutoAddServers() {
+ $value = $this->config->getAppValue('federation', 'autoAddServers', '1');
+ return $value === '1';
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * remove server from the list of trusted ownCloud servers
+ *
+ * @param int $id
+ */
+ public function removeServer($id) {
+ $this->dbHandler->removeServer($id);
+ }
+
+ /**
+ * get all trusted servers
+ *
+ * @return array
+ */
+ public function getServers() {
+ return $this->dbHandler->getAllServer();
+ }
+
+ /**
+ * check if given server is a trusted ownCloud server
+ *
+ * @param string $url
+ * @return bool
+ */
+ public function isTrustedServer($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);
+ }
+
+ /**
+ * check if URL point to a ownCloud server
+ *
+ * @param string $url
+ * @return bool
+ */
+ public function isOwnCloudServer($url) {
+ $isValidOwnCloud = false;
+ $client = $this->httpClientService->newClient();
+ try {
+ $result = $client->get(
+ $url . '/status.php',
+ [
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ );
+ if ($result->getStatusCode() === Http::STATUS_OK) {
+ $isValidOwnCloud = $this->checkOwnCloudVersion($result->getBody());
+ }
+ } catch (\Exception $e) {
+ $this->logger->error($e->getMessage(), ['app' => 'federation']);
+ return false;
+ }
+ return $isValidOwnCloud;
+ }
+
+ /**
+ * check if ownCloud version is >= 9.0
+ *
+ * @param $statusphp
+ * @return bool
+ */
+ protected function checkOwnCloudVersion($statusphp) {
+ $decoded = json_decode($statusphp, true);
+ if (!empty($decoded) && isset($decoded['version'])) {
+ return version_compare($decoded['version'], '9.0.0', '>=');
+ }
+ return false;
+ }
+
+ /**
+ * check if the URL contain a protocol, if not add https
+ *
+ * @param string $url
+ * @return string
+ */
+ protected function updateProtocol($url) {
+ if (
+ strpos($url, 'https://') === 0
+ || strpos($url, 'http://') === 0
+ ) {
+
+ return $url;
+
+ }
+
+ return 'https://' . $url;
+ }
+}
diff --git a/apps/federation/middleware/addservermiddleware.php b/apps/federation/middleware/addservermiddleware.php
new file mode 100644
index 00000000000..56552021dc2
--- /dev/null
+++ b/apps/federation/middleware/addservermiddleware.php
@@ -0,0 +1,71 @@
+<?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\Middleware ;
+
+use OC\HintException;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Middleware;
+use OCP\IL10N;
+use OCP\ILogger;
+
+class AddServerMiddleware extends Middleware {
+
+ /** @var string */
+ protected $appName;
+
+ /** @var IL10N */
+ protected $l;
+
+ /** @var ILogger */
+ protected $logger;
+
+ public function __construct($appName, IL10N $l, ILogger $logger) {
+ $this->appName = $appName;
+ $this->l = $l;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Log error message and return a response which can be displayed to the user
+ *
+ * @param \OCP\AppFramework\Controller $controller
+ * @param string $methodName
+ * @param \Exception $exception
+ * @return JSONResponse
+ */
+ public function afterException($controller, $methodName, \Exception $exception) {
+ $this->logger->error($exception->getMessage(), ['app' => $this->appName]);
+ if ($exception instanceof HintException) {
+ $message = $exception->getHint();
+ } else {
+ $message = $this->l->t('Unknown error');
+ }
+
+ return new JSONResponse(
+ ['message' => $message],
+ Http::STATUS_BAD_REQUEST
+ );
+
+ }
+
+}
diff --git a/apps/federation/settings/settings-admin.php b/apps/federation/settings/settings-admin.php
new file mode 100644
index 00000000000..76ae0c3b6e0
--- /dev/null
+++ b/apps/federation/settings/settings-admin.php
@@ -0,0 +1,43 @@
+<?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/>
+ *
+ */
+
+\OC_Util::checkAdminUser();
+
+$template = new OCP\Template('federation', 'settings-admin');
+
+$dbHandler = new \OCA\Federation\DbHandler(
+ \OC::$server->getDatabaseConnection(),
+ \OC::$server->getL10N('federation')
+);
+
+$trustedServers = new \OCA\Federation\TrustedServers(
+ $dbHandler,
+ \OC::$server->getHTTPClientService(),
+ \OC::$server->getLogger(),
+ \OC::$server->getJobList(),
+ \OC::$server->getSecureRandom(),
+ \OC::$server->getConfig()
+);
+
+$template->assign('trustedServers', $trustedServers->getServers());
+$template->assign('autoAddServers', $trustedServers->getAutoAddServers());
+
+return $template->fetchPage();
diff --git a/apps/federation/templates/settings-admin.php b/apps/federation/templates/settings-admin.php
new file mode 100644
index 00000000000..854bb744179
--- /dev/null
+++ b/apps/federation/templates/settings-admin.php
@@ -0,0 +1,40 @@
+<?php
+/** @var array $_ */
+use OCA\Federation\TrustedServers;
+
+/** @var OC_L10N $l */
+script('federation', 'settings-admin');
+style('federation', 'settings-admin')
+?>
+<div id="ocFederationSettings" class="section">
+ <h2><?php p($l->t('Federation')); ?></h2>
+ <em><?php p($l->t('ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing.')); ?></em>
+
+ <p>
+ <input id="autoAddServers" type="checkbox" class="checkbox" <?php if($_['autoAddServers']) p('checked'); ?> />
+ <label for="autoAddServers">Add server automatically once a federated share was created successfully</label>
+ </p>
+
+ <h3>Trusted ownCloud Servers</h3>
+ <p id="ocFederationAddServer">
+ <button id="ocFederationAddServerButton" class="">+ Add ownCloud server</button>
+ <input id="serverUrl" class="hidden" type="text" value="" placeholder="ownCloud Server" name="server_url"/>
+ <span class="msg"></span>
+ </p>
+ <ul id="listOfTrustedServers">
+ <?php foreach($_['trustedServers'] as $trustedServer) { ?>
+ <li id="<?php p($trustedServer['id']); ?>" class="icon-delete">
+ <?php if((int)$trustedServer['status'] === TrustedServers::STATUS_OK) { ?>
+ <span class="status success"></span>
+ <?php } elseif((int)$trustedServer['status'] === TrustedServers::STATUS_PENDING) { ?>
+ <span class="status indeterminate"></span>
+ <?php } else {?>
+ <span class="status error"></span>
+ <?php } ?>
+ <?php p($trustedServer['url']); ?>
+ </li>
+ <?php } ?>
+ </ul>
+
+</div>
+
diff --git a/apps/federation/tests/api/ocsauthapitest.php b/apps/federation/tests/api/ocsauthapitest.php
new file mode 100644
index 00000000000..a334686c24e
--- /dev/null
+++ b/apps/federation/tests/api/ocsauthapitest.php
@@ -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],
+ ];
+ }
+
+}
diff --git a/apps/federation/tests/backgroundjob/getsharedsecrettest.php b/apps/federation/tests/backgroundjob/getsharedsecrettest.php
new file mode 100644
index 00000000000..953af5ff3e1
--- /dev/null
+++ b/apps/federation/tests/backgroundjob/getsharedsecrettest.php
@@ -0,0 +1,190 @@
+<?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\BackgroundJob;
+
+
+use OCA\Federation\BackgroundJob\GetSharedSecret;
+use OCA\Files_Sharing\Tests\TestCase;
+use OCA\Federation\DbHandler;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IResponse;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+
+class GetSharedSecretTest extends TestCase {
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IClient */
+ private $httpClient;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IJobList */
+ private $jobList;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IURLGenerator */
+ private $urlGenerator;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers */
+ private $trustedServers;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */
+ private $dbHandler;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */
+ private $logger;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
+ private $response;
+
+ /** @var GetSharedSecret */
+ private $getSharedSecret;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->httpClient = $this->getMock('OCP\Http\Client\IClient');
+ $this->jobList = $this->getMock('OCP\BackgroundJob\IJobList');
+ $this->urlGenerator = $this->getMock('OCP\IURLGenerator');
+ $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers')
+ ->disableOriginalConstructor()->getMock();
+ $this->dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')
+ ->disableOriginalConstructor()->getMock();
+ $this->logger = $this->getMock('OCP\ILogger');
+ $this->response = $this->getMock('OCP\Http\Client\IResponse');
+
+ $this->getSharedSecret = new GetSharedSecret(
+ $this->httpClient,
+ $this->urlGenerator,
+ $this->jobList,
+ $this->trustedServers,
+ $this->logger,
+ $this->dbHandler
+ );
+ }
+
+ /**
+ * @dataProvider dataTestExecute
+ *
+ * @param bool $isTrustedServer
+ */
+ public function testExecute($isTrustedServer) {
+ /** @var GetSharedSecret |\PHPUnit_Framework_MockObject_MockObject $getSharedSecret */
+ $getSharedSecret = $this->getMockBuilder('OCA\Federation\BackgroundJob\GetSharedSecret')
+ ->setConstructorArgs(
+ [
+ $this->httpClient,
+ $this->urlGenerator,
+ $this->jobList,
+ $this->trustedServers,
+ $this->logger,
+ $this->dbHandler
+ ]
+ )->setMethods(['parentExecute'])->getMock();
+ $this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url']]);
+
+ $this->jobList->expects($this->once())->method('remove');
+ $this->trustedServers->expects($this->once())->method('isTrustedServer')
+ ->with('url')->willReturn($isTrustedServer);
+ if ($isTrustedServer) {
+ $getSharedSecret->expects($this->once())->method('parentExecute');
+ } else {
+ $getSharedSecret->expects($this->never())->method('parentExecute');
+ }
+
+ $getSharedSecret->execute($this->jobList);
+
+ }
+
+ public function dataTestExecute() {
+ return [
+ [true],
+ [false]
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestRun
+ *
+ * @param int $statusCode
+ */
+ public function testRun($statusCode) {
+
+ $target = 'targetURL';
+ $source = 'sourceURL';
+ $token = 'token';
+
+ $argument = ['url' => $target, 'token' => $token];
+
+ $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')->with('/')
+ ->willReturn($source);
+ $this->httpClient->expects($this->once())->method('get')
+ ->with(
+ $target . '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json',
+ [
+ 'query' =>
+ [
+ 'url' => $source,
+ 'token' => $token
+ ],
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ )->willReturn($this->response);
+
+ $this->response->expects($this->once())->method('getStatusCode')
+ ->willReturn($statusCode);
+
+ if (
+ $statusCode !== Http::STATUS_OK
+ && $statusCode !== Http::STATUS_FORBIDDEN
+ ) {
+ $this->jobList->expects($this->once())->method('add')
+ ->with('OCA\Federation\BackgroundJob\GetSharedSecret', $argument);
+ $this->dbHandler->expects($this->never())->method('addToken');
+ } else {
+ $this->dbHandler->expects($this->once())->method('addToken')->with($target, '');
+ $this->jobList->expects($this->never())->method('add');
+ }
+
+ if ($statusCode === Http::STATUS_OK) {
+ $this->response->expects($this->once())->method('getBody')
+ ->willReturn('{"ocs":{"data":{"sharedSecret":"secret"}}}');
+ $this->trustedServers->expects($this->once())->method('addSharedSecret')
+ ->with($target, 'secret');
+ } else {
+ $this->trustedServers->expects($this->never())->method('addSharedSecret');
+ }
+
+ $this->invokePrivate($this->getSharedSecret, 'run', [$argument]);
+ }
+
+ public function dataTestRun() {
+ return [
+ [Http::STATUS_OK],
+ [Http::STATUS_FORBIDDEN],
+ [Http::STATUS_CONFLICT],
+ ];
+ }
+
+}
diff --git a/apps/federation/tests/backgroundjob/requestsharedsecrettest.php b/apps/federation/tests/backgroundjob/requestsharedsecrettest.php
new file mode 100644
index 00000000000..df81113c686
--- /dev/null
+++ b/apps/federation/tests/backgroundjob/requestsharedsecrettest.php
@@ -0,0 +1,169 @@
+<?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\BackgroundJob;
+
+
+use OCA\Federation\BackgroundJob\RequestSharedSecret;
+use OCP\AppFramework\Http;
+use Test\TestCase;
+
+class RequestSharedSecretTest extends TestCase {
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IClient */
+ private $httpClient;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IJobList */
+ private $jobList;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IURLGenerator */
+ private $urlGenerator;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */
+ private $dbHandler;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers */
+ private $trustedServers;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
+ private $response;
+
+ /** @var RequestSharedSecret */
+ private $requestSharedSecret;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->httpClient = $this->getMock('OCP\Http\Client\IClient');
+ $this->jobList = $this->getMock('OCP\BackgroundJob\IJobList');
+ $this->urlGenerator = $this->getMock('OCP\IURLGenerator');
+ $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers')
+ ->disableOriginalConstructor()->getMock();
+ $this->dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')
+ ->disableOriginalConstructor()->getMock();
+ $this->response = $this->getMock('OCP\Http\Client\IResponse');
+
+ $this->requestSharedSecret = new RequestSharedSecret(
+ $this->httpClient,
+ $this->urlGenerator,
+ $this->jobList,
+ $this->trustedServers,
+ $this->dbHandler
+ );
+ }
+
+ /**
+ * @dataProvider dataTestExecute
+ *
+ * @param bool $isTrustedServer
+ */
+ public function testExecute($isTrustedServer) {
+ /** @var RequestSharedSecret |\PHPUnit_Framework_MockObject_MockObject $requestSharedSecret */
+ $requestSharedSecret = $this->getMockBuilder('OCA\Federation\BackgroundJob\RequestSharedSecret')
+ ->setConstructorArgs(
+ [
+ $this->httpClient,
+ $this->urlGenerator,
+ $this->jobList,
+ $this->trustedServers,
+ $this->dbHandler
+ ]
+ )->setMethods(['parentExecute'])->getMock();
+ $this->invokePrivate($requestSharedSecret, 'argument', [['url' => 'url']]);
+
+ $this->jobList->expects($this->once())->method('remove');
+ $this->trustedServers->expects($this->once())->method('isTrustedServer')
+ ->with('url')->willReturn($isTrustedServer);
+ if ($isTrustedServer) {
+ $requestSharedSecret->expects($this->once())->method('parentExecute');
+ } else {
+ $requestSharedSecret->expects($this->never())->method('parentExecute');
+ }
+
+ $requestSharedSecret->execute($this->jobList);
+
+ }
+
+ public function dataTestExecute() {
+ return [
+ [true],
+ [false]
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestRun
+ *
+ * @param int $statusCode
+ */
+ public function testRun($statusCode) {
+
+ $target = 'targetURL';
+ $source = 'sourceURL';
+ $token = 'token';
+
+ $argument = ['url' => $target, 'token' => $token];
+
+ $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')->with('/')
+ ->willReturn($source);
+ $this->httpClient->expects($this->once())->method('post')
+ ->with(
+ $target . '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json',
+ [
+ 'body' =>
+ [
+ 'url' => $source,
+ 'token' => $token
+ ],
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ )->willReturn($this->response);
+
+ $this->response->expects($this->once())->method('getStatusCode')
+ ->willReturn($statusCode);
+
+ if (
+ $statusCode !== Http::STATUS_OK
+ && $statusCode !== Http::STATUS_FORBIDDEN
+ ) {
+ $this->jobList->expects($this->once())->method('add')
+ ->with('OCA\Federation\BackgroundJob\RequestSharedSecret', $argument);
+ $this->dbHandler->expects($this->never())->method('addToken');
+ }
+
+ if ($statusCode === Http::STATUS_FORBIDDEN) {
+ $this->jobList->expects($this->never())->method('add');
+ $this->dbHandler->expects($this->once())->method('addToken')->with($target, '');
+ }
+
+ $this->invokePrivate($this->requestSharedSecret, 'run', [$argument]);
+ }
+
+ public function dataTestRun() {
+ return [
+ [Http::STATUS_OK],
+ [Http::STATUS_FORBIDDEN],
+ [Http::STATUS_CONFLICT],
+ ];
+ }
+}
diff --git a/apps/federation/tests/controller/settingscontrollertest.php b/apps/federation/tests/controller/settingscontrollertest.php
new file mode 100644
index 00000000000..efbc6911c52
--- /dev/null
+++ b/apps/federation/tests/controller/settingscontrollertest.php
@@ -0,0 +1,166 @@
+<?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\Controller;
+
+
+use OCA\Federation\Controller\SettingsController;
+use OCP\AppFramework\Http\DataResponse;
+use Test\TestCase;
+
+class SettingsControllerTest extends TestCase {
+
+ /** @var SettingsController */
+ private $controller;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IRequest */
+ private $request;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IL10N */
+ private $l10n;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | \OCA\Federation\TrustedServers */
+ private $trustedServers;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->request = $this->getMock('OCP\IRequest');
+ $this->l10n = $this->getMock('OCP\IL10N');
+ $this->trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers')
+ ->disableOriginalConstructor()->getMock();
+
+ $this->controller = new SettingsController(
+ 'SettingsControllerTest',
+ $this->request,
+ $this->l10n,
+ $this->trustedServers
+ );
+ }
+
+ public function testAddServer() {
+ $this->trustedServers
+ ->expects($this->once())
+ ->method('isTrustedServer')
+ ->with('url')
+ ->willReturn(false);
+ $this->trustedServers
+ ->expects($this->once())
+ ->method('isOwnCloudServer')
+ ->with('url')
+ ->willReturn(true);
+
+ $result = $this->controller->addServer('url');
+ $this->assertTrue($result instanceof DataResponse);
+
+ $data = $result->getData();
+ $this->assertSame(200, $result->getStatus());
+ $this->assertSame('url', $data['url']);
+ $this->assertArrayHasKey('id', $data);
+ }
+
+ /**
+ * @dataProvider checkServerFails
+ * @expectedException \OC\HintException
+ *
+ * @param bool $isTrustedServer
+ * @param bool $isOwnCloud
+ */
+ public function testAddServerFail($isTrustedServer, $isOwnCloud) {
+ $this->trustedServers
+ ->expects($this->any())
+ ->method('isTrustedServer')
+ ->with('url')
+ ->willReturn($isTrustedServer);
+ $this->trustedServers
+ ->expects($this->any())
+ ->method('isOwnCloudServer')
+ ->with('url')
+ ->willReturn($isOwnCloud);
+
+ $this->controller->addServer('url');
+ }
+
+ public function testRemoveServer() {
+ $this->trustedServers->expects($this->once())->method('removeServer')
+ ->with('url');
+ $result = $this->controller->removeServer('url');
+ $this->assertTrue($result instanceof DataResponse);
+ $this->assertSame(200, $result->getStatus());
+ }
+
+ public function testCheckServer() {
+ $this->trustedServers
+ ->expects($this->once())
+ ->method('isTrustedServer')
+ ->with('url')
+ ->willReturn(false);
+ $this->trustedServers
+ ->expects($this->once())
+ ->method('isOwnCloudServer')
+ ->with('url')
+ ->willReturn(true);
+
+ $this->assertTrue(
+ $this->invokePrivate($this->controller, 'checkServer', ['url'])
+ );
+
+ }
+
+ /**
+ * @dataProvider checkServerFails
+ * @expectedException \OC\HintException
+ *
+ * @param bool $isTrustedServer
+ * @param bool $isOwnCloud
+ */
+ public function testCheckServerFail($isTrustedServer, $isOwnCloud) {
+ $this->trustedServers
+ ->expects($this->any())
+ ->method('isTrustedServer')
+ ->with('url')
+ ->willReturn($isTrustedServer);
+ $this->trustedServers
+ ->expects($this->any())
+ ->method('isOwnCloudServer')
+ ->with('url')
+ ->willReturn($isOwnCloud);
+
+ $this->assertTrue(
+ $this->invokePrivate($this->controller, 'checkServer', ['url'])
+ );
+
+ }
+
+ /**
+ * data to simulate checkServer fails
+ *
+ * @return array
+ */
+ public function checkServerFails() {
+ return [
+ [true, true],
+ [false, false]
+ ];
+ }
+
+}
diff --git a/apps/federation/tests/lib/dbhandlertest.php b/apps/federation/tests/lib/dbhandlertest.php
new file mode 100644
index 00000000000..e47df092f8c
--- /dev/null
+++ b/apps/federation/tests/lib/dbhandlertest.php
@@ -0,0 +1,243 @@
+<?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\lib;
+
+
+use OCA\Federation\DbHandler;
+use OCA\Federation\TrustedServers;
+use OCP\IDBConnection;
+use Test\TestCase;
+
+/**
+ * @group DB
+ */
+class DbHandlerTest extends TestCase {
+
+ /** @var DbHandler */
+ private $dbHandler;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ private $il10n;
+
+ /** @var IDBConnection */
+ private $connection;
+
+ /** @var string */
+ private $dbTable = 'trusted_servers';
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->connection = \OC::$server->getDatabaseConnection();
+ $this->il10n = $this->getMock('OCP\IL10N');
+
+ $this->dbHandler = new DbHandler(
+ $this->connection,
+ $this->il10n
+ );
+
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertEmpty($result, 'we need to start with a empty trusted_servers table');
+ }
+
+ public function tearDown() {
+ parent::tearDown();
+ $query = $this->connection->getQueryBuilder()->delete($this->dbTable);
+ $query->execute();
+ }
+
+ public function testAddServer() {
+ $id = $this->dbHandler->addServer('server1');
+
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame('server1', $result[0]['url']);
+ $this->assertSame($id, (int)$result[0]['id']);
+ $this->assertSame(TrustedServers::STATUS_PENDING, (int)$result[0]['status']);
+ }
+
+ public function testRemove() {
+ $id1 = $this->dbHandler->addServer('server1');
+ $id2 = $this->dbHandler->addServer('server2');
+
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(2, count($result));
+ $this->assertSame('server1', $result[0]['url']);
+ $this->assertSame('server2', $result[1]['url']);
+ $this->assertSame($id1, (int)$result[0]['id']);
+ $this->assertSame($id2, (int)$result[1]['id']);
+
+ $this->dbHandler->removeServer($id2);
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame('server1', $result[0]['url']);
+ $this->assertSame($id1, (int)$result[0]['id']);
+ }
+
+ public function testGetAll() {
+ $id1 = $this->dbHandler->addServer('server1');
+ $id2 = $this->dbHandler->addServer('server2');
+
+ $result = $this->dbHandler->getAllServer();
+ $this->assertSame(2, count($result));
+ $this->assertSame('server1', $result[0]['url']);
+ $this->assertSame('server2', $result[1]['url']);
+ $this->assertSame($id1, (int)$result[0]['id']);
+ $this->assertSame($id2, (int)$result[1]['id']);
+ }
+
+ /**
+ * @dataProvider dataTestServerExists
+ *
+ * @param string $serverInTable
+ * @param string $checkForServer
+ * @param bool $expected
+ */
+ public function testServerExists($serverInTable, $checkForServer, $expected) {
+ $this->dbHandler->addServer($serverInTable);
+ $this->assertSame($expected,
+ $this->dbHandler->serverExists($checkForServer)
+ );
+ }
+
+ public function dataTestServerExists() {
+ return [
+ ['server1', 'server1', true],
+ ['server1', 'http://server1', true],
+ ['server1', 'server2', false]
+ ];
+ }
+
+ public function testAddToken() {
+ $this->dbHandler->addServer('server1');
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame(null, $result[0]['token']);
+ $this->dbHandler->addToken('http://server1', 'token');
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame('token', $result[0]['token']);
+ }
+
+ public function testGetToken() {
+ $this->dbHandler->addServer('server1');
+ $this->dbHandler->addToken('http://server1', 'token');
+ $this->assertSame('token',
+ $this->dbHandler->getToken('https://server1')
+ );
+ }
+
+ public function testAddSharedSecret() {
+ $this->dbHandler->addServer('server1');
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame(null, $result[0]['shared_secret']);
+ $this->dbHandler->addSharedSecret('http://server1', 'secret');
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame('secret', $result[0]['shared_secret']);
+ }
+
+ public function testGetSharedSecret() {
+ $this->dbHandler->addServer('server1');
+ $this->dbHandler->addSharedSecret('http://server1', 'secret');
+ $this->assertSame('secret',
+ $this->dbHandler->getSharedSecret('https://server1')
+ );
+ }
+
+ public function testSetServerStatus() {
+ $this->dbHandler->addServer('server1');
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame(TrustedServers::STATUS_PENDING, (int)$result[0]['status']);
+ $this->dbHandler->setServerStatus('http://server1', TrustedServers::STATUS_OK);
+ $query = $this->connection->getQueryBuilder()->select('*')->from($this->dbTable);
+ $result = $query->execute()->fetchAll();
+ $this->assertSame(1, count($result));
+ $this->assertSame(TrustedServers::STATUS_OK, (int)$result[0]['status']);
+ }
+
+ public function testGetServerStatus() {
+ $this->dbHandler->addServer('server1');
+ $this->dbHandler->setServerStatus('http://server1', TrustedServers::STATUS_OK);
+ $this->assertSame(TrustedServers::STATUS_OK,
+ $this->dbHandler->getServerStatus('https://server1')
+ );
+ }
+
+ /**
+ * hash should always be computed with the normalized URL
+ *
+ * @dataProvider dataTestHash
+ *
+ * @param string $url
+ * @param string $expected
+ */
+ public function testHash($url, $expected) {
+ $this->assertSame($expected,
+ $this->invokePrivate($this->dbHandler, 'hash', [$url])
+ );
+ }
+
+ public function dataTestHash() {
+ return [
+ ['server1', md5('server1')],
+ ['http://server1', md5('server1')],
+ ['https://server1', md5('server1')],
+ ['http://server1/', md5('server1')],
+ ];
+ }
+
+ /**
+ * @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'],
+ ];
+ }
+
+}
diff --git a/apps/federation/tests/lib/trustedserverstest.php b/apps/federation/tests/lib/trustedserverstest.php
new file mode 100644
index 00000000000..d067cd1c185
--- /dev/null
+++ b/apps/federation/tests/lib/trustedserverstest.php
@@ -0,0 +1,344 @@
+<?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\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\IConfig;
+use OCP\ILogger;
+use OCP\Security\ISecureRandom;
+use Test\TestCase;
+
+class TrustedServersTest extends TestCase {
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | DbHandler */
+ private $dbHandler;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IClientService */
+ private $httpClientService;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IClient */
+ private $httpClient;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
+ private $response;
+
+ /** @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();
+
+ $this->dbHandler = $this->getMockBuilder('\OCA\Federation\DbHandler')
+ ->disableOriginalConstructor()->getMock();
+ $this->httpClientService = $this->getMock('OCP\Http\Client\IClientService');
+ $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->jobList,
+ $this->secureRandom,
+ $this->config
+ );
+
+ }
+
+ /**
+ * @dataProvider dataTrueFalse
+ *
+ * @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->jobList,
+ $this->secureRandom,
+ $this->config
+ ]
+ )
+ ->setMethods(['normalizeUrl', 'updateProtocol'])
+ ->getMock();
+ $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->assertSame($success,
+ $trustedServers->addServer('url')
+ );
+ }
+
+ public function dataTrueFalse() {
+ return [
+ [true],
+ [false]
+ ];
+ }
+
+ /**
+ * @dataProvider dataTrueFalse
+ *
+ * @param bool $status
+ */
+ public function testSetAutoAddServers($status) {
+ if ($status) {
+ $this->config->expects($this->once())->method('setAppValue')
+ ->with('federation', 'autoAddServers', '1');
+ } else {
+ $this->config->expects($this->once())->method('setAppValue')
+ ->with('federation', 'autoAddServers', '0');
+ }
+
+ $this->trustedServers->setAutoAddServers($status);
+ }
+
+ /**
+ * @dataProvider dataTestGetAutoAddServers
+ *
+ * @param string $status
+ * @param bool $expected
+ */
+ public function testGetAutoAddServers($status, $expected) {
+ $this->config->expects($this->once())->method('getAppValue')
+ ->with('federation', 'autoAddServers', '1')->willReturn($status);
+
+ $this->assertSame($expected,
+ $this->trustedServers->getAutoAddServers($status)
+ );
+ }
+
+ public function dataTestGetAutoAddServers() {
+ return [
+ ['1', true],
+ ['0', false]
+ ];
+ }
+
+ public function testAddSharedSecret() {
+ $this->dbHandler->expects($this->once())->method('addSharedSecret')
+ ->with('url', 'secret');
+ $this->trustedServers->addSharedSecret('url', 'secret');
+ }
+
+ public function testGetSharedSecret() {
+ $this->dbHandler->expects($this->once())->method('getSharedSecret')
+ ->with('url')->willReturn(true);
+ $this->assertTrue(
+ $this->trustedServers->getSharedSecret('url')
+ );
+ }
+
+ public function testRemoveServer() {
+ $id = 42;
+ $this->dbHandler->expects($this->once())->method('removeServer')->with($id);
+ $this->trustedServers->removeServer($id);
+ }
+
+ public function testGetServers() {
+ $this->dbHandler->expects($this->once())->method('getAllServer')->willReturn(true);
+
+ $this->assertTrue(
+ $this->trustedServers->getServers()
+ );
+ }
+
+
+ public function testIsTrustedServer() {
+ $this->dbHandler->expects($this->once())->method('serverExists')->with('url')
+ ->willReturn(true);
+
+ $this->assertTrue(
+ $this->trustedServers->isTrustedServer('url')
+ );
+ }
+
+ public function testSetServerStatus() {
+ $this->dbHandler->expects($this->once())->method('setServerStatus')
+ ->with('url', 'status');
+ $this->trustedServers->setServerStatus('url', 'status');
+ }
+
+ public function testGetServerStatus() {
+ $this->dbHandler->expects($this->once())->method('getServerStatus')
+ ->with('url')->willReturn(true);
+ $this->assertTrue(
+ $this->trustedServers->getServerStatus('url')
+ );
+ }
+
+ /**
+ * @dataProvider dataTestIsOwnCloudServer
+ *
+ * @param int $statusCode
+ * @param bool $isValidOwnCloudVersion
+ * @param bool $expected
+ */
+ public function testIsOwnCloudServer($statusCode, $isValidOwnCloudVersion, $expected) {
+
+ $server = 'server1';
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | TrustedServers $trustedServer */
+ $trustedServers = $this->getMockBuilder('OCA\Federation\TrustedServers')
+ ->setConstructorArgs(
+ [
+ $this->dbHandler,
+ $this->httpClientService,
+ $this->logger,
+ $this->jobList,
+ $this->secureRandom,
+ $this->config
+ ]
+ )
+ ->setMethods(['checkOwnCloudVersion'])
+ ->getMock();
+
+ $this->httpClientService->expects($this->once())->method('newClient')
+ ->willReturn($this->httpClient);
+
+ $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php')
+ ->willReturn($this->response);
+
+ $this->response->expects($this->once())->method('getStatusCode')
+ ->willReturn($statusCode);
+
+ if ($statusCode === 200) {
+ $trustedServers->expects($this->once())->method('checkOwnCloudVersion')
+ ->willReturn($isValidOwnCloudVersion);
+ } else {
+ $trustedServers->expects($this->never())->method('checkOwnCloudVersion');
+ }
+
+ $this->assertSame($expected,
+ $trustedServers->isOwnCloudServer($server)
+ );
+
+ }
+
+ public function dataTestIsOwnCloudServer() {
+ return [
+ [200, true, true],
+ [200, false, false],
+ [404, true, false],
+ ];
+ }
+
+ public function testIsOwnCloudServerFail() {
+ $server = 'server1';
+
+ $this->httpClientService->expects($this->once())->method('newClient')
+ ->willReturn($this->httpClient);
+
+ $this->logger->expects($this->once())->method('error')
+ ->with('simulated exception', ['app' => 'federation']);
+
+ $this->httpClient->expects($this->once())->method('get')->with($server . '/status.php')
+ ->willReturnCallback(function () {
+ throw new \Exception('simulated exception');
+ });
+
+ $this->assertFalse($this->trustedServers->isOwnCloudServer($server));
+
+ }
+
+ /**
+ * @dataProvider dataTestCheckOwnCloudVersion
+ *
+ * @param $statusphp
+ * @param $expected
+ */
+ public function testCheckOwnCloudVersion($statusphp, $expected) {
+ $this->assertSame($expected,
+ $this->invokePrivate($this->trustedServers, 'checkOwnCloudVersion', [$statusphp])
+ );
+ }
+
+ public function dataTestCheckOwnCloudVersion() {
+ return [
+ ['{"version":"8.4.0"}', false],
+ ['{"version":"9.0.0"}', true],
+ ['{"version":"9.1.0"}', true]
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestUpdateProtocol
+ * @param string $url
+ * @param string $expected
+ */
+ public function testUpdateProtocol($url, $expected) {
+ $this->assertSame($expected,
+ $this->invokePrivate($this->trustedServers, 'updateProtocol', [$url])
+ );
+ }
+
+ public function dataTestUpdateProtocol() {
+ return [
+ ['http://owncloud.org', 'http://owncloud.org'],
+ ['https://owncloud.org', 'https://owncloud.org'],
+ ['owncloud.org', 'https://owncloud.org'],
+ ['httpserver', 'https://httpserver'],
+ ];
+ }
+}
diff --git a/apps/federation/tests/middleware/addservermiddlewaretest.php b/apps/federation/tests/middleware/addservermiddlewaretest.php
new file mode 100644
index 00000000000..1be5a342285
--- /dev/null
+++ b/apps/federation/tests/middleware/addservermiddlewaretest.php
@@ -0,0 +1,100 @@
+<?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\Middleware;
+
+
+use OC\HintException;
+use OCA\Federation\Middleware\AddServerMiddleware;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http;
+use Test\TestCase;
+
+class AddServerMiddlewareTest extends TestCase {
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | ILogger */
+ private $logger;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IL10N */
+ private $l10n;
+
+ /** @var AddServerMiddleware */
+ private $middleware;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject | Controller */
+ private $controller;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->logger = $this->getMock('OCP\ILogger');
+ $this->l10n = $this->getMock('OCP\IL10N');
+ $this->controller = $this->getMockBuilder('OCP\AppFramework\Controller')
+ ->disableOriginalConstructor()->getMock();
+
+ $this->middleware = new AddServerMiddleware(
+ 'AddServerMiddlewareTest',
+ $this->l10n,
+ $this->logger
+ );
+ }
+
+ /**
+ * @dataProvider dataTestAfterException
+ *
+ * @param \Exception $exception
+ * @param string $message
+ * @param string $hint
+ */
+ public function testAfterException($exception, $message, $hint) {
+
+ $this->logger->expects($this->once())->method('error')
+ ->with($message, ['app' => 'AddServerMiddlewareTest']);
+
+ $this->l10n->expects($this->any())->method('t')
+ ->willReturnCallback(
+ function($message) {
+ return $message;
+ }
+ );
+
+ $result = $this->middleware->afterException($this->controller, 'method', $exception);
+
+ $this->assertSame(Http::STATUS_BAD_REQUEST,
+ $result->getStatus()
+ );
+
+ $data = $result->getData();
+
+ $this->assertSame($hint,
+ $data['message']
+ );
+ }
+
+ public function dataTestAfterException() {
+ return [
+ [new HintException('message', 'hint'), 'message', 'hint'],
+ [new \Exception('message'), 'message', 'Unknown error'],
+ ];
+ }
+
+}
diff --git a/core/shipped.json b/core/shipped.json
index cd1fca4d9fe..a7466a41aef 100644
--- a/core/shipped.json
+++ b/core/shipped.json
@@ -32,7 +32,8 @@
"user_ldap",
"user_shibboleth",
"windows_network_drive",
- "password_policy"
+ "password_policy",
+ "federation"
],
"alwaysEnabled": [
"files",
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 60ba805d3ca..5a1d864734b 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -412,13 +412,13 @@ table.grid td.date{
.cronlog {
margin-left: 10px;
}
-.cronstatus {
+.status {
display: inline-block;
height: 16px;
width: 16px;
vertical-align: text-bottom;
}
-.cronstatus.success {
+.status.success {
border-radius: 50%;
}
diff --git a/settings/templates/admin.php b/settings/templates/admin.php
index 24af4964248..0721c0e0afb 100644
--- a/settings/templates/admin.php
+++ b/settings/templates/admin.php
@@ -290,18 +290,18 @@ if ($_['cronErrors']) {
$relative_time = relative_modified_date($_['lastcron']);
$absolute_time = OC_Util::formatDate($_['lastcron']);
if (time() - $_['lastcron'] <= 3600): ?>
- <span class="cronstatus success"></span>
+ <span class="status success"></span>
<span class="crondate" original-title="<?php p($absolute_time);?>">
<?php p($l->t("Last cron job execution: %s.", [$relative_time]));?>
</span>
<?php else: ?>
- <span class="cronstatus error"></span>
+ <span class="status error"></span>
<span class="crondate" original-title="<?php p($absolute_time);?>">
<?php p($l->t("Last cron job execution: %s. Something seems wrong.", [$relative_time]));?>
</span>
<?php endif;
else: ?>
- <span class="cronstatus error"></span>
+ <span class="status error"></span>
<?php p($l->t("Cron was not executed yet!"));
endif; ?>
</p>
diff --git a/tests/enable_all.php b/tests/enable_all.php
index 464155b1f39..6f2d1fa8717 100644
--- a/tests/enable_all.php
+++ b/tests/enable_all.php
@@ -22,4 +22,4 @@ enableApp('encryption');
enableApp('user_ldap');
enableApp('files_versions');
enableApp('provisioning_api');
-
+enableApp('federation');