Merge pull request #3614 from nextcloud/discover-federatedsharing-endpoints
Discover federatedsharing endpoints
This commit is contained in:
commit
b90e91144b
|
@ -75,6 +75,7 @@ class SyncService {
|
||||||
/**
|
/**
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param string $userName
|
* @param string $userName
|
||||||
|
* @param string $addressBookUrl
|
||||||
* @param string $sharedSecret
|
* @param string $sharedSecret
|
||||||
* @param string $syncToken
|
* @param string $syncToken
|
||||||
* @param int $targetBookId
|
* @param int $targetBookId
|
||||||
|
@ -83,14 +84,14 @@ class SyncService {
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function syncRemoteAddressBook($url, $userName, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) {
|
public function syncRemoteAddressBook($url, $userName, $addressBookUrl, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) {
|
||||||
// 1. create addressbook
|
// 1. create addressbook
|
||||||
$book = $this->ensureSystemAddressBookExists($targetPrincipal, $targetBookId, $targetProperties);
|
$book = $this->ensureSystemAddressBookExists($targetPrincipal, $targetBookId, $targetProperties);
|
||||||
$addressBookId = $book['id'];
|
$addressBookId = $book['id'];
|
||||||
|
|
||||||
// 2. query changes
|
// 2. query changes
|
||||||
try {
|
try {
|
||||||
$response = $this->requestSyncReport($url, $userName, $sharedSecret, $syncToken);
|
$response = $this->requestSyncReport($url, $userName, $addressBookUrl, $sharedSecret, $syncToken);
|
||||||
} catch (ClientHttpException $ex) {
|
} catch (ClientHttpException $ex) {
|
||||||
if ($ex->getCode() === Http::STATUS_UNAUTHORIZED) {
|
if ($ex->getCode() === Http::STATUS_UNAUTHORIZED) {
|
||||||
// remote server revoked access to the address book, remove it
|
// remote server revoked access to the address book, remove it
|
||||||
|
@ -105,7 +106,7 @@ class SyncService {
|
||||||
foreach ($response['response'] as $resource => $status) {
|
foreach ($response['response'] as $resource => $status) {
|
||||||
$cardUri = basename($resource);
|
$cardUri = basename($resource);
|
||||||
if (isset($status[200])) {
|
if (isset($status[200])) {
|
||||||
$vCard = $this->download($url, $sharedSecret, $resource);
|
$vCard = $this->download($url, $userName, $sharedSecret, $resource);
|
||||||
$existingCard = $this->backend->getCard($addressBookId, $cardUri);
|
$existingCard = $this->backend->getCard($addressBookId, $cardUri);
|
||||||
if ($existingCard === false) {
|
if ($existingCard === false) {
|
||||||
$this->backend->createCard($addressBookId, $cardUri, $vCard['body']);
|
$this->backend->createCard($addressBookId, $cardUri, $vCard['body']);
|
||||||
|
@ -162,6 +163,7 @@ class SyncService {
|
||||||
/**
|
/**
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param string $userName
|
* @param string $userName
|
||||||
|
* @param string $addressBookUrl
|
||||||
* @param string $sharedSecret
|
* @param string $sharedSecret
|
||||||
* @return Client
|
* @return Client
|
||||||
*/
|
*/
|
||||||
|
@ -185,14 +187,14 @@ class SyncService {
|
||||||
/**
|
/**
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param string $userName
|
* @param string $userName
|
||||||
|
* @param string $addressBookUrl
|
||||||
* @param string $sharedSecret
|
* @param string $sharedSecret
|
||||||
* @param string $syncToken
|
* @param string $syncToken
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function requestSyncReport($url, $userName, $sharedSecret, $syncToken) {
|
protected function requestSyncReport($url, $userName, $addressBookUrl, $sharedSecret, $syncToken) {
|
||||||
$client = $this->getClient($url, $userName, $sharedSecret);
|
$client = $this->getClient($url, $userName, $sharedSecret);
|
||||||
|
|
||||||
$addressBookUrl = "remote.php/dav/addressbooks/system/system/system";
|
|
||||||
$body = $this->buildSyncCollectionRequestBody($syncToken);
|
$body = $this->buildSyncCollectionRequestBody($syncToken);
|
||||||
|
|
||||||
$response = $client->request('REPORT', $addressBookUrl, $body, [
|
$response = $client->request('REPORT', $addressBookUrl, $body, [
|
||||||
|
@ -204,12 +206,13 @@ class SyncService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $url
|
* @param string $url
|
||||||
|
* @param string $userName
|
||||||
* @param string $sharedSecret
|
* @param string $sharedSecret
|
||||||
* @param string $resourcePath
|
* @param string $resourcePath
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function download($url, $sharedSecret, $resourcePath) {
|
protected function download($url, $userName, $sharedSecret, $resourcePath) {
|
||||||
$client = $this->getClient($url, 'system', $sharedSecret);
|
$client = $this->getClient($url, $userName, $sharedSecret);
|
||||||
return $client->request('GET', $resourcePath);
|
return $client->request('GET', $resourcePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SyncServiceTest extends TestCase {
|
||||||
$backend = $this->getBackendMock(0, 0, 0);
|
$backend = $this->getBackendMock(0, 0, 0);
|
||||||
|
|
||||||
$ss = $this->getSyncServiceMock($backend, []);
|
$ss = $this->getSyncServiceMock($backend, []);
|
||||||
$return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
$return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
||||||
$this->assertEquals('sync-token-1', $return);
|
$this->assertEquals('sync-token-1', $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ class SyncServiceTest extends TestCase {
|
||||||
$backend->method('getCard')->willReturn(false);
|
$backend->method('getCard')->willReturn(false);
|
||||||
|
|
||||||
$ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
|
$ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
|
||||||
$return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
$return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
||||||
$this->assertEquals('sync-token-1', $return);
|
$this->assertEquals('sync-token-1', $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ class SyncServiceTest extends TestCase {
|
||||||
$backend->method('getCard')->willReturn(true);
|
$backend->method('getCard')->willReturn(true);
|
||||||
|
|
||||||
$ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
|
$ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
|
||||||
$return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
$return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
||||||
$this->assertEquals('sync-token-1', $return);
|
$this->assertEquals('sync-token-1', $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class SyncServiceTest extends TestCase {
|
||||||
$backend = $this->getBackendMock(0, 0, 1);
|
$backend = $this->getBackendMock(0, 0, 1);
|
||||||
|
|
||||||
$ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]);
|
$ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]);
|
||||||
$return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
$return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
|
||||||
$this->assertEquals('sync-token-1', $return);
|
$this->assertEquals('sync-token-1', $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,10 +51,7 @@ class Application extends App {
|
||||||
$notification = new Notifications(
|
$notification = new Notifications(
|
||||||
$addressHandler,
|
$addressHandler,
|
||||||
$server->getHTTPClientService(),
|
$server->getHTTPClientService(),
|
||||||
new \OCA\FederatedFileSharing\DiscoveryManager(
|
$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$server->getMemCacheFactory(),
|
|
||||||
$server->getHTTPClientService()
|
|
||||||
),
|
|
||||||
\OC::$server->getJobList()
|
\OC::$server->getJobList()
|
||||||
);
|
);
|
||||||
return new RequestHandlerController(
|
return new RequestHandlerController(
|
||||||
|
@ -99,14 +96,10 @@ class Application extends App {
|
||||||
\OC::$server->getL10N('federatedfilesharing'),
|
\OC::$server->getL10N('federatedfilesharing'),
|
||||||
\OC::$server->getCloudIdManager()
|
\OC::$server->getCloudIdManager()
|
||||||
);
|
);
|
||||||
$discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$notifications = new \OCA\FederatedFileSharing\Notifications(
|
$notifications = new \OCA\FederatedFileSharing\Notifications(
|
||||||
$addressHandler,
|
$addressHandler,
|
||||||
\OC::$server->getHTTPClientService(),
|
\OC::$server->getHTTPClientService(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
\OC::$server->getJobList()
|
\OC::$server->getJobList()
|
||||||
);
|
);
|
||||||
$tokenHandler = new \OCA\FederatedFileSharing\TokenHandler(
|
$tokenHandler = new \OCA\FederatedFileSharing\TokenHandler(
|
||||||
|
|
|
@ -27,7 +27,6 @@ namespace OCA\FederatedFileSharing\BackgroundJob;
|
||||||
use OC\BackgroundJob\Job;
|
use OC\BackgroundJob\Job;
|
||||||
use OC\BackgroundJob\JobList;
|
use OC\BackgroundJob\JobList;
|
||||||
use OCA\FederatedFileSharing\AddressHandler;
|
use OCA\FederatedFileSharing\AddressHandler;
|
||||||
use OCA\FederatedFileSharing\DiscoveryManager;
|
|
||||||
use OCA\FederatedFileSharing\Notifications;
|
use OCA\FederatedFileSharing\Notifications;
|
||||||
use OCP\BackgroundJob\IJobList;
|
use OCP\BackgroundJob\IJobList;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
|
@ -68,14 +67,10 @@ class RetryJob extends Job {
|
||||||
\OC::$server->getL10N('federatedfilesharing'),
|
\OC::$server->getL10N('federatedfilesharing'),
|
||||||
\OC::$server->getCloudIdManager()
|
\OC::$server->getCloudIdManager()
|
||||||
);
|
);
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$this->notifications = new Notifications(
|
$this->notifications = new Notifications(
|
||||||
$addressHandler,
|
$addressHandler,
|
||||||
\OC::$server->getHTTPClientService(),
|
\OC::$server->getHTTPClientService(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
\OC::$server->getJobList()
|
\OC::$server->getJobList()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,17 +248,13 @@ class MountPublicLinkController extends Controller {
|
||||||
if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
|
if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
|
||||||
return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
|
return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$externalManager = new Manager(
|
$externalManager = new Manager(
|
||||||
\OC::$server->getDatabaseConnection(),
|
\OC::$server->getDatabaseConnection(),
|
||||||
Filesystem::getMountManager(),
|
Filesystem::getMountManager(),
|
||||||
Filesystem::getLoader(),
|
Filesystem::getLoader(),
|
||||||
\OC::$server->getHTTPClientService(),
|
\OC::$server->getHTTPClientService(),
|
||||||
\OC::$server->getNotificationManager(),
|
\OC::$server->getNotificationManager(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
\OC::$server->getUserSession()->getUser()->getUID()
|
\OC::$server->getUserSession()->getUser()->getUID()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -152,17 +152,13 @@ class RequestHandlerController extends OCSController {
|
||||||
|
|
||||||
\OC_Util::setupFS($shareWith);
|
\OC_Util::setupFS($shareWith);
|
||||||
|
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$externalManager = new \OCA\Files_Sharing\External\Manager(
|
$externalManager = new \OCA\Files_Sharing\External\Manager(
|
||||||
\OC::$server->getDatabaseConnection(),
|
\OC::$server->getDatabaseConnection(),
|
||||||
\OC\Files\Filesystem::getMountManager(),
|
\OC\Files\Filesystem::getMountManager(),
|
||||||
\OC\Files\Filesystem::getLoader(),
|
\OC\Files\Filesystem::getLoader(),
|
||||||
\OC::$server->getHTTPClientService(),
|
\OC::$server->getHTTPClientService(),
|
||||||
\OC::$server->getNotificationManager(),
|
\OC::$server->getNotificationManager(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$shareWith
|
$shareWith
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,143 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
||||||
*
|
|
||||||
* @author Bjoern Schiessle <bjoern@schiessle.org>
|
|
||||||
* @author Joas Schilling <coding@schilljs.com>
|
|
||||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
|
||||||
* @author Vincent Petry <pvince81@owncloud.com>
|
|
||||||
*
|
|
||||||
* @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\FederatedFileSharing;
|
|
||||||
|
|
||||||
use GuzzleHttp\Exception\ClientException;
|
|
||||||
use GuzzleHttp\Exception\ConnectException;
|
|
||||||
use OCP\Http\Client\IClient;
|
|
||||||
use OCP\Http\Client\IClientService;
|
|
||||||
use OCP\ICache;
|
|
||||||
use OCP\ICacheFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class DiscoveryManager handles the discovery of endpoints used by Federated
|
|
||||||
* Cloud Sharing.
|
|
||||||
*
|
|
||||||
* @package OCA\FederatedFileSharing
|
|
||||||
*/
|
|
||||||
class DiscoveryManager {
|
|
||||||
/** @var ICache */
|
|
||||||
private $cache;
|
|
||||||
/** @var IClient */
|
|
||||||
private $client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ICacheFactory $cacheFactory
|
|
||||||
* @param IClientService $clientService
|
|
||||||
*/
|
|
||||||
public function __construct(ICacheFactory $cacheFactory,
|
|
||||||
IClientService $clientService) {
|
|
||||||
$this->cache = $cacheFactory->create('ocs-discovery');
|
|
||||||
$this->client = $clientService->newClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the specified URL includes only safe characters, if not
|
|
||||||
* returns false
|
|
||||||
*
|
|
||||||
* @param string $url
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function isSafeUrl($url) {
|
|
||||||
return (bool)preg_match('/^[\/\.A-Za-z0-9]+$/', $url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discover the actual data and do some naive caching to ensure that the data
|
|
||||||
* is not requested multiple times.
|
|
||||||
*
|
|
||||||
* If no valid discovery data is found the Nextcloud defaults are returned.
|
|
||||||
*
|
|
||||||
* @param string $remote
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function discover($remote) {
|
|
||||||
// Check if something is in the cache
|
|
||||||
if($cacheData = $this->cache->get($remote)) {
|
|
||||||
return json_decode($cacheData, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default response body
|
|
||||||
$discoveredServices = [
|
|
||||||
'webdav' => '/public.php/webdav',
|
|
||||||
'share' => '/ocs/v1.php/cloud/shares',
|
|
||||||
];
|
|
||||||
|
|
||||||
// Read the data from the response body
|
|
||||||
try {
|
|
||||||
$response = $this->client->get($remote . '/ocs-provider/', [
|
|
||||||
'timeout' => 10,
|
|
||||||
'connect_timeout' => 10,
|
|
||||||
]);
|
|
||||||
if($response->getStatusCode() === 200) {
|
|
||||||
$decodedService = json_decode($response->getBody(), true);
|
|
||||||
if(is_array($decodedService)) {
|
|
||||||
$endpoints = [
|
|
||||||
'webdav',
|
|
||||||
'share',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach($endpoints as $endpoint) {
|
|
||||||
if(isset($decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint])) {
|
|
||||||
$endpointUrl = (string)$decodedService['services']['FEDERATED_SHARING']['endpoints'][$endpoint];
|
|
||||||
if($this->isSafeUrl($endpointUrl)) {
|
|
||||||
$discoveredServices[$endpoint] = $endpointUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClientException $e) {
|
|
||||||
// Don't throw any exception since exceptions are handled before
|
|
||||||
} catch (ConnectException $e) {
|
|
||||||
// Don't throw any exception since exceptions are handled before
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write into cache
|
|
||||||
$this->cache->set($remote, json_encode($discoveredServices));
|
|
||||||
return $discoveredServices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the public WebDAV endpoint used by the specified remote
|
|
||||||
*
|
|
||||||
* @param string $host
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getWebDavEndpoint($host) {
|
|
||||||
return $this->discover($host)['webdav'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the sharing endpoint used by the specified remote
|
|
||||||
*
|
|
||||||
* @param string $host
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getShareEndpoint($host) {
|
|
||||||
return $this->discover($host)['share'];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,6 +30,7 @@ namespace OCA\FederatedFileSharing;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
use OCP\BackgroundJob\IJobList;
|
use OCP\BackgroundJob\IJobList;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
class Notifications {
|
class Notifications {
|
||||||
const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
|
const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
|
||||||
|
@ -40,8 +41,8 @@ class Notifications {
|
||||||
/** @var IClientService */
|
/** @var IClientService */
|
||||||
private $httpClientService;
|
private $httpClientService;
|
||||||
|
|
||||||
/** @var DiscoveryManager */
|
/** @var IDiscoveryService */
|
||||||
private $discoveryManager;
|
private $discoveryService;
|
||||||
|
|
||||||
/** @var IJobList */
|
/** @var IJobList */
|
||||||
private $jobList;
|
private $jobList;
|
||||||
|
@ -49,18 +50,18 @@ class Notifications {
|
||||||
/**
|
/**
|
||||||
* @param AddressHandler $addressHandler
|
* @param AddressHandler $addressHandler
|
||||||
* @param IClientService $httpClientService
|
* @param IClientService $httpClientService
|
||||||
* @param DiscoveryManager $discoveryManager
|
* @param IDiscoveryService $discoveryService
|
||||||
* @param IJobList $jobList
|
* @param IJobList $jobList
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
AddressHandler $addressHandler,
|
AddressHandler $addressHandler,
|
||||||
IClientService $httpClientService,
|
IClientService $httpClientService,
|
||||||
DiscoveryManager $discoveryManager,
|
IDiscoveryService $discoveryService,
|
||||||
IJobList $jobList
|
IJobList $jobList
|
||||||
) {
|
) {
|
||||||
$this->addressHandler = $addressHandler;
|
$this->addressHandler = $addressHandler;
|
||||||
$this->httpClientService = $httpClientService;
|
$this->httpClientService = $httpClientService;
|
||||||
$this->discoveryManager = $discoveryManager;
|
$this->discoveryService = $discoveryService;
|
||||||
$this->jobList = $jobList;
|
$this->jobList = $jobList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +288,8 @@ class Notifications {
|
||||||
'result' => '',
|
'result' => '',
|
||||||
];
|
];
|
||||||
|
|
||||||
$endpoint = $this->discoveryManager->getShareEndpoint($remoteDomain);
|
$federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
|
||||||
|
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
|
||||||
try {
|
try {
|
||||||
$response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
|
$response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
|
||||||
'body' => $fields,
|
'body' => $fields,
|
||||||
|
|
|
@ -270,17 +270,13 @@ class RequestHandlerControllerTest extends TestCase {
|
||||||
->method('newClient')
|
->method('newClient')
|
||||||
->willReturn($client);
|
->willReturn($client);
|
||||||
|
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
$httpClientService
|
|
||||||
);
|
|
||||||
$manager = new \OCA\Files_Sharing\External\Manager(
|
$manager = new \OCA\Files_Sharing\External\Manager(
|
||||||
\OC::$server->getDatabaseConnection(),
|
\OC::$server->getDatabaseConnection(),
|
||||||
Filesystem::getMountManager(),
|
Filesystem::getMountManager(),
|
||||||
Filesystem::getLoader(),
|
Filesystem::getLoader(),
|
||||||
$httpClientService,
|
$httpClientService,
|
||||||
\OC::$server->getNotificationManager(),
|
\OC::$server->getNotificationManager(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$toDelete
|
$toDelete
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,217 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
||||||
*
|
|
||||||
* @author Björn Schießle <bjoern@schiessle.org>
|
|
||||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
|
||||||
* @author Vincent Petry <pvince81@owncloud.com>
|
|
||||||
*
|
|
||||||
* @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\FederatedFileSharing\Tests;
|
|
||||||
|
|
||||||
use OCA\FederatedFileSharing\DiscoveryManager;
|
|
||||||
use OCP\Http\Client\IClient;
|
|
||||||
use OCP\Http\Client\IClientService;
|
|
||||||
use OCP\ICache;
|
|
||||||
use OCP\ICacheFactory;
|
|
||||||
|
|
||||||
class DiscoveryManagerTest extends \Test\TestCase {
|
|
||||||
/** @var ICache */
|
|
||||||
private $cache;
|
|
||||||
/** @var IClient */
|
|
||||||
private $client;
|
|
||||||
/** @var DiscoveryManager */
|
|
||||||
private $discoveryManager;
|
|
||||||
|
|
||||||
public function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
$this->cache = $this->getMockBuilder('\OCP\ICache')
|
|
||||||
->getMock();
|
|
||||||
/** @var ICacheFactory $cacheFactory */
|
|
||||||
$cacheFactory = $this->getMockBuilder('\OCP\ICacheFactory')
|
|
||||||
->disableOriginalConstructor()->getMock();
|
|
||||||
$cacheFactory
|
|
||||||
->expects($this->once())
|
|
||||||
->method('create')
|
|
||||||
->with('ocs-discovery')
|
|
||||||
->willReturn($this->cache);
|
|
||||||
|
|
||||||
$this->client = $this->getMockBuilder('\OCP\Http\Client\IClient')
|
|
||||||
->disableOriginalConstructor()->getMock();
|
|
||||||
/** @var IClientService $clientService */
|
|
||||||
$clientService = $this->getMockBuilder('\OCP\Http\Client\IClientService')
|
|
||||||
->disableOriginalConstructor()->getMock();
|
|
||||||
$clientService
|
|
||||||
->expects($this->once())
|
|
||||||
->method('newClient')
|
|
||||||
->willReturn($this->client);
|
|
||||||
|
|
||||||
$this->discoveryManager = new DiscoveryManager(
|
|
||||||
$cacheFactory,
|
|
||||||
$clientService
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testWithMalformedFormattedEndpointCached() {
|
|
||||||
$response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
|
|
||||||
->getMock();
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getStatusCode')
|
|
||||||
->willReturn(200);
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getBody')
|
|
||||||
->willReturn('CertainlyNotJson');
|
|
||||||
$this->client
|
|
||||||
->expects($this->once())
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com/ocs-provider/', [
|
|
||||||
'timeout' => 10,
|
|
||||||
'connect_timeout' => 10,
|
|
||||||
])
|
|
||||||
->willReturn($response);
|
|
||||||
$this->cache
|
|
||||||
->expects($this->at(0))
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com')
|
|
||||||
->willReturn(null);
|
|
||||||
$this->cache
|
|
||||||
->expects($this->at(1))
|
|
||||||
->method('set')
|
|
||||||
->with('https://myhost.com', '{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
|
|
||||||
$this->cache
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com')
|
|
||||||
->willReturn('{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
|
|
||||||
|
|
||||||
$this->assertSame('/public.php/webdav', $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
|
|
||||||
$this->assertSame('/ocs/v1.php/cloud/shares', $this->discoveryManager->getShareEndpoint('https://myhost.com'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetWebDavEndpointWithValidFormattedEndpointAndNotCached() {
|
|
||||||
$response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
|
|
||||||
->getMock();
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getStatusCode')
|
|
||||||
->willReturn(200);
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getBody')
|
|
||||||
->willReturn('{"version":2,"services":{"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cloud\/shares","webdav":"\/public.php\/MyCustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}}');
|
|
||||||
$this->client
|
|
||||||
->expects($this->once())
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com/ocs-provider/', [
|
|
||||||
'timeout' => 10,
|
|
||||||
'connect_timeout' => 10,
|
|
||||||
])
|
|
||||||
->willReturn($response);
|
|
||||||
|
|
||||||
$expectedResult = '/public.php/MyCustomEndpoint/';
|
|
||||||
$this->assertSame($expectedResult, $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetWebDavEndpointWithValidFormattedEndpointWithoutDataAndNotCached() {
|
|
||||||
$response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
|
|
||||||
->getMock();
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getStatusCode')
|
|
||||||
->willReturn(200);
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getBody')
|
|
||||||
->willReturn('{"version":2,"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cloud\/shares","webdav":"\/public.php\/MyCustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}');
|
|
||||||
$this->client
|
|
||||||
->expects($this->once())
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com/ocs-provider/', [
|
|
||||||
'timeout' => 10,
|
|
||||||
'connect_timeout' => 10,
|
|
||||||
])
|
|
||||||
->willReturn($response);
|
|
||||||
|
|
||||||
$expectedResult = '/public.php/webdav';
|
|
||||||
$this->assertSame($expectedResult, $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetShareEndpointWithValidFormattedEndpointAndNotCached() {
|
|
||||||
$response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
|
|
||||||
->getMock();
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getStatusCode')
|
|
||||||
->willReturn(200);
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getBody')
|
|
||||||
->willReturn('{"version":2,"services":{"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cloud\/MyCustomShareEndpoint","webdav":"\/public.php\/MyCustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}}');
|
|
||||||
$this->client
|
|
||||||
->expects($this->once())
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com/ocs-provider/', [
|
|
||||||
'timeout' => 10,
|
|
||||||
'connect_timeout' => 10,
|
|
||||||
])
|
|
||||||
->willReturn($response);
|
|
||||||
|
|
||||||
$expectedResult = '/ocs/v2.php/cloud/MyCustomShareEndpoint';
|
|
||||||
$this->assertSame($expectedResult, $this->discoveryManager->getShareEndpoint('https://myhost.com'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testWithMaliciousEndpointCached() {
|
|
||||||
$response = $this->getMockBuilder('\OCP\Http\Client\IResponse')
|
|
||||||
->getMock();
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getStatusCode')
|
|
||||||
->willReturn(200);
|
|
||||||
$response
|
|
||||||
->expects($this->once())
|
|
||||||
->method('getBody')
|
|
||||||
->willReturn('{"version":2,"services":{"PRIVATE_DATA":{"version":1,"endpoints":{"store":"\/ocs\/v2.php\/privatedata\/setattribute","read":"\/ocs\/v2.php\/privatedata\/getattribute","delete":"\/ocs\/v2.php\/privatedata\/deleteattribute"}},"SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/apps\/files_sharing\/api\/v1\/shares"}},"FEDERATED_SHARING":{"version":1,"endpoints":{"share":"\/ocs\/v2.php\/cl@oud\/MyCustomShareEndpoint","webdav":"\/public.php\/MyC:ustomEndpoint\/"}},"ACTIVITY":{"version":1,"endpoints":{"list":"\/ocs\/v2.php\/cloud\/activity"}},"PROVISIONING":{"version":1,"endpoints":{"user":"\/ocs\/v2.php\/cloud\/users","groups":"\/ocs\/v2.php\/cloud\/groups","apps":"\/ocs\/v2.php\/cloud\/apps"}}}}');
|
|
||||||
$this->client
|
|
||||||
->expects($this->once())
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com/ocs-provider/', [
|
|
||||||
'timeout' => 10,
|
|
||||||
'connect_timeout' => 10,
|
|
||||||
])
|
|
||||||
->willReturn($response);
|
|
||||||
$this->cache
|
|
||||||
->expects($this->at(0))
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com')
|
|
||||||
->willReturn(null);
|
|
||||||
$this->cache
|
|
||||||
->expects($this->at(1))
|
|
||||||
->method('set')
|
|
||||||
->with('https://myhost.com', '{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
|
|
||||||
$this->cache
|
|
||||||
->expects($this->at(2))
|
|
||||||
->method('get')
|
|
||||||
->with('https://myhost.com')
|
|
||||||
->willReturn('{"webdav":"\/public.php\/webdav","share":"\/ocs\/v1.php\/cloud\/shares"}');
|
|
||||||
|
|
||||||
$this->assertSame('/public.php/webdav', $this->discoveryManager->getWebDavEndpoint('https://myhost.com'));
|
|
||||||
$this->assertSame('/ocs/v1.php/cloud/shares', $this->discoveryManager->getShareEndpoint('https://myhost.com'));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,10 +25,10 @@ namespace OCA\FederatedFileSharing\Tests;
|
||||||
|
|
||||||
|
|
||||||
use OCA\FederatedFileSharing\AddressHandler;
|
use OCA\FederatedFileSharing\AddressHandler;
|
||||||
use OCA\FederatedFileSharing\DiscoveryManager;
|
|
||||||
use OCA\FederatedFileSharing\Notifications;
|
use OCA\FederatedFileSharing\Notifications;
|
||||||
use OCP\BackgroundJob\IJobList;
|
use OCP\BackgroundJob\IJobList;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
class NotificationsTest extends \Test\TestCase {
|
class NotificationsTest extends \Test\TestCase {
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ class NotificationsTest extends \Test\TestCase {
|
||||||
/** @var IClientService | \PHPUnit_Framework_MockObject_MockObject*/
|
/** @var IClientService | \PHPUnit_Framework_MockObject_MockObject*/
|
||||||
private $httpClientService;
|
private $httpClientService;
|
||||||
|
|
||||||
/** @var DiscoveryManager | \PHPUnit_Framework_MockObject_MockObject */
|
/** @var IDiscoveryService | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $discoveryManager;
|
private $discoveryService;
|
||||||
|
|
||||||
/** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */
|
/** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $jobList;
|
private $jobList;
|
||||||
|
@ -48,8 +48,7 @@ class NotificationsTest extends \Test\TestCase {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->jobList = $this->getMockBuilder('OCP\BackgroundJob\IJobList')->getMock();
|
$this->jobList = $this->getMockBuilder('OCP\BackgroundJob\IJobList')->getMock();
|
||||||
$this->discoveryManager = $this->getMockBuilder('OCA\FederatedFileSharing\DiscoveryManager')
|
$this->discoveryService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
|
||||||
->disableOriginalConstructor()->getMock();
|
|
||||||
$this->httpClientService = $this->getMockBuilder('OCP\Http\Client\IClientService')->getMock();
|
$this->httpClientService = $this->getMockBuilder('OCP\Http\Client\IClientService')->getMock();
|
||||||
$this->addressHandler = $this->getMockBuilder('OCA\FederatedFileSharing\AddressHandler')
|
$this->addressHandler = $this->getMockBuilder('OCA\FederatedFileSharing\AddressHandler')
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
|
@ -67,7 +66,7 @@ class NotificationsTest extends \Test\TestCase {
|
||||||
$instance = new Notifications(
|
$instance = new Notifications(
|
||||||
$this->addressHandler,
|
$this->addressHandler,
|
||||||
$this->httpClientService,
|
$this->httpClientService,
|
||||||
$this->discoveryManager,
|
$this->discoveryService,
|
||||||
$this->jobList
|
$this->jobList
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,7 +75,7 @@ class NotificationsTest extends \Test\TestCase {
|
||||||
[
|
[
|
||||||
$this->addressHandler,
|
$this->addressHandler,
|
||||||
$this->httpClientService,
|
$this->httpClientService,
|
||||||
$this->discoveryManager,
|
$this->discoveryService,
|
||||||
$this->jobList
|
$this->jobList
|
||||||
]
|
]
|
||||||
)->setMethods($mockedMethods)->getMock();
|
)->setMethods($mockedMethods)->getMock();
|
||||||
|
|
|
@ -45,12 +45,12 @@ $application->registerRoutes(
|
||||||
'ocs' => [
|
'ocs' => [
|
||||||
// old endpoints, only used by Nextcloud and ownCloud
|
// old endpoints, only used by Nextcloud and ownCloud
|
||||||
[
|
[
|
||||||
'name' => 'OCSAuthAPI#getSharedSecret',
|
'name' => 'OCSAuthAPI#getSharedSecretLegacy',
|
||||||
'url' => '/api/v1/shared-secret',
|
'url' => '/api/v1/shared-secret',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'OCSAuthAPI#requestSharedSecret',
|
'name' => 'OCSAuthAPI#requestSharedSecretLegacy',
|
||||||
'url' => '/api/v1/request-shared-secret',
|
'url' => '/api/v1/request-shared-secret',
|
||||||
'verb' => 'POST',
|
'verb' => 'POST',
|
||||||
],
|
],
|
||||||
|
|
|
@ -135,7 +135,8 @@ class Application extends \OCP\AppFramework\App {
|
||||||
public function getSyncService() {
|
public function getSyncService() {
|
||||||
$syncService = \OC::$server->query('CardDAVSyncService');
|
$syncService = \OC::$server->query('CardDAVSyncService');
|
||||||
$dbHandler = $this->getContainer()->query('DbHandler');
|
$dbHandler = $this->getContainer()->query('DbHandler');
|
||||||
return new SyncFederationAddressBooks($dbHandler, $syncService);
|
$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
|
||||||
|
return new SyncFederationAddressBooks($dbHandler, $syncService, $discoveryService);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ use OCP\Http\Client\IClient;
|
||||||
use OCP\Http\Client\IResponse;
|
use OCP\Http\Client\IResponse;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class GetSharedSecret
|
* Class GetSharedSecret
|
||||||
|
@ -62,13 +63,18 @@ class GetSharedSecret extends Job{
|
||||||
/** @var DbHandler */
|
/** @var DbHandler */
|
||||||
private $dbHandler;
|
private $dbHandler;
|
||||||
|
|
||||||
|
/** @var IDiscoveryService */
|
||||||
|
private $ocsDiscoveryService;
|
||||||
|
|
||||||
/** @var ILogger */
|
/** @var ILogger */
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $retainJob = false;
|
protected $retainJob = false;
|
||||||
|
|
||||||
private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json';
|
private $format = '?format=json';
|
||||||
|
|
||||||
|
private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RequestSharedSecret constructor.
|
* RequestSharedSecret constructor.
|
||||||
|
@ -79,6 +85,7 @@ class GetSharedSecret extends Job{
|
||||||
* @param TrustedServers $trustedServers
|
* @param TrustedServers $trustedServers
|
||||||
* @param ILogger $logger
|
* @param ILogger $logger
|
||||||
* @param DbHandler $dbHandler
|
* @param DbHandler $dbHandler
|
||||||
|
* @param IDiscoveryService $ocsDiscoveryService
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IClient $httpClient = null,
|
IClient $httpClient = null,
|
||||||
|
@ -86,13 +93,15 @@ class GetSharedSecret extends Job{
|
||||||
IJobList $jobList = null,
|
IJobList $jobList = null,
|
||||||
TrustedServers $trustedServers = null,
|
TrustedServers $trustedServers = null,
|
||||||
ILogger $logger = null,
|
ILogger $logger = null,
|
||||||
DbHandler $dbHandler = null
|
DbHandler $dbHandler = null,
|
||||||
|
IDiscoveryService $ocsDiscoveryService = null
|
||||||
) {
|
) {
|
||||||
$this->logger = $logger ? $logger : \OC::$server->getLogger();
|
$this->logger = $logger ? $logger : \OC::$server->getLogger();
|
||||||
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
|
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
|
||||||
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
|
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
|
||||||
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
|
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
|
||||||
$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
|
$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
|
||||||
|
$this->ocsDiscoveryService = $ocsDiscoveryService ? $ocsDiscoveryService : \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
|
||||||
if ($trustedServers) {
|
if ($trustedServers) {
|
||||||
$this->trustedServers = $trustedServers;
|
$this->trustedServers = $trustedServers;
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,10 +151,16 @@ class GetSharedSecret extends Job{
|
||||||
$source = rtrim($source, '/');
|
$source = rtrim($source, '/');
|
||||||
$token = $argument['token'];
|
$token = $argument['token'];
|
||||||
|
|
||||||
|
$endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
|
||||||
|
$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
|
||||||
|
|
||||||
|
// make sure that we have a well formated url
|
||||||
|
$url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
|
||||||
|
|
||||||
$result = null;
|
$result = null;
|
||||||
try {
|
try {
|
||||||
$result = $this->httpClient->get(
|
$result = $this->httpClient->get(
|
||||||
$target . $this->endPoint,
|
$url,
|
||||||
[
|
[
|
||||||
'query' =>
|
'query' =>
|
||||||
[
|
[
|
||||||
|
|
|
@ -37,6 +37,7 @@ use OCP\BackgroundJob\IJobList;
|
||||||
use OCP\Http\Client\IClient;
|
use OCP\Http\Client\IClient;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RequestSharedSecret
|
* Class RequestSharedSecret
|
||||||
|
@ -62,7 +63,8 @@ class RequestSharedSecret extends Job {
|
||||||
/** @var TrustedServers */
|
/** @var TrustedServers */
|
||||||
private $trustedServers;
|
private $trustedServers;
|
||||||
|
|
||||||
private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json';
|
/** @var IDiscoveryService */
|
||||||
|
private $ocsDiscoveryService;
|
||||||
|
|
||||||
/** @var ILogger */
|
/** @var ILogger */
|
||||||
private $logger;
|
private $logger;
|
||||||
|
@ -70,6 +72,10 @@ class RequestSharedSecret extends Job {
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $retainJob = false;
|
protected $retainJob = false;
|
||||||
|
|
||||||
|
private $format = '?format=json';
|
||||||
|
|
||||||
|
private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RequestSharedSecret constructor.
|
* RequestSharedSecret constructor.
|
||||||
*
|
*
|
||||||
|
@ -78,19 +84,22 @@ class RequestSharedSecret extends Job {
|
||||||
* @param IJobList $jobList
|
* @param IJobList $jobList
|
||||||
* @param TrustedServers $trustedServers
|
* @param TrustedServers $trustedServers
|
||||||
* @param DbHandler $dbHandler
|
* @param DbHandler $dbHandler
|
||||||
|
* @param IDiscoveryService $ocsDiscoveryService
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IClient $httpClient = null,
|
IClient $httpClient = null,
|
||||||
IURLGenerator $urlGenerator = null,
|
IURLGenerator $urlGenerator = null,
|
||||||
IJobList $jobList = null,
|
IJobList $jobList = null,
|
||||||
TrustedServers $trustedServers = null,
|
TrustedServers $trustedServers = null,
|
||||||
DbHandler $dbHandler = null
|
DbHandler $dbHandler = null,
|
||||||
|
IDiscoveryService $ocsDiscoveryService = null
|
||||||
) {
|
) {
|
||||||
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
|
$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
|
||||||
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
|
$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
|
||||||
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
|
$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
|
||||||
$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
|
$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
|
||||||
$this->logger = \OC::$server->getLogger();
|
$this->logger = \OC::$server->getLogger();
|
||||||
|
$this->ocsDiscoveryService = $ocsDiscoveryService ? $ocsDiscoveryService : \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
|
||||||
if ($trustedServers) {
|
if ($trustedServers) {
|
||||||
$this->trustedServers = $trustedServers;
|
$this->trustedServers = $trustedServers;
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,9 +151,15 @@ class RequestSharedSecret extends Job {
|
||||||
$source = rtrim($source, '/');
|
$source = rtrim($source, '/');
|
||||||
$token = $argument['token'];
|
$token = $argument['token'];
|
||||||
|
|
||||||
|
$endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
|
||||||
|
$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
|
||||||
|
|
||||||
|
// make sure that we have a well formated url
|
||||||
|
$url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$result = $this->httpClient->post(
|
$result = $this->httpClient->post(
|
||||||
$target . $this->endPoint,
|
$url,
|
||||||
[
|
[
|
||||||
'body' => [
|
'body' => [
|
||||||
'url' => $source,
|
'url' => $source,
|
||||||
|
|
|
@ -90,6 +90,37 @@ class OCSAuthAPIController extends OCSController{
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoCSRFRequired
|
||||||
|
* @PublicPage
|
||||||
|
*
|
||||||
|
* request received to ask remote server for a shared secret, for legacy end-points
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param string $token
|
||||||
|
* @return Http\DataResponse
|
||||||
|
* @throws OCSForbiddenException
|
||||||
|
*/
|
||||||
|
public function requestSharedSecretLegacy($url, $token) {
|
||||||
|
return $this->requestSharedSecret($url, $token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoCSRFRequired
|
||||||
|
* @PublicPage
|
||||||
|
*
|
||||||
|
* create shared secret and return it, for legacy end-points
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param string $token
|
||||||
|
* @return Http\DataResponse
|
||||||
|
* @throws OCSForbiddenException
|
||||||
|
*/
|
||||||
|
public function getSharedSecretLegacy($url, $token) {
|
||||||
|
return $this->getSharedSecret($url, $token);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
|
|
|
@ -23,12 +23,10 @@
|
||||||
*/
|
*/
|
||||||
namespace OCA\Federation;
|
namespace OCA\Federation;
|
||||||
|
|
||||||
|
use OC\OCS\DiscoveryService;
|
||||||
use OCA\DAV\CardDAV\SyncService;
|
use OCA\DAV\CardDAV\SyncService;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use OCP\OCS\IDiscoveryService;
|
||||||
use Symfony\Component\Console\Helper\ProgressBar;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
|
|
||||||
class SyncFederationAddressBooks {
|
class SyncFederationAddressBooks {
|
||||||
|
|
||||||
|
@ -38,13 +36,21 @@ class SyncFederationAddressBooks {
|
||||||
/** @var SyncService */
|
/** @var SyncService */
|
||||||
private $syncService;
|
private $syncService;
|
||||||
|
|
||||||
|
/** @var DiscoveryService */
|
||||||
|
private $ocsDiscoveryService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DbHandler $dbHandler
|
* @param DbHandler $dbHandler
|
||||||
* @param SyncService $syncService
|
* @param SyncService $syncService
|
||||||
|
* @param IDiscoveryService $ocsDiscoveryService
|
||||||
*/
|
*/
|
||||||
function __construct(DbHandler $dbHandler, SyncService $syncService) {
|
public function __construct(DbHandler $dbHandler,
|
||||||
|
SyncService $syncService,
|
||||||
|
IDiscoveryService $ocsDiscoveryService
|
||||||
|
) {
|
||||||
$this->syncService = $syncService;
|
$this->syncService = $syncService;
|
||||||
$this->dbHandler = $dbHandler;
|
$this->dbHandler = $dbHandler;
|
||||||
|
$this->ocsDiscoveryService = $ocsDiscoveryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,6 +65,10 @@ class SyncFederationAddressBooks {
|
||||||
$sharedSecret = $trustedServer['shared_secret'];
|
$sharedSecret = $trustedServer['shared_secret'];
|
||||||
$syncToken = $trustedServer['sync_token'];
|
$syncToken = $trustedServer['sync_token'];
|
||||||
|
|
||||||
|
$endPoints = $this->ocsDiscoveryService->discover($url, 'FEDERATED_SHARING');
|
||||||
|
$cardDavUser = isset($endPoints['carddav-user']) ? $endPoints['carddav-user'] : 'system';
|
||||||
|
$addressBookUrl = isset($endPoints['system-address-book']) ? trim($endPoints['system-address-book'], '/') : 'remote.php/dav/addressbooks/system/system/system';
|
||||||
|
|
||||||
if (is_null($sharedSecret)) {
|
if (is_null($sharedSecret)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +78,7 @@ class SyncFederationAddressBooks {
|
||||||
'{DAV:}displayname' => $url
|
'{DAV:}displayname' => $url
|
||||||
];
|
];
|
||||||
try {
|
try {
|
||||||
$newToken = $this->syncService->syncRemoteAddressBook($url, 'system', $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetBookProperties);
|
$newToken = $this->syncService->syncRemoteAddressBook($url, $cardDavUser, $addressBookUrl, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetBookProperties);
|
||||||
if ($newToken !== $syncToken) {
|
if ($newToken !== $syncToken) {
|
||||||
$this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken);
|
$this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ use OCP\Http\Client\IClient;
|
||||||
use OCP\Http\Client\IResponse;
|
use OCP\Http\Client\IResponse;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class GetSharedSecretTest
|
* Class GetSharedSecretTest
|
||||||
|
@ -67,6 +68,9 @@ class GetSharedSecretTest extends TestCase {
|
||||||
/** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
|
/** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
|
||||||
private $response;
|
private $response;
|
||||||
|
|
||||||
|
/** @var \PHPUnit_Framework_MockObject_MockObject | IDiscoveryService */
|
||||||
|
private $discoverService;
|
||||||
|
|
||||||
/** @var GetSharedSecret */
|
/** @var GetSharedSecret */
|
||||||
private $getSharedSecret;
|
private $getSharedSecret;
|
||||||
|
|
||||||
|
@ -82,6 +86,9 @@ class GetSharedSecretTest extends TestCase {
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
$this->logger = $this->getMockBuilder(ILogger::class)->getMock();
|
$this->logger = $this->getMockBuilder(ILogger::class)->getMock();
|
||||||
$this->response = $this->getMockBuilder(IResponse::class)->getMock();
|
$this->response = $this->getMockBuilder(IResponse::class)->getMock();
|
||||||
|
$this->discoverService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
|
||||||
|
|
||||||
|
$this->discoverService->expects($this->any())->method('discover')->willReturn([]);
|
||||||
|
|
||||||
$this->getSharedSecret = new GetSharedSecret(
|
$this->getSharedSecret = new GetSharedSecret(
|
||||||
$this->httpClient,
|
$this->httpClient,
|
||||||
|
@ -89,7 +96,8 @@ class GetSharedSecretTest extends TestCase {
|
||||||
$this->jobList,
|
$this->jobList,
|
||||||
$this->trustedServers,
|
$this->trustedServers,
|
||||||
$this->logger,
|
$this->logger,
|
||||||
$this->dbHandler
|
$this->dbHandler,
|
||||||
|
$this->discoverService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +117,8 @@ class GetSharedSecretTest extends TestCase {
|
||||||
$this->jobList,
|
$this->jobList,
|
||||||
$this->trustedServers,
|
$this->trustedServers,
|
||||||
$this->logger,
|
$this->logger,
|
||||||
$this->dbHandler
|
$this->dbHandler,
|
||||||
|
$this->discoverService
|
||||||
]
|
]
|
||||||
)->setMethods(['parentExecute'])->getMock();
|
)->setMethods(['parentExecute'])->getMock();
|
||||||
$this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url']]);
|
$this->invokePrivate($getSharedSecret, 'argument', [['url' => 'url']]);
|
||||||
|
|
|
@ -33,6 +33,7 @@ use OCP\BackgroundJob\IJobList;
|
||||||
use OCP\Http\Client\IClient;
|
use OCP\Http\Client\IClient;
|
||||||
use OCP\Http\Client\IResponse;
|
use OCP\Http\Client\IResponse;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
use Test\TestCase;
|
use Test\TestCase;
|
||||||
|
|
||||||
class RequestSharedSecretTest extends TestCase {
|
class RequestSharedSecretTest extends TestCase {
|
||||||
|
@ -55,6 +56,9 @@ class RequestSharedSecretTest extends TestCase {
|
||||||
/** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
|
/** @var \PHPUnit_Framework_MockObject_MockObject | IResponse */
|
||||||
private $response;
|
private $response;
|
||||||
|
|
||||||
|
/** @var \PHPUnit_Framework_MockObject_MockObject | IDiscoveryService */
|
||||||
|
private $discoveryService;
|
||||||
|
|
||||||
/** @var RequestSharedSecret */
|
/** @var RequestSharedSecret */
|
||||||
private $requestSharedSecret;
|
private $requestSharedSecret;
|
||||||
|
|
||||||
|
@ -69,13 +73,17 @@ class RequestSharedSecretTest extends TestCase {
|
||||||
$this->dbHandler = $this->getMockBuilder(DbHandler::class)
|
$this->dbHandler = $this->getMockBuilder(DbHandler::class)
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
$this->response = $this->getMockBuilder(IResponse::class)->getMock();
|
$this->response = $this->getMockBuilder(IResponse::class)->getMock();
|
||||||
|
$this->discoveryService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
|
||||||
|
|
||||||
|
$this->discoveryService->expects($this->any())->method('discover')->willReturn([]);
|
||||||
|
|
||||||
$this->requestSharedSecret = new RequestSharedSecret(
|
$this->requestSharedSecret = new RequestSharedSecret(
|
||||||
$this->httpClient,
|
$this->httpClient,
|
||||||
$this->urlGenerator,
|
$this->urlGenerator,
|
||||||
$this->jobList,
|
$this->jobList,
|
||||||
$this->trustedServers,
|
$this->trustedServers,
|
||||||
$this->dbHandler
|
$this->dbHandler,
|
||||||
|
$this->discoveryService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +102,8 @@ class RequestSharedSecretTest extends TestCase {
|
||||||
$this->urlGenerator,
|
$this->urlGenerator,
|
||||||
$this->jobList,
|
$this->jobList,
|
||||||
$this->trustedServers,
|
$this->trustedServers,
|
||||||
$this->dbHandler
|
$this->dbHandler,
|
||||||
|
$this->discoveryService
|
||||||
]
|
]
|
||||||
)->setMethods(['parentExecute'])->getMock();
|
)->setMethods(['parentExecute'])->getMock();
|
||||||
$this->invokePrivate($requestSharedSecret, 'argument', [['url' => 'url']]);
|
$this->invokePrivate($requestSharedSecret, 'argument', [['url' => 'url']]);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
namespace OCA\Federation\Tests;
|
namespace OCA\Federation\Tests;
|
||||||
|
|
||||||
|
use OC\OCS\DiscoveryService;
|
||||||
use OCA\Federation\DbHandler;
|
use OCA\Federation\DbHandler;
|
||||||
use OCA\Federation\SyncFederationAddressBooks;
|
use OCA\Federation\SyncFederationAddressBooks;
|
||||||
|
|
||||||
|
@ -32,7 +33,18 @@ class SyncFederationAddressbooksTest extends \Test\TestCase {
|
||||||
/** @var array */
|
/** @var array */
|
||||||
private $callBacks = [];
|
private $callBacks = [];
|
||||||
|
|
||||||
function testSync() {
|
/** @var \PHPUnit_Framework_MockObject_MockObject | DiscoveryService */
|
||||||
|
private $discoveryService;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->discoveryService = $this->getMockBuilder(DiscoveryService::class)
|
||||||
|
->disableOriginalConstructor()->getMock();
|
||||||
|
$this->discoveryService->expects($this->any())->method('discover')->willReturn([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSync() {
|
||||||
/** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $dbHandler */
|
/** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $dbHandler */
|
||||||
$dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')->
|
$dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')->
|
||||||
disableOriginalConstructor()->
|
disableOriginalConstructor()->
|
||||||
|
@ -55,14 +67,14 @@ class SyncFederationAddressbooksTest extends \Test\TestCase {
|
||||||
->willReturn(1);
|
->willReturn(1);
|
||||||
|
|
||||||
/** @var \OCA\DAV\CardDAV\SyncService $syncService */
|
/** @var \OCA\DAV\CardDAV\SyncService $syncService */
|
||||||
$s = new SyncFederationAddressBooks($dbHandler, $syncService);
|
$s = new SyncFederationAddressBooks($dbHandler, $syncService, $this->discoveryService);
|
||||||
$s->syncThemAll(function($url, $ex) {
|
$s->syncThemAll(function($url, $ex) {
|
||||||
$this->callBacks[] = [$url, $ex];
|
$this->callBacks[] = [$url, $ex];
|
||||||
});
|
});
|
||||||
$this->assertEquals(1, count($this->callBacks));
|
$this->assertEquals(1, count($this->callBacks));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testException() {
|
public function testException() {
|
||||||
/** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $dbHandler */
|
/** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $dbHandler */
|
||||||
$dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')->
|
$dbHandler = $this->getMockBuilder('OCA\Federation\DbHandler')->
|
||||||
disableOriginalConstructor()->
|
disableOriginalConstructor()->
|
||||||
|
@ -83,7 +95,7 @@ class SyncFederationAddressbooksTest extends \Test\TestCase {
|
||||||
->willThrowException(new \Exception('something did not work out'));
|
->willThrowException(new \Exception('something did not work out'));
|
||||||
|
|
||||||
/** @var \OCA\DAV\CardDAV\SyncService $syncService */
|
/** @var \OCA\DAV\CardDAV\SyncService $syncService */
|
||||||
$s = new SyncFederationAddressBooks($dbHandler, $syncService);
|
$s = new SyncFederationAddressBooks($dbHandler, $syncService, $this->discoveryService);
|
||||||
$s->syncThemAll(function($url, $ex) {
|
$s->syncThemAll(function($url, $ex) {
|
||||||
$this->callBacks[] = [$url, $ex];
|
$this->callBacks[] = [$url, $ex];
|
||||||
});
|
});
|
||||||
|
|
|
@ -92,17 +92,13 @@ class Application extends App {
|
||||||
$container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) {
|
$container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) {
|
||||||
$user = $server->getUserSession()->getUser();
|
$user = $server->getUserSession()->getUser();
|
||||||
$uid = $user ? $user->getUID() : null;
|
$uid = $user ? $user->getUID() : null;
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
return new \OCA\Files_Sharing\External\Manager(
|
return new \OCA\Files_Sharing\External\Manager(
|
||||||
$server->getDatabaseConnection(),
|
$server->getDatabaseConnection(),
|
||||||
\OC\Files\Filesystem::getMountManager(),
|
\OC\Files\Filesystem::getMountManager(),
|
||||||
\OC\Files\Filesystem::getLoader(),
|
\OC\Files\Filesystem::getLoader(),
|
||||||
$server->getHTTPClientService(),
|
$server->getHTTPClientService(),
|
||||||
$server->getNotificationManager(),
|
$server->getNotificationManager(),
|
||||||
$discoveryManager,
|
$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$uid
|
$uid
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,8 +32,11 @@ namespace OCA\Files_Sharing\External;
|
||||||
use OC\Files\Filesystem;
|
use OC\Files\Filesystem;
|
||||||
use OCA\FederatedFileSharing\DiscoveryManager;
|
use OCA\FederatedFileSharing\DiscoveryManager;
|
||||||
use OCP\Files;
|
use OCP\Files;
|
||||||
|
use OCP\Files\Storage\IStorageFactory;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
|
use OCP\IDBConnection;
|
||||||
use OCP\Notification\IManager;
|
use OCP\Notification\IManager;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
class Manager {
|
class Manager {
|
||||||
const STORAGE = '\OCA\Files_Sharing\External\Storage';
|
const STORAGE = '\OCA\Files_Sharing\External\Storage';
|
||||||
|
@ -44,7 +47,7 @@ class Manager {
|
||||||
private $uid;
|
private $uid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \OCP\IDBConnection
|
* @var IDBConnection
|
||||||
*/
|
*/
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
|
@ -54,7 +57,7 @@ class Manager {
|
||||||
private $mountManager;
|
private $mountManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \OCP\Files\Storage\IStorageFactory
|
* @var IStorageFactory
|
||||||
*/
|
*/
|
||||||
private $storageLoader;
|
private $storageLoader;
|
||||||
|
|
||||||
|
@ -67,24 +70,27 @@ class Manager {
|
||||||
* @var IManager
|
* @var IManager
|
||||||
*/
|
*/
|
||||||
private $notificationManager;
|
private $notificationManager;
|
||||||
/** @var DiscoveryManager */
|
|
||||||
private $discoveryManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \OCP\IDBConnection $connection
|
* @var IDiscoveryService
|
||||||
|
*/
|
||||||
|
private $discoveryService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param IDBConnection $connection
|
||||||
* @param \OC\Files\Mount\Manager $mountManager
|
* @param \OC\Files\Mount\Manager $mountManager
|
||||||
* @param \OCP\Files\Storage\IStorageFactory $storageLoader
|
* @param IStorageFactory $storageLoader
|
||||||
* @param IClientService $clientService
|
* @param IClientService $clientService
|
||||||
* @param IManager $notificationManager
|
* @param IManager $notificationManager
|
||||||
* @param DiscoveryManager $discoveryManager
|
* @param IDiscoveryService $discoveryService
|
||||||
* @param string $uid
|
* @param string $uid
|
||||||
*/
|
*/
|
||||||
public function __construct(\OCP\IDBConnection $connection,
|
public function __construct(IDBConnection $connection,
|
||||||
\OC\Files\Mount\Manager $mountManager,
|
\OC\Files\Mount\Manager $mountManager,
|
||||||
\OCP\Files\Storage\IStorageFactory $storageLoader,
|
IStorageFactory $storageLoader,
|
||||||
IClientService $clientService,
|
IClientService $clientService,
|
||||||
IManager $notificationManager,
|
IManager $notificationManager,
|
||||||
DiscoveryManager $discoveryManager,
|
IDiscoveryService $discoveryService,
|
||||||
$uid) {
|
$uid) {
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
$this->mountManager = $mountManager;
|
$this->mountManager = $mountManager;
|
||||||
|
@ -92,7 +98,7 @@ class Manager {
|
||||||
$this->clientService = $clientService;
|
$this->clientService = $clientService;
|
||||||
$this->uid = $uid;
|
$this->uid = $uid;
|
||||||
$this->notificationManager = $notificationManager;
|
$this->notificationManager = $notificationManager;
|
||||||
$this->discoveryManager = $discoveryManager;
|
$this->discoveryService = $discoveryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,7 +266,10 @@ class Manager {
|
||||||
*/
|
*/
|
||||||
private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
|
private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
|
||||||
|
|
||||||
$url = rtrim($remote, '/') . $this->discoveryManager->getShareEndpoint($remote) . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
|
$federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING');
|
||||||
|
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
|
||||||
|
|
||||||
|
$url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
|
||||||
$fields = array('token' => $token);
|
$fields = array('token' => $token);
|
||||||
|
|
||||||
$client = $this->clientService->newClient();
|
$client = $this->clientService->newClient();
|
||||||
|
|
|
@ -51,8 +51,6 @@ class Storage extends DAV implements ISharedStorage {
|
||||||
private $memcacheFactory;
|
private $memcacheFactory;
|
||||||
/** @var \OCP\Http\Client\IClientService */
|
/** @var \OCP\Http\Client\IClientService */
|
||||||
private $httpClient;
|
private $httpClient;
|
||||||
/** @var \OCP\ICertificateManager */
|
|
||||||
private $certificateManager;
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $updateChecked = false;
|
private $updateChecked = false;
|
||||||
|
|
||||||
|
@ -64,14 +62,11 @@ class Storage extends DAV implements ISharedStorage {
|
||||||
public function __construct($options) {
|
public function __construct($options) {
|
||||||
$this->memcacheFactory = \OC::$server->getMemCacheFactory();
|
$this->memcacheFactory = \OC::$server->getMemCacheFactory();
|
||||||
$this->httpClient = $options['HttpClientService'];
|
$this->httpClient = $options['HttpClientService'];
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
$this->memcacheFactory,
|
|
||||||
$this->httpClient
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->manager = $options['manager'];
|
$this->manager = $options['manager'];
|
||||||
$this->certificateManager = $options['certificateManager'];
|
|
||||||
$this->cloudId = $options['cloudId'];
|
$this->cloudId = $options['cloudId'];
|
||||||
|
$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
|
||||||
|
|
||||||
list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
|
list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
|
||||||
if (strpos($remote, '/')) {
|
if (strpos($remote, '/')) {
|
||||||
list($host, $root) = explode('/', $remote, 2);
|
list($host, $root) = explode('/', $remote, 2);
|
||||||
|
@ -80,9 +75,12 @@ class Storage extends DAV implements ISharedStorage {
|
||||||
$root = '';
|
$root = '';
|
||||||
}
|
}
|
||||||
$secure = $protocol === 'https';
|
$secure = $protocol === 'https';
|
||||||
$root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->cloudId->getRemote());
|
$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
|
||||||
|
$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
|
||||||
|
$root = rtrim($root, '/') . $webDavEndpoint;
|
||||||
$this->mountPoint = $options['mountpoint'];
|
$this->mountPoint = $options['mountpoint'];
|
||||||
$this->token = $options['token'];
|
$this->token = $options['token'];
|
||||||
|
|
||||||
parent::__construct(array(
|
parent::__construct(array(
|
||||||
'secure' => $secure,
|
'secure' => $secure,
|
||||||
'host' => $host,
|
'host' => $host,
|
||||||
|
|
|
@ -32,17 +32,13 @@ use OCA\FederatedFileSharing\DiscoveryManager;
|
||||||
class Hooks {
|
class Hooks {
|
||||||
|
|
||||||
public static function deleteUser($params) {
|
public static function deleteUser($params) {
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$manager = new External\Manager(
|
$manager = new External\Manager(
|
||||||
\OC::$server->getDatabaseConnection(),
|
\OC::$server->getDatabaseConnection(),
|
||||||
\OC\Files\Filesystem::getMountManager(),
|
\OC\Files\Filesystem::getMountManager(),
|
||||||
\OC\Files\Filesystem::getLoader(),
|
\OC\Files\Filesystem::getLoader(),
|
||||||
\OC::$server->getHTTPClientService(),
|
\OC::$server->getHTTPClientService(),
|
||||||
\OC::$server->getNotificationManager(),
|
\OC::$server->getNotificationManager(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$params['uid']);
|
$params['uid']);
|
||||||
|
|
||||||
$manager->removeUserShares($params['uid']);
|
$manager->removeUserShares($params['uid']);
|
||||||
|
|
|
@ -70,17 +70,14 @@ class ManagerTest extends TestCase {
|
||||||
$this->mountManager = new \OC\Files\Mount\Manager();
|
$this->mountManager = new \OC\Files\Mount\Manager();
|
||||||
$this->clientService = $this->getMockBuilder('\OCP\Http\Client\IClientService')
|
$this->clientService = $this->getMockBuilder('\OCP\Http\Client\IClientService')
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$this->manager = new Manager(
|
$this->manager = new Manager(
|
||||||
\OC::$server->getDatabaseConnection(),
|
\OC::$server->getDatabaseConnection(),
|
||||||
$this->mountManager,
|
$this->mountManager,
|
||||||
new StorageFactory(),
|
new StorageFactory(),
|
||||||
$this->clientService,
|
$this->clientService,
|
||||||
\OC::$server->getNotificationManager(),
|
\OC::$server->getNotificationManager(),
|
||||||
$discoveryManager,
|
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$this->uid
|
$this->uid
|
||||||
);
|
);
|
||||||
$this->testMountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() {
|
$this->testMountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() {
|
||||||
|
@ -143,7 +140,7 @@ class ManagerTest extends TestCase {
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
$client->expects($this->once())
|
$client->expects($this->once())
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id']), $this->anything())
|
->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $openShares[0]['remote_id']), $this->anything())
|
||||||
->willReturn($response);
|
->willReturn($response);
|
||||||
|
|
||||||
// Accept the first share
|
// Accept the first share
|
||||||
|
@ -186,7 +183,7 @@ class ManagerTest extends TestCase {
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
$client->expects($this->once())
|
$client->expects($this->once())
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[1]['remote_id'] . '/decline'), $this->anything())
|
->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $openShares[1]['remote_id'] . '/decline'), $this->anything())
|
||||||
->willReturn($response);
|
->willReturn($response);
|
||||||
|
|
||||||
// Decline the third share
|
// Decline the third share
|
||||||
|
@ -226,11 +223,11 @@ class ManagerTest extends TestCase {
|
||||||
->disableOriginalConstructor()->getMock();
|
->disableOriginalConstructor()->getMock();
|
||||||
$client1->expects($this->once())
|
$client1->expects($this->once())
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id'] . '/decline'), $this->anything())
|
->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $openShares[0]['remote_id'] . '/decline'), $this->anything())
|
||||||
->willReturn($response);
|
->willReturn($response);
|
||||||
$client2->expects($this->once())
|
$client2->expects($this->once())
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $acceptedShares[0]['remote_id'] . '/decline'), $this->anything())
|
->with($this->stringStartsWith('http://localhost/ocs/v2.php/cloud/shares/' . $acceptedShares[0]['remote_id'] . '/decline'), $this->anything())
|
||||||
->willReturn($response);
|
->willReturn($response);
|
||||||
|
|
||||||
$this->manager->removeUserShares($this->uid);
|
$this->manager->removeUserShares($this->uid);
|
||||||
|
|
|
@ -220,6 +220,7 @@ return array(
|
||||||
'OCP\\Notification\\IManager' => $baseDir . '/lib/public/Notification/IManager.php',
|
'OCP\\Notification\\IManager' => $baseDir . '/lib/public/Notification/IManager.php',
|
||||||
'OCP\\Notification\\INotification' => $baseDir . '/lib/public/Notification/INotification.php',
|
'OCP\\Notification\\INotification' => $baseDir . '/lib/public/Notification/INotification.php',
|
||||||
'OCP\\Notification\\INotifier' => $baseDir . '/lib/public/Notification/INotifier.php',
|
'OCP\\Notification\\INotifier' => $baseDir . '/lib/public/Notification/INotifier.php',
|
||||||
|
'OCP\\OCS\\IDiscoveryService' => $baseDir . '/lib/public/OCS/IDiscoveryService.php',
|
||||||
'OCP\\PreConditionNotMetException' => $baseDir . '/lib/public/PreConditionNotMetException.php',
|
'OCP\\PreConditionNotMetException' => $baseDir . '/lib/public/PreConditionNotMetException.php',
|
||||||
'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php',
|
'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php',
|
||||||
'OCP\\Response' => $baseDir . '/lib/public/Response.php',
|
'OCP\\Response' => $baseDir . '/lib/public/Response.php',
|
||||||
|
@ -662,6 +663,7 @@ return array(
|
||||||
'OC\\Notification\\Manager' => $baseDir . '/lib/private/Notification/Manager.php',
|
'OC\\Notification\\Manager' => $baseDir . '/lib/private/Notification/Manager.php',
|
||||||
'OC\\Notification\\Notification' => $baseDir . '/lib/private/Notification/Notification.php',
|
'OC\\Notification\\Notification' => $baseDir . '/lib/private/Notification/Notification.php',
|
||||||
'OC\\OCS\\CoreCapabilities' => $baseDir . '/lib/private/OCS/CoreCapabilities.php',
|
'OC\\OCS\\CoreCapabilities' => $baseDir . '/lib/private/OCS/CoreCapabilities.php',
|
||||||
|
'OC\\OCS\\DiscoveryService' => $baseDir . '/lib/private/OCS/DiscoveryService.php',
|
||||||
'OC\\OCS\\Exception' => $baseDir . '/lib/private/OCS/Exception.php',
|
'OC\\OCS\\Exception' => $baseDir . '/lib/private/OCS/Exception.php',
|
||||||
'OC\\OCS\\PrivateData' => $baseDir . '/lib/private/OCS/PrivateData.php',
|
'OC\\OCS\\PrivateData' => $baseDir . '/lib/private/OCS/PrivateData.php',
|
||||||
'OC\\OCS\\Provider' => $baseDir . '/lib/private/OCS/Provider.php',
|
'OC\\OCS\\Provider' => $baseDir . '/lib/private/OCS/Provider.php',
|
||||||
|
|
|
@ -250,6 +250,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
||||||
'OCP\\Notification\\IManager' => __DIR__ . '/../../..' . '/lib/public/Notification/IManager.php',
|
'OCP\\Notification\\IManager' => __DIR__ . '/../../..' . '/lib/public/Notification/IManager.php',
|
||||||
'OCP\\Notification\\INotification' => __DIR__ . '/../../..' . '/lib/public/Notification/INotification.php',
|
'OCP\\Notification\\INotification' => __DIR__ . '/../../..' . '/lib/public/Notification/INotification.php',
|
||||||
'OCP\\Notification\\INotifier' => __DIR__ . '/../../..' . '/lib/public/Notification/INotifier.php',
|
'OCP\\Notification\\INotifier' => __DIR__ . '/../../..' . '/lib/public/Notification/INotifier.php',
|
||||||
|
'OCP\\OCS\\IDiscoveryService' => __DIR__ . '/../../..' . '/lib/public/OCS/IDiscoveryService.php',
|
||||||
'OCP\\PreConditionNotMetException' => __DIR__ . '/../../..' . '/lib/public/PreConditionNotMetException.php',
|
'OCP\\PreConditionNotMetException' => __DIR__ . '/../../..' . '/lib/public/PreConditionNotMetException.php',
|
||||||
'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php',
|
'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php',
|
||||||
'OCP\\Response' => __DIR__ . '/../../..' . '/lib/public/Response.php',
|
'OCP\\Response' => __DIR__ . '/../../..' . '/lib/public/Response.php',
|
||||||
|
@ -692,6 +693,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
||||||
'OC\\Notification\\Manager' => __DIR__ . '/../../..' . '/lib/private/Notification/Manager.php',
|
'OC\\Notification\\Manager' => __DIR__ . '/../../..' . '/lib/private/Notification/Manager.php',
|
||||||
'OC\\Notification\\Notification' => __DIR__ . '/../../..' . '/lib/private/Notification/Notification.php',
|
'OC\\Notification\\Notification' => __DIR__ . '/../../..' . '/lib/private/Notification/Notification.php',
|
||||||
'OC\\OCS\\CoreCapabilities' => __DIR__ . '/../../..' . '/lib/private/OCS/CoreCapabilities.php',
|
'OC\\OCS\\CoreCapabilities' => __DIR__ . '/../../..' . '/lib/private/OCS/CoreCapabilities.php',
|
||||||
|
'OC\\OCS\\DiscoveryService' => __DIR__ . '/../../..' . '/lib/private/OCS/DiscoveryService.php',
|
||||||
'OC\\OCS\\Exception' => __DIR__ . '/../../..' . '/lib/private/OCS/Exception.php',
|
'OC\\OCS\\Exception' => __DIR__ . '/../../..' . '/lib/private/OCS/Exception.php',
|
||||||
'OC\\OCS\\PrivateData' => __DIR__ . '/../../..' . '/lib/private/OCS/PrivateData.php',
|
'OC\\OCS\\PrivateData' => __DIR__ . '/../../..' . '/lib/private/OCS/PrivateData.php',
|
||||||
'OC\\OCS\\Provider' => __DIR__ . '/../../..' . '/lib/private/OCS/Provider.php',
|
'OC\\OCS\\Provider' => __DIR__ . '/../../..' . '/lib/private/OCS/Provider.php',
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace OC\OCS;
|
||||||
|
|
||||||
|
use OCP\AppFramework\Http;
|
||||||
|
use OCP\Http\Client\IClient;
|
||||||
|
use OCP\Http\Client\IClientService;
|
||||||
|
use OCP\ICache;
|
||||||
|
use OCP\ICacheFactory;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
|
||||||
|
class DiscoveryService implements IDiscoveryService {
|
||||||
|
|
||||||
|
/** @var ICache */
|
||||||
|
private $cache;
|
||||||
|
|
||||||
|
/** @var IClient */
|
||||||
|
private $client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ICacheFactory $cacheFactory
|
||||||
|
* @param IClientService $clientService
|
||||||
|
*/
|
||||||
|
public function __construct(ICacheFactory $cacheFactory,
|
||||||
|
IClientService $clientService
|
||||||
|
) {
|
||||||
|
$this->cache = $cacheFactory->create('ocs-discovery');
|
||||||
|
$this->client = $clientService->newClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover OCS end-points
|
||||||
|
*
|
||||||
|
* If no valid discovery data is found the defaults are returned
|
||||||
|
*
|
||||||
|
* @param string $remote
|
||||||
|
* @param string $service the service you want to discover
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function discover($remote, $service) {
|
||||||
|
// Check the cache first
|
||||||
|
$cacheData = $this->cache->get($remote . '#' . $service);
|
||||||
|
if($cacheData) {
|
||||||
|
return json_decode($cacheData, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$discoveredServices = [];
|
||||||
|
|
||||||
|
// query the remote server for available services
|
||||||
|
try {
|
||||||
|
$response = $this->client->get($remote . '/ocs-provider/', [
|
||||||
|
'timeout' => 10,
|
||||||
|
'connect_timeout' => 10,
|
||||||
|
]);
|
||||||
|
if($response->getStatusCode() === Http::STATUS_OK) {
|
||||||
|
$decodedServices = json_decode($response->getBody(), true);
|
||||||
|
$discoveredServices = $this->getEndpoints($decodedServices, $service);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// if we couldn't discover the service or any end-points we return a empty array
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write into cache
|
||||||
|
$this->cache->set($remote . '#' . $service, json_encode($discoveredServices));
|
||||||
|
return $discoveredServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get requested end-points from the requested service
|
||||||
|
*
|
||||||
|
* @param $decodedServices
|
||||||
|
* @param $service
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getEndpoints($decodedServices, $service) {
|
||||||
|
|
||||||
|
$discoveredServices = [];
|
||||||
|
|
||||||
|
if(is_array($decodedServices) &&
|
||||||
|
isset($decodedServices['services'][$service]['endpoints'])
|
||||||
|
) {
|
||||||
|
foreach ($decodedServices['services'][$service]['endpoints'] as $endpoint => $url) {
|
||||||
|
if($this->isSafeUrl($url)) {
|
||||||
|
$discoveredServices[$endpoint] = $url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $discoveredServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the specified URL includes only safe characters, if not
|
||||||
|
* returns false
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isSafeUrl($url) {
|
||||||
|
return (bool)preg_match('/^[\/\.\-A-Za-z0-9]+$/', $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -77,6 +77,7 @@ use OC\Mail\Mailer;
|
||||||
use OC\Memcache\ArrayCache;
|
use OC\Memcache\ArrayCache;
|
||||||
use OC\Memcache\Factory;
|
use OC\Memcache\Factory;
|
||||||
use OC\Notification\Manager;
|
use OC\Notification\Manager;
|
||||||
|
use OC\OCS\DiscoveryService;
|
||||||
use OC\Repair\NC11\CleanPreviewsBackgroundJob;
|
use OC\Repair\NC11\CleanPreviewsBackgroundJob;
|
||||||
use OC\RichObjectStrings\Validator;
|
use OC\RichObjectStrings\Validator;
|
||||||
use OC\Security\Bruteforce\Throttler;
|
use OC\Security\Bruteforce\Throttler;
|
||||||
|
@ -938,6 +939,10 @@ class Server extends ServerContainer implements IServerContainer {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->registerService(\OCP\OCS\IDiscoveryService::class, function (Server $c) {
|
||||||
|
return new DiscoveryService($c->getMemCacheFactory(), $c->getHTTPClientService());
|
||||||
|
});
|
||||||
|
|
||||||
$this->registerService(ICloudIdManager::class, function (Server $c) {
|
$this->registerService(ICloudIdManager::class, function (Server $c) {
|
||||||
return new CloudIdManager();
|
return new CloudIdManager();
|
||||||
});
|
});
|
||||||
|
|
|
@ -2742,12 +2742,10 @@ class Share extends Constants {
|
||||||
'result' => '',
|
'result' => '',
|
||||||
];
|
];
|
||||||
$try = 0;
|
$try = 0;
|
||||||
$discoveryManager = new DiscoveryManager(
|
$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
|
||||||
\OC::$server->getMemCacheFactory(),
|
|
||||||
\OC::$server->getHTTPClientService()
|
|
||||||
);
|
|
||||||
while ($result['success'] === false && $try < 2) {
|
while ($result['success'] === false && $try < 2) {
|
||||||
$endpoint = $discoveryManager->getShareEndpoint($protocol . $remoteDomain);
|
$federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
|
||||||
|
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
|
||||||
$result = \OC::$server->getHTTPHelper()->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, $fields);
|
$result = \OC::$server->getHTTPHelper()->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, $fields);
|
||||||
$try++;
|
$try++;
|
||||||
$protocol = 'http://';
|
$protocol = 'http://';
|
||||||
|
|
|
@ -104,14 +104,10 @@ class ProviderFactory implements IProviderFactory {
|
||||||
$l,
|
$l,
|
||||||
$this->serverContainer->getCloudIdManager()
|
$this->serverContainer->getCloudIdManager()
|
||||||
);
|
);
|
||||||
$discoveryManager = new DiscoveryManager(
|
|
||||||
$this->serverContainer->getMemCacheFactory(),
|
|
||||||
$this->serverContainer->getHTTPClientService()
|
|
||||||
);
|
|
||||||
$notifications = new Notifications(
|
$notifications = new Notifications(
|
||||||
$addressHandler,
|
$addressHandler,
|
||||||
$this->serverContainer->getHTTPClientService(),
|
$this->serverContainer->getHTTPClientService(),
|
||||||
$discoveryManager,
|
$this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
|
||||||
$this->serverContainer->getJobList()
|
$this->serverContainer->getJobList()
|
||||||
);
|
);
|
||||||
$tokenHandler = new TokenHandler(
|
$tokenHandler = new TokenHandler(
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace OCP\OCS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface IDiscoveryService
|
||||||
|
*
|
||||||
|
* Allows you to discover OCS end-points on a remote server
|
||||||
|
*
|
||||||
|
* @package OCP\OCS
|
||||||
|
* @since 12.0.0
|
||||||
|
*/
|
||||||
|
interface IDiscoveryService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover OCS end-points
|
||||||
|
*
|
||||||
|
* If no valid discovery data is found the defaults are returned
|
||||||
|
*
|
||||||
|
* @since 12.0.0
|
||||||
|
*
|
||||||
|
* @param string $remote
|
||||||
|
* @param string $service the service you want to discover
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function discover($remote, $service);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace Test\OCS;
|
||||||
|
|
||||||
|
|
||||||
|
use OC\OCS\DiscoveryService;
|
||||||
|
use OCP\Http\Client\IClientService;
|
||||||
|
use OCP\ICacheFactory;
|
||||||
|
use OCP\OCS\IDiscoveryService;
|
||||||
|
use Test\TestCase;
|
||||||
|
|
||||||
|
class DiscoveryServiceTest extends TestCase {
|
||||||
|
|
||||||
|
/** @var \PHPUnit_Framework_MockObject_MockObject | ICacheFactory */
|
||||||
|
private $cacheFactory;
|
||||||
|
|
||||||
|
/** @var \PHPUnit_Framework_MockObject_MockObject | IClientService */
|
||||||
|
private $clientService;
|
||||||
|
|
||||||
|
/** @var IDiscoveryService */
|
||||||
|
private $discoveryService;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->cacheFactory = $this->getMockBuilder(ICacheFactory::class)->getMock();
|
||||||
|
$this->clientService = $this->getMockBuilder(IClientService::class)->getMock();
|
||||||
|
|
||||||
|
$this->discoveryService = new DiscoveryService(
|
||||||
|
$this->cacheFactory,
|
||||||
|
$this->clientService
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataTestIsSafeUrl
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param bool $expected
|
||||||
|
*/
|
||||||
|
public function testIsSafeUrl($url, $expected) {
|
||||||
|
$result = $this->invokePrivate($this->discoveryService, 'isSafeUrl', [$url]);
|
||||||
|
$this->assertSame($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataTestIsSafeUrl() {
|
||||||
|
return [
|
||||||
|
['api/ocs/v1.php/foo', true],
|
||||||
|
['/api/ocs/v1.php/foo', true],
|
||||||
|
['api/ocs/v1.php/foo/', true],
|
||||||
|
['api/ocs/v1.php/foo-bar/', true],
|
||||||
|
['api/ocs/v1:php/foo', false],
|
||||||
|
['api/ocs/<v1.php/foo', false],
|
||||||
|
['api/ocs/v1.php>/foo', false],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataTestGetEndpoints
|
||||||
|
*
|
||||||
|
* @param array $decodedServices
|
||||||
|
* @param string $service
|
||||||
|
* @param array $expected
|
||||||
|
*/
|
||||||
|
public function testGetEndpoints($decodedServices, $service, $expected) {
|
||||||
|
$result = $this->invokePrivate($this->discoveryService, 'getEndpoints', [$decodedServices, $service]);
|
||||||
|
$this->assertSame($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataTestGetEndpoints() {
|
||||||
|
return [
|
||||||
|
[['services' => ['myService' => ['endpoints' => []]]], 'myService', []],
|
||||||
|
[['services' => ['myService' => ['endpoints' => ['foo' => '/bar']]]], 'myService', ['foo' => '/bar']],
|
||||||
|
[['services' => ['myService' => ['endpoints' => ['foo' => '/bar']]]], 'anotherService', []],
|
||||||
|
[['services' => ['myService' => ['endpoints' => ['foo' => '/bar</foo']]]], 'myService', []],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1064,11 +1064,11 @@ class ShareTest extends \Test\TestCase {
|
||||||
|
|
||||||
$httpHelperMock->expects($this->at(0))
|
$httpHelperMock->expects($this->at(0))
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v1.php/cloud/shares'), $this->anything())
|
->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v2.php/cloud/shares'), $this->anything())
|
||||||
->willReturn(['success' => false, 'result' => 'Exception']);
|
->willReturn(['success' => false, 'result' => 'Exception']);
|
||||||
$httpHelperMock->expects($this->at(1))
|
$httpHelperMock->expects($this->at(1))
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v1.php/cloud/shares'), $this->anything())
|
->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v2.php/cloud/shares'), $this->anything())
|
||||||
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
||||||
|
|
||||||
\OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, $shareWith, \OCP\Constants::PERMISSION_READ);
|
\OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, $shareWith, \OCP\Constants::PERMISSION_READ);
|
||||||
|
@ -1077,11 +1077,11 @@ class ShareTest extends \Test\TestCase {
|
||||||
|
|
||||||
$httpHelperMock->expects($this->at(0))
|
$httpHelperMock->expects($this->at(0))
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v1.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
|
->with($this->stringStartsWith('https://' . $urlHost . '/ocs/v2.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
|
||||||
->willReturn(['success' => false, 'result' => 'Exception']);
|
->willReturn(['success' => false, 'result' => 'Exception']);
|
||||||
$httpHelperMock->expects($this->at(1))
|
$httpHelperMock->expects($this->at(1))
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v1.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
|
->with($this->stringStartsWith('http://' . $urlHost . '/ocs/v2.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
|
||||||
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
||||||
|
|
||||||
\OCP\Share::unshare('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, $shareWith);
|
\OCP\Share::unshare('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, $shareWith);
|
||||||
|
@ -1490,7 +1490,7 @@ class ShareTest extends \Test\TestCase {
|
||||||
|
|
||||||
$httpHelperMock->expects($this->at(0))
|
$httpHelperMock->expects($this->at(0))
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('https://localhost/ocs/v1.php/cloud/shares'), $this->anything())
|
->with($this->stringStartsWith('https://localhost/ocs/v2.php/cloud/shares'), $this->anything())
|
||||||
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
||||||
|
|
||||||
\OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, 'foo@localhost', \OCP\Constants::PERMISSION_READ);
|
\OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, 'foo@localhost', \OCP\Constants::PERMISSION_READ);
|
||||||
|
@ -1507,7 +1507,7 @@ class ShareTest extends \Test\TestCase {
|
||||||
|
|
||||||
$httpHelperMock->expects($this->at(0))
|
$httpHelperMock->expects($this->at(0))
|
||||||
->method('post')
|
->method('post')
|
||||||
->with($this->stringStartsWith('https://localhost/ocs/v1.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
|
->with($this->stringStartsWith('https://localhost/ocs/v2.php/cloud/shares/' . $share['id'] . '/unshare'), $this->anything())
|
||||||
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
->willReturn(['success' => true, 'result' => json_encode(['ocs' => ['meta' => ['statuscode' => 100]]])]);
|
||||||
|
|
||||||
\OCP\Share::unshare('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, 'foo@localhost');
|
\OCP\Share::unshare('test', 'test.txt', \OCP\Share::SHARE_TYPE_REMOTE, 'foo@localhost');
|
||||||
|
|
Loading…
Reference in New Issue