From bc6010df0f7db37334e1fc7f2f6aa75a9b5d0b13 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Wed, 4 Feb 2026 22:50:16 +0000 Subject: [PATCH 1/9] chore: Initial setup for OpenAPI 3.1 documentation Signed-off-by: matiasperrone-exo --- .env.example | 9 + .gitignore | 2 +- app/Swagger/GenericSchemas.php | 31 +++ app/Swagger/OpenApiInfo.php | 26 ++ composer.json | 4 +- composer.lock | 438 ++++++++++++++++++++++++++++++++- config/l5-swagger.php | 323 ++++++++++++++++++++++++ 7 files changed, 830 insertions(+), 3 deletions(-) create mode 100644 app/Swagger/GenericSchemas.php create mode 100644 app/Swagger/OpenApiInfo.php create mode 100644 config/l5-swagger.php diff --git a/.env.example b/.env.example index 30eb92d0..9afe5d6e 100644 --- a/.env.example +++ b/.env.example @@ -149,3 +149,12 @@ OTEL_TRACES_SAMPLER_PARENT=false # OTEL_INSTRUMENTATION_VIEW=true # OTEL_INSTRUMENTATION_LIVEWIRE=true # OTEL_INSTRUMENTATION_CONSOLE=true + +# OpenAPI CONFIG (former Swagger) + +L5_SWAGGER_CONST_HOST=${APP_URL} +L5_SWAGGER_CONST_AUTH_URL=${IDP_AUTHORIZATION_ENDPOINT} +L5_SWAGGER_CONST_TOKEN_URL=${IDP_TOKEN_ENDPOINT} +# L5_FORMAT_TO_USE_FOR_DOCS=yaml +L5_SWAGGER_GENERATE_ALWAYS=true # Dev setting +L5_SWAGGER_OPEN_API_SPEC_VERSION=3.2.0 diff --git a/.gitignore b/.gitignore index ffd7efd9..2b975b7c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ Homestead.yaml Homestead.json .env .env.* -storage/proxies +storage/* /public/assets/jquery-cookie/ /public/assets/crypto-js/ /public/assets/bootstrap-tagsinput/ diff --git a/app/Swagger/GenericSchemas.php b/app/Swagger/GenericSchemas.php new file mode 100644 index 00000000..231700fc --- /dev/null +++ b/app/Swagger/GenericSchemas.php @@ -0,0 +1,31 @@ +=5.18.3", + "symfony/yaml": "^5.0 || ^6.0 || ^7.0", + "zircote/swagger-php": "^5.0.0" + }, + "require-dev": { + "mockery/mockery": "1.*", + "orchestra/testbench": "^10.0 || ^9.0 || ^8.0 || 7.* || ^6.15 || 5.*", + "php-coveralls/php-coveralls": "^2.0", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "L5Swagger": "L5Swagger\\L5SwaggerFacade" + }, + "providers": [ + "L5Swagger\\L5SwaggerServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "L5Swagger\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Darius Matulionis", + "email": "darius@matulionis.lt" + } + ], + "description": "OpenApi or Swagger integration to Laravel", + "keywords": [ + "api", + "documentation", + "laravel", + "openapi", + "specification", + "swagger", + "ui" + ], + "support": { + "issues": "https://github.com/DarkaOnLine/L5-Swagger/issues", + "source": "https://github.com/DarkaOnLine/L5-Swagger/tree/9.0.1" + }, + "funding": [ + { + "url": "https://github.com/DarkaOnLine", + "type": "github" + } + ], + "time": "2025-02-28T06:25:02+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.3", @@ -550,6 +631,83 @@ }, "time": "2024-07-08T12:26:09+00:00" }, + { + "name": "doctrine/annotations", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/901c2ee5d26eb64ff43c47976e114bf00843acf7", + "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2 || ^3", + "ext-tokenizer": "*", + "php": "^7.2 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^2.0", + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.10.28", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^5.4 || ^6.4 || ^7", + "vimeo/psalm": "^4.30 || ^5.14" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/2.0.2" + }, + "abandoned": true, + "time": "2024-09-05T10:17:24+00:00" + }, { "name": "doctrine/cache", "version": "2.2.0", @@ -6488,6 +6646,53 @@ }, "time": "2024-02-26T14:37:15+00:00" }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" + }, + "time": "2026-01-25T14:56:51+00:00" + }, { "name": "predis/predis", "version": "v2.2.2", @@ -7961,6 +8166,67 @@ ], "time": "2025-07-17T15:46:43+00:00" }, + { + "name": "swagger-api/swagger-ui", + "version": "v5.31.0", + "source": { + "type": "git", + "url": "https://github.com/swagger-api/swagger-ui.git", + "reference": "61dddd44389bf25922639afd682f50b8a0fb5cf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/61dddd44389bf25922639afd682f50b8a0fb5cf4", + "reference": "61dddd44389bf25922639afd682f50b8a0fb5cf4", + "shasum": "" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Anna Bodnia", + "email": "anna.bodnia@gmail.com" + }, + { + "name": "Buu Nguyen", + "email": "buunguyen@gmail.com" + }, + { + "name": "Josh Ponelat", + "email": "jponelat@gmail.com" + }, + { + "name": "Kyle Shockey", + "email": "kyleshockey1@gmail.com" + }, + { + "name": "Robert Barnwell", + "email": "robert@robertismy.name" + }, + { + "name": "Sahar Jafari", + "email": "shr.jafari@gmail.com" + } + ], + "description": " Swagger UI is a collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.", + "homepage": "http://swagger.io", + "keywords": [ + "api", + "documentation", + "openapi", + "specification", + "swagger", + "ui" + ], + "support": { + "issues": "https://github.com/swagger-api/swagger-ui/issues", + "source": "https://github.com/swagger-api/swagger-ui/tree/v5.31.0" + }, + "time": "2025-12-11T15:57:42+00:00" + }, { "name": "symfony/cache", "version": "v7.3.0", @@ -10763,6 +11029,82 @@ ], "time": "2025-05-15T09:04:05+00:00" }, + { + "name": "symfony/yaml", + "version": "v7.4.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", + "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0|^8.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.4.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-12-04T18:11:45+00:00" + }, { "name": "tbachert/spi", "version": "v1.0.5", @@ -11288,6 +11630,100 @@ "source": "https://github.com/webmozarts/assert/tree/1.11.0" }, "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "zircote/swagger-php", + "version": "5.8.0", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "9cf5d1a0c159894026708c9e837e69140c2d3922" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/9cf5d1a0c159894026708c9e837e69140c2d3922", + "reference": "9cf5d1a0c159894026708c9e837e69140c2d3922", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nikic/php-parser": "^4.19 || ^5.0", + "php": ">=7.4", + "phpstan/phpdoc-parser": "^2.0", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "symfony/deprecation-contracts": "^2 || ^3", + "symfony/finder": "^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "conflict": { + "symfony/process": ">=6, <6.4.14" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/annotations": "^2.0", + "friendsofphp/php-cs-fixer": "^3.62.0", + "phpstan/phpstan": "^1.6 || ^2.0", + "phpunit/phpunit": "^9.0", + "rector/rector": "^1.0 || ^2.3.1", + "vimeo/psalm": "^4.30 || ^5.0" + }, + "suggest": { + "doctrine/annotations": "^2.0", + "radebatz/type-info-extras": "^1.0.2" + }, + "bin": [ + "bin/openapi" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenApi\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Robert Allen", + "email": "zircote@gmail.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "https://bfanger.nl" + }, + { + "name": "Martin Rademacher", + "email": "mano@radebatz.net", + "homepage": "https://radebatz.net" + } + ], + "description": "Generate interactive documentation for your RESTful API using PHP attributes (preferred) or PHPDoc annotations", + "homepage": "https://github.com/zircote/swagger-php", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "support": { + "issues": "https://github.com/zircote/swagger-php/issues", + "source": "https://github.com/zircote/swagger-php/tree/5.8.0" + }, + "funding": [ + { + "url": "https://github.com/zircote", + "type": "github" + } + ], + "time": "2026-01-28T01:27:48+00:00" } ], "packages-dev": [ diff --git a/config/l5-swagger.php b/config/l5-swagger.php new file mode 100644 index 00000000..27d53ac2 --- /dev/null +++ b/config/l5-swagger.php @@ -0,0 +1,323 @@ + 'default', + 'enable' => true, + 'documentations' => [ + 'default' => [ + 'api' => [ + 'title' => 'Summit API Swagger UI', + ], + + 'routes' => [ + /* + * Route for accessing api documentation interface + */ + 'api' => '/api/documentation', + ], + 'paths' => [ + /* + * Edit to include full URL in ui for assets + */ + 'use_absolute_path' => env('L5_SWAGGER_USE_ABSOLUTE_PATH', true), + + /* + * Edit to set path where swagger ui assets should be stored + */ + 'swagger_ui_assets_path' => env('L5_SWAGGER_UI_ASSETS_PATH', 'vendor/swagger-api/swagger-ui/dist/'), + + /* + * File name of the generated json documentation file + */ + 'docs_json' => 'api-docs.json', + + /* + * File name of the generated YAML documentation file + */ + 'docs_yaml' => 'api-docs.yaml', + + /* + * Set this to `json` or `yaml` to determine which documentation file to use in UI + */ + 'format_to_use_for_docs' => env('L5_FORMAT_TO_USE_FOR_DOCS', 'json'), + + /* + * Absolute paths to directory containing the swagger annotations are stored. + */ + 'annotations' => [ + base_path('app'), + ], + ], + ], + ], + 'defaults' => [ + 'routes' => [ + /* + * Route for accessing parsed swagger annotations. + */ + 'docs' => 'docs', + + /* + * Route for Oauth2 authentication callback. + */ + 'oauth2_callback' => 'api/oauth2-callback', + + /* + * Middleware allows to prevent unexpected access to API documentation + */ + 'middleware' => [ + 'api' => [], + 'asset' => [], + 'docs' => [], + 'oauth2_callback' => [], + ], + + /* + * Route Group options + */ + 'group_options' => [], + + ], + + 'paths' => [ + /* + * Absolute path to location where parsed annotations will be stored + */ + 'docs' => storage_path('api-docs'), + + /* + * Absolute path to directory where to export views + */ + 'views' => base_path('resources/views/vendor/l5-swagger'), + + /* + * Edit to set the api's base path + */ + 'base' => env('L5_SWAGGER_BASE_PATH', null), + + /* + * Absolute path to directories that should be excluded from scanning + * @deprecated Please use `scanOptions.exclude` + * `scanOptions.exclude` overwrites this + */ + 'excludes' => [], + ], + + 'scanOptions' => [ + /** + * Configuration for default processors. Allows to pass processors configuration to swagger-php. + * + * @link https://zircote.github.io/swagger-php/reference/processors.html + */ + 'default_processors_configuration' => [ + /** Example */ + /** + * 'operationId.hash' => true, + * 'pathFilter' => [ + * 'tags' => [ + * '/pets/', + * '/store/', + * ], + * ],. + */ + ], + + /** + * analyser: defaults to \OpenApi\StaticAnalyser . + * + * @see \OpenApi\scan + */ + 'analyser' => null, + + /** + * analysis: defaults to a new \OpenApi\Analysis . + * + * @see \OpenApi\scan + */ + 'analysis' => null, + + /** + * Custom query path processors classes. + * + * @link https://github.com/zircote/swagger-php/tree/master/Examples/processors/schema-query-parameter + * @see \OpenApi\scan + */ + 'processors' => [ + // new \App\SwaggerProcessors\SchemaQueryParameter(), + ], + + /** + * pattern: string $pattern File pattern(s) to scan (default: *.php) . + * + * @see \OpenApi\scan + */ + 'pattern' => null, + + /* + * Absolute path to directories that should be excluded from scanning + * @note This option overwrites `paths.excludes` + * @see \OpenApi\scan + */ + 'exclude' => [], + + /* + * Allows to generate specs either for OpenAPI 3.0.0 or OpenAPI 3.1.0. + * By default the spec will be in version 3.0.0 + */ + 'open_api_spec_version' => env('L5_SWAGGER_OPEN_API_SPEC_VERSION', \L5Swagger\Generator::OPEN_API_DEFAULT_SPEC_VERSION), + ], + + /* + * API security definitions. Will be generated into documentation file. + */ + 'securityDefinitions' => [ + 'securitySchemes' => [ + /* + * Examples of Security schemes + */ + /* + 'api_key_security_example' => [ // Unique name of security + 'type' => 'apiKey', // The type of the security scheme. Valid values are "basic", "apiKey" or "oauth2". + 'description' => 'A short description for security scheme', + 'name' => 'api_key', // The name of the header or query parameter to be used. + 'in' => 'header', // The location of the API key. Valid values are "query" or "header". + ], + 'oauth2_security_example' => [ // Unique name of security + 'type' => 'oauth2', // The type of the security scheme. Valid values are "basic", "apiKey" or "oauth2". + 'description' => 'A short description for oauth2 security scheme.', + 'flow' => 'implicit', // The flow used by the OAuth2 security scheme. Valid values are "implicit", "password", "application" or "accessCode". + 'authorizationUrl' => 'http://example.com/auth', // The authorization URL to be used for (implicit/accessCode) + //'tokenUrl' => 'http://example.com/auth' // The authorization URL to be used for (password/application/accessCode) + 'scopes' => [ + 'read:projects' => 'read your projects', + 'write:projects' => 'modify projects in your account', + ] + ], + */ + + /* Open API 3.0 support + 'passport' => [ // Unique name of security + 'type' => 'oauth2', // The type of the security scheme. Valid values are "basic", "apiKey" or "oauth2". + 'description' => 'Laravel passport oauth2 security.', + 'in' => 'header', + 'scheme' => 'https', + 'flows' => [ + "password" => [ + "authorizationUrl" => config('app.url') . '/oauth/authorize', + "tokenUrl" => config('app.url') . '/oauth/token', + "refreshUrl" => config('app.url') . '/token/refresh', + "scopes" => [] + ], + ], + ], + 'sanctum' => [ // Unique name of security + 'type' => 'apiKey', // Valid values are "basic", "apiKey" or "oauth2". + 'description' => 'Enter token in format (Bearer )', + 'name' => 'Authorization', // The name of the header or query parameter to be used. + 'in' => 'header', // The location of the API key. Valid values are "query" or "header". + ], + */ + ], + 'security' => [ + /* + * Examples of Securities + */ + [ + /* + 'oauth2_security_example' => [ + 'read', + 'write' + ], + + 'passport' => [] + */ + ], + ], + ], + + /* + * Set this to `true` in development mode so that docs would be regenerated on each request + * Set this to `false` to disable swagger generation on production + */ + 'generate_always' => env('L5_SWAGGER_GENERATE_ALWAYS', true), + + /* + * Set this to `true` to generate a copy of documentation in yaml format + */ + 'generate_yaml_copy' => env('L5_SWAGGER_GENERATE_YAML_COPY', false), + + /* + * Edit to trust the proxy's ip address - needed for AWS Load Balancer + * string[] + */ + 'proxy' => false, + + /* + * Configs plugin allows to fetch external configs instead of passing them to SwaggerUIBundle. + * See more at: https://github.com/swagger-api/swagger-ui#configs-plugin + */ + 'additional_config_url' => null, + + /* + * Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), + * 'method' (sort by HTTP method). + * Default is the order returned by the server unchanged. + */ + 'operations_sort' => env('L5_SWAGGER_OPERATIONS_SORT', null), + + /* + * Pass the validatorUrl parameter to SwaggerUi init on the JS side. + * A null value here disables validation. + */ + 'validator_url' => null, + + /* + * Swagger UI configuration parameters + */ + 'ui' => [ + 'display' => [ + 'dark_mode' => env('L5_SWAGGER_UI_DARK_MODE', false), + /* + * Controls the default expansion setting for the operations and tags. It can be : + * 'list' (expands only the tags), + * 'full' (expands the tags and operations), + * 'none' (expands nothing). + */ + 'doc_expansion' => env('L5_SWAGGER_UI_DOC_EXPANSION', 'none'), + + /** + * If set, enables filtering. The top bar will show an edit box that + * you can use to filter the tagged operations that are shown. Can be + * Boolean to enable or disable, or a string, in which case filtering + * will be enabled using that string as the filter expression. Filtering + * is case-sensitive matching the filter expression anywhere inside + * the tag. + */ + 'filter' => env('L5_SWAGGER_UI_FILTERS', true), // true | false + ], + + 'authorization' => [ + /* + * If set to true, it persists authorization data, and it would not be lost on browser close/refresh + */ + 'persist_authorization' => env('L5_SWAGGER_UI_PERSIST_AUTHORIZATION', false), + + 'oauth2' => [ + /* + * If set to true, adds PKCE to AuthorizationCodeGrant flow + */ + 'use_pkce_with_authorization_code_grant' => false, + ], + ], + ], + /* + * Constants which can be used in annotations + */ + 'constants' => [ + 'L5_SWAGGER_CONST_HOST' => env('L5_SWAGGER_CONST_HOST', 'http://localhost'), + 'L5_SWAGGER_CONST_AUTH_URL' => env('L5_SWAGGER_CONST_AUTH_URL', 'http://localhost/oauth/authorize'), + 'L5_SWAGGER_CONST_TOKEN_URL' => env('L5_SWAGGER_CONST_TOKEN_URL', 'http://localhost/oauth/token'), + + ], + ], +]; From 6adfbfc224cc04c69d396ff025f40e89a5a2b442 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 5 Feb 2026 19:40:45 +0000 Subject: [PATCH 2/9] chore: Move to OpenAPI v3.1.2 so UI supports it Signed-off-by: matiasperrone-exo --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 9afe5d6e..c2886741 100644 --- a/.env.example +++ b/.env.example @@ -157,4 +157,4 @@ L5_SWAGGER_CONST_AUTH_URL=${IDP_AUTHORIZATION_ENDPOINT} L5_SWAGGER_CONST_TOKEN_URL=${IDP_TOKEN_ENDPOINT} # L5_FORMAT_TO_USE_FOR_DOCS=yaml L5_SWAGGER_GENERATE_ALWAYS=true # Dev setting -L5_SWAGGER_OPEN_API_SPEC_VERSION=3.2.0 +L5_SWAGGER_OPEN_API_SPEC_VERSION=3.1.2 From e89e6ebe36edb007be08804eb82e8c079bd32b8a Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 5 Feb 2026 20:10:24 +0000 Subject: [PATCH 3/9] chore: Add Basic schema which will be referenced by all the other Models schemas Signed-off-by: matiasperrone-exo --- app/Swagger/GenericSchemas.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/Swagger/GenericSchemas.php b/app/Swagger/GenericSchemas.php index 231700fc..ee8f0b2d 100644 --- a/app/Swagger/GenericSchemas.php +++ b/app/Swagger/GenericSchemas.php @@ -28,4 +28,18 @@ class BearerAuthSchema )] class PaginateDataSchemaResponseSchema { +} + +#[OA\Schema( + schema: 'BaseSerializerSchema', + type: 'object', + properties: [ + new OA\Property(property: 'id', type: 'integer', description: 'Unique identifier', example: 1), + new OA\Property(property: 'created_at', type: 'integer', description: 'Creation timestamp (epoch)', example: 1609459200), + new OA\Property(property: 'updated_at', type: 'integer', description: 'Last update timestamp (epoch)', example: 1609459200), + ], + description: 'Base serializer fields' +)] +class BaseSerializerSchema +{ } \ No newline at end of file From 4214f1bc4912db0dc992cd4644d3f9a3c05e1df5 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 5 Feb 2026 20:34:06 +0000 Subject: [PATCH 4/9] chore: change name for Base schema Signed-off-by: matiasperrone-exo --- app/Swagger/GenericSchemas.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Swagger/GenericSchemas.php b/app/Swagger/GenericSchemas.php index ee8f0b2d..df4432c4 100644 --- a/app/Swagger/GenericSchemas.php +++ b/app/Swagger/GenericSchemas.php @@ -31,7 +31,7 @@ class PaginateDataSchemaResponseSchema } #[OA\Schema( - schema: 'BaseSerializerSchema', + schema: 'Base', type: 'object', properties: [ new OA\Property(property: 'id', type: 'integer', description: 'Unique identifier', example: 1), @@ -40,6 +40,6 @@ class PaginateDataSchemaResponseSchema ], description: 'Base serializer fields' )] -class BaseSerializerSchema +class BaseSchema { } \ No newline at end of file From 7c0a67bb01a99b3686265769b4ac4fa610e83eca Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 5 Feb 2026 21:02:18 +0000 Subject: [PATCH 5/9] chore: Add requested changes Signed-off-by: matiasperrone-exo --- app/Swagger/OpenApiInfo.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Swagger/OpenApiInfo.php b/app/Swagger/OpenApiInfo.php index ad0fb16b..8e627c47 100644 --- a/app/Swagger/OpenApiInfo.php +++ b/app/Swagger/OpenApiInfo.php @@ -13,12 +13,12 @@ email: "support@openstack.org" ), license: new OA\License( - name: "MIT", - url: "https://opensource.org/licenses/MIT" + name: "Apache 2.0", + url: "http://www.apache.org/licenses/LICENSE-2.0" ) )] #[OA\Server( - url: "/", + url: L5_SWAGGER_CONST_HOST, description: "IDP API Server" )] class OpenApiInfo From dbc1af1d92d3ebd8600eae46287580a9789c7b6e Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Wed, 11 Feb 2026 21:26:33 +0000 Subject: [PATCH 6/9] chore: remove unneeded schema Signed-off-by: matiasperrone-exo --- app/Swagger/GenericSchemas.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/Swagger/GenericSchemas.php b/app/Swagger/GenericSchemas.php index df4432c4..b0cbd1b8 100644 --- a/app/Swagger/GenericSchemas.php +++ b/app/Swagger/GenericSchemas.php @@ -5,16 +5,6 @@ use OpenApi\Attributes as OA; -#[OA\SecurityScheme( - securityScheme: "bearerAuth", - type: "http", - scheme: "bearer", - bearerFormat: "JWT" -)] -class BearerAuthSchema -{ -} - #[OA\Schema( schema: 'PaginateDataSchemaResponse', type: 'object', From 20eed023f7b2094c16ba03a4cf45ef5bc7562395 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Wed, 11 Feb 2026 22:42:10 +0000 Subject: [PATCH 7/9] update .env.example with right values for OpenAPI docs Signed-off-by: matiasperrone-exo --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index c2886741..0e19658e 100644 --- a/.env.example +++ b/.env.example @@ -153,8 +153,8 @@ OTEL_TRACES_SAMPLER_PARENT=false # OpenAPI CONFIG (former Swagger) L5_SWAGGER_CONST_HOST=${APP_URL} -L5_SWAGGER_CONST_AUTH_URL=${IDP_AUTHORIZATION_ENDPOINT} -L5_SWAGGER_CONST_TOKEN_URL=${IDP_TOKEN_ENDPOINT} +L5_SWAGGER_CONST_AUTH_URL='/oauth2/auth' +L5_SWAGGER_CONST_TOKEN_URL='/oauth2/token' # L5_FORMAT_TO_USE_FOR_DOCS=yaml L5_SWAGGER_GENERATE_ALWAYS=true # Dev setting L5_SWAGGER_OPEN_API_SPEC_VERSION=3.1.2 From a2595292ff3012208000bda64b52177b2ca2f141 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 12 Feb 2026 19:14:00 +0000 Subject: [PATCH 8/9] chore: change API name in config Signed-off-by: matiasperrone-exo --- config/l5-swagger.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/config/l5-swagger.php b/config/l5-swagger.php index 27d53ac2..6cf40432 100644 --- a/config/l5-swagger.php +++ b/config/l5-swagger.php @@ -6,7 +6,7 @@ 'documentations' => [ 'default' => [ 'api' => [ - 'title' => 'Summit API Swagger UI', + 'title' => 'OpenStackID API Swagger UI', ], 'routes' => [ @@ -22,8 +22,8 @@ 'use_absolute_path' => env('L5_SWAGGER_USE_ABSOLUTE_PATH', true), /* - * Edit to set path where swagger ui assets should be stored - */ + * Edit to set path where swagger ui assets should be stored + */ 'swagger_ui_assets_path' => env('L5_SWAGGER_UI_ASSETS_PATH', 'vendor/swagger-api/swagger-ui/dist/'), /* @@ -110,16 +110,16 @@ * @link https://zircote.github.io/swagger-php/reference/processors.html */ 'default_processors_configuration' => [ - /** Example */ - /** - * 'operationId.hash' => true, - * 'pathFilter' => [ - * 'tags' => [ - * '/pets/', - * '/store/', - * ], - * ],. - */ + /** Example */ + /** + * 'operationId.hash' => true, + * 'pathFilter' => [ + * 'tags' => [ + * '/pets/', + * '/store/', + * ], + * ],. + */ ], /** @@ -169,7 +169,7 @@ /* * API security definitions. Will be generated into documentation file. - */ + */ 'securityDefinitions' => [ 'securitySchemes' => [ /* @@ -315,9 +315,9 @@ */ 'constants' => [ 'L5_SWAGGER_CONST_HOST' => env('L5_SWAGGER_CONST_HOST', 'http://localhost'), - 'L5_SWAGGER_CONST_AUTH_URL' => env('L5_SWAGGER_CONST_AUTH_URL', 'http://localhost/oauth/authorize'), - 'L5_SWAGGER_CONST_TOKEN_URL' => env('L5_SWAGGER_CONST_TOKEN_URL', 'http://localhost/oauth/token'), + 'L5_SWAGGER_CONST_AUTH_URL' => env('L5_SWAGGER_CONST_AUTH_URL', 'http://localhost/oauth/authorize'), + 'L5_SWAGGER_CONST_TOKEN_URL' => env('L5_SWAGGER_CONST_TOKEN_URL', 'http://localhost/oauth/token'), ], ], -]; +]; \ No newline at end of file From 84105859884843870e96e9a99d05e6622df03ae1 Mon Sep 17 00:00:00 2001 From: matiasperrone-exo Date: Thu, 12 Feb 2026 21:11:16 +0000 Subject: [PATCH 9/9] feat: Add OpenAPI documentation for OAuth2RocketChatSSOApiController v1 Signed-off-by: matiasperrone-exo --- .../OAuth2RocketChatSSOApiController.php | 43 +++++++++++++++++++ .../Models/RocketChatUserProfileSchema.php | 16 +++++++ ...cketChatSSOApiControllerSecuritySchema.php | 23 ++++++++++ 3 files changed, 82 insertions(+) create mode 100644 app/Swagger/Models/RocketChatUserProfileSchema.php create mode 100644 app/Swagger/Security/OAuth2RocketChatSSOApiControllerSecuritySchema.php diff --git a/app/Http/Controllers/Api/OAuth2/OAuth2RocketChatSSOApiController.php b/app/Http/Controllers/Api/OAuth2/OAuth2RocketChatSSOApiController.php index 8e7d82cb..60d8ad04 100644 --- a/app/Http/Controllers/Api/OAuth2/OAuth2RocketChatSSOApiController.php +++ b/app/Http/Controllers/Api/OAuth2/OAuth2RocketChatSSOApiController.php @@ -17,6 +17,9 @@ use models\exceptions\ValidationException; use OAuth2\IResourceServerContext; use Utils\Services\ILogService; +use App\libs\OAuth2\IUserScopes; +use OpenApi\Attributes as OA; +use Symfony\Component\HttpFoundation\Response as HttpResponse; /** * Class OAuth2RocketChatSSOApiController * @package App\Http\Controllers\Api\OAuth2 @@ -39,6 +42,46 @@ public function __construct $this->service = $service; } + + #[OA\Get( + path: '/api/v1/sso/rocket-chat/{forum_slug}/profile', + operationId: 'getRocketChatUserProfile', + summary: 'Get Rocket Chat user profile for a forum.', + description: 'Returns Rocket Chat user profile data for the authenticated user in the context of the specified forum. The content of the response is defined by "data" portion of the Rocket Chat login endpoint response structure', + security: [['OAuth2RocketChatSSOSecurity' => [IUserScopes::SSO]]], + tags: ['Rocket Chat SSO'], + parameters: [ + new OA\Parameter( + name: 'forum_slug', + description: 'Forum slug', + in: 'path', + required: true, + schema: new OA\Schema(type: 'string') + ), + ], + responses: [ + new OA\Response( + response: HttpResponse::HTTP_OK, + description: 'OK, returns Rocket Chat user profile data on login success', + content: new OA\JsonContent( + // The content of the response is defined by "data" portion of + // the Rocket Chat login endpoint response structure + ) + ), + new OA\Response( + response: HttpResponse::HTTP_NOT_FOUND, + description: 'Not Found' + ), + new OA\Response( + response: HttpResponse::HTTP_PRECONDITION_FAILED, + description: 'Validation Error' + ), + new OA\Response( + response: HttpResponse::HTTP_INTERNAL_SERVER_ERROR, + description: 'Server Error' + ), + ] + )] /** * @param string $forum_slug * @return \Illuminate\Http\JsonResponse|mixed diff --git a/app/Swagger/Models/RocketChatUserProfileSchema.php b/app/Swagger/Models/RocketChatUserProfileSchema.php new file mode 100644 index 00000000..c5af2f59 --- /dev/null +++ b/app/Swagger/Models/RocketChatUserProfileSchema.php @@ -0,0 +1,16 @@ + 'Single Sign-On access'] + ), + ] +)] +class OAuth2RocketChatSSOApiControllerSecuritySchema +{ +} \ No newline at end of file