From 3688015b96dfe59d168e1796fc5f00792d646b38 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Mon, 10 Mar 2025 09:20:55 +0100 Subject: [PATCH] fix(scopes): Correctly merge full scopes if multiple operations with the same path belong to different scopes Signed-off-by: provokateurin --- generate-spec.php | 11 +- tests/appinfo/routes.php | 2 + tests/lib/Controller/SettingsController.php | 24 ++++ tests/openapi-administration.json | 142 ++++++++++++++++++++ tests/openapi-federation.json | 72 ++++++++++ tests/openapi-full.json | 142 ++++++++++++++++++++ 6 files changed, 392 insertions(+), 1 deletion(-) diff --git a/generate-spec.php b/generate-spec.php index b6b25a3..acca389 100755 --- a/generate-spec.php +++ b/generate-spec.php @@ -966,7 +966,16 @@ } if ($scope === 'full') { - $openapiScope['paths'] = array_merge(...$fullScopePathArrays); + foreach ($fullScopePathArrays as $fullScopePaths) { + foreach ($fullScopePaths as $fullScopePath => $operations) { + $openapiScope['paths'][$fullScopePath] ??= []; + foreach ($operations as $method => $operation) { + // Don't need to check if we overwrite an existing operation, + // as we already check for collisions when validating the routes. + $openapiScope['paths'][$fullScopePath][$method] = $operation; + } + } + } $openapiScope['components']['schemas'] = $schemas; } else { $usedRefs = []; diff --git a/tests/appinfo/routes.php b/tests/appinfo/routes.php index 13984da..bfc2147 100644 --- a/tests/appinfo/routes.php +++ b/tests/appinfo/routes.php @@ -83,5 +83,7 @@ ['name' => 'Settings#deprecatedParameterGet', 'url' => '/api/{apiVersion}/deprecated-parameter-get', 'verb' => 'GET', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#deprecatedRouteAndParameter', 'url' => '/api/{apiVersion}/deprecated-route-parameter', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#deprecatedRouteAndParameterGet', 'url' => '/api/{apiVersion}/deprecated-route-parameter-get', 'verb' => 'GET', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#samePathGet', 'url' => '/api/{apiVersion}/same-path', 'verb' => 'GET', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#samePathPost', 'url' => '/api/{apiVersion}/same-path', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ], ]; diff --git a/tests/lib/Controller/SettingsController.php b/tests/lib/Controller/SettingsController.php index 7e68448..36356d6 100644 --- a/tests/lib/Controller/SettingsController.php +++ b/tests/lib/Controller/SettingsController.php @@ -715,4 +715,28 @@ public function deprecatedRouteAndParameter(bool $active, bool $deprecated): Dat public function deprecatedRouteAndParameterGet(bool $active, bool $deprecated): DataResponse { return new DataResponse(); } + + /** + * A GET method with the same path as the POST method + * + * @return DataResponse, array{}> + * + * 200: Admin settings updated + */ + #[OpenAPI(scope: OpenAPI::SCOPE_ADMINISTRATION)] + #[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)] + public function samePathGet(): DataResponse { + return new DataResponse(); + } + + /** + * A POST method with the same path as the GET method + * + * @return DataResponse, array{}> + * + * 200: Admin settings updated + */ + public function samePathPost(): DataResponse { + return new DataResponse(); + } } diff --git a/tests/openapi-administration.json b/tests/openapi-administration.json index 21fc144..cb2acf9 100644 --- a/tests/openapi-administration.json +++ b/tests/openapi-administration.json @@ -5210,6 +5210,148 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/same-path": { + "get": { + "operationId": "settings-same-path-get", + "summary": "A GET method with the same path as the POST method", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "settings-same-path-post", + "summary": "A POST method with the same path as the GET method", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, "/ocs/v2.php/tests/attribute-ocs/{param}": { "get": { "operationId": "routing-attributeocs-route", diff --git a/tests/openapi-federation.json b/tests/openapi-federation.json index ec11a89..f084fbd 100644 --- a/tests/openapi-federation.json +++ b/tests/openapi-federation.json @@ -156,6 +156,78 @@ } } } + }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/same-path": { + "get": { + "operationId": "settings-same-path-get", + "summary": "A GET method with the same path as the POST method", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } } }, "tags": [] diff --git a/tests/openapi-full.json b/tests/openapi-full.json index 50c67cd..3386143 100644 --- a/tests/openapi-full.json +++ b/tests/openapi-full.json @@ -5367,6 +5367,148 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/same-path": { + "get": { + "operationId": "settings-same-path-get", + "summary": "A GET method with the same path as the POST method", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "settings-same-path-post", + "summary": "A POST method with the same path as the GET method", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, "/ocs/v2.php/tests/attribute-ocs/{param}": { "get": { "operationId": "routing-attributeocs-route",