Skip to content

Commit

Permalink
Merge pull request #40885 from nextcloud/bugfix/noid/fix-OCM-provider
Browse files Browse the repository at this point in the history
Fix OCM provider public API and handling to allow apps to register
  • Loading branch information
nickvergessen committed Oct 13, 2023
2 parents 925df86 + 21e7a82 commit 160a2b7
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 73 deletions.
4 changes: 2 additions & 2 deletions apps/cloud_federation_api/appinfo/info.xml
Expand Up @@ -12,8 +12,8 @@
<types>
<filesystem/>
</types>
<category>files</category>
<bugs>https://github.com/nextcloud/cloud_federation/issues</bugs>
<category>integration</category>
<bugs>https://github.com/nextcloud/server/issues</bugs>
<dependencies>
<nextcloud min-version="28" max-version="28"/>
</dependencies>
Expand Down
18 changes: 8 additions & 10 deletions apps/cloud_federation_api/lib/Capabilities.php
Expand Up @@ -28,18 +28,17 @@

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;
use OCP\OCM\IOCMProvider;

class Capabilities implements ICapability {

public const API_VERSION = '1.0-proposal1';

public function __construct(
private IURLGenerator $urlGenerator,
private IOCMProvider $provider,
) {
}

Expand All @@ -63,24 +62,23 @@ public function __construct(
public function getCapabilities() {
$url = $this->urlGenerator->linkToRouteAbsolute('cloud_federation_api.requesthandlercontroller.addShare');

$provider = new OCMProvider();
$provider->setEnabled(true);
$provider->setApiVersion(self::API_VERSION);
$this->provider->setEnabled(true);
$this->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));
$this->provider->setEndPoint(substr($url, 0, $pos));

$resource = new OCMResource();
$resource = $this->provider->createNewResourceType();
$resource->setName('file')
->setShareTypes(['user', 'group'])
->setProtocols(['webdav' => '/public.php/webdav/']);

$provider->setResourceTypes([$resource]);
$this->provider->addResourceType($resource);

return ['ocm' => $provider->jsonSerialize()];
return ['ocm' => $this->provider->jsonSerialize()];
}
}
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Expand Up @@ -537,6 +537,7 @@
'OCP\\Notification\\IManager' => $baseDir . '/lib/public/Notification/IManager.php',
'OCP\\Notification\\INotification' => $baseDir . '/lib/public/Notification/INotification.php',
'OCP\\Notification\\INotifier' => $baseDir . '/lib/public/Notification/INotifier.php',
'OCP\\OCM\\Events\\ResourceTypeRegisterEvent' => $baseDir . '/lib/public/OCM/Events/ResourceTypeRegisterEvent.php',
'OCP\\OCM\\Exceptions\\OCMArgumentException' => $baseDir . '/lib/public/OCM/Exceptions/OCMArgumentException.php',
'OCP\\OCM\\Exceptions\\OCMProviderException' => $baseDir . '/lib/public/OCM/Exceptions/OCMProviderException.php',
'OCP\\OCM\\IOCMDiscoveryService' => $baseDir . '/lib/public/OCM/IOCMDiscoveryService.php',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Expand Up @@ -570,6 +570,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Notification\\IManager' => __DIR__ . '/../../..' . '/lib/public/Notification/IManager.php',
'OCP\\Notification\\INotification' => __DIR__ . '/../../..' . '/lib/public/Notification/INotification.php',
'OCP\\Notification\\INotifier' => __DIR__ . '/../../..' . '/lib/public/Notification/INotifier.php',
'OCP\\OCM\\Events\\ResourceTypeRegisterEvent' => __DIR__ . '/../../..' . '/lib/public/OCM/Events/ResourceTypeRegisterEvent.php',
'OCP\\OCM\\Exceptions\\OCMArgumentException' => __DIR__ . '/../../..' . '/lib/public/OCM/Exceptions/OCMArgumentException.php',
'OCP\\OCM\\Exceptions\\OCMProviderException' => __DIR__ . '/../../..' . '/lib/public/OCM/Exceptions/OCMProviderException.php',
'OCP\\OCM\\IOCMDiscoveryService' => __DIR__ . '/../../..' . '/lib/public/OCM/IOCMDiscoveryService.php',
Expand Down
57 changes: 40 additions & 17 deletions lib/private/OCM/Model/OCMProvider.php
Expand Up @@ -26,27 +26,36 @@

namespace OC\OCM\Model;

use JsonSerializable;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\OCM\Events\ResourceTypeRegisterEvent;
use OCP\OCM\Exceptions\OCMArgumentException;
use OCP\OCM\Exceptions\OCMProviderException;
use OCP\OCM\IOCMProvider;
use OCP\OCM\IOCMResource;

/**
* @since 28.0.0
*/
class OCMProvider implements IOCMProvider, JsonSerializable {
class OCMProvider implements IOCMProvider {
private bool $enabled = false;
private string $apiVersion = '';
private string $endPoint = '';
/** @var OCMResource[] */
/** @var IOCMResource[] */
private array $resourceTypes = [];

private bool $emittedEvent = false;

public function __construct(
protected IEventDispatcher $dispatcher,
) {
}

/**
* @param bool $enabled
*
* @return OCMProvider
* @return $this
*/
public function setEnabled(bool $enabled): self {
public function setEnabled(bool $enabled): static {
$this->enabled = $enabled;

return $this;
Expand All @@ -62,9 +71,9 @@ public function isEnabled(): bool {
/**
* @param string $apiVersion
*
* @return OCMProvider
* @return $this
*/
public function setApiVersion(string $apiVersion): self {
public function setApiVersion(string $apiVersion): static {
$this->apiVersion = $apiVersion;

return $this;
Expand All @@ -80,9 +89,9 @@ public function getApiVersion(): string {
/**
* @param string $endPoint
*
* @return OCMProvider
* @return $this
*/
public function setEndPoint(string $endPoint): self {
public function setEndPoint(string $endPoint): static {
$this->endPoint = $endPoint;

return $this;
Expand All @@ -96,31 +105,45 @@ public function getEndPoint(): string {
}

/**
* @param OCMResource $resource
* create a new resource to later add it with {@see IOCMProvider::addResourceType()}
* @return IOCMResource
*/
public function createNewResourceType(): IOCMResource {
return new OCMResource();
}

/**
* @param IOCMResource $resource
*
* @return $this
*/
public function addResourceType(OCMResource $resource): self {
public function addResourceType(IOCMResource $resource): static {
$this->resourceTypes[] = $resource;

return $this;
}

/**
* @param OCMResource[] $resourceTypes
* @param IOCMResource[] $resourceTypes
*
* @return OCMProvider
* @return $this
*/
public function setResourceTypes(array $resourceTypes): self {
public function setResourceTypes(array $resourceTypes): static {
$this->resourceTypes = $resourceTypes;

return $this;
}

/**
* @return OCMResource[]
* @return IOCMResource[]
*/
public function getResourceTypes(): array {
if (!$this->emittedEvent) {
$this->emittedEvent = true;
$event = new ResourceTypeRegisterEvent($this);
$this->dispatcher->dispatchTyped($event);
}

return $this->resourceTypes;
}

Expand Down Expand Up @@ -151,11 +174,11 @@ public function extractProtocolEntry(string $resourceName, string $protocol): st
*
* @param array $data
*
* @return self
* @return $this
* @throws OCMProviderException in case a descent provider cannot be generated from data
* @see self::jsonSerialize()
*/
public function import(array $data): self {
public function import(array $data): static {
$this->setEnabled(is_bool($data['enabled'] ?? '') ? $data['enabled'] : false)
->setApiVersion((string)($data['apiVersion'] ?? ''))
->setEndPoint($data['endPoint'] ?? '');
Expand Down
18 changes: 8 additions & 10 deletions lib/private/OCM/Model/OCMResource.php
Expand Up @@ -26,13 +26,12 @@

namespace OC\OCM\Model;

use JsonSerializable;
use OCP\OCM\IOCMResource;

/**
* @since 28.0.0
*/
class OCMResource implements IOCMResource, JsonSerializable {
class OCMResource implements IOCMResource {
private string $name = '';
/** @var string[] */
private array $shareTypes = [];
Expand All @@ -42,9 +41,9 @@ class OCMResource implements IOCMResource, JsonSerializable {
/**
* @param string $name
*
* @return OCMResource
* @return $this
*/
public function setName(string $name): self {
public function setName(string $name): static {
$this->name = $name;

return $this;
Expand All @@ -60,9 +59,9 @@ public function getName(): string {
/**
* @param string[] $shareTypes
*
* @return OCMResource
* @return $this
*/
public function setShareTypes(array $shareTypes): self {
public function setShareTypes(array $shareTypes): static {
$this->shareTypes = $shareTypes;

return $this;
Expand All @@ -80,7 +79,7 @@ public function getShareTypes(): array {
*
* @return $this
*/
public function setProtocols(array $protocols): self {
public function setProtocols(array $protocols): static {
$this->protocols = $protocols;

return $this;
Expand All @@ -98,17 +97,16 @@ public function getProtocols(): array {
*
* @param array $data
*
* @return self
* @return $this
* @see self::jsonSerialize()
*/
public function import(array $data): self {
public function import(array $data): static {
return $this->setName((string)($data['name'] ?? ''))
->setShareTypes($data['shareTypes'] ?? [])
->setProtocols($data['protocols'] ?? []);
}

/**
*
* @return array{
* name: string,
* shareTypes: string[],
Expand Down
17 changes: 8 additions & 9 deletions lib/private/OCM/OCMDiscoveryService.php
Expand Up @@ -27,7 +27,6 @@
namespace OC\OCM;

use JsonException;
use OC\OCM\Model\OCMProvider;
use OCP\AppFramework\Http;
use OCP\Http\Client\IClientService;
use OCP\ICache;
Expand All @@ -54,7 +53,8 @@ public function __construct(
ICacheFactory $cacheFactory,
private IClientService $clientService,
private IConfig $config,
private LoggerInterface $logger
private IOCMProvider $provider,
private LoggerInterface $logger,
) {
$this->cache = $cacheFactory->createDistributed('ocm-discovery');
}
Expand All @@ -69,13 +69,12 @@ public function __construct(
*/
public function discover(string $remote, bool $skipCache = false): IOCMProvider {
$remote = rtrim($remote, '/');
$provider = new OCMProvider();

if (!$skipCache) {
try {
$provider->import(json_decode($this->cache->get($remote) ?? '', true, 8, JSON_THROW_ON_ERROR) ?? []);
if ($this->supportedAPIVersion($provider->getApiVersion())) {
return $provider; // if cache looks valid, we use it
$this->provider->import(json_decode($this->cache->get($remote) ?? '', true, 8, JSON_THROW_ON_ERROR) ?? []);
if ($this->supportedAPIVersion($this->provider->getApiVersion())) {
return $this->provider; // if cache looks valid, we use it
}
} catch (JsonException|OCMProviderException $e) {
// we ignore cache on issues
Expand All @@ -96,7 +95,7 @@ public function discover(string $remote, bool $skipCache = false): IOCMProvider
if ($response->getStatusCode() === Http::STATUS_OK) {
$body = $response->getBody();
// update provider with data returned by the request
$provider->import(json_decode($body, true, 8, JSON_THROW_ON_ERROR) ?? []);
$this->provider->import(json_decode($body, true, 8, JSON_THROW_ON_ERROR) ?? []);
$this->cache->set($remote, $body, 60 * 60 * 24);
}
} catch (JsonException|OCMProviderException $e) {
Expand All @@ -109,11 +108,11 @@ public function discover(string $remote, bool $skipCache = false): IOCMProvider
throw new OCMProviderException('error while requesting remote ocm provider');
}

if (!$this->supportedAPIVersion($provider->getApiVersion())) {
if (!$this->supportedAPIVersion($this->provider->getApiVersion())) {
throw new OCMProviderException('API version not supported');
}

return $provider;
return $this->provider;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions lib/private/Server.php
Expand Up @@ -124,6 +124,7 @@
use OC\Metadata\IMetadataManager;
use OC\Metadata\MetadataManager;
use OC\Notification\Manager;
use OC\OCM\Model\OCMProvider;
use OC\OCM\OCMDiscoveryService;
use OC\OCS\DiscoveryService;
use OC\Preview\GeneratorHelper;
Expand Down Expand Up @@ -232,6 +233,7 @@
use OCP\Log\ILogFactory;
use OCP\Mail\IMailer;
use OCP\OCM\IOCMDiscoveryService;
use OCP\OCM\IOCMProvider;
use OCP\Remote\Api\IApiFactory;
use OCP\Remote\IInstanceFactory;
use OCP\RichObjectStrings\IValidator;
Expand Down Expand Up @@ -1426,6 +1428,8 @@ public function __construct($webRoot, \OC\Config $config) {

$this->registerAlias(IPhoneNumberUtil::class, PhoneNumberUtil::class);

$this->registerAlias(IOCMProvider::class, OCMProvider::class);

$this->connectDispatcher();
}

Expand Down

0 comments on commit 160a2b7

Please sign in to comment.