diff options
author | Kate <26026535+provokateurin@users.noreply.github.com> | 2023-07-13 08:17:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-13 08:17:59 +0200 |
commit | b6e73c82ba364b57ced3a974a54dda07de050d33 (patch) | |
tree | a751185e8d5a3595755ca0940a191e616f04b832 /apps | |
parent | 41540ad4c3b154a523dbcc62512956caa53a5edd (diff) | |
parent | 6843bcd029ce2d7bb10807dc5cd901600f2d7e12 (diff) | |
download | nextcloud-server-b6e73c82ba364b57ced3a974a54dda07de050d33.tar.gz nextcloud-server-b6e73c82ba364b57ced3a974a54dda07de050d33.zip |
Merge pull request #39318 from nextcloud/feature/openapi/cloud_federation_api
cloud_federation_api: Add OpenAPI spec
Diffstat (limited to 'apps')
6 files changed, 134 insertions, 41 deletions
diff --git a/apps/cloud_federation_api/composer/composer/autoload_classmap.php b/apps/cloud_federation_api/composer/composer/autoload_classmap.php index 94d538619a3..dd096ebf563 100644 --- a/apps/cloud_federation_api/composer/composer/autoload_classmap.php +++ b/apps/cloud_federation_api/composer/composer/autoload_classmap.php @@ -11,4 +11,5 @@ return array( 'OCA\\CloudFederationAPI\\Capabilities' => $baseDir . '/../lib/Capabilities.php', 'OCA\\CloudFederationAPI\\Config' => $baseDir . '/../lib/Config.php', 'OCA\\CloudFederationAPI\\Controller\\RequestHandlerController' => $baseDir . '/../lib/Controller/RequestHandlerController.php', + 'OCA\\CloudFederationAPI\\ResponseDefinitions' => $baseDir . '/../lib/ResponseDefinitions.php', ); diff --git a/apps/cloud_federation_api/composer/composer/autoload_static.php b/apps/cloud_federation_api/composer/composer/autoload_static.php index a1dfe33706c..75557a20126 100644 --- a/apps/cloud_federation_api/composer/composer/autoload_static.php +++ b/apps/cloud_federation_api/composer/composer/autoload_static.php @@ -26,6 +26,7 @@ class ComposerStaticInitCloudFederationAPI 'OCA\\CloudFederationAPI\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php', 'OCA\\CloudFederationAPI\\Config' => __DIR__ . '/..' . '/../lib/Config.php', 'OCA\\CloudFederationAPI\\Controller\\RequestHandlerController' => __DIR__ . '/..' . '/../lib/Controller/RequestHandlerController.php', + 'OCA\\CloudFederationAPI\\ResponseDefinitions' => __DIR__ . '/..' . '/../lib/ResponseDefinitions.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/apps/cloud_federation_api/lib/Capabilities.php b/apps/cloud_federation_api/lib/Capabilities.php index 91fd5219215..f1398661ebe 100644 --- a/apps/cloud_federation_api/lib/Capabilities.php +++ b/apps/cloud_federation_api/lib/Capabilities.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org> * * @author Bjoern Schiessle <bjoern@schiessle.org> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license GNU AGPL version 3 or any later version * @@ -36,6 +37,21 @@ class Capabilities implements ICapability { /** * Function an app uses to return the capabilities + * + * @return array{ + * ocm: array{ + * enabled: bool, + * apiVersion: string, + * endPoint: string, + * resourceTypes: array{ + * name: string, + * shareTypes: string[], + * protocols: array{ + * webdav: string, + * }, + * }[], + * }, + * } */ public function getCapabilities() { $url = $this->urlGenerator->linkToRouteAbsolute('cloud_federation_api.requesthandlercontroller.addShare'); diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php index ef77f2fa317..416dca67160 100644 --- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php +++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php @@ -5,6 +5,7 @@ * @author Bjoern Schiessle <bjoern@schiessle.org> * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Kate Döen <kate.doeen@nextcloud.com> * * @license GNU AGPL version 3 or any later version * @@ -25,6 +26,7 @@ namespace OCA\CloudFederationAPI\Controller; use OCA\CloudFederationAPI\Config; +use OCA\CloudFederationAPI\ResponseDefinitions; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; @@ -44,11 +46,13 @@ use OCP\Share\Exceptions\ShareNotFound; use Psr\Log\LoggerInterface; /** - * Class RequestHandlerController - * - * handle API between different Cloud instances + * Open-Cloud-Mesh-API * * @package OCA\CloudFederationAPI\Controller + * + * @psalm-import-type CloudFederationApiAddShare from ResponseDefinitions + * @psalm-import-type CloudFederationApiValidationError from ResponseDefinitions + * @psalm-import-type CloudFederationApiError from ResponseDefinitions */ class RequestHandlerController extends Controller { @@ -100,26 +104,28 @@ class RequestHandlerController extends Controller { } /** - * add share + * Add share * * @NoCSRFRequired * @PublicPage * @BruteForceProtection(action=receiveFederatedShare) * - * @param string $shareWith - * @param string $name resource name (e.g. document.odt) - * @param string $description share description (optional) - * @param string $providerId resource UID on the provider side - * @param string $owner provider specific UID of the user who owns the resource - * @param string $ownerDisplayName display name of the user who shared the item - * @param string $sharedBy provider specific UID of the user who shared the resource - * @param string $sharedByDisplayName display name of the user who shared the resource - * @param array $protocol (e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]]) - * @param string $shareType ('group' or 'user' share) - * @param $resourceType ('file', 'calendar',...) - * @return Http\DataResponse|JSONResponse + * @param string $shareWith The user who the share will be shared with + * @param string $name The resource name (e.g. document.odt) + * @param string|null $description Share description + * @param string $providerId Resource UID on the provider side + * @param string $owner Provider specific UID of the user who owns the resource + * @param string|null $ownerDisplayName Display name of the user who shared the item + * @param string|null $sharedBy Provider specific UID of the user who shared the resource + * @param string|null $sharedByDisplayName Display name of the user who shared the resource + * @param array{name: string[], options: array<string, mixed>} $protocol e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]] + * @param string $shareType 'group' or 'user' share + * @param string $resourceType 'file', 'calendar',... * - * 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 + * @return JSONResponse<Http::STATUS_CREATED, CloudFederationApiAddShare, array{}>|JSONResponse<Http::STATUS_BAD_REQUEST, CloudFederationApiValidationError, array{}>|JSONResponse<Http::STATUS_NOT_IMPLEMENTED, CloudFederationApiError, array{}> + * 201: The notification was successfully received. The display name of the recipient might be returned in the body + * 400: Bad request due to invalid parameters, e.g. when `shareWith` is not found or required properties are missing + * 501: Share type or the resource type is not supported */ public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) { @@ -137,7 +143,10 @@ class RequestHandlerController extends Controller { !isset($protocol['options']['sharedSecret']) ) { return new JSONResponse( - ['message' => 'Missing arguments'], + [ + 'message' => 'Missing arguments', + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); } @@ -158,7 +167,10 @@ class RequestHandlerController extends Controller { if (!$this->userManager->userExists($shareWith)) { $response = new JSONResponse( - ['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()], + [ + 'message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl(), + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); $response->throttle(); @@ -169,7 +181,10 @@ class RequestHandlerController extends Controller { if ($shareType === 'group') { if (!$this->groupManager->groupExists($shareWith)) { $response = new JSONResponse( - ['message' => 'Group "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()], + [ + 'message' => 'Group "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl(), + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); $response->throttle(); @@ -192,20 +207,18 @@ class RequestHandlerController extends Controller { $share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType); $share->setProtocol($protocol); $provider->shareReceived($share); - } catch (ProviderDoesNotExistsException $e) { + } catch (ProviderDoesNotExistsException|ProviderCouldNotAddShareException $e) { return new JSONResponse( ['message' => $e->getMessage()], Http::STATUS_NOT_IMPLEMENTED ); - } catch (ProviderCouldNotAddShareException $e) { - return new JSONResponse( - ['message' => $e->getMessage()], - $e->getCode() - ); } catch (\Exception $e) { $this->logger->error($e->getMessage(), ['exception' => $e]); return new JSONResponse( - ['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()], + [ + 'message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl(), + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); } @@ -222,19 +235,24 @@ class RequestHandlerController extends Controller { } /** - * receive notification about existing share + * Send a notification about an existing share * * @NoCSRFRequired * @PublicPage * @BruteForceProtection(action=receiveFederatedShareNotification) * - * @param string $notificationType (notification type, e.g. SHARE_ACCEPTED) - * @param string $resourceType (calendar, file, contact,...) - * @param string $providerId id of the share - * @param array $notification the actual payload of the notification - * @return JSONResponse + * @param string $notificationType Notification type, e.g. SHARE_ACCEPTED + * @param string $resourceType calendar, file, contact,... + * @param string|null $providerId ID of the share + * @param array<string, mixed>|null $notification The actual payload of the notification + * + * @return JSONResponse<Http::STATUS_CREATED, array<string, mixed>, array{}>|JSONResponse<Http::STATUS_BAD_REQUEST, CloudFederationApiValidationError, array{}>|JSONResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_IMPLEMENTED, CloudFederationApiError, array{}> + * 201: The notification was successfully received + * 400: Bad request due to invalid parameters, e.g. when `type` is invalid or missing + * 403: Getting resource is not allowed + * 501: The resource type is not supported */ - public function receiveNotification($notificationType, $resourceType, $providerId, array $notification) { + public function receiveNotification($notificationType, $resourceType, $providerId, ?array $notification) { // check if all required parameters are set if ($notificationType === null || @@ -243,7 +261,10 @@ class RequestHandlerController extends Controller { !is_array($notification) ) { return new JSONResponse( - ['message' => 'Missing arguments'], + [ + 'message' => 'Missing arguments', + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); } @@ -253,12 +274,18 @@ class RequestHandlerController extends Controller { $result = $provider->notificationReceived($notificationType, $providerId, $notification); } catch (ProviderDoesNotExistsException $e) { return new JSONResponse( - ['message' => $e->getMessage()], + [ + 'message' => $e->getMessage(), + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); } catch (ShareNotFound $e) { $response = new JSONResponse( - ['message' => $e->getMessage()], + [ + 'message' => $e->getMessage(), + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); $response->throttle(); @@ -276,7 +303,10 @@ class RequestHandlerController extends Controller { return $response; } catch (\Exception $e) { return new JSONResponse( - ['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()], + [ + 'message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl(), + 'validationErrors' => [], + ], Http::STATUS_BAD_REQUEST ); } diff --git a/apps/cloud_federation_api/lib/ResponseDefinitions.php b/apps/cloud_federation_api/lib/ResponseDefinitions.php new file mode 100644 index 00000000000..06b8124cc32 --- /dev/null +++ b/apps/cloud_federation_api/lib/ResponseDefinitions.php @@ -0,0 +1,45 @@ +<?php +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Kate Döen <kate.doeen@nextcloud.com> + * + * @author Kate Döen <kate.doeen@nextcloud.com> + * + * @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 OCA\CloudFederationAPI; + +/** + * @psalm-type CloudFederationApiAddShare = array{ + * recipientDisplayName: string, + * } + * + * @psalm-type CloudFederationApiError = array{ + * message: string, + * } + * + * @psalm-type CloudFederationApiValidationError = CloudFederationApiError&array{ + * validationErrors: array{ + * name: string, + * message: string|null, + * }[], + * } + */ +class ResponseDefinitions { +} diff --git a/apps/cloud_federation_api/openapi.json b/apps/cloud_federation_api/openapi.json index f017b864a27..ecefd063548 100644 --- a/apps/cloud_federation_api/openapi.json +++ b/apps/cloud_federation_api/openapi.json @@ -351,8 +351,8 @@ "content": { "application/json": { "schema": { - "type": "array", - "items": { + "type": "object", + "additionalProperties": { "type": "object" } } @@ -370,7 +370,7 @@ } }, "403": { - "description": "Getting resource not allowed", + "description": "Getting resource is not allowed", "content": { "application/json": { "schema": { |