From bf187cdfd4d62b2f0acc57f04df03d6924308c7e Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 7 Dec 2023 12:15:50 +0100 Subject: [PATCH] Also export schemas that are only referenced by other schemas Signed-off-by: Joas Schilling --- generate-spec | 14 ++- tests/lib/Controller/ApiController.php | 121 +++++++++++++++++++++++++ tests/lib/ResponseDefinitions.php | 7 +- tests/openapi-administration.json | 32 +++++-- 4 files changed, 162 insertions(+), 12 deletions(-) create mode 100644 tests/lib/Controller/ApiController.php diff --git a/generate-spec b/generate-spec index d5359fb..1bec5c9 100755 --- a/generate-spec +++ b/generate-spec @@ -745,7 +745,7 @@ foreach ($scopePaths as $scope => $paths) { } $scopedSchemas = []; - foreach ($usedSchemas as $usedSchema) { + while ($usedSchema = array_shift($usedSchemas)) { if (!str_starts_with($usedSchema, '#/components/schemas/')) { continue; } @@ -756,6 +756,18 @@ foreach ($scopePaths as $scope => $paths) { Logger::error("app", "Schema $schemaName used by scope $scope is not defined"); } + // Queue potential sub-refs for exporting as well + if (isset($schemas[$schemaName]['allOf'])) { + foreach ($schemas[$schemaName]['allOf'] as $subType) { + $newRefs = Helpers::collectUsedRefs($subType); + foreach ($newRefs as $newRef) { + if (!isset($scopedSchemas[substr($newRef, strlen('#/components/schemas/'))])) { + $usedSchemas[] = $newRef; + } + } + } + } + $scopedSchemas[$schemaName] = $schemas[$schemaName]; } diff --git a/tests/lib/Controller/ApiController.php b/tests/lib/Controller/ApiController.php new file mode 100644 index 0000000..a37155e --- /dev/null +++ b/tests/lib/Controller/ApiController.php @@ -0,0 +1,121 @@ + + * + * @author Julien Barnoin + * + * @license AGPL-3.0-or-later + * + * 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 . + * + */ + +namespace OCA\Notifications\Controller; + +use OCA\Notifications\ResponseDefinitions; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCSController; + +/** + * @psalm-import-type NotificationsPushDevice from ResponseDefinitions + */ +#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)] +class ApiController extends OCSController { + + /** + * @NoAdminRequired + * + * Route is ignored because of scope on the controller + * + * @return DataResponse, array{}> + * + * 200: OK + */ + public function federationByController(): DataResponse { + return new DataResponse(); + } + + /** + * @NoAdminRequired + * + * Route is ignored because of scope on the method + * + * @return DataResponse, array{}> + * + * 200: OK + */ + #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] + public function ignoreByMethod(): DataResponse { + return new DataResponse(); + } + + /** + * @NoAdminRequired + * + * Route is only in the default scope + * + * @return DataResponse, array{}> + * + * 200: Personal settings updated + */ + #[OpenAPI] + public function defaultScope(): DataResponse { + return new DataResponse(); + } + + /** + * @NoAdminRequired + * + * Route is only in the admin scope due to defined scope + * + * @return DataResponse + * + * 200: Admin settings updated + */ + #[OpenAPI(scope: OpenAPI::SCOPE_ADMINISTRATION)] + public function adminScope(): DataResponse { + return new DataResponse($this->createNotificationsPushDevice()); + } + + /** + * @return NotificationsPushDevice + */ + protected function createNotificationsPushDevice(): array { + return [ + 'publicKey' => 'publicKey', + 'deviceIdentifier' => 'deviceIdentifier', + 'signature' => 'signature', + ]; + } + + /** + * @NoAdminRequired + * + * Route is in admin and default scope + * + * @return DataResponse, array{}> + * + * 200: Admin settings updated + */ + #[OpenAPI] + #[OpenAPI(scope: OpenAPI::SCOPE_ADMINISTRATION)] + public function doubleScope(): DataResponse { + return new DataResponse(); + } +} diff --git a/tests/lib/ResponseDefinitions.php b/tests/lib/ResponseDefinitions.php index 39df467..80ba8f2 100644 --- a/tests/lib/ResponseDefinitions.php +++ b/tests/lib/ResponseDefinitions.php @@ -53,9 +53,12 @@ * shouldNotify?: bool, * } * - * @psalm-type NotificationsPushDevice = array{ - * publicKey: string, + * @psalm-type NotificationsPushDeviceBase = array{ * deviceIdentifier: string, + * } + * + * @psalm-type NotificationsPushDevice = NotificationsPushDeviceBase&array{ + * publicKey: string, * signature: string, * } */ diff --git a/tests/openapi-administration.json b/tests/openapi-administration.json index c55dec4..4b839ea 100644 --- a/tests/openapi-administration.json +++ b/tests/openapi-administration.json @@ -45,21 +45,35 @@ } }, "PushDevice": { + "allOf": [ + { + "$ref": "#/components/schemas/PushDeviceBase" + }, + { + "type": "object", + "required": [ + "publicKey", + "signature" + ], + "properties": { + "publicKey": { + "type": "string" + }, + "signature": { + "type": "string" + } + } + } + ] + }, + "PushDeviceBase": { "type": "object", "required": [ - "publicKey", - "deviceIdentifier", - "signature" + "deviceIdentifier" ], "properties": { - "publicKey": { - "type": "string" - }, "deviceIdentifier": { "type": "string" - }, - "signature": { - "type": "string" } } }