diff --git a/generate-spec.php b/generate-spec.php index c1d4b0c..8343358 100755 --- a/generate-spec.php +++ b/generate-spec.php @@ -452,6 +452,7 @@ $isIgnored = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, 'IgnoreOpenAPI'); $isPasswordConfirmation = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, 'PasswordConfirmationRequired'); $isExApp = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, 'ExAppRequired'); + $isCORS = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, 'CORS'); $scopes = Helpers::getOpenAPIAttributeScopes($classMethod, $routeName); if ($isIgnored) { @@ -505,7 +506,7 @@ ]; } - $classMethodInfo = ControllerMethod::parse($routeName, $definitions, $methodFunction, $isAdmin, $isDeprecated, $isPasswordConfirmation); + $classMethodInfo = ControllerMethod::parse($routeName, $definitions, $methodFunction, $isAdmin, $isDeprecated, $isPasswordConfirmation, $isCORS); if ($classMethodInfo->returns !== []) { Logger::error($routeName, 'Returns an invalid response'); continue; diff --git a/src/ControllerMethod.php b/src/ControllerMethod.php index 7b17b58..8955ae8 100644 --- a/src/ControllerMethod.php +++ b/src/ControllerMethod.php @@ -34,7 +34,14 @@ public function __construct( ) { } - public static function parse(string $context, array $definitions, ClassMethod $method, bool $isAdmin, bool $isDeprecated, bool $isPasswordConfirmation): ControllerMethod { + public static function parse(string $context, + array $definitions, + ClassMethod $method, + bool $isAdmin, + bool $isDeprecated, + bool $isPasswordConfirmation, + bool $isCORS, + ): ControllerMethod { global $phpDocParser, $lexer, $allowMissingDocs; $parameters = []; @@ -210,6 +217,10 @@ public static function parse(string $context, array $definitions, ClassMethod $m $methodDescription[] = 'This endpoint requires password confirmation'; } + if ($isCORS) { + $methodDescription[] = 'This endpoint allows CORS requests'; + } + if (count($methodDescription) == 1) { $methodSummary = $methodDescription[0]; $methodDescription = []; diff --git a/tests/appinfo/routes.php b/tests/appinfo/routes.php index bcc9ffe..5bf7eb9 100644 --- a/tests/appinfo/routes.php +++ b/tests/appinfo/routes.php @@ -74,5 +74,7 @@ ['name' => 'Settings#parameterRequestBody', 'url' => '/api/{apiVersion}/parameterPATCH', 'verb' => 'PATCH', 'postfix' => 'PATCH', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#objectDefaults', 'url' => '/api/{apiVersion}/objectDefaults', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#whitespace', 'url' => '/api/{apiVersion}/whitespace', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#withCorsAnnotation', 'url' => '/api/{apiVersion}/cors/annotation', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#withCorsAttribute', 'url' => '/api/{apiVersion}/cors/attribute', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ], ]; diff --git a/tests/lib/Controller/SettingsController.php b/tests/lib/Controller/SettingsController.php index 6b76d78..4634ac0 100644 --- a/tests/lib/Controller/SettingsController.php +++ b/tests/lib/Controller/SettingsController.php @@ -11,6 +11,7 @@ use OCA\Notifications\ResponseDefinitions; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\CORS; use OCP\AppFramework\Http\Attribute\IgnoreOpenAPI; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; @@ -571,4 +572,28 @@ public function objectDefaults(array $empty = [], array $values = ['key' => 'val public function whitespace(int $value): DataResponse { return new DataResponse(); } + + /** + * Route with CORS annotation + * + * @CORS + * @return DataResponse, array{}> + * + * 200: OK + */ + public function withCorsAnnotation(): DataResponse { + return new DataResponse(); + } + + /** + * Route with CORS attribute + * + * @return DataResponse, array{}> + * + * 200: OK + */ + #[CORS] + public function withCorsAttribute(): DataResponse { + return new DataResponse(); + } } diff --git a/tests/openapi-administration.json b/tests/openapi-administration.json index bc315e9..8cfc83d 100644 --- a/tests/openapi-administration.json +++ b/tests/openapi-administration.json @@ -4500,6 +4500,144 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/cors/annotation": { + "post": { + "operationId": "settings-with-cors-annotation", + "summary": "Route with CORS annotation", + "description": "This endpoint requires admin access\nThis endpoint allows CORS requests", + "tags": [ + "settings" + ], + "security": [ + { + "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": "OK", + "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/apps/notifications/api/{apiVersion}/cors/attribute": { + "post": { + "operationId": "settings-with-cors-attribute", + "summary": "Route with CORS attribute", + "description": "This endpoint requires admin access\nThis endpoint allows CORS requests", + "tags": [ + "settings" + ], + "security": [ + { + "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": "OK", + "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-full.json b/tests/openapi-full.json index 2519a54..09b560b 100644 --- a/tests/openapi-full.json +++ b/tests/openapi-full.json @@ -4650,6 +4650,144 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/cors/annotation": { + "post": { + "operationId": "settings-with-cors-annotation", + "summary": "Route with CORS annotation", + "description": "This endpoint requires admin access\nThis endpoint allows CORS requests", + "tags": [ + "settings" + ], + "security": [ + { + "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": "OK", + "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/apps/notifications/api/{apiVersion}/cors/attribute": { + "post": { + "operationId": "settings-with-cors-attribute", + "summary": "Route with CORS attribute", + "description": "This endpoint requires admin access\nThis endpoint allows CORS requests", + "tags": [ + "settings" + ], + "security": [ + { + "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": "OK", + "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",