diff --git a/composer.json b/composer.json index 81eee65a..5cbb1481 100644 --- a/composer.json +++ b/composer.json @@ -44,12 +44,13 @@ "illuminate/database": "^10.23", "illuminate/support": "^10.23", "league/oauth2-client": "^2.7", + "league/openapi-psr7-validator": "^0.21", "nikic/fast-route": "^1.3", "nyholm/psr7": "^1.8", "psr/container": "^2.0", + "psr/http-message": "^1.1", "psr/http-server-middleware": "^1.0", "psr/log": "^3.0", - "psr/http-message": "^1.1", "rcrowe/twigbridge": "^0.14.0", "respect/validation": "^1.1", "symfony/http-foundation": "^6.3", diff --git a/composer.lock b/composer.lock index 229201ef..9c89acaa 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": "e0d1151ec998274861b46a7a7393a64e", + "content-hash": "8fff41c785b41238209e086e390539c7", "packages": [ { "name": "brick/math", @@ -61,6 +61,80 @@ ], "time": "2023-01-15T23:15:59+00:00" }, + { + "name": "devizzent/cebe-php-openapi", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/DEVizzent/cebe-php-openapi.git", + "reference": "de3a406a1fa5daa275da3f6aed6765c170de7954" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DEVizzent/cebe-php-openapi/zipball/de3a406a1fa5daa275da3f6aed6765c170de7954", + "reference": "de3a406a1fa5daa275da3f6aed6765c170de7954", + "shasum": "" + }, + "require": { + "ext-json": "*", + "justinrainbow/json-schema": "^5.2", + "php": ">=7.1.0", + "symfony/yaml": "^3.4 || ^4 || ^5 || ^6" + }, + "conflict": { + "symfony/yaml": "3.4.0 - 3.4.4 || 4.0.0 - 4.4.17 || 5.0.0 - 5.1.9 || 5.2.0" + }, + "require-dev": { + "apis-guru/openapi-directory": "1.0.0", + "cebe/indent": "*", + "mermade/openapi3-examples": "1.0.0", + "nexmo/api-specification": "1.0.0", + "oai/openapi-specification-3.0": "3.0.3", + "oai/openapi-specification-3.1": "3.1.0", + "phpstan/phpstan": "^0.12.0", + "phpunit/phpunit": "^6.5 || ^7.5 || ^8.5 || ^9.4" + }, + "bin": [ + "bin/php-openapi" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "cebe\\openapi\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "https://cebe.cc/", + "role": "Creator" + }, + { + "name": "Vicent Valls", + "email": "vizzent@gmail.com" + } + ], + "description": "Read and write OpenAPI yaml/json files and make the content accessable in PHP objects.", + "homepage": "https://github.com/DEVizzent/cebe-php-openapi#readme", + "keywords": [ + "openapi" + ], + "support": { + "issues": "https://github.com/DEVizzent/cebe-php-openapi/issues", + "source": "https://github.com/DEVizzent/cebe-php-openapi" + }, + "time": "2023-10-26T20:41:58+00:00" + }, { "name": "doctrine/cache", "version": "2.2.0", @@ -156,16 +230,16 @@ }, { "name": "doctrine/dbal", - "version": "3.6.6", + "version": "3.7.1", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "63646ffd71d1676d2f747f871be31b7e921c7864" + "reference": "5b7bd66c9ff58c04c5474ab85edce442f8081cb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/63646ffd71d1676d2f747f871be31b7e921c7864", - "reference": "63646ffd71d1676d2f747f871be31b7e921c7864", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/5b7bd66c9ff58c04c5474ab85edce442f8081cb2", + "reference": "5b7bd66c9ff58c04c5474ab85edce442f8081cb2", "shasum": "" }, "require": { @@ -181,9 +255,9 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.29", + "phpstan/phpstan": "1.10.35", "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.9", + "phpunit/phpunit": "9.6.13", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", "squizlabs/php_codesniffer": "3.7.2", @@ -249,7 +323,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.6.6" + "source": "https://github.com/doctrine/dbal/tree/3.7.1" }, "funding": [ { @@ -265,20 +339,20 @@ "type": "tidelift" } ], - "time": "2023-08-17T05:38:17+00:00" + "time": "2023-10-06T05:06:20+00:00" }, { "name": "doctrine/deprecations", - "version": "v1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", - "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", "shasum": "" }, "require": { @@ -310,9 +384,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + "source": "https://github.com/doctrine/deprecations/tree/1.1.2" }, - "time": "2023-06-03T09:27:29+00:00" + "time": "2023-09-27T20:04:15+00:00" }, { "name": "doctrine/event-manager", @@ -575,16 +649,16 @@ }, { "name": "egulias/email-validator", - "version": "4.0.1", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff" + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/3a85486b709bc384dae8eb78fb2eec649bdb64ff", - "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", "shasum": "" }, "require": { @@ -593,8 +667,8 @@ "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^4.30" + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -630,7 +704,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.1" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" }, "funding": [ { @@ -638,7 +712,7 @@ "type": "github" } ], - "time": "2023-01-14T14:17:03+00:00" + "time": "2023-10-06T06:47:41+00:00" }, { "name": "erusev/parsedown", @@ -1301,7 +1375,7 @@ }, { "name": "illuminate/bus", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/bus.git", @@ -1354,16 +1428,16 @@ }, { "name": "illuminate/collections", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "939a975daa8a5f77974ffa6a24067f5e947683f4" + "reference": "bb8784ce913bd46f944b4bd67cd857f40d9cfe68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/939a975daa8a5f77974ffa6a24067f5e947683f4", - "reference": "939a975daa8a5f77974ffa6a24067f5e947683f4", + "url": "https://api.github.com/repos/illuminate/collections/zipball/bb8784ce913bd46f944b4bd67cd857f40d9cfe68", + "reference": "bb8784ce913bd46f944b4bd67cd857f40d9cfe68", "shasum": "" }, "require": { @@ -1405,11 +1479,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-18T18:32:31+00:00" + "time": "2023-10-10T12:55:25+00:00" }, { "name": "illuminate/conditionable", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -1455,7 +1529,7 @@ }, { "name": "illuminate/container", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", @@ -1506,16 +1580,16 @@ }, { "name": "illuminate/contracts", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "6c39fba7b2311e28f5c6ac7d729e3d49a2a98406" + "reference": "f6bf37a272fda164f6c451407c99f820eb1eb95b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/6c39fba7b2311e28f5c6ac7d729e3d49a2a98406", - "reference": "6c39fba7b2311e28f5c6ac7d729e3d49a2a98406", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/f6bf37a272fda164f6c451407c99f820eb1eb95b", + "reference": "f6bf37a272fda164f6c451407c99f820eb1eb95b", "shasum": "" }, "require": { @@ -1550,20 +1624,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-05T19:07:46+00:00" + "time": "2023-10-30T00:59:22+00:00" }, { "name": "illuminate/database", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/database.git", - "reference": "dbf15dca652e25f2bd9607e78dc527464edbec1d" + "reference": "1cd72b9404b41c3ed4c9d443679e8016030ae82b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/database/zipball/dbf15dca652e25f2bd9607e78dc527464edbec1d", - "reference": "dbf15dca652e25f2bd9607e78dc527464edbec1d", + "url": "https://api.github.com/repos/illuminate/database/zipball/1cd72b9404b41c3ed4c9d443679e8016030ae82b", + "reference": "1cd72b9404b41c3ed4c9d443679e8016030ae82b", "shasum": "" }, "require": { @@ -1619,20 +1693,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-19T14:11:01+00:00" + "time": "2023-10-30T14:29:38+00:00" }, { "name": "illuminate/events", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/events.git", - "reference": "e8cbfa31e1ada8d178ffcd7a5e26e101ec280c59" + "reference": "8d84d6220a6b3446a0bf3e4138e2eb0e10792bb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/events/zipball/e8cbfa31e1ada8d178ffcd7a5e26e101ec280c59", - "reference": "e8cbfa31e1ada8d178ffcd7a5e26e101ec280c59", + "url": "https://api.github.com/repos/illuminate/events/zipball/8d84d6220a6b3446a0bf3e4138e2eb0e10792bb1", + "reference": "8d84d6220a6b3446a0bf3e4138e2eb0e10792bb1", "shasum": "" }, "require": { @@ -1674,11 +1748,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-08-11T15:02:04+00:00" + "time": "2023-10-30T00:59:35+00:00" }, { "name": "illuminate/filesystem", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", @@ -1742,7 +1816,7 @@ }, { "name": "illuminate/macroable", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -1788,7 +1862,7 @@ }, { "name": "illuminate/pipeline", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/pipeline.git", @@ -1836,16 +1910,16 @@ }, { "name": "illuminate/support", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "f3ac48a059e3f1a0cb72c926f83a77af77d7a7f3" + "reference": "5244b825e8988db7c91254c31ce224dc3892eeae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/f3ac48a059e3f1a0cb72c926f83a77af77d7a7f3", - "reference": "f3ac48a059e3f1a0cb72c926f83a77af77d7a7f3", + "url": "https://api.github.com/repos/illuminate/support/zipball/5244b825e8988db7c91254c31ce224dc3892eeae", + "reference": "5244b825e8988db7c91254c31ce224dc3892eeae", "shasum": "" }, "require": { @@ -1903,20 +1977,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-19T14:13:21+00:00" + "time": "2023-10-30T01:00:17+00:00" }, { "name": "illuminate/view", - "version": "v10.24.0", + "version": "v10.30.1", "source": { "type": "git", "url": "https://github.com/illuminate/view.git", - "reference": "a0636443ddffc49218abaff50247f7404d9394b7" + "reference": "482ea8ac83bb4290b7f65ac086bd52b27b9bec48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/view/zipball/a0636443ddffc49218abaff50247f7404d9394b7", - "reference": "a0636443ddffc49218abaff50247f7404d9394b7", + "url": "https://api.github.com/repos/illuminate/view/zipball/482ea8ac83bb4290b7f65ac086bd52b27b9bec48", + "reference": "482ea8ac83bb4290b7f65ac086bd52b27b9bec48", "shasum": "" }, "require": { @@ -1957,7 +2031,77 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-09-13T18:10:09+00:00" + "time": "2023-10-13T14:15:52+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "v5.2.13", + "source": { + "type": "git", + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793", + "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/v5.2.13" + }, + "time": "2023-09-26T02:20:38+00:00" }, { "name": "league/oauth2-client", @@ -2030,17 +2174,250 @@ "time": "2023-04-16T18:19:15+00:00" }, { - "name": "nesbot/carbon", - "version": "2.70.0", + "name": "league/openapi-psr7-validator", + "version": "0.21", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "d3298b38ea8612e5f77d38d1a99438e42f70341d" + "url": "https://github.com/thephpleague/openapi-psr7-validator.git", + "reference": "bccdd3f5037c796fff3ef3f11dcf8c073aaa6192" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d3298b38ea8612e5f77d38d1a99438e42f70341d", - "reference": "d3298b38ea8612e5f77d38d1a99438e42f70341d", + "url": "https://api.github.com/repos/thephpleague/openapi-psr7-validator/zipball/bccdd3f5037c796fff3ef3f11dcf8c073aaa6192", + "reference": "bccdd3f5037c796fff3ef3f11dcf8c073aaa6192", + "shasum": "" + }, + "require": { + "devizzent/cebe-php-openapi": "^1.0", + "ext-json": "*", + "league/uri": "^6.3", + "php": ">=7.2", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/http-message": "^1.0", + "psr/http-server-middleware": "^1.0", + "respect/validation": "^1.1.3 || ^2.0", + "riverline/multipart-parser": "^2.0.3", + "symfony/polyfill-php80": "^1.27", + "webmozart/assert": "^1.4" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "guzzlehttp/psr7": "^1.5", + "hansott/psr7-cookies": "^3.0.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-webmozart-assert": "^1", + "phpunit/phpunit": "^7 || ^8 || ^9", + "symfony/cache": "^5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\OpenAPIValidation\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Validate PSR-7 messages against OpenAPI (3.0.2) specifications expressed in YAML or JSON", + "homepage": "https://github.com/thephpleague/openapi-psr7-validator", + "keywords": [ + "http", + "openapi", + "psr7", + "validation" + ], + "support": { + "issues": "https://github.com/thephpleague/openapi-psr7-validator/issues", + "source": "https://github.com/thephpleague/openapi-psr7-validator/tree/0.21" + }, + "time": "2023-04-03T21:49:07+00:00" + }, + { + "name": "league/uri", + "version": "6.8.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/a700b4656e4c54371b799ac61e300ab25a2d1d39", + "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39", + "shasum": "" + }, + "require": { + "ext-json": "*", + "league/uri-interfaces": "^2.3", + "php": "^8.1", + "psr/http-message": "^1.0.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v3.9.5", + "nyholm/psr7": "^1.5.1", + "php-http/psr7-integration-tests": "^1.1.1", + "phpbench/phpbench": "^1.2.6", + "phpstan/phpstan": "^1.8.5", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.1.1", + "phpstan/phpstan-strict-rules": "^1.4.3", + "phpunit/phpunit": "^9.5.24", + "psr/http-factory": "^1.0.1" + }, + "suggest": { + "ext-fileinfo": "Needed to create Data URI from a filepath", + "ext-intl": "Needed to improve host validation", + "league/uri-components": "Needed to easily manipulate URI objects", + "psr/http-factory": "Needed to use the URI factory" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri/issues", + "source": "https://github.com/thephpleague/uri/tree/6.8.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2022-09-13T19:58:47+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", + "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19", + "phpstan/phpstan": "^0.12.90", + "phpstan/phpstan-phpunit": "^0.12.19", + "phpstan/phpstan-strict-rules": "^0.12.9", + "phpunit/phpunit": "^8.5.15 || ^9.5" + }, + "suggest": { + "ext-intl": "to use the IDNA feature", + "symfony/intl": "to use the IDNA feature via Symfony Polyfill" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interface for URI representation", + "homepage": "http://github.com/thephpleague/uri-interfaces", + "keywords": [ + "rfc3986", + "rfc3987", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/thephpleague/uri-interfaces/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2021-06-28T04:27:21+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.71.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "98276233188583f2ff845a0f992a235472d9466a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/98276233188583f2ff845a0f992a235472d9466a", + "reference": "98276233188583f2ff845a0f992a235472d9466a", "shasum": "" }, "require": { @@ -2133,7 +2510,7 @@ "type": "tidelift" } ], - "time": "2023-09-07T16:43:50+00:00" + "time": "2023-09-25T11:31:05+00:00" }, { "name": "nikic/fast-route", @@ -2590,16 +2967,16 @@ }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { @@ -2636,9 +3013,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", @@ -3149,6 +3526,62 @@ }, "time": "2019-05-28T06:10:06+00:00" }, + { + "name": "riverline/multipart-parser", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/Riverline/multipart-parser.git", + "reference": "2418bdfc2eab01e39bcffee808b1a365c166292a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Riverline/multipart-parser/zipball/2418bdfc2eab01e39bcffee808b1a365c166292a", + "reference": "2418bdfc2eab01e39bcffee808b1a365c166292a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.6.0" + }, + "require-dev": { + "laminas/laminas-diactoros": "^1.8.7 || ^2.11.1", + "phpunit/phpunit": "^5.7 || ^9.0", + "psr/http-message": "^1.0", + "symfony/psr-http-message-bridge": "^1.1 || ^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Riverline\\MultiPartParser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Romain Cambien", + "email": "romain@cambien.net" + }, + { + "name": "Riverline", + "homepage": "http://www.riverline.fr" + } + ], + "description": "One class library to parse multipart content with encoding and charset support.", + "keywords": [ + "http", + "multipart", + "parser" + ], + "support": { + "issues": "https://github.com/Riverline/multipart-parser/issues", + "source": "https://github.com/Riverline/multipart-parser/tree/2.1.1" + }, + "time": "2023-04-28T18:53:59+00:00" + }, { "name": "symfony/deprecation-contracts", "version": "v3.3.0", @@ -3374,16 +3807,16 @@ }, { "name": "symfony/finder", - "version": "v6.3.3", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e" + "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9915db259f67d21eefee768c1abcf1cc61b1fc9e", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e", + "url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4", + "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4", "shasum": "" }, "require": { @@ -3418,7 +3851,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.3" + "source": "https://github.com/symfony/finder/tree/v6.3.5" }, "funding": [ { @@ -3434,20 +3867,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T08:31:44+00:00" + "time": "2023-09-26T12:56:25+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.3.4", + "version": "v6.3.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "cac1556fdfdf6719668181974104e6fcfa60e844" + "reference": "59d1837d5d992d16c2628cd0d6b76acf8d69b33e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cac1556fdfdf6719668181974104e6fcfa60e844", - "reference": "cac1556fdfdf6719668181974104e6fcfa60e844", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/59d1837d5d992d16c2628cd0d6b76acf8d69b33e", + "reference": "59d1837d5d992d16c2628cd0d6b76acf8d69b33e", "shasum": "" }, "require": { @@ -3457,12 +3890,12 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.2" + "symfony/cache": "<6.3" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3.0", + "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^5.4|^6.0", + "symfony/cache": "^6.3", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", @@ -3495,7 +3928,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.3.4" + "source": "https://github.com/symfony/http-foundation/tree/v6.3.7" }, "funding": [ { @@ -3511,20 +3944,20 @@ "type": "tidelift" } ], - "time": "2023-08-22T08:20:46+00:00" + "time": "2023-10-28T23:55:27+00:00" }, { "name": "symfony/mailer", - "version": "v6.3.0", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435" + "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/7b03d9be1dea29bfec0a6c7b603f5072a4c97435", - "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435", + "url": "https://api.github.com/repos/symfony/mailer/zipball/d89611a7830d51b5e118bca38e390dea92f9ea06", + "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06", "shasum": "" }, "require": { @@ -3575,7 +4008,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.3.0" + "source": "https://github.com/symfony/mailer/tree/v6.3.5" }, "funding": [ { @@ -3591,20 +4024,20 @@ "type": "tidelift" } ], - "time": "2023-05-29T12:49:39+00:00" + "time": "2023-09-06T09:47:15+00:00" }, { "name": "symfony/mime", - "version": "v6.3.3", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "9a0cbd52baa5ba5a5b1f0cacc59466f194730f98" + "reference": "d5179eedf1cb2946dbd760475ebf05c251ef6a6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/9a0cbd52baa5ba5a5b1f0cacc59466f194730f98", - "reference": "9a0cbd52baa5ba5a5b1f0cacc59466f194730f98", + "url": "https://api.github.com/repos/symfony/mime/zipball/d5179eedf1cb2946dbd760475ebf05c251ef6a6e", + "reference": "d5179eedf1cb2946dbd760475ebf05c251ef6a6e", "shasum": "" }, "require": { @@ -3659,7 +4092,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.3.3" + "source": "https://github.com/symfony/mime/tree/v6.3.5" }, "funding": [ { @@ -3675,7 +4108,7 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-09-29T06:59:36+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4425,16 +4858,16 @@ }, { "name": "symfony/translation", - "version": "v6.3.3", + "version": "v6.3.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd" + "reference": "30212e7c87dcb79c83f6362b00bde0e0b1213499" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd", - "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd", + "url": "https://api.github.com/repos/symfony/translation/zipball/30212e7c87dcb79c83f6362b00bde0e0b1213499", + "reference": "30212e7c87dcb79c83f6362b00bde0e0b1213499", "shasum": "" }, "require": { @@ -4500,7 +4933,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.3.3" + "source": "https://github.com/symfony/translation/tree/v6.3.7" }, "funding": [ { @@ -4516,7 +4949,7 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-10-28T23:11:45+00:00" }, { "name": "symfony/translation-contracts", @@ -4596,6 +5029,78 @@ ], "time": "2023-05-30T17:17:10+00:00" }, + { + "name": "symfony/yaml", + "version": "v6.3.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "9758b6c69d179936435d0ffb577c3708d57e38a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/9758b6c69d179936435d0ffb577c3708d57e38a8", + "reference": "9758b6c69d179936435d0ffb577c3708d57e38a8", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.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/v6.3.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-10-28T23:31:00+00:00" + }, { "name": "twig/twig", "version": "v3.7.1", @@ -4824,6 +5329,64 @@ } ], "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "packages-dev": [ @@ -5135,16 +5698,16 @@ }, { "name": "filp/whoops", - "version": "2.15.3", + "version": "2.15.4", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "c83e88a30524f9360b11f585f71e6b17313b7187" + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187", - "reference": "c83e88a30524f9360b11f585f71e6b17313b7187", + "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", "shasum": "" }, "require": { @@ -5194,7 +5757,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.15.3" + "source": "https://github.com/filp/whoops/tree/2.15.4" }, "funding": [ { @@ -5202,7 +5765,7 @@ "type": "github" } ], - "time": "2023-07-13T12:00:00+00:00" + "time": "2023-11-03T12:00:00+00:00" }, { "name": "myclabs/deep-copy", @@ -5432,16 +5995,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.1", + "version": "1.24.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01" + "reference": "bcad8d995980440892759db0c32acae7c8e79442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", - "reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442", + "reference": "bcad8d995980440892759db0c32acae7c8e79442", "shasum": "" }, "require": { @@ -5473,22 +6036,22 @@ "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/1.24.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2" }, - "time": "2023-09-18T12:18:02+00:00" + "time": "2023-09-26T12:28:12+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.35", + "version": "1.10.40", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3" + "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e730e5facb75ffe09dfb229795e8c01a459f26c3", - "reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d", + "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d", "shasum": "" }, "require": { @@ -5537,7 +6100,7 @@ "type": "tidelift" } ], - "time": "2023-09-19T15:27:56+00:00" + "time": "2023-10-30T14:48:31+00:00" }, { "name": "phpunit/php-code-coverage", @@ -6927,32 +7490,32 @@ }, { "name": "slevomat/coding-standard", - "version": "8.13.4", + "version": "8.14.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "4b2af2fb17773656d02fbfb5d18024ebd19fe322" + "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/4b2af2fb17773656d02fbfb5d18024ebd19fe322", - "reference": "4b2af2fb17773656d02fbfb5d18024ebd19fe322", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/fea1fd6f137cc84f9cba0ae30d549615dbc6a926", + "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.23.0", + "phpstan/phpdoc-parser": "^1.23.1", "squizlabs/php_codesniffer": "^3.7.1" }, "require-dev": { "phing/phing": "2.17.4", "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.10.26", - "phpstan/phpstan-deprecation-rules": "1.1.3", - "phpstan/phpstan-phpunit": "1.3.13", + "phpstan/phpstan": "1.10.37", + "phpstan/phpstan-deprecation-rules": "1.1.4", + "phpstan/phpstan-phpunit": "1.3.14", "phpstan/phpstan-strict-rules": "1.5.1", - "phpunit/phpunit": "7.5.20|8.5.21|9.6.8|10.2.6" + "phpunit/phpunit": "8.5.21|9.6.8|10.3.5" }, "type": "phpcodesniffer-standard", "extra": { @@ -6976,7 +7539,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.13.4" + "source": "https://github.com/slevomat/coding-standard/tree/8.14.1" }, "funding": [ { @@ -6988,7 +7551,7 @@ "type": "tidelift" } ], - "time": "2023-07-25T10:28:55+00:00" + "time": "2023-10-08T07:28:08+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -7049,16 +7612,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.3.4", + "version": "v6.3.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45" + "reference": "999ede244507c32b8e43aebaa10e9fce20de7c97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2027be14f8ae8eae999ceadebcda5b4909b81d45", - "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/999ede244507c32b8e43aebaa10e9fce20de7c97", + "reference": "999ede244507c32b8e43aebaa10e9fce20de7c97", "shasum": "" }, "require": { @@ -7113,7 +7676,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.3.4" + "source": "https://github.com/symfony/var-dumper/tree/v6.3.6" }, "funding": [ { @@ -7129,7 +7692,7 @@ "type": "tidelift" } ], - "time": "2023-08-24T14:51:05+00:00" + "time": "2023-10-12T18:45:56+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/routes.php b/config/routes.php index 389338d1..7e188818 100644 --- a/config/routes.php +++ b/config/routes.php @@ -108,7 +108,29 @@ $route->addGroup( ); // API -$route->get('/api[/{resource:.+}]', 'ApiController@index'); +$route->addGroup( + '/api', + function (RouteCollector $route): void { + $route->get('/', 'ApiController@index'); + + $route->addGroup( + '/v0-beta', + function (RouteCollector $route): void { + $route->addRoute(['OPTIONS'], '[/{resource:.+}]', 'ApiController@options'); + $route->get('/', 'ApiController@indexV0'); + + $route->get('/news', 'ApiController@news'); + + $route->addRoute( + ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'], + '[/{resource:.+}]', + 'ApiController@notImplemented' + ); + } + ); + $route->get('[/{resource:.+}]', 'ApiController@notImplemented'); + } +); // Feeds $route->get('/atom', 'FeedController@atom'); diff --git a/db/migrations/2023_05_21_000000_create_api_permissions.php b/db/migrations/2023_05_21_000000_create_api_permissions.php new file mode 100644 index 00000000..8c9b8702 --- /dev/null +++ b/db/migrations/2023_05_21_000000_create_api_permissions.php @@ -0,0 +1,45 @@ +schema->getConnection(); + $db->table('privileges')->insert([ + ['name' => 'api', 'description' => 'Use the API'], + ]); + $db->table('groups')->insert([ + ['id' => 40, 'name' => 'API'], + ]); + + $bureaucratGroup = 80; + $apiId = $db->table('privileges')->where('name', 'api')->first()->id; + $db->table('group_privileges')->insert([ + ['group_id' => $bureaucratGroup, 'privilege_id' => $apiId], + ['group_id' => 40, 'privilege_id' => $apiId], + ]); + } + + /** + * Reverse the migration + */ + public function down(): void + { + $db = $this->schema->getConnection(); + $db->table('privileges') + ->where('name', 'api') + ->delete(); + $db->table('groups') + ->where('id', 40) + ->delete(); + } +} diff --git a/resources/api/openapi.yml b/resources/api/openapi.yml new file mode 100644 index 00000000..2da287f3 --- /dev/null +++ b/resources/api/openapi.yml @@ -0,0 +1,96 @@ +openapi: 3.0.3 + +info: + version: 0.0.1-beta + title: Engelsystem + description: | + This API description is as stable as a **beta** version might be. + It could burst into flames and morph into a monster at any second! + (But we try to keep it somewhat consistent, at least during events). + contact: + name: GitHub Issues + url: https://github.com/engelsystem/engelsystem/issues + license: + name: GPL 2.0 + # identifier: GPL-2.0 + +servers: + - url: /api/v0-beta + description: This server + - url: http://localhost:5080/api/v0-beta + description: Your local dev instance + +tags: + - name: news + description: News and Meeting announcements + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: API key from settings + + responses: + UnauthorizedError: + description: Access token is missing or invalid + ForbiddenError: + description: The client is not allowed to acces + + schemas: + News: + type: object + properties: + id: + type: integer + example: 42 + title: + type: string + example: First helper introduction + text: + type: string + example: | + The first introduction meeting takes place at the **Foo Hall** at 13:37. + Please bring your own seating as it might take some time. + is_meeting: + type: boolean + example: true + description: Whether or not the news announces a meeting + is_pinned: + type: boolean + example: false + description: True if the news is pinned to the top + is_highlighted: + type: boolean + example: false + description: True if the news should be highlightet and shown on the dashboard + created_at: + type: string + example: 2023-05-13T13:37:42.000000Z + updated_at: + type: string + nullable: true + example: 2023-05-13T23:00:00.000000Z + +security: + - bearerAuth: [ ] + +paths: + /news: + get: + tags: + - news + summary: Get a list of all news + responses: + '200': + description: Ok + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/News' + '401': + $ref: '#/components/responses/UnauthorizedError' + '403': + $ref: '#/components/responses/ForbiddenError' diff --git a/resources/api/readme.md b/resources/api/readme.md new file mode 100644 index 00000000..786cc614 --- /dev/null +++ b/resources/api/readme.md @@ -0,0 +1,6 @@ +# Engelsystem API documentation +Here you can find the OpenAPI files that describe the Engelsystem API. +Please be aware that the API is still in Beta and might change every second (but we try to keep it consistent during events ;)) + +## Links +* [OpenAPI Spec](https://swagger.io/specification/) diff --git a/src/Application.php b/src/Application.php index cbc014e2..87cfacfb 100644 --- a/src/Application.php +++ b/src/Application.php @@ -101,6 +101,7 @@ class Application extends Container $this->instance('path', $appPath); $this->instance('path.config', $appPath . DIRECTORY_SEPARATOR . 'config'); $this->instance('path.resources', $appPath . DIRECTORY_SEPARATOR . 'resources'); + $this->instance('path.resources.api', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'api'); $this->instance('path.public', $appPath . DIRECTORY_SEPARATOR . 'public'); $this->instance('path.assets', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'assets'); $this->instance('path.assets.public', $this->get('path.public') . DIRECTORY_SEPARATOR . 'assets'); diff --git a/src/Controllers/ApiController.php b/src/Controllers/ApiController.php index e257b426..2c5a4c9c 100644 --- a/src/Controllers/ApiController.php +++ b/src/Controllers/ApiController.php @@ -5,18 +5,66 @@ declare(strict_types=1); namespace Engelsystem\Controllers; use Engelsystem\Http\Response; +use Engelsystem\Models\News; class ApiController extends BaseController { + public array $permissions = [ + 'api', + ]; + public function __construct(protected Response $response) { + $this->response = $this->response + ->withHeader('content-type', 'application/json') + ->withHeader('Access-Control-Allow-Origin', '*'); } public function index(): Response + { + return $this->response + ->withContent(json_encode([ + 'versions' => [ + '0.0.1-beta' => '/v0-beta', + ], + ])); + } + + public function indexV0(): Response + { + return $this->response + ->withContent(json_encode([ + 'version' => '0.0.1-beta', + 'description' => 'Beta API, might break any second.', + 'paths' => [ + '/news', + ], + ])); + } + + public function options(): Response + { + return $this->response + ->setStatusCode(204) + ->withHeader('Allow', 'OPTIONS, HEAD, GET') + ->withHeader('Access-Control-Allow-Headers', 'Authorization'); + } + + public function notImplemented(): Response { return $this->response ->setStatusCode(501) - ->withHeader('content-type', 'application/json') ->withContent(json_encode(['error' => 'Not implemented'])); } + + public function news(): Response + { + $news = News::query() + ->orderByDesc('updated_at') + ->orderByDesc('created_at') + ->get(['id', 'title', 'text', 'is_meeting', 'is_pinned', 'is_highlighted', 'created_at', 'updated_at']); + + return $this->response + ->withContent(json_encode($news)); + } } diff --git a/src/Middleware/SessionHandler.php b/src/Middleware/SessionHandler.php index e66559a1..bf75c0e2 100644 --- a/src/Middleware/SessionHandler.php +++ b/src/Middleware/SessionHandler.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Engelsystem\Middleware; +use Illuminate\Support\Str; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -13,14 +14,18 @@ use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; class SessionHandler implements MiddlewareInterface { - public function __construct(protected SessionStorageInterface $session, protected array $paths = []) - { + public function __construct( + protected SessionStorageInterface $session, + protected array $paths = [], + protected ?string $apiPrefix = null + ) { } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $requestPath = $request->getAttribute('route-request-path'); - $isApi = in_array($requestPath, $this->paths); + $isApi = in_array($requestPath, $this->paths) + || ($this->apiPrefix && Str::startsWith($requestPath, $this->apiPrefix)); $request = $request->withAttribute('route-api', $isApi); $return = $handler->handle($request); diff --git a/src/Middleware/SessionHandlerServiceProvider.php b/src/Middleware/SessionHandlerServiceProvider.php index 97e9145d..808fdc4c 100644 --- a/src/Middleware/SessionHandlerServiceProvider.php +++ b/src/Middleware/SessionHandlerServiceProvider.php @@ -15,7 +15,6 @@ class SessionHandlerServiceProvider extends ServiceProvider ->needs('$paths') ->give(function () { return [ - '/api', '/atom', '/rss', '/health', @@ -25,5 +24,9 @@ class SessionHandlerServiceProvider extends ServiceProvider '/stats', ]; }); + $this->app + ->when(SessionHandler::class) + ->needs('$apiPrefix') + ->give('/api'); } } diff --git a/tests/Unit/ApplicationTest.php b/tests/Unit/ApplicationTest.php index 547eace3..f929acf6 100644 --- a/tests/Unit/ApplicationTest.php +++ b/tests/Unit/ApplicationTest.php @@ -52,6 +52,7 @@ class ApplicationTest extends TestCase $this->assertTrue($app->has('path.config')); $this->assertTrue($app->has('path.lang')); $this->assertTrue($app->has('path.resources')); + $this->assertTrue($app->has('path.resources.api')); $this->assertTrue($app->has('path.views')); $this->assertTrue($app->has('path.storage')); $this->assertTrue($app->has('path.cache')); diff --git a/tests/Unit/Controllers/ApiControllerTest.php b/tests/Unit/Controllers/ApiControllerTest.php index fce58a7d..72430bb1 100644 --- a/tests/Unit/Controllers/ApiControllerTest.php +++ b/tests/Unit/Controllers/ApiControllerTest.php @@ -6,10 +6,15 @@ namespace Engelsystem\Test\Unit\Controllers; use Engelsystem\Controllers\ApiController; use Engelsystem\Http\Response; -use PHPUnit\Framework\TestCase; +use Engelsystem\Models\News; +use League\OpenAPIValidation\PSR7\OperationAddress as OpenApiAddress; +use League\OpenAPIValidation\PSR7\ResponseValidator as OpenApiResponseValidator; +use League\OpenAPIValidation\PSR7\ValidatorBuilder; -class ApiControllerTest extends TestCase +class ApiControllerTest extends ControllerTest { + protected OpenApiResponseValidator $validator; + /** * @covers \Engelsystem\Controllers\ApiController::__construct * @covers \Engelsystem\Controllers\ApiController::index @@ -20,8 +25,89 @@ class ApiControllerTest extends TestCase $response = $controller->index(); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals(['application/json'], $response->getHeader('content-type')); + $this->assertEquals(['*'], $response->getHeader('Access-Control-Allow-Origin')); + $this->assertJson($response->getContent()); + + $data = json_decode($response->getContent(), true); + $this->assertArrayHasKey('versions', $data); + } + + /** + * @covers \Engelsystem\Controllers\ApiController::indexV0 + */ + public function testIndexV0(): void + { + $controller = new ApiController(new Response()); + + $response = $controller->indexV0(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertJson($response->getContent()); + + $data = json_decode($response->getContent(), true); + $this->assertArrayHasKey('version', $data); + $this->assertArrayHasKey('paths', $data); + } + + /** + * @covers \Engelsystem\Controllers\ApiController::options + */ + public function testOptions(): void + { + $controller = new ApiController(new Response()); + + $response = $controller->options(); + + $this->assertEquals(204, $response->getStatusCode()); + $this->assertNotEmpty($response->getHeader('Allow')); + $this->assertNotEmpty($response->getHeader('Access-Control-Allow-Headers')); + } + + /** + * @covers \Engelsystem\Controllers\ApiController::notImplemented + */ + public function testNotImplemented(): void + { + $controller = new ApiController(new Response()); + + $response = $controller->notImplemented(); + $this->assertEquals(501, $response->getStatusCode()); $this->assertEquals(['application/json'], $response->getHeader('content-type')); $this->assertJson($response->getContent()); } + + /** + * @covers \Engelsystem\Controllers\ApiController::news + */ + public function testNews(): void + { + $this->initDatabase(); + News::factory(3)->create(); + + $controller = new ApiController(new Response()); + + $response = $controller->news(); + + $operation = new OpenApiAddress('/news', 'get'); + $this->validator->validate($operation, $response); + + $this->assertEquals(['application/json'], $response->getHeader('content-type')); + $this->assertJson($response->getContent()); + + $data = json_decode($response->getContent(), true); + $this->assertCount(3, $data); + } + + public function setUp(): void + { + parent::setUp(); + + $openApiDefinition = $this->app->get('path.resources.api') . '/openapi.yml'; + $this->validator = (new ValidatorBuilder()) + ->fromYamlFile($openApiDefinition) + ->getResponseValidator(); + } }