diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2023-09-22 17:25:33 -0100 |
---|---|---|
committer | Maxence Lange <maxence@artificial-owl.com> | 2023-09-22 17:26:02 -0100 |
commit | 0fac750bcd5eccc65f2861a3bb7633912fb30039 (patch) | |
tree | ab6497eca13125d5e579bc77b2315bf727506589 /apps | |
parent | 0acad69840ff21a103f532548907e480fc5a982a (diff) | |
download | nextcloud-server-0fac750bcd5eccc65f2861a3bb7633912fb30039.tar.gz nextcloud-server-0fac750bcd5eccc65f2861a3bb7633912fb30039.zip |
ocm services
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
Diffstat (limited to 'apps')
8 files changed, 146 insertions, 135 deletions
diff --git a/apps/cloud_federation_api/appinfo/routes.php b/apps/cloud_federation_api/appinfo/routes.php index d70b06f821c..966ff2ce3a1 100644 --- a/apps/cloud_federation_api/appinfo/routes.php +++ b/apps/cloud_federation_api/appinfo/routes.php @@ -6,6 +6,7 @@ declare(strict_types=1); * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> + * @author Maxence Lange <maxence@artificial-owl.com> * * @license GNU AGPL version 3 or any later version * @@ -27,15 +28,21 @@ return [ 'routes' => [ [ 'name' => 'RequestHandler#addShare', - 'url' => '/ocm/shares', + 'url' => '/shares', 'verb' => 'POST', - 'root' => '', + 'root' => '/ocm', ], [ 'name' => 'RequestHandler#receiveNotification', - 'url' => '/ocm/notifications', + 'url' => '/notifications', 'verb' => 'POST', - 'root' => '', + 'root' => '/ocm', ], +// [ +// 'name' => 'RequestHandler#inviteAccepted', +// 'url' => '/invite-accepted', +// 'verb' => 'POST', +// 'root' => '/ocm', +// ] ], ]; diff --git a/apps/cloud_federation_api/lib/Capabilities.php b/apps/cloud_federation_api/lib/Capabilities.php index 6164c0e0dba..60d6186b840 100644 --- a/apps/cloud_federation_api/lib/Capabilities.php +++ b/apps/cloud_federation_api/lib/Capabilities.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org> * @@ -20,45 +23,61 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + namespace OCA\CloudFederationAPI; +use OC\OCM\Model\OCMProvider; +use OC\OCM\Model\OCMResource; use OCP\Capabilities\ICapability; use OCP\IURLGenerator; +use OCP\OCM\Exceptions\OCMArgumentException; class Capabilities implements ICapability { - /** @var IURLGenerator */ - private $urlGenerator; + public const API_VERSION = '1.0-proposal1'; - public function __construct(IURLGenerator $urlGenerator) { - $this->urlGenerator = $urlGenerator; + public function __construct( + private IURLGenerator $urlGenerator, + ) { } /** * Function an app uses to return the capabilities * - * @return array Array containing the apps capabilities - * @since 8.2.0 + * @return array{ + * ocm: array{ + * enabled: bool, + * apiVersion: string, + * endPoint: string, + * resourceTypes: array{ + * name: string, + * shareTypes: string[], + * protocols: array<string, string> + * }[], + * }, + * } + * @throws OCMArgumentException */ public function getCapabilities() { $url = $this->urlGenerator->linkToRouteAbsolute('cloud_federation_api.requesthandlercontroller.addShare'); - $capabilities = ['ocm' => - [ - 'enabled' => true, - 'apiVersion' => '1.0-proposal1', - 'endPoint' => substr($url, 0, strrpos($url, '/')), - 'resourceTypes' => [ - [ - 'name' => 'file', - 'shareTypes' => ['user', 'group'], - 'protocols' => [ - 'webdav' => '/public.php/webdav/', - ] - ], - ] - ] - ]; + $provider = new OCMProvider(); + $provider->setEnabled(true); + $provider->setApiVersion(self::API_VERSION); + + $pos = strrpos($url, '/'); + if (false === $pos) { + throw new OCMArgumentException('generated route should contains a slash character'); + } + + $provider->setEndPoint(substr($url, 0, $pos)); + + $resource = new OCMResource(); + $resource->setName('file') + ->setShareTypes(['user', 'group']) + ->setProtocols(['webdav' => '/public.php/webdav/']); + + $provider->setResourceTypes([$resource]); - return $capabilities; + return ['ocm' => $provider->jsonSerialize()]; } } diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php index ef77f2fa317..fd55746a83c 100644 --- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php +++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php @@ -4,6 +4,7 @@ * * @author Bjoern Schiessle <bjoern@schiessle.org> * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @author Maxence Lange <maxence@artificial-owl.com> * @author Roeland Jago Douma <roeland@famdouma.nl> * * @license GNU AGPL version 3 or any later version @@ -51,52 +52,19 @@ use Psr\Log\LoggerInterface; * @package OCA\CloudFederationAPI\Controller */ class RequestHandlerController extends Controller { - - /** @var LoggerInterface */ - private $logger; - - /** @var IUserManager */ - private $userManager; - - /** @var IGroupManager */ - private $groupManager; - - /** @var IURLGenerator */ - private $urlGenerator; - - /** @var ICloudFederationProviderManager */ - private $cloudFederationProviderManager; - - /** @var Config */ - private $config; - - /** @var ICloudFederationFactory */ - private $factory; - - /** @var ICloudIdManager */ - private $cloudIdManager; - - public function __construct($appName, - IRequest $request, - LoggerInterface $logger, - IUserManager $userManager, - IGroupManager $groupManager, - IURLGenerator $urlGenerator, - ICloudFederationProviderManager $cloudFederationProviderManager, - Config $config, - ICloudFederationFactory $factory, - ICloudIdManager $cloudIdManager + public function __construct( + string $appName, + IRequest $request, + private LoggerInterface $logger, + private IUserManager $userManager, + private IGroupManager $groupManager, + private IURLGenerator $urlGenerator, + private ICloudFederationProviderManager $cloudFederationProviderManager, + private Config $config, + private ICloudFederationFactory $factory, + private ICloudIdManager $cloudIdManager ) { parent::__construct($appName, $request); - - $this->logger = $logger; - $this->userManager = $userManager; - $this->groupManager = $groupManager; - $this->urlGenerator = $urlGenerator; - $this->cloudFederationProviderManager = $cloudFederationProviderManager; - $this->config = $config; - $this->factory = $factory; - $this->cloudIdManager = $cloudIdManager; } /** @@ -122,7 +90,6 @@ class RequestHandlerController extends Controller { * Example: curl -H "Content-Type: application/json" -X POST -d '{"shareWith":"admin1@serve1","name":"welcome server2.txt","description":"desc","providerId":"2","owner":"admin2@http://localhost/server2","ownerDisplayName":"admin2 display","shareType":"user","resourceType":"file","protocol":{"name":"webdav","options":{"sharedSecret":"secret","permissions":"webdav-property"}}}' http://localhost/server/index.php/ocm/shares */ public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) { - // check if all required parameters are set if ($shareWith === null || $name === null || @@ -281,7 +248,7 @@ class RequestHandlerController extends Controller { ); } - return new JSONResponse($result,Http::STATUS_CREATED); + return new JSONResponse($result, Http::STATUS_CREATED); } /** diff --git a/apps/cloud_federation_api/openapi.json b/apps/cloud_federation_api/openapi.json index f017b864a27..e54324c9635 100644 --- a/apps/cloud_federation_api/openapi.json +++ b/apps/cloud_federation_api/openapi.json @@ -76,13 +76,8 @@ }, "protocols": { "type": "object", - "required": [ - "webdav" - ], - "properties": { - "webdav": { - "type": "string" - } + "additionalProperties": { + "type": "string" } } } diff --git a/apps/files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob.php b/apps/files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob.php index 687dcd25f8b..75606960e4b 100644 --- a/apps/files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob.php +++ b/apps/files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob.php @@ -6,6 +6,7 @@ declare(strict_types=1); * @copyright 2018, Roeland Jago Douma <roeland@famdouma.nl> * * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @author Maxence Lange <maxence@artificial-owl.com> * @author Roeland Jago Douma <roeland@famdouma.nl> * * @license GNU AGPL version 3 or any later version @@ -29,21 +30,21 @@ namespace OCA\Files_Sharing\BackgroundJob; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; use OCP\IDBConnection; +use OCP\OCM\Exceptions\OCMProviderException; +use OCP\OCM\IOCMDiscoveryService; use OCP\OCS\IDiscoveryService; +use Psr\Log\LoggerInterface; class FederatedSharesDiscoverJob extends TimedJob { - /** @var IDBConnection */ - private $connection; - /** @var IDiscoveryService */ - private $discoveryService; - - public function __construct(ITimeFactory $time, - IDBConnection $connection, - IDiscoveryService $discoveryService) { - parent::__construct($time); - $this->connection = $connection; - $this->discoveryService = $discoveryService; + public function __construct( + ITimeFactory $time, + private IDBConnection $connection, + private IDiscoveryService $discoveryService, + private IOCMDiscoveryService $ocmDiscoveryService, + private LoggerInterface $logger, + ) { + parent::__construct($time); $this->setInterval(86400); } @@ -56,6 +57,11 @@ class FederatedSharesDiscoverJob extends TimedJob { $result = $qb->execute(); while ($row = $result->fetch()) { $this->discoveryService->discover($row['remote'], 'FEDERATED_SHARING', true); + try { + $this->ocmDiscoveryService->discover($row['remote'], true); + } catch (OCMProviderException $e) { + $this->logger->info('exception while running files_sharing/lib/BackgroundJob/FederatedSharesDiscoverJob', ['exception' => $e]); + } } $result->closeCursor(); } diff --git a/apps/files_sharing/lib/Controller/ExternalSharesController.php b/apps/files_sharing/lib/Controller/ExternalSharesController.php index 9fab8d4e1a0..4ddfa7e2e63 100644 --- a/apps/files_sharing/lib/Controller/ExternalSharesController.php +++ b/apps/files_sharing/lib/Controller/ExternalSharesController.php @@ -134,14 +134,14 @@ class ExternalSharesController extends Controller { } if ( - $this->testUrl('https://' . $remote . '/ocs-provider/') || - $this->testUrl('https://' . $remote . '/ocs-provider/index.php') || + $this->testUrl('https://' . $remote . '/ocm-provider/') || + $this->testUrl('https://' . $remote . '/ocm-provider/index.php') || $this->testUrl('https://' . $remote . '/status.php', true) ) { return new DataResponse('https'); } elseif ( - $this->testUrl('http://' . $remote . '/ocs-provider/') || - $this->testUrl('http://' . $remote . '/ocs-provider/index.php') || + $this->testUrl('http://' . $remote . '/ocm-provider/') || + $this->testUrl('http://' . $remote . '/ocm-provider/index.php') || $this->testUrl('http://' . $remote . '/status.php', true) ) { return new DataResponse('http'); diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php index f33334ca346..24cfc07e6d1 100644 --- a/apps/files_sharing/lib/External/Storage.php +++ b/apps/files_sharing/lib/External/Storage.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -8,6 +11,7 @@ * @author Daniel Kesselberg <mail@danielkesselberg.de> * @author Joas Schilling <coding@schilljs.com> * @author Lukas Reschke <lukas@statuscode.ch> + * @author Maxence Lange <maxence@artificial-owl.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> * @author Roeland Jago Douma <roeland@famdouma.nl> @@ -36,8 +40,8 @@ use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\RequestException; use OC\Files\Storage\DAV; use OC\ForbiddenException; -use OCA\Files_Sharing\ISharedStorage; use OCA\Files_Sharing\External\Manager as ExternalShareManager; +use OCA\Files_Sharing\ISharedStorage; use OCP\AppFramework\Http; use OCP\Constants; use OCP\Federation\ICloudId; @@ -46,25 +50,23 @@ use OCP\Files\Storage\IDisableEncryptionStorage; use OCP\Files\Storage\IReliableEtagStorage; use OCP\Files\StorageInvalidException; use OCP\Files\StorageNotAvailableException; -use OCP\Http\Client\LocalServerException; use OCP\Http\Client\IClientService; +use OCP\Http\Client\LocalServerException; +use OCP\ICacheFactory; +use OCP\OCM\Exceptions\OCMArgumentException; +use OCP\OCM\Exceptions\OCMProviderException; +use OCP\OCM\IOCMDiscoveryService; +use OCP\Server; +use Psr\Log\LoggerInterface; class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage, IReliableEtagStorage { - /** @var ICloudId */ - private $cloudId; - /** @var string */ - private $mountPoint; - /** @var string */ - private $token; - /** @var \OCP\ICacheFactory */ - private $memcacheFactory; - /** @var \OCP\Http\Client\IClientService */ - private $httpClient; - /** @var bool */ - private $updateChecked = false; - - /** @var ExternalShareManager */ - private $manager; + private ICloudId $cloudId; + private string $mountPoint; + private string $token; + private ICacheFactory $memcacheFactory; + private IClientService $httpClient; + private bool $updateChecked = false; + private ExternalShareManager $manager; /** * @param array{HttpClientService: IClientService, manager: ExternalShareManager, cloudId: ICloudId, mountpoint: string, token: string, password: ?string}|array $options @@ -72,32 +74,45 @@ class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage, public function __construct($options) { $this->memcacheFactory = \OC::$server->getMemCacheFactory(); $this->httpClient = $options['HttpClientService']; - $this->manager = $options['manager']; $this->cloudId = $options['cloudId']; - $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class); + $this->logger = Server::get(LoggerInterface::class); + $discoveryService = Server::get(IOCMDiscoveryService::class); - [$protocol, $remote] = explode('://', $this->cloudId->getRemote()); - if (strpos($remote, '/')) { - [$host, $root] = explode('/', $remote, 2); - } else { - $host = $remote; - $root = ''; + // use default path to webdav if not found on discovery + try { + $ocmProvider = $discoveryService->discover($this->cloudId->getRemote()); + $webDavEndpoint = $ocmProvider->extractProtocolEntry('file', 'webdav'); + $remote = $ocmProvider->getEndPoint(); + } catch (OCMProviderException|OCMArgumentException $e) { + $this->logger->notice('exception while retrieving webdav endpoint', ['exception' => $e]); + $webDavEndpoint = '/public.php/webdav'; + $remote = $this->cloudId->getRemote(); + } + + $host = parse_url($remote, PHP_URL_HOST); + $port = parse_url($remote, PHP_URL_PORT); + $host .= (null === $port) ? '' : ':' . $port; // we add port if available + + // in case remote NC is on a sub folder and using deprecated ocm provider + $tmpPath = rtrim(parse_url($this->cloudId->getRemote(), PHP_URL_PATH) ?? '', '/'); + if (!str_starts_with($webDavEndpoint, $tmpPath)) { + $webDavEndpoint = $tmpPath . $webDavEndpoint; } - $secure = $protocol === 'https'; - $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->token = $options['token']; - parent::__construct([ - 'secure' => $secure, - 'host' => $host, - 'root' => $root, - 'user' => $options['token'], - 'password' => (string)$options['password'] - ]); + parent::__construct( + [ + 'secure' => ((parse_url($remote, PHP_URL_SCHEME) ?? 'https') === 'https'), + 'host' => $host, + 'root' => $webDavEndpoint, + 'user' => $options['token'], + 'authType' => \Sabre\DAV\Client::AUTH_BASIC, + 'password' => (string)$options['password'] + ] + ); } public function getWatcher($path = '', $storage = null) { @@ -255,9 +270,9 @@ class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage, */ protected function testRemote(): bool { try { - return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php') - || $this->testRemoteUrl($this->getRemote() . '/ocs-provider/') - || $this->testRemoteUrl($this->getRemote() . '/status.php'); + return $this->testRemoteUrl($this->getRemote() . '/ocm-provider/index.php') + || $this->testRemoteUrl($this->getRemote() . '/ocm-provider/') + || $this->testRemoteUrl($this->getRemote() . '/status.php'); } catch (\Exception $e) { return false; } diff --git a/apps/files_sharing/tests/ExternalStorageTest.php b/apps/files_sharing/tests/ExternalStorageTest.php index 7709abbf6eb..d180b06d641 100644 --- a/apps/files_sharing/tests/ExternalStorageTest.php +++ b/apps/files_sharing/tests/ExternalStorageTest.php @@ -28,6 +28,7 @@ namespace OCA\Files_Sharing\Tests; use OC\Federation\CloudId; +use OCA\Files_Sharing\External\Manager as ExternalShareManager; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; use OCP\Http\Client\IResponse; @@ -75,6 +76,7 @@ class ExternalStorageTest extends \Test\TestCase { private function getTestStorage($uri) { $certificateManager = \OC::$server->getCertificateManager(); $httpClientService = $this->createMock(IClientService::class); + $manager = $this->createMock(ExternalShareManager::class); $client = $this->createMock(IClient::class); $response = $this->createMock(IResponse::class); $client @@ -98,7 +100,7 @@ class ExternalStorageTest extends \Test\TestCase { 'mountpoint' => 'remoteshare', 'token' => 'abcdef', 'password' => '', - 'manager' => null, + 'manager' => $manager, 'certificateManager' => $certificateManager, 'HttpClientService' => $httpClientService, ] |