From 69ff6d5cb1ebc833442a273b67980747e95d10aa Mon Sep 17 00:00:00 2001 From: provokateurin Date: Tue, 2 Jul 2024 09:01:55 +0200 Subject: [PATCH 1/2] build: Add nextcloud/ocp to resolve types in tests Signed-off-by: provokateurin --- composer.json | 3 +- composer.lock | 252 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 252 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index c6e95fc..23a6c06 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "phpstan/phpdoc-parser": "^1.28" }, "require-dev": { - "nextcloud/coding-standard": "^1.2" + "nextcloud/coding-standard": "^1.2", + "nextcloud/ocp": "dev-master" }, "scripts": { "lint": "find . -name \\*.php -not -path './tests/*' -not -path './vendor/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l && php -l generate-spec && php -l merge-specs", diff --git a/composer.lock b/composer.lock index 31a8c85..a431a35 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fc5dbdb675d13c475babdd099a7fbd84", + "content-hash": "fb4ef3fe74f666cdd46bae5bfdaa80eb", "packages": [ { "name": "adhocore/cli", @@ -224,6 +224,51 @@ }, "time": "2024-02-01T14:54:37+00:00" }, + { + "name": "nextcloud/ocp", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "55a0fedc6b7e0d3b7c26ee4823a131870627617b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/55a0fedc6b7e0d3b7c26ee4823a131870627617b", + "reference": "55a0fedc6b7e0d3b7c26ee4823a131870627617b", + "shasum": "" + }, + "require": { + "php": "~8.0 || ~8.1 || ~8.2 || ~8.3", + "psr/clock": "^1.0", + "psr/container": "^2.0.2", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.1.4" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "30.0.0-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" + } + ], + "description": "Composer package containing Nextcloud's public API (classes, interfaces)", + "support": { + "issues": "https://github.com/nextcloud-deps/ocp/issues", + "source": "https://github.com/nextcloud-deps/ocp/tree/master" + }, + "time": "2024-07-02T00:36:29+00:00" + }, { "name": "php-cs-fixer/shim", "version": "v3.41.1", @@ -275,11 +320,214 @@ "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.41.1" }, "time": "2023-12-10T19:59:57+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "nextcloud/ocp": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From 48cb793a7d2bbad4f24f96f9d3417673700d5b4f Mon Sep 17 00:00:00 2001 From: provokateurin Date: Tue, 2 Jul 2024 09:03:18 +0200 Subject: [PATCH 2/2] feat(scopes): Add ex_app scope Signed-off-by: provokateurin --- generate-spec | 3 + tests/appinfo/routes.php | 3 + .../Controller/ExAppSettingsController.php | 39 ++++ tests/openapi-ex_app.json | 195 ++++++++++++++++++ tests/openapi-full.json | 143 +++++++++++++ 5 files changed, 383 insertions(+) create mode 100644 tests/lib/Controller/ExAppSettingsController.php create mode 100644 tests/openapi-ex_app.json diff --git a/generate-spec b/generate-spec index 35a01e9..f79709e 100755 --- a/generate-spec +++ b/generate-spec @@ -446,6 +446,7 @@ foreach ($parsedRoutes as $key => $value) { $isDeprecated = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, "deprecated"); $isIgnored = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, "IgnoreOpenAPI"); $isPasswordConfirmation = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, "PasswordConfirmationRequired"); + $isExApp = Helpers::classMethodHasAnnotationOrAttribute($methodFunction, "ExAppRequired"); $scopes = Helpers::getOpenAPIAttributeScopes($classMethod, $routeName); if ($isIgnored) { @@ -469,6 +470,8 @@ foreach ($parsedRoutes as $key => $value) { if (empty($scopes)) { if (!empty($controllerScopes)) { $scopes = $controllerScopes; + } elseif ($isExApp) { + $scopes = ['ex_app']; } elseif ($isAdmin) { $scopes = ['administration']; } else { diff --git a/tests/appinfo/routes.php b/tests/appinfo/routes.php index 9f13e71..e11ed48 100644 --- a/tests/appinfo/routes.php +++ b/tests/appinfo/routes.php @@ -31,6 +31,9 @@ ['name' => 'AdminSettings#movedToSettingsTag', 'url' => '/api/{apiVersion}/moved-with-tag', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'AdminSettings#movedToSettingsTagUnnamed', 'url' => '/api/{apiVersion}/moved-with-unnamed-tag', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'ExAppSettings#exAppScopeAttribute', 'url' => '/api/{apiVersion}/ex-app-attribute', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'ExAppSettings#exAppScopeOverride', 'url' => '/api/{apiVersion}/ex-app-override', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Federation#federationByController', 'url' => '/api/{apiVersion}/controller-scope', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Federation#movedToDefaultScope', 'url' => '/api/{apiVersion}/default-scope', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], diff --git a/tests/lib/Controller/ExAppSettingsController.php b/tests/lib/Controller/ExAppSettingsController.php new file mode 100644 index 0000000..b246117 --- /dev/null +++ b/tests/lib/Controller/ExAppSettingsController.php @@ -0,0 +1,39 @@ +, array{}> + * + * 200: Personal settings updated + */ + #[ExAppRequired] + public function exAppScopeAttribute(): DataResponse { + return new DataResponse(); + } + + /** + * Route is in ex_app scope because of the override + * + * @return DataResponse, array{}> + * + * 200: Personal settings updated + */ + #[NoAdminRequired] + #[OpenAPI(OpenAPI::SCOPE_EX_APP)] + public function exAppScopeOverride(): DataResponse { + return new DataResponse(); + } +} diff --git a/tests/openapi-ex_app.json b/tests/openapi-ex_app.json new file mode 100644 index 0000000..a1dd633 --- /dev/null +++ b/tests/openapi-ex_app.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "notifications-ex_app", + "version": "0.0.1", + "description": "This app provides a backend and frontend for the notification API available in Nextcloud.", + "license": { + "name": "agpl" + } + }, + "components": { + "securitySchemes": { + "basic_auth": { + "type": "http", + "scheme": "basic" + }, + "bearer_auth": { + "type": "http", + "scheme": "bearer" + } + }, + "schemas": { + "OCSMeta": { + "type": "object", + "required": [ + "status", + "statuscode" + ], + "properties": { + "status": { + "type": "string" + }, + "statuscode": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "totalitems": { + "type": "string" + }, + "itemsperpage": { + "type": "string" + } + } + } + } + }, + "paths": { + "/ocs/v2.php/apps/notifications/api/{apiVersion}/ex-app-attribute": { + "post": { + "operationId": "ex_app_settings-ex-app-scope-attribute", + "summary": "Route is in ex_app scope because of the attribute", + "description": "This endpoint requires admin access", + "tags": [ + "ex_app_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": "Personal 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/apps/notifications/api/{apiVersion}/ex-app-override": { + "post": { + "operationId": "ex_app_settings-ex-app-scope-override", + "summary": "Route is in ex_app scope because of the override", + "tags": [ + "ex_app_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": "Personal 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 8e85a0e..b7035fd 100644 --- a/tests/openapi-full.json +++ b/tests/openapi-full.json @@ -4113,6 +4113,149 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/ex-app-attribute": { + "post": { + "operationId": "ex_app_settings-ex-app-scope-attribute", + "summary": "Route is in ex_app scope because of the attribute", + "description": "This endpoint requires admin access", + "tags": [ + "ex_app_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": "Personal 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/apps/notifications/api/{apiVersion}/ex-app-override": { + "post": { + "operationId": "ex_app_settings-ex-app-scope-override", + "summary": "Route is in ex_app scope because of the override", + "tags": [ + "ex_app_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": "Personal 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/apps/notifications/api/{apiVersion}/controller-scope": { "post": { "operationId": "federation-federation-by-controller",