diff --git a/.gitattributes b/.gitattributes index 73edd20..0707f51 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,5 +17,6 @@ CHANGELOG.md export-ignore docker-compose.override.yml.example export-ignore docker-compose.yml export-ignore +phpstan.neon.dist export-ignore phpunit.xml.dist export-ignore UPGRADE.md diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6aafc97..399e29f 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -9,12 +9,12 @@ jobs: strategy: matrix: php: - - "7.4" - "8.0" - "8.1" + - "8.2" services: db: - image: mongo:4.2 + image: mongo:5.0 ports: - "27017:27017" steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e9728..9328e6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,140 @@ # Release Notes -## [Unreleased](https://github.com/laravel/passport/compare/v10.4.0...10.x) +## [Unreleased](https://github.com/laravel/passport/compare/v11.8.3...11.x) + +## [v11.8.3](https://github.com/laravel/passport/compare/v11.8.2...v11.8.3) - 2023-03-01 + +- Allow overriding the `AccessToken` class by @hafezdivandari in https://github.com/laravel/passport/pull/1638 +- Make `$userId` nullable in `ClientRepository->createPersonalAccessClient` by @bram-pkg in https://github.com/laravel/passport/pull/1642 + +## [v11.8.2](https://github.com/laravel/passport/compare/v11.8.1...v11.8.2) - 2023-02-20 + +- Re-apply "Added AuthenticationException to extend the behaviour of Laravel's default exception handler" by @driesvints in https://github.com/laravel/passport/commit/67c3e336af163f6eba5dbca8e5db46275ff0e433 + +## [v11.8.1](https://github.com/laravel/passport/compare/v11.8.0...v11.8.1) - 2023-02-20 + +- Revert "Move AuthenticationException into the scope of Laravel Passport" by @driesvints in https://github.com/laravel/passport/commit/db543b0cc13ed3f56f1bffda04707fbe2a8c7ab5 + +## [v11.8.0](https://github.com/laravel/passport/compare/v11.7.0...v11.8.0) - 2023-02-17 + +- Move AuthenticationException into the scope of Laravel Passport by @chrispage1 in https://github.com/laravel/passport/pull/1633 +- Custom authorization view response by @JonErickson in https://github.com/laravel/passport/pull/1629 +- Fix deprecated $dates property by @TonyWong9527 in https://github.com/laravel/passport/pull/1636 + +## [v11.7.0](https://github.com/laravel/passport/compare/v11.6.1...v11.7.0) - 2023-02-08 + +### Added + +- Add support for `EncryptCookies` middleware by @axlon in https://github.com/laravel/passport/pull/1628 + +## [v11.6.1](https://github.com/laravel/passport/compare/v11.6.0...v11.6.1) - 2023-02-03 + +### Changed + +- Indicate current token can be `TransientToken` by @axlon in https://github.com/laravel/passport/pull/1627 + +## [v11.6.0](https://github.com/laravel/passport/compare/v11.5.1...v11.6.0) - 2023-01-31 + +### Changed + +- Update ClientCommand.php's user_id description by @Smoggert in https://github.com/laravel/passport/pull/1619 +- Get model PK instead of forcibly id column by @lucaspanik in https://github.com/laravel/passport/pull/1626 + +### Fixed + +- Fix doc block for `withAccessToken()` by @axlon in https://github.com/laravel/passport/pull/1620 + +## [v11.5.1](https://github.com/laravel/passport/compare/v11.5.0...v11.5.1) - 2023-01-16 + +### Fixed + +- Get authenticated user from the guard by @hafezdivandari in https://github.com/laravel/passport/pull/1617 + +## [v11.5.0](https://github.com/laravel/passport/compare/v11.4.0...v11.5.0) - 2023-01-09 + +### Added + +- Laravel v10 Support by @driesvints in https://github.com/laravel/passport/pull/1615 + +## [v11.4.0](https://github.com/laravel/passport/compare/v11.3.1...v11.4.0) - 2023-01-03 + +### Changed + +- Uses PHP Native Type Declarations 🐘 by @nunomaduro in https://github.com/laravel/passport/pull/1594 + +## [v11.3.1](https://github.com/laravel/passport/compare/v11.3.0...v11.3.1) - 2022-12-02 + +### Changed + +- Add auth guard to routes by @hafezdivandari in https://github.com/laravel/passport/pull/1603 + +## [v11.3.0](https://github.com/laravel/passport/compare/v11.2.1...v11.3.0) - 2022-10-22 + +### Added + +- Support prompting login when redirecting for authorization by @hafezdivandari in https://github.com/laravel/passport/pull/1577 + +### Changed + +- Update PurgeCommand.php by @fatoskurtishi in https://github.com/laravel/passport/pull/1586 +- Fix ClientRepository doc blocks by @axlon in https://github.com/laravel/passport/pull/1587 +- Update docblock by @mnabialek in https://github.com/laravel/passport/pull/1588 + +## [v11.2.1](https://github.com/laravel/passport/compare/v11.2.0...v11.2.1) - 2022-09-29 + +### Fixed + +- Improve token guard return type by @axlon in https://github.com/laravel/passport/pull/1579 + +## [v11.2.0](https://github.com/laravel/passport/compare/v11.1.0...v11.2.0) - 2022-09-07 + +### Changed + +- Let OAuth2 server handle the denying response by @hafezdivandari in https://github.com/laravel/passport/pull/1572 + +## [v11.1.0](https://github.com/laravel/passport/compare/v11.0.1...v11.1.0) - 2022-09-05 + +### Added + +- Support prompting re-consent when redirecting for authorization by @hafezdivandari in https://github.com/laravel/passport/pull/1567 +- Support disabling prompt when redirecting for authorization by @hafezdivandari in https://github.com/laravel/passport/pull/1569 + +## [v11.0.1](https://github.com/laravel/passport/compare/v11.0.0...v11.0.1) - 2022-08-29 + +### Changed + +- Custom days and hours to passport purge command by @rubengg86 in https://github.com/laravel/passport/pull/1563 +- Allow for bootstrapping without loading routes by @axlon in https://github.com/laravel/passport/pull/1564 + +## [v11.0.0](https://github.com/laravel/passport/compare/v10.4.1...v11.0.0) - 2022-08-19 + +### Added + +- Allow authenticated client to be retrieved from the guard by @axlon in https://github.com/laravel/passport/pull/1508 + +### Changed + +- Revert model DB connection customization by @driesvints in https://github.com/laravel/passport/pull/1412 +- Allow timestamps on Token model by @driesvints in https://github.com/laravel/passport/pull/1425 +- Improve authenticateViaBearerToken() performance by @alecpl in https://github.com/laravel/passport/pull/1447 +- Refactor routes to dedicated file by @driesvints in https://github.com/laravel/passport/pull/1464 + +### Fixed + +- Stub client on guard when calling Passport::actingAsClient() by @axlon in https://github.com/laravel/passport/pull/1519 +- Fix scope inheritance when using Passport::actingAs() by @axlon in https://github.com/laravel/passport/pull/1551 + +### Removed + +- Drop PHP 7.x and Laravel v8 by @driesvints in https://github.com/laravel/passport/pull/1558 +- Remove deprecated properties by @driesvints in https://github.com/laravel/passport/pull/1560 +- Remove deprecated functionality and simplify some feature tests by @driesvints in https://github.com/laravel/passport/pull/1559 + +## [v10.4.1](https://github.com/laravel/passport/compare/v10.4.0...v10.4.1) - 2022-04-16 + +### Changed + +- Add new URI Rule to validate URI and use it to RedirectRule. by @victorbalssa in https://github.com/laravel/passport/pull/1544 ## [v10.4.0](https://github.com/laravel/passport/compare/v10.3.3...v10.4.0) - 2022-03-30 diff --git a/README.md b/README.md index f141569..49c5324 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Documentation for Passport can be found on the [Laravel website](https://laravel | mongolid-passport | laravel-passport | mongolid-laravel | mongolid | |-------------------|------------------|------------------|----------| +| 12.0.0 | 11.8.4 | 3.5.0 | 3.5.x | | 11.1.0 | 10.4.1 | 3.4.0 | 3.4.x | | 11.0.0 | 10.1.1 | 3.0.0 | 3.1.x | | 10.x | 10.x | 2.3.x | 2.4.x | diff --git a/composer.json b/composer.json index 4fab64e..c4d98bf 100644 --- a/composer.json +++ b/composer.json @@ -18,32 +18,33 @@ } ], "require": { - "php": ">=7.4", + "php": "^8.0", "ext-json": "*", "ext-mongodb": "*", - "firebase/php-jwt": "^6.0", - "illuminate/auth": "^8.37|^9.0", - "illuminate/console": "^8.37|^9.0", - "illuminate/container": "^8.37|^9.0", - "illuminate/contracts": "^8.37|^9.0", - "illuminate/cookie": "^8.37|^9.0", - "illuminate/database": "^8.37|^9.0", - "illuminate/encryption": "^8.37|^9.0", - "illuminate/http": "^8.37|^9.0", - "illuminate/support": "^8.37|^9.0", + "firebase/php-jwt": "^6.3.1", + "illuminate/auth": "^9.0|^10.0", + "illuminate/console": "^9.0|^10.0", + "illuminate/container": "^9.0|^10.0", + "illuminate/contracts": "^9.0|^10.0", + "illuminate/cookie": "^9.0|^10.0", + "illuminate/database": "^9.0|^10.0", + "illuminate/encryption": "^9.0|^10.0", + "illuminate/http": "^9.0|^10.0", + "illuminate/support": "^9.0|^10.0", "lcobucci/jwt": "^3.4|^4.0", "league/oauth2-server": "^8.2", - "leroy-merlin-br/mongolid": "v3.4", - "leroy-merlin-br/mongolid-laravel": "v3.4", + "leroy-merlin-br/mongolid": "v3.5", + "leroy-merlin-br/mongolid-laravel": "v3.5", "mongodb/mongodb": "1.15.0", "nyholm/psr7": "^1.3", "phpseclib/phpseclib": "^2.0|^3.0", "symfony/psr-http-message-bridge": "^2.0" }, "require-dev": { - "mockery/mockery": "^1.5.1", - "orchestra/testbench": "^6.0|^7.0", - "phpunit/phpunit": "^9.5.27" + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.0|^8.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.3" }, "autoload": { "psr-4": { @@ -58,7 +59,7 @@ }, "extra": { "branch-alias": { - "dev-master": "10.x-dev" + "dev-master": "11.x-dev" }, "laravel": { "providers": [ @@ -70,7 +71,7 @@ "sort-packages": true }, "replace": { - "laravel/passport": "10.*" + "laravel/passport": "11.*" }, "minimum-stability": "dev", "prefer-stable": true diff --git a/composer.lock b/composer.lock index 7599738..e86d33d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,30 +4,29 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "92b002f399a68cb19bfecb5b807cf0f7", + "content-hash": "e0393221eb9bc812a47c13c7b040532d", "packages": [ { "name": "brick/math", - "version": "0.9.3", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae" + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae", - "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae", + "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478", + "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^7.1 || ^8.0" + "php": "^8.0" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", - "vimeo/psalm": "4.9.2" + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "5.0.0" }, "type": "library", "autoload": { @@ -52,32 +51,28 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.9.3" + "source": "https://github.com/brick/math/tree/0.11.0" }, "funding": [ { "url": "https://github.com/BenMorel", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/brick/math", - "type": "tidelift" } ], - "time": "2021-08-15T20:50:18+00:00" + "time": "2023-01-15T23:15:59+00:00" }, { "name": "defuse/php-encryption", - "version": "v2.3.1", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/defuse/php-encryption.git", - "reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2" + "reference": "f53396c2d34225064647a05ca76c1da9d99e5828" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/defuse/php-encryption/zipball/77880488b9954b7884c25555c2a0ea9e7053f9d2", - "reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/f53396c2d34225064647a05ca76c1da9d99e5828", + "reference": "f53396c2d34225064647a05ca76c1da9d99e5828", "shasum": "" }, "require": { @@ -86,7 +81,8 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "^4|^5|^6|^7|^8|^9" + "phpunit/phpunit": "^5|^6|^7|^8|^9|^10", + "yoast/phpunit-polyfills": "^2.0.0" }, "bin": [ "bin/generate-defuse-key" @@ -128,9 +124,9 @@ ], "support": { "issues": "https://github.com/defuse/php-encryption/issues", - "source": "https://github.com/defuse/php-encryption/tree/v2.3.1" + "source": "https://github.com/defuse/php-encryption/tree/v2.4.0" }, - "time": "2021-04-09T23:57:26+00:00" + "time": "2023-06-19T06:10:36+00:00" }, { "name": "dflydev/dot-access-data", @@ -207,30 +203,77 @@ }, "time": "2022-10-27T11:44:00+00:00" }, + { + "name": "doctrine/deprecations", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "time": "2023-06-03T09:27:29+00:00" + }, { "name": "doctrine/inflector", - "version": "2.0.6", + "version": "2.0.8", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024" + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^10", + "doctrine/coding-standard": "^11.0", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.3", "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25" + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", "autoload": { @@ -280,7 +323,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.6" + "source": "https://github.com/doctrine/inflector/tree/2.0.8" }, "funding": [ { @@ -296,35 +339,37 @@ "type": "tidelift" } ], - "time": "2022-10-20T09:10:12+00:00" + "time": "2023-06-16T13:40:37+00:00" }, { "name": "doctrine/lexer", - "version": "1.2.3", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.0", "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9.0", + "doctrine/coding-standard": "^9 || ^10", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -356,7 +401,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, "funding": [ { @@ -372,20 +417,20 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.2", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", "shasum": "" }, "require": { @@ -425,7 +470,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" }, "funding": [ { @@ -433,31 +478,30 @@ "type": "github" } ], - "time": "2022-09-10T18:51:20+00:00" + "time": "2023-08-10T19:36:49+00:00" }, { "name": "egulias/email-validator", - "version": "2.1.25", + "version": "3.2.6", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4" + "reference": "e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/0dbf5d78455d4d6a41d186da50adc1122ec066f4", - "reference": "0dbf5d78455d4d6a41d186da50adc1122ec066f4", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7", + "reference": "e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7", "shasum": "" }, "require": { - "doctrine/lexer": "^1.0.1", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.10" + "doctrine/lexer": "^1.2|^2", + "php": ">=7.2", + "symfony/polyfill-intl-idn": "^1.15" }, "require-dev": { - "dominicsayers/isemail": "^3.0.7", - "phpunit/phpunit": "^4.8.36|^7.5.15", - "satooshi/php-coveralls": "^1.0.1" + "phpunit/phpunit": "^8.5.8|^9.3.3", + "vimeo/psalm": "^4" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -465,7 +509,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -493,7 +537,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + "source": "https://github.com/egulias/EmailValidator/tree/3.2.6" }, "funding": [ { @@ -501,34 +545,35 @@ "type": "github" } ], - "time": "2020-12-29T14:50:06+00:00" + "time": "2023-06-01T07:04:22+00:00" }, { "name": "firebase/php-jwt", - "version": "v6.3.2", + "version": "v6.8.1", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "ea7dda77098b96e666c5ef382452f94841e439cd" + "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/ea7dda77098b96e666c5ef382452f94841e439cd", - "reference": "ea7dda77098b96e666c5ef382452f94841e439cd", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26", + "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26", "shasum": "" }, "require": { - "php": "^7.1||^8.0" + "php": "^7.4||^8.0" }, "require-dev": { "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", "psr/cache": "^1.0||^2.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0" }, "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" }, "type": "library", @@ -561,30 +606,101 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.3.2" + "source": "https://github.com/firebase/php-jwt/tree/v6.8.1" + }, + "time": "2023-07-14T18:33:00+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/58571acbaa5f9f462c9c77e911700ac66f446d4e", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } }, - "time": "2022-12-19T17:10:46+00:00" + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2022-02-20T15:07:15+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8" + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8", - "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", + "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9" + "phpoption/phpoption": "^1.9.1" }, "require-dev": { - "phpunit/phpunit": "^8.5.28 || ^9.5.21" + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" }, "type": "library", "autoload": { @@ -613,7 +729,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1" }, "funding": [ { @@ -625,7 +741,91 @@ "type": "tidelift" } ], - "time": "2022-07-30T15:56:11+00:00" + "time": "2023-02-25T20:23:15+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2", + "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.19 || ^9.5.8", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2021-10-07T12:57:01+00:00" }, { "name": "jean85/pretty-package-versions", @@ -688,56 +888,64 @@ }, { "name": "laravel/framework", - "version": "v8.83.27", + "version": "v9.52.15", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e1afe088b4ca613fb96dc57e6d8dbcb8cc2c6b49" + "reference": "e3350e87a52346af9cc655a3012d2175d2d05ad7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e1afe088b4ca613fb96dc57e6d8dbcb8cc2c6b49", - "reference": "e1afe088b4ca613fb96dc57e6d8dbcb8cc2c6b49", + "url": "https://api.github.com/repos/laravel/framework/zipball/e3350e87a52346af9cc655a3012d2175d2d05ad7", + "reference": "e3350e87a52346af9cc655a3012d2175d2d05ad7", "shasum": "" }, "require": { - "doctrine/inflector": "^1.4|^2.0", - "dragonmantank/cron-expression": "^3.0.2", - "egulias/email-validator": "^2.1.10", - "ext-json": "*", + "brick/math": "^0.9.3|^0.10.2|^0.11", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.3.2", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", "ext-mbstring": "*", "ext-openssl": "*", - "laravel/serializable-closure": "^1.0", - "league/commonmark": "^1.3|^2.0.2", - "league/flysystem": "^1.1", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/serializable-closure": "^1.2.2", + "league/commonmark": "^2.2.1", + "league/flysystem": "^3.8.0", "monolog/monolog": "^2.0", - "nesbot/carbon": "^2.53.1", - "opis/closure": "^3.6", - "php": "^7.3|^8.0", - "psr/container": "^1.0", - "psr/log": "^1.0|^2.0", - "psr/simple-cache": "^1.0", - "ramsey/uuid": "^4.2.2", - "swiftmailer/swiftmailer": "^6.3", - "symfony/console": "^5.4", - "symfony/error-handler": "^5.4", - "symfony/finder": "^5.4", - "symfony/http-foundation": "^5.4", - "symfony/http-kernel": "^5.4", - "symfony/mime": "^5.4", - "symfony/process": "^5.4", - "symfony/routing": "^5.4", - "symfony/var-dumper": "^5.4", - "tijsverkoyen/css-to-inline-styles": "^2.2.2", + "nesbot/carbon": "^2.62.1", + "nunomaduro/termwind": "^1.13", + "php": "^8.0.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^6.0.9", + "symfony/error-handler": "^6.0", + "symfony/finder": "^6.0", + "symfony/http-foundation": "^6.0", + "symfony/http-kernel": "^6.0", + "symfony/mailer": "^6.0", + "symfony/mime": "^6.0", + "symfony/process": "^6.0", + "symfony/routing": "^6.0", + "symfony/uid": "^6.0", + "symfony/var-dumper": "^6.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", "vlucas/phpdotenv": "^5.4.1", - "voku/portable-ascii": "^1.6.1" + "voku/portable-ascii": "^2.0" }, "conflict": { "tightenco/collect": "<5.5.33" }, "provide": { - "psr/container-implementation": "1.0", - "psr/simple-cache-implementation": "1.0" + "psr/container-implementation": "1.1|2.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" }, "replace": { "illuminate/auth": "self.version", @@ -745,6 +953,7 @@ "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/collections": "self.version", + "illuminate/conditionable": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", "illuminate/container": "self.version", @@ -773,53 +982,68 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "^3.198.1", + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.235.5", "doctrine/dbal": "^2.13.3|^3.1.4", - "filp/whoops": "^2.14.3", - "guzzlehttp/guzzle": "^6.5.5|^7.0.1", - "league/flysystem-cached-adapter": "^1.0", - "mockery/mockery": "^1.4.4", - "orchestra/testbench-core": "^6.27", + "ext-gmp": "*", + "fakerphp/faker": "^1.21", + "guzzlehttp/guzzle": "^7.5", + "league/flysystem-aws-s3-v3": "^3.0", + "league/flysystem-ftp": "^3.0", + "league/flysystem-path-prefixing": "^3.3", + "league/flysystem-read-only": "^3.3", + "league/flysystem-sftp-v3": "^3.0", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^7.24", "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^8.5.19|^9.5.8", - "predis/predis": "^1.1.9", - "symfony/cache": "^5.4" + "phpstan/phpdoc-parser": "^1.15", + "phpstan/phpstan": "^1.4.7", + "phpunit/phpunit": "^9.5.8", + "predis/predis": "^1.1.9|^2.0.2", + "symfony/cache": "^6.0", + "symfony/http-client": "^6.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.198.1).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", "brianium/paratest": "Required to run tests in parallel (^6.0).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", - "ext-bcmath": "Required to use the multiple_of validation rule.", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", "ext-memcached": "Required to use the memcache cache driver.", - "ext-pcntl": "Required to use all features of the queue worker.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", "ext-posix": "Required to use all features of the queue worker.", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", - "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).", + "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", "laravel/tinker": "Required to use the tinker console command (^2.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", - "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", - "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", - "mockery/mockery": "Required to use mocking (^1.4.4).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", + "league/flysystem-read-only": "Required to use read-only disks (^3.3)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "mockery/mockery": "Required to use mocking (^1.5.1).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", - "phpunit/phpunit": "Required to use assertions and run tests (^8.5.19|^9.5.8).", - "predis/predis": "Required to use the predis connector (^1.1.9).", + "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8).", + "predis/predis": "Required to use the predis connector (^1.1.9|^2.0.2).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0|^6.0|^7.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.4).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^5.4).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", - "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^6.0).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^6.0).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.0).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "8.x-dev" + "dev-master": "9.x-dev" } }, "autoload": { @@ -833,7 +1057,8 @@ "Illuminate\\": "src/Illuminate/", "Illuminate\\Support\\": [ "src/Illuminate/Macroable/", - "src/Illuminate/Collections/" + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" ] } }, @@ -857,20 +1082,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-12-08T15:28:55+00:00" + "time": "2023-08-08T14:28:40+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.2.2", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae" + "reference": "e5a3057a5591e1cfe8183034b0203921abe2c902" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/47afb7fae28ed29057fdca37e16a84f90cc62fae", - "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/e5a3057a5591e1cfe8183034b0203921abe2c902", + "reference": "e5a3057a5591e1cfe8183034b0203921abe2c902", "shasum": "" }, "require": { @@ -917,35 +1142,35 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2022-09-08T13:45:54+00:00" + "time": "2023-07-14T13:56:28+00:00" }, { "name": "lcobucci/clock", - "version": "2.0.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3" + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/353d83fe2e6ae95745b16b3d911813df6a05bfb3", - "reference": "353d83fe2e6ae95745b16b3d911813df6a05bfb3", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/fb533e093fd61321bfcbac08b131ce805fe183d3", + "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "php": "^8.0", + "stella-maris/clock": "^0.1.4" }, "require-dev": { - "infection/infection": "^0.17", - "lcobucci/coding-standard": "^6.0", - "phpstan/extension-installer": "^1.0", + "infection/infection": "^0.26", + "lcobucci/coding-standard": "^8.0", + "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^0.12", "phpstan/phpstan-deprecation-rules": "^0.12", "phpstan/phpstan-phpunit": "^0.12", "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/php-code-coverage": "9.1.4", - "phpunit/phpunit": "9.3.7" + "phpunit/phpunit": "^9.5" }, "type": "library", "autoload": { @@ -966,7 +1191,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/2.0.x" + "source": "https://github.com/lcobucci/clock/tree/2.2.0" }, "funding": [ { @@ -978,20 +1203,20 @@ "type": "patreon" } ], - "time": "2020-08-27T18:56:02+00:00" + "time": "2022-04-19T19:34:17+00:00" }, { "name": "lcobucci/jwt", - "version": "4.2.1", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "72ac6d807ee51a70ad376ee03a2387e8646e10f3" + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/72ac6d807ee51a70ad376ee03a2387e8646e10f3", - "reference": "72ac6d807ee51a70ad376ee03a2387e8646e10f3", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/4d7de2fe0d51a96418c0d04004986e410e87f6b4", + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4", "shasum": "" }, "require": { @@ -1000,7 +1225,7 @@ "ext-mbstring": "*", "ext-openssl": "*", "ext-sodium": "*", - "lcobucci/clock": "^2.0", + "lcobucci/clock": "^2.0 || ^3.0", "php": "^7.4 || ^8.0" }, "require-dev": { @@ -1040,7 +1265,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/4.2.1" + "source": "https://github.com/lcobucci/jwt/tree/4.3.0" }, "funding": [ { @@ -1052,20 +1277,20 @@ "type": "patreon" } ], - "time": "2022-08-19T23:14:07+00:00" + "time": "2023-01-02T13:28:00+00:00" }, { "name": "league/commonmark", - "version": "2.3.8", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "c493585c130544c4e91d2e0e131e6d35cb0cbc47" + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c493585c130544c4e91d2e0e131e6d35cb0cbc47", - "reference": "c493585c130544c4e91d2e0e131e6d35cb0cbc47", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d44a24690f16b8c1808bf13b1bd54ae4c63ea048", + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048", "shasum": "" }, "require": { @@ -1101,7 +1326,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "2.5-dev" } }, "autoload": { @@ -1158,7 +1383,7 @@ "type": "tidelift" } ], - "time": "2022-12-10T16:02:17+00:00" + "time": "2023-03-24T15:16:10+00:00" }, { "name": "league/config", @@ -1298,54 +1523,50 @@ }, { "name": "league/flysystem", - "version": "1.1.10", + "version": "3.15.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1" + "reference": "a141d430414fcb8bf797a18716b09f759a385bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3239285c825c152bcc315fe0e87d6b55f5972ed1", - "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a141d430414fcb8bf797a18716b09f759a385bed", + "reference": "a141d430414fcb8bf797a18716b09f759a385bed", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "league/mime-type-detection": "^1.3", - "php": "^7.2.5 || ^8.0" + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" }, "conflict": { - "league/flysystem-sftp": "<1.0.6" + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" }, "require-dev": { - "phpspec/prophecy": "^1.11.1", - "phpunit/phpunit": "^8.5.8" - }, - "suggest": { - "ext-ftp": "Allows you to use FTP server storage", - "ext-openssl": "Allows you to use FTPS server storage", - "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", - "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", - "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", - "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", - "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", - "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", - "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", - "league/flysystem-webdav": "Allows you to use WebDAV storage", - "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", - "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", - "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" + "async-aws/s3": "^1.5", + "async-aws/simple-s3": "^1.1", + "aws/aws-sdk-php": "^3.220.0", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "microsoft/azure-storage-blob": "^1.1", + "phpseclib/phpseclib": "^3.0.14", + "phpstan/phpstan": "^0.12.26", + "phpunit/phpunit": "^9.5.11", + "sabre/dav": "^4.3.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "autoload": { "psr-4": { - "League\\Flysystem\\": "src/" + "League\\Flysystem\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1355,63 +1576,121 @@ "authors": [ { "name": "Frank de Jonge", - "email": "info@frenky.net" + "email": "info@frankdejonge.nl" } ], - "description": "Filesystem abstraction: Many filesystems, one API.", + "description": "File storage abstraction for PHP", "keywords": [ - "Cloud Files", "WebDAV", - "abstraction", "aws", "cloud", - "copy.com", - "dropbox", - "file systems", + "file", "files", "filesystem", "filesystems", "ftp", - "rackspace", - "remote", "s3", "sftp", "storage" ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/1.1.10" + "source": "https://github.com/thephpleague/flysystem/tree/3.15.1" }, "funding": [ { - "url": "https://offset.earth/frankdejonge", - "type": "other" + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + } + ], + "time": "2023-05-04T09:04:26+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.15.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/543f64c397fefdf9cfeac443ffb6beff602796b3", + "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem-local/issues", + "source": "https://github.com/thephpleague/flysystem-local/tree/3.15.0" + }, + "funding": [ + { + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" } ], - "time": "2022-10-04T09:16:37+00:00" + "time": "2023-05-02T20:02:14+00:00" }, { "name": "league/mime-type-detection", - "version": "1.11.0", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd" + "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd", - "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96", + "reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96", "shasum": "" }, "require": { "ext-fileinfo": "*", - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "phpstan/phpstan": "^0.12.68", - "phpunit/phpunit": "^8.5.8 || ^9.3" + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" }, "type": "library", "autoload": { @@ -1432,7 +1711,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0" }, "funding": [ { @@ -1444,41 +1723,41 @@ "type": "tidelift" } ], - "time": "2022-04-17T13:12:02+00:00" + "time": "2023-08-05T12:09:49+00:00" }, { "name": "league/oauth2-server", - "version": "8.3.6", + "version": "8.5.3", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-server.git", - "reference": "28c5441716c10d0c936bd731860dc385d0f6d1a8" + "reference": "eb91b4190e7f6169053ebf8ffa352d47e756b2ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/28c5441716c10d0c936bd731860dc385d0f6d1a8", - "reference": "28c5441716c10d0c936bd731860dc385d0f6d1a8", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/eb91b4190e7f6169053ebf8ffa352d47e756b2ce", + "reference": "eb91b4190e7f6169053ebf8ffa352d47e756b2ce", "shasum": "" }, "require": { - "defuse/php-encryption": "^2.2.1", - "ext-json": "*", + "defuse/php-encryption": "^2.3", "ext-openssl": "*", - "lcobucci/jwt": "^3.4.6 || ^4.0.4", + "lcobucci/clock": "^2.2 || ^3.0", + "lcobucci/jwt": "^4.3 || ^5.0", "league/event": "^2.2", - "league/uri": "^6.4", - "php": "^7.2 || ^8.0", - "psr/http-message": "^1.0.1" + "league/uri": "^6.7", + "php": "^8.0", + "psr/http-message": "^1.0.1 || ^2.0" }, "replace": { "league/oauth2server": "*", "lncd/oauth2": "*" }, "require-dev": { - "laminas/laminas-diactoros": "^2.4.1", + "laminas/laminas-diactoros": "^3.0.0", "phpstan/phpstan": "^0.12.57", "phpstan/phpstan-phpunit": "^0.12.16", - "phpunit/phpunit": "^8.5.13", + "phpunit/phpunit": "^9.6.6", "roave/security-advisories": "dev-master" }, "type": "library", @@ -1524,7 +1803,7 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-server/issues", - "source": "https://github.com/thephpleague/oauth2-server/tree/8.3.6" + "source": "https://github.com/thephpleague/oauth2-server/tree/8.5.3" }, "funding": [ { @@ -1532,7 +1811,7 @@ "type": "github" } ], - "time": "2022-11-14T19:42:00+00:00" + "time": "2023-07-05T23:01:32+00:00" }, { "name": "league/uri", @@ -1706,30 +1985,29 @@ }, { "name": "leroy-merlin-br/mongolid", - "version": "v3.4", + "version": "v3.5", "source": { "type": "git", "url": "git@github.com:leroy-merlin-br/mongolid.git", - "reference": "d0ede8b61b74a1ce66499570594806522788c15c" + "reference": "47b77c2eb84b7fe21aceb43dc4c9309f74a02d6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/leroy-merlin-br/mongolid/zipball/d0ede8b61b74a1ce66499570594806522788c15c", - "reference": "d0ede8b61b74a1ce66499570594806522788c15c", + "url": "https://api.github.com/repos/leroy-merlin-br/mongolid/zipball/47b77c2eb84b7fe21aceb43dc4c9309f74a02d6c", + "reference": "47b77c2eb84b7fe21aceb43dc4c9309f74a02d6c", "shasum": "" }, "require": { "ext-mongodb": "*", - "illuminate/container": "^5.4 || ^6.0 || ^7.0 || ^8.0", - "illuminate/support": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "illuminate/container": "^9.0 || ^10.0", + "illuminate/support": "^9.0 || ^10.0", "mongodb/mongodb": "^1.15", - "php": ">=7.4" + "php": "^8.0" }, "require-dev": { "leroy-merlin-br/coding-standard": "^3.1.0", - "mockery/mockery": "^1.5.1", - "phpunit/phpunit": "^9.5.27", - "symfony/var-dumper": "^5.4.14" + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^9.0" }, "suggest": { "leroy-merlin-br/mongolid-laravel": "Easy, powerful and ultrafast MongoDB ODM for Laravel." @@ -1772,34 +2050,34 @@ "nosql", "odm" ], - "time": "2022-12-21T12:14:18+00:00" + "time": "2023-08-11T17:48:21+00:00" }, { "name": "leroy-merlin-br/mongolid-laravel", - "version": "v3.4.0", + "version": "v3.5.0", "source": { "type": "git", "url": "git@github.com:leroy-merlin-br/mongolid-laravel.git", - "reference": "558a606aff00dc47fe4c4f0e214d2ea590a49635" + "reference": "b2b2aacd20d7cdba30466c82c947a18d102480ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/leroy-merlin-br/mongolid-laravel/zipball/558a606aff00dc47fe4c4f0e214d2ea590a49635", - "reference": "558a606aff00dc47fe4c4f0e214d2ea590a49635", + "url": "https://api.github.com/repos/leroy-merlin-br/mongolid-laravel/zipball/b2b2aacd20d7cdba30466c82c947a18d102480ae", + "reference": "b2b2aacd20d7cdba30466c82c947a18d102480ae", "shasum": "" }, "require": { - "illuminate/auth": "^5.4 || ^6.0 || ^7.0 || ^8.0", - "illuminate/queue": "^5.4 || ^6.0 || ^7.0 || ^8.0", - "illuminate/support": "^5.4 || ^6.0 || ^7.0 || ^8.0", - "leroy-merlin-br/mongolid": "v3.4", - "php": ">=7.4" + "illuminate/auth": "^9.0 || ^10.0", + "illuminate/queue": "^9.0 || ^10.0", + "illuminate/support": "^9.0 || ^10.0", + "leroy-merlin-br/mongolid": "v3.5", + "php": "^8.0" }, "require-dev": { "leroy-merlin-br/coding-standard": "^3.1.0", "mockery/mockery": "^1.5.1", - "orchestra/testbench": "^6.25.1", - "phpunit/phpunit": "^9.5.27" + "orchestra/testbench": "^7.0 || ^8.0", + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { @@ -1833,6 +2111,10 @@ { "name": "Guilherme Guitte", "email": "guilherme.guitte@gmail.com" + }, + { + "name": "Boitatá", + "email": "boitata@leroymerlin.com.br" } ], "description": "Easy, powerful and ultrafast MongoDB ODM for Laravel.", @@ -1843,7 +2125,7 @@ "nosql", "odm" ], - "time": "2022-12-21T17:36:52+00:00" + "time": "2023-08-11T20:23:19+00:00" }, { "name": "mongodb/mongodb", @@ -1917,16 +2199,16 @@ }, { "name": "monolog/monolog", - "version": "2.8.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "720488632c590286b88b80e62aa3d3d551ad4a50" + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50", - "reference": "720488632c590286b88b80e62aa3d3d551ad4a50", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", "shasum": "" }, "require": { @@ -1941,7 +2223,7 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", @@ -2003,7 +2285,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.8.0" + "source": "https://github.com/Seldaek/monolog/tree/2.9.1" }, "funding": [ { @@ -2015,20 +2297,20 @@ "type": "tidelift" } ], - "time": "2022-07-24T11:55:47+00:00" + "time": "2023-02-06T13:44:46+00:00" }, { "name": "nesbot/carbon", - "version": "2.64.0", + "version": "2.68.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "889546413c97de2d05063b8cb7b193c2531ea211" + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/889546413c97de2d05063b8cb7b193c2531ea211", - "reference": "889546413c97de2d05063b8cb7b193c2531ea211", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4f991ed2a403c85efbc4f23eb4030063fdbe01da", + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da", "shasum": "" }, "require": { @@ -2117,25 +2399,25 @@ "type": "tidelift" } ], - "time": "2022-11-26T17:36:00+00:00" + "time": "2023-06-20T18:29:04+00:00" }, { "name": "nette/schema", - "version": "v1.2.3", + "version": "v1.2.4", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f" + "reference": "c9ff517a53903b3d4e29ec547fb20feecb05b8ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", - "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", + "url": "https://api.github.com/repos/nette/schema/zipball/c9ff517a53903b3d4e29ec547fb20feecb05b8ab", + "reference": "c9ff517a53903b3d4e29ec547fb20feecb05b8ab", "shasum": "" }, "require": { "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", - "php": ">=7.1 <8.3" + "php": "7.1 - 8.3" }, "require-dev": { "nette/tester": "^2.3 || ^2.4", @@ -2177,34 +2459,36 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.3" + "source": "https://github.com/nette/schema/tree/v1.2.4" }, - "time": "2022-10-13T01:24:26+00:00" + "time": "2023-08-05T18:56:25+00:00" }, { "name": "nette/utils", - "version": "v3.2.8", + "version": "v4.0.1", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368" + "reference": "9124157137da01b1f5a5a22d6486cb975f26db7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/02a54c4c872b99e4ec05c4aec54b5a06eb0f6368", - "reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368", + "url": "https://api.github.com/repos/nette/utils/zipball/9124157137da01b1f5a5a22d6486cb975f26db7e", + "reference": "9124157137da01b1f5a5a22d6486cb975f26db7e", "shasum": "" }, "require": { - "php": ">=7.2 <8.3" + "php": ">=8.0 <8.4" }, "conflict": { - "nette/di": "<3.0.6" + "nette/finder": "<3", + "nette/schema": "<1.2.2" }, "require-dev": { - "nette/tester": "~2.0", + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.5", "phpstan/phpstan": "^1.0", - "tracy/tracy": "^2.3" + "tracy/tracy": "^2.9" }, "suggest": { "ext-gd": "to use Image", @@ -2218,7 +2502,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2262,49 +2546,55 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v3.2.8" + "source": "https://github.com/nette/utils/tree/v4.0.1" }, - "time": "2022-09-12T23:36:20+00:00" + "time": "2023-07-30T15:42:21+00:00" }, { - "name": "nyholm/psr7", - "version": "1.5.1", + "name": "nunomaduro/termwind", + "version": "v1.15.1", "source": { "type": "git", - "url": "https://github.com/Nyholm/psr7.git", - "reference": "f734364e38a876a23be4d906a2a089e1315be18a" + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7/zipball/f734364e38a876a23be4d906a2a089e1315be18a", - "reference": "f734364e38a876a23be4d906a2a089e1315be18a", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/8ab0b32c8caa4a2e09700ea32925441385e4a5dc", + "reference": "8ab0b32c8caa4a2e09700ea32925441385e4a5dc", "shasum": "" }, "require": { - "php": ">=7.1", - "php-http/message-factory": "^1.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" + "ext-mbstring": "*", + "php": "^8.0", + "symfony/console": "^5.3.0|^6.0.0" }, "require-dev": { - "http-interop/http-factory-tests": "^0.9", - "php-http/psr7-integration-tests": "^1.0", - "phpunit/phpunit": "^7.5 || 8.5 || 9.4", - "symfony/error-handler": "^4.4" + "ergebnis/phpstan-rules": "^1.0.", + "illuminate/console": "^8.0|^9.0", + "illuminate/support": "^8.0|^9.0", + "laravel/pint": "^1.0.0", + "pestphp/pest": "^1.21.0", + "pestphp/pest-plugin-mock": "^1.0", + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-strict-rules": "^1.1.0", + "symfony/var-dumper": "^5.2.7|^6.0.0", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] } }, "autoload": { + "files": [ + "src/Functions.php" + ], "psr-4": { - "Nyholm\\Psr7\\": "src/" + "Termwind\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2313,69 +2603,79 @@ ], "authors": [ { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com" - }, - { - "name": "Martijn van der Ven", - "email": "martijn@vanderven.se" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "A fast PHP7 implementation of PSR-7", - "homepage": "https://tnyholm.se", + "description": "Its like Tailwind CSS, but for the console.", "keywords": [ - "psr-17", - "psr-7" + "cli", + "console", + "css", + "package", + "php", + "style" ], "support": { - "issues": "https://github.com/Nyholm/psr7/issues", - "source": "https://github.com/Nyholm/psr7/tree/1.5.1" + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v1.15.1" }, "funding": [ { - "url": "https://github.com/Zegnat", + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", "type": "github" }, { - "url": "https://github.com/nyholm", + "url": "https://github.com/xiCO2k", "type": "github" } ], - "time": "2022-06-22T07:13:36+00:00" + "time": "2023-02-08T01:06:31+00:00" }, { - "name": "opis/closure", - "version": "3.6.3", + "name": "nyholm/psr7", + "version": "1.8.0", "source": { "type": "git", - "url": "https://github.com/opis/closure.git", - "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad" + "url": "https://github.com/Nyholm/psr7.git", + "reference": "3cb4d163b58589e47b35103e8e5e6a6a475b47be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad", - "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/3cb4d163b58589e47b35103e8e5e6a6a475b47be", + "reference": "3cb4d163b58589e47b35103e8e5e6a6a475b47be", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0" + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" }, "require-dev": { - "jeremeamia/superclosure": "^2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.6.x-dev" + "dev-master": "1.8-dev" } }, "autoload": { - "files": [ - "functions.php" - ], "psr-4": { - "Opis\\Closure\\": "src/" + "Nyholm\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2384,29 +2684,35 @@ ], "authors": [ { - "name": "Marius Sarca", - "email": "marius.sarca@gmail.com" + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" }, { - "name": "Sorin Sarca", - "email": "sarca_sorin@hotmail.com" + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" } ], - "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", - "homepage": "https://opis.io/closure", + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", "keywords": [ - "anonymous functions", - "closure", - "function", - "serializable", - "serialization", - "serialize" + "psr-17", + "psr-7" ], "support": { - "issues": "https://github.com/opis/closure/issues", - "source": "https://github.com/opis/closure/tree/3.6.3" + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.0" }, - "time": "2022-01-27T09:35:39+00:00" + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2023-05-02T11:26:24+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2525,80 +2831,26 @@ }, "time": "2020-10-15T08:29:30+00:00" }, - { - "name": "php-http/message-factory", - "version": "v1.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-http/message-factory.git", - "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", - "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", - "shasum": "" - }, - "require": { - "php": ">=5.4", - "psr/http-message": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" - } - ], - "description": "Factory interfaces for PSR-7 HTTP Message", - "homepage": "http://php-http.org", - "keywords": [ - "factory", - "http", - "message", - "stream", - "uri" - ], - "support": { - "issues": "https://github.com/php-http/message-factory/issues", - "source": "https://github.com/php-http/message-factory/tree/master" - }, - "time": "2015-12-19T14:08:53+00:00" - }, { "name": "phpoption/phpoption", - "version": "1.9.0", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab" + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab", - "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8", - "phpunit/phpunit": "^8.5.28 || ^9.5.21" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" }, "type": "library", "extra": { @@ -2640,7 +2892,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.0" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" }, "funding": [ { @@ -2652,20 +2904,20 @@ "type": "tidelift" } ], - "time": "2022-07-30T15:51:26+00:00" + "time": "2023-02-25T19:38:58+00:00" }, { "name": "phpseclib/phpseclib", - "version": "3.0.18", + "version": "3.0.21", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "f28693d38ba21bb0d9f0c411ee5dae2b178201da" + "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/f28693d38ba21bb0d9f0c411ee5dae2b178201da", - "reference": "f28693d38ba21bb0d9f0c411ee5dae2b178201da", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4580645d3fc05c189024eb3b834c6c1e4f0f30a1", + "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1", "shasum": "" }, "require": { @@ -2746,7 +2998,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.18" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.21" }, "funding": [ { @@ -2762,26 +3014,79 @@ "type": "tidelift" } ], - "time": "2022-12-17T18:26:50+00:00" + "time": "2023-07-09T15:24:48+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": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "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/" @@ -2808,9 +3113,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -2864,21 +3169,21 @@ }, { "name": "psr/http-factory", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { "php": ">=7.0.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -2898,7 +3203,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for PSR-7 HTTP message factories", @@ -2913,31 +3218,31 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, - "time": "2019-04-30T12:38:16+00:00" + "time": "2023-04-10T20:10:41+00:00" }, { "name": "psr/http-message", - "version": "1.0.1", + "version": "1.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -2966,36 +3271,36 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/1.1" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:50:52+00:00" }, { "name": "psr/log", - "version": "1.1.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -3016,31 +3321,31 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.0" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2021-07-14T16:46:02+00:00" }, { "name": "psr/simple-cache", - "version": "1.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -3055,7 +3360,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -3067,48 +3372,59 @@ "simple-cache" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" }, - "time": "2017-10-23T01:57:42+00:00" + "time": "2021-10-29T13:26:27+00:00" }, { "name": "ramsey/collection", - "version": "1.2.2", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", - "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", + "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", "shasum": "" }, "require": { - "php": "^7.3 || ^8", + "php": "^7.4 || ^8.0", "symfony/polyfill-php81": "^1.23" }, "require-dev": { - "captainhook/captainhook": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "ergebnis/composer-normalize": "^2.6", - "fakerphp/faker": "^1.5", - "hamcrest/hamcrest-php": "^2", - "jangregor/phpstan-prophecy": "^0.8", - "mockery/mockery": "^1.3", + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.28.3", + "fakerphp/faker": "^1.21", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^1.0", + "mockery/mockery": "^1.5", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcsstandards/phpcsutils": "^1.0.0-rc1", "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1", - "phpstan/phpstan": "^0.12.32", - "phpstan/phpstan-mockery": "^0.12.5", - "phpstan/phpstan-phpunit": "^0.12.11", - "phpunit/phpunit": "^8.5 || ^9", - "psy/psysh": "^0.10.4", - "slevomat/coding-standard": "^6.3", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.4" + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18.4", + "ramsey/coding-standard": "^2.0.3", + "ramsey/conventional-commits": "^1.3", + "vimeo/psalm": "^5.4" }, "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, "autoload": { "psr-4": { "Ramsey\\Collection\\": "src/" @@ -3136,7 +3452,7 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/1.2.2" + "source": "https://github.com/ramsey/collection/tree/1.3.0" }, "funding": [ { @@ -3148,29 +3464,27 @@ "type": "tidelift" } ], - "time": "2021-10-10T03:01:02+00:00" + "time": "2022-12-27T19:12:24+00:00" }, { "name": "ramsey/uuid", - "version": "4.2.3", + "version": "4.7.4", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df" + "reference": "60a4c63ab724854332900504274f6150ff26d286" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", - "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286", + "reference": "60a4c63ab724854332900504274f6150ff26d286", "shasum": "" }, "require": { - "brick/math": "^0.8 || ^0.9", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11", "ext-json": "*", - "php": "^7.2 || ^8.0", - "ramsey/collection": "^1.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php80": "^1.14" + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" }, "replace": { "rhumsaa/uuid": "self.version" @@ -3182,24 +3496,23 @@ "doctrine/annotations": "^1.8", "ergebnis/composer-normalize": "^2.15", "mockery/mockery": "^1.3", - "moontoast/math": "^1.1", "paragonie/random-lib": "^2", "php-mock/php-mock": "^2.2", "php-mock/php-mock-mockery": "^1.3", "php-parallel-lint/php-parallel-lint": "^1.1", "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-mockery": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", "phpunit/phpunit": "^8.5 || ^9", - "slevomat/coding-standard": "^7.0", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.5", "vimeo/psalm": "^4.9" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", - "ext-ctype": "Enables faster processing of character classification using ctype functions.", "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", @@ -3207,9 +3520,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "4.x-dev" - }, "captainhook": { "force-install": true } @@ -3234,7 +3544,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.2.3" + "source": "https://github.com/ramsey/uuid/tree/4.7.4" }, "funding": [ { @@ -3246,46 +3556,31 @@ "type": "tidelift" } ], - "time": "2021-09-25T23:10:38+00:00" + "time": "2023-04-15T23:01:58+00:00" }, { - "name": "swiftmailer/swiftmailer", - "version": "v6.3.0", + "name": "stella-maris/clock", + "version": "0.1.7", "source": { "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c" + "url": "https://github.com/stella-maris-solutions/clock.git", + "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8a5d5072dca8f48460fce2f4131fcc495eec654c", - "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c", + "url": "https://api.github.com/repos/stella-maris-solutions/clock/zipball/fa23ce16019289a18bb3446fdecd45befcdd94f8", + "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8", "shasum": "" }, "require": { - "egulias/email-validator": "^2.0|^3.1", - "php": ">=7.0.0", - "symfony/polyfill-iconv": "^1.0", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "symfony/phpunit-bridge": "^4.4|^5.4" - }, - "suggest": { - "ext-intl": "Needed to support internationalized email addresses" + "php": "^7.0|^8.0", + "psr/clock": "^1.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" - } - }, "autoload": { - "files": [ - "lib/swift_required.php" - ] + "psr-4": { + "StellaMaris\\Clock\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3293,79 +3588,61 @@ ], "authors": [ { - "name": "Chris Corbyn" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Andreas Heigl", + "role": "Maintainer" } ], - "description": "Swiftmailer, free feature-rich PHP mailer", - "homepage": "https://swiftmailer.symfony.com", + "description": "A pre-release of the proposed PSR-20 Clock-Interface", + "homepage": "https://gitlab.com/stella-maris/clock", "keywords": [ - "email", - "mail", - "mailer" + "clock", + "datetime", + "point in time", + "psr20" ], "support": { - "issues": "https://github.com/swiftmailer/swiftmailer/issues", - "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.3.0" + "source": "https://github.com/stella-maris-solutions/clock/tree/0.1.7" }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer", - "type": "tidelift" - } - ], - "abandoned": "symfony/mailer", - "time": "2021-10-18T15:26:12+00:00" + "time": "2022-11-25T16:15:06+00:00" }, { "name": "symfony/console", - "version": "v5.4.16", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "8e9b9c8dfb33af6057c94e1b44846bee700dc5ef" + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/8e9b9c8dfb33af6057c94e1b44846bee700dc5ef", - "reference": "8e9b9c8dfb33af6057c94e1b44846bee700dc5ef", + "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.0.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/string": "^5.4|^6.0" }, "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" }, "suggest": { "psr/log": "For using the console logger", @@ -3405,7 +3682,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.16" + "source": "https://github.com/symfony/console/tree/v6.0.19" }, "funding": [ { @@ -3421,25 +3698,24 @@ "type": "tidelift" } ], - "time": "2022-11-25T14:09:27+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/css-selector", - "version": "v5.4.11", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "c1681789f059ab756001052164726ae88512ae3d" + "reference": "f1d00bddb83a4cb2138564b2150001cb6ce272b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/c1681789f059ab756001052164726ae88512ae3d", - "reference": "c1681789f059ab756001052164726ae88512ae3d", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/f1d00bddb83a4cb2138564b2150001cb6ce272b1", + "reference": "f1d00bddb83a4cb2138564b2150001cb6ce272b1", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2" }, "type": "library", "autoload": { @@ -3471,7 +3747,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.11" + "source": "https://github.com/symfony/css-selector/tree/v6.0.19" }, "funding": [ { @@ -3487,29 +3763,29 @@ "type": "tidelift" } ], - "time": "2022-06-27T16:58:25+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -3538,7 +3814,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -3554,31 +3830,31 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/error-handler", - "version": "v5.4.15", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "539cf1428b8442303c6e876ad7bf5a7babd91091" + "reference": "c7df52182f43a68522756ac31a532dd5b1e6db67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/539cf1428b8442303c6e876ad7bf5a7babd91091", - "reference": "539cf1428b8442303c6e876ad7bf5a7babd91091", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c7df52182f43a68522756ac31a532dd5b1e6db67", + "reference": "c7df52182f43a68522756ac31a532dd5b1e6db67", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4.4|^5.0|^6.0" + "symfony/var-dumper": "^5.4|^6.0" }, "require-dev": { "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/serializer": "^4.4|^5.0|^6.0" + "symfony/http-kernel": "^5.4|^6.0", + "symfony/serializer": "^5.4|^6.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -3609,7 +3885,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.4.15" + "source": "https://github.com/symfony/error-handler/tree/v6.0.19" }, "funding": [ { @@ -3625,44 +3901,42 @@ "type": "tidelift" } ], - "time": "2022-10-27T06:32:25+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.9", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc" + "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", - "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", + "reference": "2eaf8e63bc5b8cefabd4a800157f0d0c094f677a", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2", + "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<5.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" + "symfony/stopwatch": "^5.4|^6.0" }, "suggest": { "symfony/dependency-injection": "", @@ -3694,7 +3968,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.9" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.19" }, "funding": [ { @@ -3710,24 +3984,24 @@ "type": "tidelift" } ], - "time": "2022-05-05T16:45:39+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", + "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "psr/event-dispatcher": "^1" }, "suggest": { @@ -3736,7 +4010,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -3773,7 +4047,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" }, "funding": [ { @@ -3789,26 +4063,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/finder", - "version": "v5.4.11", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c" + "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/7872a66f57caffa2916a584db1aa7f12adc76f8c", - "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c", + "url": "https://api.github.com/repos/symfony/finder/zipball/5cc9cac6586fc0c28cd173780ca696e419fefa11", + "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2" }, "type": "library", "autoload": { @@ -3836,7 +4108,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.11" + "source": "https://github.com/symfony/finder/tree/v6.0.19" }, "funding": [ { @@ -3852,35 +4124,34 @@ "type": "tidelift" } ], - "time": "2022-07-29T07:37:50+00:00" + "time": "2023-01-20T17:44:14+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.4.16", + "version": "v6.0.20", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "5032c5849aef24741e1970cb03511b0dd131d838" + "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5032c5849aef24741e1970cb03511b0dd131d838", - "reference": "5032c5849aef24741e1970cb03511b0dd131d838", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e16b2676a4b3b1fa12378a20b29c364feda2a8d6", + "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { "predis/predis": "~1.0", - "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/cache": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^5.4|^6.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/mime": "^5.4|^6.0", "symfony/rate-limiter": "^5.2|^6.0" }, "suggest": { @@ -3912,7 +4183,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.16" + "source": "https://github.com/symfony/http-foundation/tree/v6.0.20" }, "funding": [ { @@ -3928,67 +4199,64 @@ "type": "tidelift" } ], - "time": "2022-11-07T08:06:40+00:00" + "time": "2023-01-30T15:41:07+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.4.16", + "version": "v6.0.20", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b432c57c5de73634b1859093c1f58e3cd84455a1" + "reference": "6dc70833fd0ef5e861e17c7854c12d7d86679349" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b432c57c5de73634b1859093c1f58e3cd84455a1", - "reference": "b432c57c5de73634b1859093c1f58e3cd84455a1", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6dc70833fd0ef5e861e17c7854c12d7d86679349", + "reference": "6dc70833fd0ef5e861e17c7854c12d7d86679349", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/log": "^1|^2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^5.0|^6.0", - "symfony/http-foundation": "^5.3.7|^6.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2", + "psr/log": "^1|^2|^3", + "symfony/error-handler": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/console": "<4.4", - "symfony/dependency-injection": "<5.3", - "symfony/doctrine-bridge": "<5.0", - "symfony/form": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", + "symfony/cache": "<5.4", + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/doctrine-bridge": "<5.4", + "symfony/form": "<5.4", + "symfony/http-client": "<5.4", + "symfony/mailer": "<5.4", + "symfony/messenger": "<5.4", + "symfony/translation": "<5.4", + "symfony/twig-bridge": "<5.4", + "symfony/validator": "<5.4", "twig/twig": "<2.13" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^5.3|^6.0", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/css-selector": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/dom-crawler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/stopwatch": "^4.4|^5.0|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/routing": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0", + "symfony/translation": "^5.4|^6.0", "symfony/translation-contracts": "^1.1|^2|^3", "twig/twig": "^2.13|^3.0.4" }, @@ -4024,7 +4292,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.4.16" + "source": "https://github.com/symfony/http-kernel/tree/v6.0.20" }, "funding": [ { @@ -4040,48 +4308,42 @@ "type": "tidelift" } ], - "time": "2022-11-28T18:08:58+00:00" + "time": "2023-02-01T08:22:55+00:00" }, { - "name": "symfony/mime", - "version": "v5.4.16", + "name": "symfony/mailer", + "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/symfony/mime.git", - "reference": "46eeedb08f0832b1b61a84c612d945fc85ee4734" + "url": "https://github.com/symfony/mailer.git", + "reference": "cd60799210c488f545ddde2444dc1aa548322872" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/46eeedb08f0832b1b61a84c612d945fc85ee4734", - "reference": "46eeedb08f0832b1b61a84c612d945fc85ee4734", + "url": "https://api.github.com/repos/symfony/mailer/zipball/cd60799210c488f545ddde2444dc1aa548322872", + "reference": "cd60799210c488f545ddde2444dc1aa548322872", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16" + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.0.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/mime": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3" }, "conflict": { - "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<4.4", - "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + "symfony/http-kernel": "<5.4" }, "require-dev": { - "egulias/email-validator": "^2.1.10|^3.1", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/property-access": "^4.4|^5.1|^6.0", - "symfony/property-info": "^4.4|^5.1|^6.0", - "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/messenger": "^5.4|^6.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Mime\\": "" + "Symfony\\Component\\Mailer\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -4101,14 +4363,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Allows manipulating MIME messages", + "description": "Helps sending emails", "homepage": "https://symfony.com", - "keywords": [ - "mime", - "mime-type" - ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.4.16" + "source": "https://github.com/symfony/mailer/tree/v6.0.19" }, "funding": [ { @@ -4124,48 +4382,50 @@ "type": "tidelift" } ], - "time": "2022-11-26T16:45:22+00:00" + "time": "2023-01-11T11:50:03+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "name": "symfony/mime", + "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "url": "https://github.com/symfony/mime.git", + "reference": "d7052547a0070cbeadd474e172b527a00d657301" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/mime/zipball/d7052547a0070cbeadd474e172b527a00d657301", + "reference": "d7052547a0070cbeadd474e172b527a00d657301", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.0.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" }, - "provide": { - "ext-ctype": "*" + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" }, - "suggest": { - "ext-ctype": "For best performance" + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0", + "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4173,24 +4433,22 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Allows manipulating MIME messages", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" + "mime", + "mime-type" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/mime/tree/v6.0.19" }, "funding": [ { @@ -4206,30 +4464,30 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-11T11:50:03+00:00" }, { - "name": "symfony/polyfill-iconv", + "name": "symfony/polyfill-ctype", "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "927013f3aac555983a5059aada98e1907d842695" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/927013f3aac555983a5059aada98e1907d842695", - "reference": "927013f3aac555983a5059aada98e1907d842695", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", "shasum": "" }, "require": { "php": ">=7.1" }, "provide": { - "ext-iconv": "*" + "ext-ctype": "*" }, "suggest": { - "ext-iconv": "For best performance" + "ext-ctype": "For best performance" }, "type": "library", "extra": { @@ -4246,7 +4504,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Iconv\\": "" + "Symfony\\Polyfill\\Ctype\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -4255,25 +4513,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Iconv extension", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "iconv", + "ctype", "polyfill", - "portable", - "shim" + "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-iconv/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" }, "funding": [ { @@ -4703,17 +4960,17 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php73", + "name": "symfony/polyfill-php80", "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "shasum": "" }, "require": { @@ -4734,7 +4991,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" @@ -4745,6 +5002,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -4754,7 +5015,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4763,7 +5024,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" }, "funding": [ { @@ -4782,17 +5043,17 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php80", + "name": "symfony/polyfill-php81", "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", "shasum": "" }, "require": { @@ -4813,7 +5074,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" @@ -4824,10 +5085,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -4837,7 +5094,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4846,7 +5103,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" }, "funding": [ { @@ -4865,22 +5122,28 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php81", + "name": "symfony/polyfill-uuid", "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166", + "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, "type": "library", "extra": { "branch-alias": { @@ -4896,11 +5159,8 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] + "Symfony\\Polyfill\\Uuid\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4908,24 +5168,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill for uuid functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "polyfill", "portable", - "shim" + "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0" }, "funding": [ { @@ -4945,21 +5205,20 @@ }, { "name": "symfony/process", - "version": "v5.4.11", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1" + "reference": "2114fd60f26a296cc403a7939ab91478475a33d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6e75fe6874cbc7e4773d049616ab450eff537bf1", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1", + "url": "https://api.github.com/repos/symfony/process/zipball/2114fd60f26a296cc403a7939ab91478475a33d4", + "reference": "2114fd60f26a296cc403a7939ab91478475a33d4", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2" }, "type": "library", "autoload": { @@ -4987,7 +5246,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.11" + "source": "https://github.com/symfony/process/tree/v6.0.19" }, "funding": [ { @@ -5003,36 +5262,37 @@ "type": "tidelift" } ], - "time": "2022-06-27T16:58:25+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v2.1.4", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "a125b93ef378c492e274f217874906fb9babdebb" + "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/a125b93ef378c492e274f217874906fb9babdebb", - "reference": "a125b93ef378c492e274f217874906fb9babdebb", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/581ca6067eb62640de5ff08ee1ba6850a0ee472e", + "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e", "shasum": "" }, "require": { - "php": ">=7.1", - "psr/http-message": "^1.0", - "symfony/http-foundation": "^4.4 || ^5.0 || ^6.0" + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0", + "symfony/http-foundation": "^5.4 || ^6.0" }, "require-dev": { "nyholm/psr7": "^1.1", "psr/log": "^1.1 || ^2 || ^3", - "symfony/browser-kit": "^4.4 || ^5.0 || ^6.0", - "symfony/config": "^4.4 || ^5.0 || ^6.0", - "symfony/event-dispatcher": "^4.4 || ^5.0 || ^6.0", - "symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0", - "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0", - "symfony/phpunit-bridge": "^5.4@dev || ^6.0" + "symfony/browser-kit": "^5.4 || ^6.0", + "symfony/config": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/framework-bundle": "^5.4 || ^6.0", + "symfony/http-kernel": "^5.4 || ^6.0", + "symfony/phpunit-bridge": "^6.2" }, "suggest": { "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" @@ -5040,7 +5300,7 @@ "type": "symfony-bridge", "extra": { "branch-alias": { - "dev-main": "2.1-dev" + "dev-main": "2.3-dev" } }, "autoload": { @@ -5075,7 +5335,7 @@ ], "support": { "issues": "https://github.com/symfony/psr-http-message-bridge/issues", - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.4" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.3.1" }, "funding": [ { @@ -5091,41 +5351,39 @@ "type": "tidelift" } ], - "time": "2022-11-28T22:46:34+00:00" + "time": "2023-07-26T11:53:26+00:00" }, { "name": "symfony/routing", - "version": "v5.4.15", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "5c9b129efe9abce9470e384bf65d8a7e262eee69" + "reference": "e56ca9b41c1ec447193474cd86ad7c0b547755ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/5c9b129efe9abce9470e384bf65d8a7e262eee69", - "reference": "5c9b129efe9abce9470e384bf65d8a7e262eee69", + "url": "https://api.github.com/repos/symfony/routing/zipball/e56ca9b41c1ec447193474cd86ad7c0b547755ac", + "reference": "e56ca9b41c1ec447193474cd86ad7c0b547755ac", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2" }, "conflict": { "doctrine/annotations": "<1.12", - "symfony/config": "<5.3", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/yaml": "<5.4" }, "require-dev": { - "doctrine/annotations": "^1.12", + "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^5.3|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" }, "suggest": { "symfony/config": "For using the all-in-one router or any loader", @@ -5165,7 +5423,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.4.15" + "source": "https://github.com/symfony/routing/tree/v6.0.19" }, "funding": [ { @@ -5181,26 +5439,25 @@ "type": "tidelift" } ], - "time": "2022-10-13T14:10:41+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.2", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.0.2", + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -5211,7 +5468,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -5248,7 +5505,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" }, "funding": [ { @@ -5264,38 +5521,37 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2022-05-30T19:17:58+00:00" }, { "name": "symfony/string", - "version": "v5.4.15", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed" + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/571334ce9f687e3e6af72db4d3b2a9431e4fd9ed", - "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed", + "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.0" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -5334,7 +5590,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.15" + "source": "https://github.com/symfony/string/tree/v6.0.19" }, "funding": [ { @@ -5350,52 +5606,50 @@ "type": "tidelift" } ], - "time": "2022-10-05T15:16:54+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/translation", - "version": "v5.4.14", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "f0ed07675863aa6e3939df8b1bc879450b585cab" + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/f0ed07675863aa6e3939df8b1bc879450b585cab", - "reference": "f0ed07675863aa6e3939df8b1bc879450b585cab", + "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.0.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^2.3" + "symfony/translation-contracts": "^2.3|^3.0" }, "conflict": { - "symfony/config": "<4.4", - "symfony/console": "<5.3", - "symfony/dependency-injection": "<5.0", - "symfony/http-kernel": "<5.0", - "symfony/twig-bundle": "<5.0", - "symfony/yaml": "<4.4" + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" }, "provide": { - "symfony/translation-implementation": "2.3" + "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", + "symfony/config": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" + "symfony/yaml": "^5.4|^6.0" }, "suggest": { "psr/log-implementation": "To use logging capability in translator", @@ -5431,7 +5685,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.4.14" + "source": "https://github.com/symfony/translation/tree/v6.0.19" }, "funding": [ { @@ -5447,24 +5701,24 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:01:20+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.5.2", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=8.0.2" }, "suggest": { "symfony/translation-implementation": "" @@ -5472,7 +5726,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -5509,7 +5763,81 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + }, + "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": "2022-06-27T17:10:44+00:00" + }, + { + "name": "symfony/uid", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d", + "reference": "6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d", + "shasum": "" + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v6.0.19" }, "funding": [ { @@ -5525,36 +5853,35 @@ "type": "tidelift" } ], - "time": "2022-06-27T16:58:25+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.4.14", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "6894d06145fefebd9a4c7272baa026a1c394a430" + "reference": "eb980457fa6899840fe1687e8627a03a7d8a3d52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6894d06145fefebd9a4c7272baa026a1c394a430", - "reference": "6894d06145fefebd9a4c7272baa026a1c394a430", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eb980457fa6899840fe1687e8627a03a7d8a3d52", + "reference": "eb980457fa6899840fe1687e8627a03a7d8a3d52", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4" + "symfony/console": "<5.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, "suggest": { @@ -5598,7 +5925,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.14" + "source": "https://github.com/symfony/var-dumper/tree/v6.0.19" }, "funding": [ { @@ -5614,20 +5941,20 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:01:20+00:00" + "time": "2023-01-20T17:44:14+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "2.2.5", + "version": "2.2.6", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19" + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/4348a3a06651827a27d989ad1d13efec6bb49b19", - "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", "shasum": "" }, "require": { @@ -5665,9 +5992,9 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.5" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.6" }, - "time": "2022-09-12T13:28:28+00:00" + "time": "2023-01-03T09:29:04+00:00" }, { "name": "vlucas/phpdotenv", @@ -5755,16 +6082,16 @@ }, { "name": "voku/portable-ascii", - "version": "1.6.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "87337c91b9dfacee02452244ee14ab3c43bc485a" + "reference": "b56450eed252f6801410d810c8e1727224ae0743" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/87337c91b9dfacee02452244ee14ab3c43bc485a", - "reference": "87337c91b9dfacee02452244ee14ab3c43bc485a", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", "shasum": "" }, "require": { @@ -5801,7 +6128,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/1.6.1" + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" }, "funding": [ { @@ -5825,7 +6152,7 @@ "type": "tidelift" } ], - "time": "2022-01-24T18:55:24+00:00" + "time": "2022-03-08T17:03:00+00:00" }, { "name": "webmozart/assert", @@ -5889,30 +6216,30 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.16 || ^1", "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -5939,7 +6266,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -5955,20 +6282,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "fakerphp/faker", - "version": "v1.21.0", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d" + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/92efad6a967f0b79c499705c69b662f738cc9e4d", - "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", "shasum": "" }, "require": { @@ -6021,28 +6348,28 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.21.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" }, - "time": "2022-12-13T13:54:32+00:00" + "time": "2023-06-12T08:44:38+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.4.3", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "67c26b443f348a51926030c83481b85718457d3d" + "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d", - "reference": "67c26b443f348a51926030c83481b85718457d3d", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", + "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", + "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0" }, "provide": { @@ -6062,9 +6389,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "2.4-dev" } }, "autoload": { @@ -6126,7 +6450,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.4.3" + "source": "https://github.com/guzzle/psr7/tree/2.6.0" }, "funding": [ { @@ -6142,7 +6466,7 @@ "type": "tidelift" } ], - "time": "2022-10-26T14:07:24+00:00" + "time": "2023-08-03T15:06:02+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -6197,38 +6521,40 @@ }, { "name": "mockery/mockery", - "version": "1.5.1", + "version": "1.6.6", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" + "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", - "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "url": "https://api.github.com/repos/mockery/mockery/zipball/b8e0bb7d8c604046539c1115994632c74dcb361e", + "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": "^7.3 || ^8.0" + "php": ">=7.3" }, "conflict": { "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.3" + "phpunit/phpunit": "^8.5 || ^9.6.10", + "psalm/plugin-phpunit": "^0.18.4", + "symplify/easy-coding-standard": "^11.5.0", + "vimeo/psalm": "^4.30" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, "autoload": { - "psr-0": { - "Mockery": "library/" + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", @@ -6239,12 +6565,20 @@ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "homepage": "https://github.com/padraic", + "role": "Author" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } ], "description": "Mockery is a simple yet flexible PHP mock object framework", @@ -6262,23 +6596,26 @@ "testing" ], "support": { + "docs": "https://docs.mockery.io/", "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.5.1" + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" }, - "time": "2022-09-07T15:32:08+00:00" + "time": "2023-08-09T00:03:52+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -6316,7 +6653,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -6324,20 +6661,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.2", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", - "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -6378,36 +6715,40 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2022-11-12T15:38:23+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "orchestra/testbench", - "version": "v6.25.1", + "version": "v7.26.2", "source": { "type": "git", "url": "https://github.com/orchestral/testbench.git", - "reference": "0516123d26d64117bc04f7e9cb982eae2624e750" + "reference": "6355e41b4f279875e996836f39204ef130f703f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench/zipball/0516123d26d64117bc04f7e9cb982eae2624e750", - "reference": "0516123d26d64117bc04f7e9cb982eae2624e750", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/6355e41b4f279875e996836f39204ef130f703f1", + "reference": "6355e41b4f279875e996836f39204ef130f703f1", "shasum": "" }, "require": { - "laravel/framework": "^8.75", - "mockery/mockery": "^1.4.4", - "orchestra/testbench-core": "^6.29.1", - "php": "^7.3 || ^8.0", - "phpunit/phpunit": "^8.5.21 || ^9.5.10", - "spatie/laravel-ray": "^1.26.2" + "fakerphp/faker": "^1.21", + "laravel/framework": "^9.52.15", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^7.26.2", + "php": "^8.0", + "phpunit/phpunit": "^9.5.10", + "spatie/laravel-ray": "^1.32.4", + "symfony/process": "^6.0.9", + "symfony/yaml": "^6.0.9", + "vlucas/phpdotenv": "^5.4.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "7.0-dev" } }, "notification-url": "https://packagist.org/downloads/", @@ -6426,62 +6767,57 @@ "keywords": [ "BDD", "TDD", + "dev", "laravel", - "orchestra-platform", - "orchestral", + "laravel-packages", "testing" ], "support": { "issues": "https://github.com/orchestral/testbench/issues", - "source": "https://github.com/orchestral/testbench/tree/v6.25.1" + "source": "https://github.com/orchestral/testbench/tree/v7.26.2" }, - "funding": [ - { - "url": "https://paypal.me/crynobone", - "type": "custom" - }, - { - "url": "https://liberapay.com/crynobone", - "type": "liberapay" - } - ], - "time": "2022-10-11T14:01:10+00:00" + "time": "2023-08-10T02:40:53+00:00" }, { "name": "orchestra/testbench-core", - "version": "v6.29.1", + "version": "v7.26.3", "source": { "type": "git", "url": "https://github.com/orchestral/testbench-core.git", - "reference": "29a7586915885f89b8d2203efe20f76afe9cf956" + "reference": "cbffadcc4da002b19503ac0e45a145fbc987c0e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/29a7586915885f89b8d2203efe20f76afe9cf956", - "reference": "29a7586915885f89b8d2203efe20f76afe9cf956", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/cbffadcc4da002b19503ac0e45a145fbc987c0e6", + "reference": "cbffadcc4da002b19503ac0e45a145fbc987c0e6", "shasum": "" }, "require": { - "fakerphp/faker": "^1.9.1", - "php": "^7.3 || ^8.0", - "symfony/yaml": "^5.0", - "vlucas/phpdotenv": "^5.1" + "php": "^8.0" }, "require-dev": { - "laravel/framework": "^8.75", - "laravel/laravel": "8.x-dev", - "mockery/mockery": "^1.4.4", - "orchestra/canvas": "^6.1", - "phpunit/phpunit": "^8.5.21 || ^9.5.10", - "spatie/laravel-ray": "^1.7.1", - "symfony/process": "^5.0" + "fakerphp/faker": "^1.21", + "laravel/framework": "^9.52.9", + "laravel/pint": "^1.4", + "mockery/mockery": "^1.5.1", + "phpstan/phpstan": "^1.10.7", + "phpunit/phpunit": "^9.5.10", + "spatie/laravel-ray": "^1.32.4", + "symfony/process": "^6.0.9", + "symfony/yaml": "^6.0.9", + "vlucas/phpdotenv": "^5.4.1" }, "suggest": { - "laravel/framework": "Required for testing (^8.75).", - "mockery/mockery": "Allow using Mockery for testing (^1.4.4).", - "orchestra/testbench-browser-kit": "Allow using legacy Laravel BrowserKit for testing (^6.0).", - "orchestra/testbench-dusk": "Allow using Laravel Dusk for testing (^6.0).", - "phpunit/phpunit": "Allow using PHPUnit for testing (^8.5.21|^9.5.10|^10.0)." + "brianium/paratest": "Allow using parallel tresting (^6.4).", + "fakerphp/faker": "Allow using Faker for testing (^1.21).", + "laravel/framework": "Required for testing (^9.52.9).", + "mockery/mockery": "Allow using Mockery for testing (^1.5.1).", + "nunomaduro/collision": "Allow using Laravel style tests output and parallel testing (^6.2).", + "orchestra/testbench-browser-kit": "Allow using legacy Laravel BrowserKit for testing (^7.0).", + "orchestra/testbench-dusk": "Allow using Laravel Dusk for testing (^7.0).", + "phpunit/phpunit": "Allow using PHPUnit for testing (^9.5.10).", + "symfony/yaml": "Required for CLI Commander (^6.0.9).", + "vlucas/phpdotenv": "Required for CLI Commander (^5.4.1)." }, "bin": [ "testbench" @@ -6489,7 +6825,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -6516,26 +6852,16 @@ "keywords": [ "BDD", "TDD", + "dev", "laravel", - "orchestra-platform", - "orchestral", + "laravel-packages", "testing" ], "support": { "issues": "https://github.com/orchestral/testbench/issues", "source": "https://github.com/orchestral/testbench-core" }, - "funding": [ - { - "url": "https://paypal.me/crynobone", - "type": "custom" - }, - { - "url": "https://liberapay.com/crynobone", - "type": "liberapay" - } - ], - "time": "2022-10-11T12:12:52+00:00" + "time": "2023-08-11T08:18:39+00:00" }, { "name": "phar-io/manifest", @@ -6648,25 +6974,87 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.10.28", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e4545b55904ebef470423d3ddddb74fa7325497a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4545b55904ebef470423d3ddddb74fa7325497a", + "reference": "e4545b55904ebef470423d3ddddb74fa7325497a", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-08-08T12:33:42+00:00" + }, { "name": "phpunit/php-code-coverage", - "version": "9.2.22", + "version": "9.2.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "e4bf60d2220b4baaa0572986b5d69870226b06df" + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e4bf60d2220b4baaa0572986b5d69870226b06df", - "reference": "e4bf60d2220b4baaa0572986b5d69870226b06df", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -6681,8 +7069,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -6715,7 +7103,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.22" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" }, "funding": [ { @@ -6723,7 +7112,7 @@ "type": "github" } ], - "time": "2022-12-18T16:40:55+00:00" + "time": "2023-07-26T13:44:30+00:00" }, { "name": "phpunit/php-file-iterator", @@ -6968,20 +7357,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.27", + "version": "9.6.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38" + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38", - "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328", + "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -7010,8 +7399,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -7019,7 +7408,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -7050,7 +7439,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10" }, "funding": [ { @@ -7066,7 +7456,7 @@ "type": "tidelift" } ], - "time": "2022-12-09T07:31:23+00:00" + "time": "2023-07-10T04:04:23+00:00" }, { "name": "pimple/pimple", @@ -7465,16 +7855,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -7519,7 +7909,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -7527,20 +7917,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -7582,7 +7972,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -7590,7 +7980,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -7671,16 +8061,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -7723,7 +8113,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -7731,7 +8121,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -7904,16 +8294,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -7952,10 +8342,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -7963,7 +8353,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -8022,16 +8412,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -8066,7 +8456,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -8074,7 +8464,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -8131,16 +8521,16 @@ }, { "name": "spatie/backtrace", - "version": "1.2.1", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "4ee7d41aa5268107906ea8a4d9ceccde136dbd5b" + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/4ee7d41aa5268107906ea8a4d9ceccde136dbd5b", - "reference": "4ee7d41aa5268107906ea8a4d9ceccde136dbd5b", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/483f76a82964a0431aa836b6ed0edde0c248e3ab", + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab", "shasum": "" }, "require": { @@ -8149,6 +8539,7 @@ "require-dev": { "ext-json": "*", "phpunit/phpunit": "^9.3", + "spatie/phpunit-snapshot-assertions": "^4.2", "symfony/var-dumper": "^5.1" }, "type": "library", @@ -8176,8 +8567,7 @@ "spatie" ], "support": { - "issues": "https://github.com/spatie/backtrace/issues", - "source": "https://github.com/spatie/backtrace/tree/1.2.1" + "source": "https://github.com/spatie/backtrace/tree/1.5.3" }, "funding": [ { @@ -8189,41 +8579,42 @@ "type": "other" } ], - "time": "2021-11-09T10:57:15+00:00" + "time": "2023-06-28T12:59:17+00:00" }, { "name": "spatie/laravel-ray", - "version": "1.31.0", + "version": "1.32.6", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ray.git", - "reference": "7394694afd89d05879e7a69c54abab73c1199acd" + "reference": "8526dd6c6c838b4bac4e0df2ea7896b688b0d43e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/7394694afd89d05879e7a69c54abab73c1199acd", - "reference": "7394694afd89d05879e7a69c54abab73c1199acd", + "url": "https://api.github.com/repos/spatie/laravel-ray/zipball/8526dd6c6c838b4bac4e0df2ea7896b688b0d43e", + "reference": "8526dd6c6c838b4bac4e0df2ea7896b688b0d43e", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/contracts": "^7.20|^8.19|^9.0", - "illuminate/database": "^7.20|^8.19|^9.0", - "illuminate/queue": "^7.20|^8.19|^9.0", - "illuminate/support": "^7.20|^8.19|^9.0", - "php": "^7.3|^8.0", + "illuminate/contracts": "^7.20|^8.19|^9.0|^10.0", + "illuminate/database": "^7.20|^8.19|^9.0|^10.0", + "illuminate/queue": "^7.20|^8.19|^9.0|^10.0", + "illuminate/support": "^7.20|^8.19|^9.0|^10.0", + "php": "^7.4|^8.0", "spatie/backtrace": "^1.0", - "spatie/ray": "^1.33", + "spatie/ray": "^1.37", "symfony/stopwatch": "4.2|^5.1|^6.0", "zbateson/mail-mime-parser": "^1.3.1|^2.0" }, "require-dev": { "guzzlehttp/guzzle": "^7.3", - "laravel/framework": "^7.20|^8.19|^9.0", - "orchestra/testbench-core": "^5.0|^6.0|^7.0", + "laravel/framework": "^7.20|^8.19|^9.0|^10.0", + "orchestra/testbench-core": "^5.0|^6.0|^7.0|^8.0", + "pestphp/pest": "^1.22", "phpstan/phpstan": "^0.12.93", "phpunit/phpunit": "^9.3", - "spatie/phpunit-snapshot-assertions": "^4.2" + "spatie/pest-plugin-snapshots": "^1.1" }, "type": "library", "extra": { @@ -8261,7 +8652,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-ray/issues", - "source": "https://github.com/spatie/laravel-ray/tree/1.31.0" + "source": "https://github.com/spatie/laravel-ray/tree/1.32.6" }, "funding": [ { @@ -8273,24 +8664,24 @@ "type": "other" } ], - "time": "2022-09-20T13:13:22+00:00" + "time": "2023-07-19T12:30:16+00:00" }, { "name": "spatie/macroable", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/spatie/macroable.git", - "reference": "7a99549fc001c925714b329220dea680c04bfa48" + "reference": "ec2c320f932e730607aff8052c44183cf3ecb072" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/macroable/zipball/7a99549fc001c925714b329220dea680c04bfa48", - "reference": "7a99549fc001c925714b329220dea680c04bfa48", + "url": "https://api.github.com/repos/spatie/macroable/zipball/ec2c320f932e730607aff8052c44183cf3ecb072", + "reference": "ec2c320f932e730607aff8052c44183cf3ecb072", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "php": "^8.0" }, "require-dev": { "phpunit/phpunit": "^8.0|^9.3" @@ -8321,22 +8712,22 @@ ], "support": { "issues": "https://github.com/spatie/macroable/issues", - "source": "https://github.com/spatie/macroable/tree/1.0.1" + "source": "https://github.com/spatie/macroable/tree/2.0.0" }, - "time": "2020-11-03T10:15:05+00:00" + "time": "2021-03-26T22:39:02+00:00" }, { "name": "spatie/ray", - "version": "1.36.0", + "version": "1.37.2", "source": { "type": "git", "url": "https://github.com/spatie/ray.git", - "reference": "4a4def8cda4806218341b8204c98375aa8c34323" + "reference": "dea16182d4bc9d9833adec7e39fbb3d7b553425d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ray/zipball/4a4def8cda4806218341b8204c98375aa8c34323", - "reference": "4a4def8cda4806218341b8204c98375aa8c34323", + "url": "https://api.github.com/repos/spatie/ray/zipball/dea16182d4bc9d9833adec7e39fbb3d7b553425d", + "reference": "dea16182d4bc9d9833adec7e39fbb3d7b553425d", "shasum": "" }, "require": { @@ -8351,8 +8742,9 @@ }, "require-dev": { "illuminate/support": "6.x|^8.18|^9.0", - "nesbot/carbon": "^2.43", - "phpstan/phpstan": "^0.12.92", + "nesbot/carbon": "^2.63", + "pestphp/pest": "^1.22", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5", "spatie/phpunit-snapshot-assertions": "^4.2", "spatie/test-time": "^1.2" @@ -8386,7 +8778,7 @@ ], "support": { "issues": "https://github.com/spatie/ray/issues", - "source": "https://github.com/spatie/ray/tree/1.36.0" + "source": "https://github.com/spatie/ray/tree/1.37.2" }, "funding": [ { @@ -8398,24 +8790,107 @@ "type": "other" } ], - "time": "2022-08-11T14:04:18+00:00" + "time": "2023-05-17T06:35:47+00:00" + }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "927013f3aac555983a5059aada98e1907d842695" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/927013f3aac555983a5059aada98e1907d842695", + "reference": "927013f3aac555983a5059aada98e1907d842695", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-iconv": "*" + }, + "suggest": { + "ext-iconv": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Iconv\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Iconv extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "iconv", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.27.0" + }, + "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": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/stopwatch", - "version": "v5.4.13", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "6df7a3effde34d81717bbef4591e5ffe32226d69" + "reference": "011e781839dd1d2eb8119f65ac516a530f60226d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6df7a3effde34d81717bbef4591e5ffe32226d69", - "reference": "6df7a3effde34d81717bbef4591e5ffe32226d69", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/011e781839dd1d2eb8119f65ac516a530f60226d", + "reference": "011e781839dd1d2eb8119f65ac516a530f60226d", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "symfony/service-contracts": "^1|^2|^3" }, "type": "library", @@ -8444,7 +8919,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.13" + "source": "https://github.com/symfony/stopwatch/tree/v6.0.19" }, "funding": [ { @@ -8460,32 +8935,31 @@ "type": "tidelift" } ], - "time": "2022-09-28T13:19:49+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.16", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "ebd37c71f62d5ec5f6e27de3e06fee492d4c6298" + "reference": "deec3a812a0305a50db8ae689b183f43d915c884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/ebd37c71f62d5ec5f6e27de3e06fee492d4c6298", - "reference": "ebd37c71f62d5ec5f6e27de3e06fee492d4c6298", + "url": "https://api.github.com/repos/symfony/yaml/zipball/deec3a812a0305a50db8ae689b183f43d915c884", + "reference": "deec3a812a0305a50db8ae689b183f43d915c884", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.0.2", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.3" + "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.3|^6.0" + "symfony/console": "^5.4|^6.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" @@ -8519,7 +8993,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.16" + "source": "https://github.com/symfony/yaml/tree/v6.0.19" }, "funding": [ { @@ -8535,7 +9009,7 @@ "type": "tidelift" } ], - "time": "2022-11-25T16:04:03+00:00" + "time": "2023-01-11T11:50:03+00:00" }, { "name": "theseer/tokenizer", @@ -8589,28 +9063,30 @@ }, { "name": "zbateson/mail-mime-parser", - "version": "2.2.3", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/zbateson/mail-mime-parser.git", - "reference": "295c7f82a8c44af685680d9df6714beb812e90ff" + "reference": "20b3e48eb799537683780bc8782fbbe9bc25934a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/295c7f82a8c44af685680d9df6714beb812e90ff", - "reference": "295c7f82a8c44af685680d9df6714beb812e90ff", + "url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/20b3e48eb799537683780bc8782fbbe9bc25934a", + "reference": "20b3e48eb799537683780bc8782fbbe9bc25934a", "shasum": "" }, "require": { "guzzlehttp/psr7": "^1.7.0|^2.0", - "php": ">=5.4", + "php": ">=7.1", "pimple/pimple": "^3.0", "zbateson/mb-wrapper": "^1.0.1", "zbateson/stream-decorators": "^1.0.6" }, "require-dev": { + "friendsofphp/php-cs-fixer": "*", "mikey179/vfsstream": "^1.6.0", - "sanmai/phpunit-legacy-adapter": "^6.3 || ^8.2" + "phpstan/phpstan": "*", + "phpunit/phpunit": "<10" }, "suggest": { "ext-iconv": "For best support/performance", @@ -8658,29 +9134,31 @@ "type": "github" } ], - "time": "2022-09-28T16:31:49+00:00" + "time": "2023-02-14T22:58:03+00:00" }, { "name": "zbateson/mb-wrapper", - "version": "1.1.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/zbateson/mb-wrapper.git", - "reference": "5d9d190ef18ce6d424e3ac6f5ebe13901f92b74a" + "reference": "faf35dddfacfc5d4d5f9210143eafd7a7fe74334" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/5d9d190ef18ce6d424e3ac6f5ebe13901f92b74a", - "reference": "5d9d190ef18ce6d424e3ac6f5ebe13901f92b74a", + "url": "https://api.github.com/repos/zbateson/mb-wrapper/zipball/faf35dddfacfc5d4d5f9210143eafd7a7fe74334", + "reference": "faf35dddfacfc5d4d5f9210143eafd7a7fe74334", "shasum": "" }, "require": { - "php": ">=5.4", + "php": ">=7.1", "symfony/polyfill-iconv": "^1.9", "symfony/polyfill-mbstring": "^1.9" }, "require-dev": { - "sanmai/phpunit-legacy-adapter": "^6.3 || ^8" + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "<=9.0" }, "suggest": { "ext-iconv": "For best support/performance", @@ -8717,7 +9195,7 @@ ], "support": { "issues": "https://github.com/zbateson/mb-wrapper/issues", - "source": "https://github.com/zbateson/mb-wrapper/tree/1.1.2" + "source": "https://github.com/zbateson/mb-wrapper/tree/1.2.0" }, "funding": [ { @@ -8725,29 +9203,31 @@ "type": "github" } ], - "time": "2022-05-26T15:55:05+00:00" + "time": "2023-01-11T23:05:44+00:00" }, { "name": "zbateson/stream-decorators", - "version": "1.0.7", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/zbateson/stream-decorators.git", - "reference": "8f8ca208572963258b7e6d91106181706deacd10" + "reference": "783b034024fda8eafa19675fb2552f8654d3a3e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/8f8ca208572963258b7e6d91106181706deacd10", - "reference": "8f8ca208572963258b7e6d91106181706deacd10", + "url": "https://api.github.com/repos/zbateson/stream-decorators/zipball/783b034024fda8eafa19675fb2552f8654d3a3e9", + "reference": "783b034024fda8eafa19675fb2552f8654d3a3e9", "shasum": "" }, "require": { - "guzzlehttp/psr7": "^1.7.0|^2.0", - "php": ">=5.4", + "guzzlehttp/psr7": "^1.9 | ^2.0", + "php": ">=7.2", "zbateson/mb-wrapper": "^1.0.0" }, "require-dev": { - "sanmai/phpunit-legacy-adapter": "^6.3 || ^8" + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "<10.0" }, "type": "library", "autoload": { @@ -8778,7 +9258,7 @@ ], "support": { "issues": "https://github.com/zbateson/stream-decorators/issues", - "source": "https://github.com/zbateson/stream-decorators/tree/1.0.7" + "source": "https://github.com/zbateson/stream-decorators/tree/1.2.1" }, "funding": [ { @@ -8786,7 +9266,7 @@ "type": "github" } ], - "time": "2022-09-08T15:44:55+00:00" + "time": "2023-05-30T22:51:52+00:00" } ], "aliases": [], @@ -8795,7 +9275,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=7.4", + "php": "^8.0", "ext-json": "*", "ext-mongodb": "*" }, diff --git a/config/passport.php b/config/passport.php index ccf9fe2..5fe712e 100644 --- a/config/passport.php +++ b/config/passport.php @@ -2,6 +2,19 @@ return [ + /* + |-------------------------------------------------------------------------- + | Passport Guard + |-------------------------------------------------------------------------- + | + | Here you may specify which authentication guard Passport will use when + | authenticating users. This value should correspond with one of your + | guards that is already present in your "auth" configuration file. + | + */ + + 'guard' => 'web', + /* |-------------------------------------------------------------------------- | Encryption Keys diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 195685f..7b93b40 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -6,31 +6,12 @@ return new class extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { - $this->schema->create('oauth_auth_codes', function (Blueprint $table) { + Schema::create('oauth_auth_codes', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->unsignedBigInteger('user_id')->index(); $table->unsignedBigInteger('client_id'); @@ -42,21 +23,9 @@ public function up() /** * Reverse the migrations. - * - * @return void - */ - public function down() - { - $this->schema->dropIfExists('oauth_auth_codes'); - } - - /** - * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function down(): void { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_auth_codes'); } }; diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index c8ecd72..598798e 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -6,31 +6,12 @@ return new class extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { - $this->schema->create('oauth_access_tokens', function (Blueprint $table) { + Schema::create('oauth_access_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->unsignedBigInteger('user_id')->nullable()->index(); $table->unsignedBigInteger('client_id'); @@ -44,21 +25,9 @@ public function up() /** * Reverse the migrations. - * - * @return void - */ - public function down() - { - $this->schema->dropIfExists('oauth_access_tokens'); - } - - /** - * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function down(): void { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_access_tokens'); } }; diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index 998b631..b007904 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -6,31 +6,12 @@ return new class extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { - $this->schema->create('oauth_refresh_tokens', function (Blueprint $table) { + Schema::create('oauth_refresh_tokens', function (Blueprint $table) { $table->string('id', 100)->primary(); $table->string('access_token_id', 100)->index(); $table->boolean('revoked'); @@ -40,21 +21,9 @@ public function up() /** * Reverse the migrations. - * - * @return void - */ - public function down() - { - $this->schema->dropIfExists('oauth_refresh_tokens'); - } - - /** - * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function down(): void { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_refresh_tokens'); } }; diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 51e597c..776ccfa 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -6,41 +6,12 @@ return new class extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - - /** - * Get the migration connection name. - * - * @return string|null - */ - public function getConnection() - { - return config('passport.storage.database.connection'); - } - /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { - $this->schema->create('oauth_clients', function (Blueprint $table) { + Schema::create('oauth_clients', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('user_id')->nullable()->index(); $table->string('name'); @@ -56,11 +27,9 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { - $this->schema->dropIfExists('oauth_clients'); + Schema::dropIfExists('oauth_clients'); } }; diff --git a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php index e12920a..7c9d1e8 100644 --- a/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php @@ -6,31 +6,12 @@ return new class extends Migration { - /** - * The database schema. - * - * @var \Illuminate\Database\Schema\Builder - */ - protected $schema; - - /** - * Create a new migration instance. - * - * @return void - */ - public function __construct() - { - $this->schema = Schema::connection($this->getConnection()); - } - /** * Run the migrations. - * - * @return void */ - public function up() + public function up(): void { - $this->schema->create('oauth_personal_access_clients', function (Blueprint $table) { + Schema::create('oauth_personal_access_clients', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('client_id'); $table->timestamps(); @@ -39,21 +20,9 @@ public function up() /** * Reverse the migrations. - * - * @return void - */ - public function down() - { - $this->schema->dropIfExists('oauth_personal_access_clients'); - } - - /** - * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function down(): void { - return config('passport.storage.database.connection'); + Schema::dropIfExists('oauth_personal_access_clients'); } }; diff --git a/docker-compose.yml b/docker-compose.yml index 619e650..7622d3e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: - .:/var/www/html db: - image: mongo:4.2 + image: mongo:5.0 command: mongod volumes: - db:/data/db diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index a5e4cde..f6abbb8 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.4-fpm +FROM php:8.0-fpm USER root:root @@ -11,7 +11,7 @@ RUN apt-get update -qq \ zlib1g-dev libicu-dev \ && apt-get clean -RUN pecl install xdebug-3.1.6 mongodb \ +RUN pecl install xdebug-3.2.1 mongodb \ && docker-php-ext-enable \ mongodb xdebug \ && docker-php-ext-configure \ diff --git a/docs/upgrade/upgrade-8.x-9.0.md b/docs/upgrade/upgrade-8.x-9.0.md index 071e3c5..f31f7cb 100644 --- a/docs/upgrade/upgrade-8.x-9.0.md +++ b/docs/upgrade/upgrade-8.x-9.0.md @@ -2,6 +2,50 @@ ## General Notes +## Upgrading To 11.0 From 10.x + +### Minimum PHP Version + +PHP 8.0 is now the minimum required version. + +### Minimum Laravel Version + +Laravel 9.0 is now the minimum required version. + +### Reverting Model DB Connection Customization + +PR: https://github.com/laravel/passport/pull/1412 + +Customizing model database connections through the migration files has been reverted. This was first introduced in [this PR](https://github.com/laravel/passport/pull/1255). + +If you need to customize the database connection for a model you should override the models [as explained in the documentation](https://laravel.com/docs/9.x/passport#overriding-default-models). + +### Allow Timestamps On Token model + +PR: https://github.com/laravel/passport/pull/1425 + +Timestamps are now allowed on the `Token` model. If you specifically didn't want these model's timestamps to be updated then you may override the `Token` model [as explained in the documentation](https://laravel.com/docs/9.x/passport#overriding-default-models). + +### Refactor Routes To Dedicated File + +PR: https://github.com/laravel/passport/pull/1464 + +Passport's routes have been moved to a dedicated route file. You can remove the `Passport::routes()` call from your application's service provider. + +If you previously relied on overwriting routes using `routes($callback = null, array $options = [])` you may now achieve the same behavior by simply overwriting the routes in your application's own `web.php` route file. + +### Stubbing Client In Tests + +PR: https://github.com/laravel/passport/pull/1519 + +Previously, a stubbed client created via `Passport::actingAsClient(...)` wasn't retrieved when calling the `->client()` method on the API guard. This has been fixed in Passport v11 to reflect real-world situations and you may need to accommodate for this behavior in your tests. + +### Scope Inheritance In Tests + +PR: https://github.com/laravel/passport/pull/1551 + +Previously, scopes weren't inherited when using `Passport::actingAs(...)`. This has been fixed in Passport v11 to reflect real-world situations and you may need to accommodate for this behavior in your tests. + ## Upgrading To 10.0 From 9.x ### Minimum PHP Version diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..649776a --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,11 @@ +parameters: + paths: + - config + - database + - routes + - src + + level: 0 + + ignoreErrors: + - "#Unsafe usage of new static\\(\\)#" diff --git a/routes/web.php b/routes/web.php new file mode 100644 index 0000000..fa2ecf3 --- /dev/null +++ b/routes/web.php @@ -0,0 +1,84 @@ + 'AccessTokenController@issueToken', + 'as' => 'token', + 'middleware' => 'throttle', +]); + +Route::get('/authorize', [ + 'uses' => 'AuthorizationController@authorize', + 'as' => 'authorizations.authorize', + 'middleware' => 'web', +]); + +$guard = config('passport.guard', null); + +Route::middleware(['web', $guard ? 'auth:'.$guard : 'auth'])->group(function () { + Route::post('/token/refresh', [ + 'uses' => 'TransientTokenController@refresh', + 'as' => 'token.refresh', + ]); + + Route::post('/authorize', [ + 'uses' => 'ApproveAuthorizationController@approve', + 'as' => 'authorizations.approve', + ]); + + Route::delete('/authorize', [ + 'uses' => 'DenyAuthorizationController@deny', + 'as' => 'authorizations.deny', + ]); + + Route::get('/tokens', [ + 'uses' => 'AuthorizedAccessTokenController@forUser', + 'as' => 'tokens.index', + ]); + + Route::delete('/tokens/{token_id}', [ + 'uses' => 'AuthorizedAccessTokenController@destroy', + 'as' => 'tokens.destroy', + ]); + + Route::get('/clients', [ + 'uses' => 'ClientController@forUser', + 'as' => 'clients.index', + ]); + + Route::post('/clients', [ + 'uses' => 'ClientController@store', + 'as' => 'clients.store', + ]); + + Route::put('/clients/{client_id}', [ + 'uses' => 'ClientController@update', + 'as' => 'clients.update', + ]); + + Route::delete('/clients/{client_id}', [ + 'uses' => 'ClientController@destroy', + 'as' => 'clients.destroy', + ]); + + Route::get('/scopes', [ + 'uses' => 'ScopeController@all', + 'as' => 'scopes.index', + ]); + + Route::get('/personal-access-tokens', [ + 'uses' => 'PersonalAccessTokenController@forUser', + 'as' => 'personal.tokens.index', + ]); + + Route::post('/personal-access-tokens', [ + 'uses' => 'PersonalAccessTokenController@store', + 'as' => 'personal.tokens.store', + ]); + + Route::delete('/personal-access-tokens/{token_id}', [ + 'uses' => 'PersonalAccessTokenController@destroy', + 'as' => 'personal.tokens.destroy', + ]); +}); diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index c6993df..c4d143d 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -5,6 +5,7 @@ use MongoDB\BSON\UTCDateTime; use Illuminate\Contracts\Events\Dispatcher; use Laravel\Passport\Events\AccessTokenCreated; +use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; @@ -46,7 +47,7 @@ public function __construct(TokenRepository $tokenRepository, Dispatcher $events */ public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null) { - return new AccessToken($userIdentifier, $scopes, $clientEntity); + return new Passport::$accessTokenEntity($userIdentifier, $scopes, $clientEntity); } /** diff --git a/src/ClientRepository.php b/src/ClientRepository.php index e231ede..cdbf58a 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Support\Str; +use MongoDB\BSON\ObjectId; use RuntimeException; class ClientRepository @@ -37,7 +38,7 @@ public function __construct($personalAccessClientId = null, $personalAccessClien /** * Get a client by the given ID. * - * @param int $id + * @param string|ObjectId $id * * @return \Laravel\Passport\Client|null */ @@ -51,7 +52,7 @@ public function find($id) /** * Get an active client by the given ID. * - * @param string|int $id + * @param string|ObjectId $id * * @return \Laravel\Passport\Client|null */ @@ -65,8 +66,8 @@ public function findActive($id) /** * Get a client instance for the given ID and user ID. * - * @param int $clientId - * @param mixed $userId + * @param string|ObjectId $clientId + * @param mixed $userId * * @return \Laravel\Passport\Client|null */ @@ -140,14 +141,14 @@ public function personalAccessClient() /** * Store a new client. * - * @param int $userId - * @param string $name - * @param string $redirect - * @param string|null $provider - * @param bool $personalAccess - * @param bool $password - * @param bool $confidential - * @param string $allowedScopes + * @param string|ObjectId $userId + * @param string $name + * @param string $redirect + * @param string|null $provider + * @param bool $personalAccess + * @param bool $password + * @param bool $confidential + * @param string $allowedScopes * * @return \Laravel\Passport\Client */ @@ -178,9 +179,9 @@ public function create($userId, $name, $redirect, $provider = null, $personalAcc /** * Store a new personal access token client. * - * @param int $userId - * @param string $name - * @param string $redirect + * @param string|ObjectId $userId + * @param string $name + * @param string $redirect * * @return \Laravel\Passport\Client */ @@ -196,10 +197,10 @@ public function createPersonalAccessClient($userId, $name, $redirect) /** * Store a new password grant client. * - * @param int $userId - * @param string $name - * @param string $redirect - * @param string|null $provider + * @param string|ObjectId $userId + * @param string $name + * @param string $redirect + * @param string|null $provider * * @return \Laravel\Passport\Client */ @@ -256,7 +257,7 @@ public function regenerateSecret(Client $client) /** * Determine if the given client is revoked. * - * @param int $id + * @param string|ObjectId $id * * @return bool */ diff --git a/src/Console/ClientCommand.php b/src/Console/ClientCommand.php index f02f617..a0e9a93 100644 --- a/src/Console/ClientCommand.php +++ b/src/Console/ClientCommand.php @@ -143,7 +143,7 @@ protected function createClientCredentialsClient(ClientRepository $clients) protected function createAuthCodeClient(ClientRepository $clients) { $userId = $this->option('user_id') ?: $this->ask( - 'Which user ID should the client be assigned to?' + 'Which user ID should the client be assigned to? (Optional)' ); $name = $this->option('name') ?: $this->ask( @@ -155,10 +155,8 @@ protected function createAuthCodeClient(ClientRepository $clients) url('/auth/callback') ); - $allowedScopes = config('auth.authorization_code.allowed_scopes'); - $client = $clients->create( - $userId, $name, $redirect, null, false, false, !$this->option('public'), $allowedScopes + $userId, $name, $redirect, null, false, false, !$this->option('public') ); $this->info('New client created successfully.'); @@ -180,7 +178,7 @@ protected function outputClientDetails(Client $client) } $this->line('Client ID: '.$client->_id); - $this->line('Client secret: '.($client->plainSecret ?? $client->secret)); + $this->line('Client secret: '.$client->plainSecret); } /** diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index d3a8a66..ae74aac 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -17,7 +17,8 @@ class PurgeCommand extends Command */ protected $signature = 'passport:purge {--revoked : Only purge revoked tokens and authentication codes} - {--expired : Only purge expired tokens and authentication codes}'; + {--expired : Only purge expired tokens and authentication codes} + {--hours= : The number of hours to retain expired tokens}'; /** * The console command description. @@ -31,20 +32,27 @@ class PurgeCommand extends Command */ public function handle() { - $expired = new UTCDateTime(Carbon::now()->subDays(7)); + $expired = $this->option('hours') + ? Carbon::now()->subHours($this->option('hours')) + : Carbon::now()->subDays(7); + $expired = new UTCDateTime($expired); $query = []; $message = ''; if (($this->option('revoked') && $this->option('expired')) || (! $this->option('revoked') && ! $this->option('expired'))) { $query = ['$or' => [['revoked' => true], ['expires_at' => ['$lt' => $expired]]]]; - $message = 'Purged revoked items and items expired for more than seven days.'; + $message = $this->option('hours') + ? 'Purged revoked items and items expired for more than '.$this->option('hours').' hours.' + : 'Purged revoked items and items expired for more than seven days.'; } elseif ($this->option('revoked')) { $query = ['revoked' => true]; $message = 'Purged revoked items.'; } elseif ($this->option('expired')) { $query = ['expires_at' => ['$lt' => $expired]]; - $message = 'Purged items expired for more than seven days.'; + $message = $this->option('hours') + ? 'Purged items expired for more than '.$this->option('hours').' hours.' + : 'Purged items expired for more than seven days.'; } if ($tokens = Passport::tokenModel()::where($query)) { diff --git a/src/Contracts/AuthorizationViewResponse.php b/src/Contracts/AuthorizationViewResponse.php new file mode 100644 index 0000000..6594c66 --- /dev/null +++ b/src/Contracts/AuthorizationViewResponse.php @@ -0,0 +1,16 @@ +server = $server; $this->tokens = $tokens; $this->clients = $clients; $this->provider = $provider; $this->encrypter = $encrypter; + $this->request = $request; } /** - * Determine if the requested provider matches the client's provider. + * Get the user for the incoming request. * - * @param \Illuminate\Http\Request $request - * @return bool + * @return mixed */ - protected function hasValidProvider(Request $request) + public function user() { - $client = $this->client($request); - - if ($client && ! $client->provider) { - return true; + if (! is_null($this->user)) { + return $this->user; } - return $client && $client->provider === $this->provider->getProviderName(); + if ($this->request->bearerToken()) { + return $this->user = $this->authenticateViaBearerToken($this->request); + } elseif ($this->request->cookie(Passport::cookie())) { + return $this->user = $this->authenticateViaCookie($this->request); + } } /** - * Get the user for the incoming request. + * Validate a user's credentials. * - * @param \Illuminate\Http\Request $request - * @return mixed + * @param array $credentials + * @return bool */ - public function user(Request $request) + public function validate(array $credentials = []) { - if ($request->bearerToken()) { - return $this->authenticateViaBearerToken($request); - } elseif ($request->cookie(Passport::cookie())) { - return $this->authenticateViaCookie($request); - } + return ! is_null((new static( + $this->server, + $this->provider, + $this->tokens, + $this->clients, + $this->encrypter, + $credentials['request'], + ))->user()); } /** * Get the client for the incoming request. * - * @param \Illuminate\Http\Request $request - * @return mixed + * @return \Laravel\Passport\Client|null */ - public function client(Request $request) + public function client() { - if ($request->bearerToken()) { - if (! $psr = $this->getPsrRequestViaBearerToken($request)) { + if (! is_null($this->client)) { + return $this->client; + } + + if ($this->request->bearerToken()) { + if (! $psr = $this->getPsrRequestViaBearerToken($this->request)) { return; } - return $this->clients->findActive( + return $this->client = $this->clients->findActive( $psr->getAttribute('oauth_client_id') ); - } elseif ($request->cookie(Passport::cookie())) { - if ($token = $this->getTokenViaCookie($request)) { - return $this->clients->findActive($token['aud']); + } elseif ($this->request->cookie(Passport::cookie())) { + if ($token = $this->getTokenViaCookie($this->request)) { + return $this->client = $this->clients->findActive($token['aud']); } } } @@ -149,7 +179,13 @@ protected function authenticateViaBearerToken($request) return; } - if (! $this->hasValidProvider($request)) { + $client = $this->clients->findActive( + $psr->getAttribute('oauth_client_id') + ); + + if (! $client || + ($client->provider && + $client->provider !== $this->provider->getProviderName())) { return; } @@ -171,15 +207,6 @@ protected function authenticateViaBearerToken($request) $psr->getAttribute('oauth_access_token_id') ); - $clientId = $psr->getAttribute('oauth_client_id'); - - // Finally, we will verify if the client that issued this token is still valid and - // its tokens may still be used. If not, we will bail out since we don't want a - // user to be able to send access tokens for deleted or revoked applications. - if ($this->clients->revoked($clientId)) { - return; - } - return $token ? $user->withAccessToken($token) : null; } @@ -187,7 +214,7 @@ protected function authenticateViaBearerToken($request) * Authenticate and get the incoming PSR-7 request via the Bearer token. * * @param \Illuminate\Http\Request $request - * @return \Psr\Http\Message\ServerRequestInterface + * @return \Psr\Http\Message\ServerRequestInterface|null */ protected function getPsrRequestViaBearerToken($request) { @@ -268,8 +295,12 @@ protected function getTokenViaCookie($request) */ protected function decodeJwtTokenCookie($request) { + $jwt = $request->cookie(Passport::cookie()); + return (array) JWT::decode( - CookieValuePrefix::remove($this->encrypter->decrypt($request->cookie(Passport::cookie()), Passport::$unserializesCookies)), + Passport::$decryptsCookies + ? CookieValuePrefix::remove($this->encrypter->decrypt($jwt, Passport::$unserializesCookies)) + : $jwt, new Key(Passport::tokenEncryptionKey($this->encrypter), 'HS256') ); } @@ -305,6 +336,19 @@ protected function getTokenFromRequest($request) return $token; } + /** + * Set the current request instance. + * + * @param \Illuminate\Http\Request $request + * @return $this + */ + public function setRequest(Request $request) + { + $this->request = $request; + + return $this; + } + /** * Determine if the cookie contents should be serialized. * @@ -314,4 +358,17 @@ public static function serialized() { return EncryptCookies::serialized('XSRF-TOKEN'); } + + /** + * Set the client for the current request. + * + * @param \Laravel\Passport\Client $client + * @return $this + */ + public function setClient(Client $client) + { + $this->client = $client; + + return $this; + } } diff --git a/src/HasApiTokens.php b/src/HasApiTokens.php index 91e5a84..d586684 100644 --- a/src/HasApiTokens.php +++ b/src/HasApiTokens.php @@ -9,7 +9,7 @@ trait HasApiTokens /** * The current access token for the authentication user. * - * @var \Laravel\Passport\Token + * @var \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null */ protected $accessToken; @@ -37,7 +37,7 @@ public function tokens() /** * Get the current access token being used by the user. * - * @return \Laravel\Passport\Token|null + * @return \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null */ public function token() { @@ -72,7 +72,7 @@ public function createToken($name, array $scopes = []) /** * Set the current access token for the user. * - * @param \Laravel\Passport\Token $accessToken + * @param \Laravel\Passport\Token|\Laravel\Passport\TransientToken $accessToken * @return $this */ public function withAccessToken($accessToken) diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index 3667c2d..7c3b395 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -3,7 +3,6 @@ namespace Laravel\Passport\Http\Controllers; use Laravel\Passport\TokenRepository; -use Lcobucci\JWT\Parser as JwtParser; use League\OAuth2\Server\AuthorizationServer; use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; @@ -26,28 +25,16 @@ class AccessTokenController */ protected $tokens; - /** - * The JWT parser instance. - * - * @var \Lcobucci\JWT\Parser - * - * @deprecated This property will be removed in a future Passport version. - */ - protected $jwt; - /** * Create a new controller instance. * * @param \League\OAuth2\Server\AuthorizationServer $server * @param \Laravel\Passport\TokenRepository $tokens - * @param \Lcobucci\JWT\Parser $jwt * @return void */ public function __construct(AuthorizationServer $server, - TokenRepository $tokens, - JwtParser $jwt) + TokenRepository $tokens) { - $this->jwt = $jwt; $this->server = $server; $this->tokens = $tokens; } diff --git a/src/Http/Controllers/ApproveAuthorizationController.php b/src/Http/Controllers/ApproveAuthorizationController.php index 90023d5..6a2d415 100644 --- a/src/Http/Controllers/ApproveAuthorizationController.php +++ b/src/Http/Controllers/ApproveAuthorizationController.php @@ -8,7 +8,7 @@ class ApproveAuthorizationController { - use ConvertsPsrResponses, RetrievesAuthRequestFromSession; + use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession; /** * The authorization server. @@ -40,8 +40,12 @@ public function approve(Request $request) $authRequest = $this->getAuthRequestFromSession($request); - return $this->convertResponse( - $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) - ); + $authRequest->setAuthorizationApproved(true); + + return $this->withErrorHandling(function () use ($authRequest) { + return $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + ); + }); } } diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index f6a8828..bdbcdce 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -2,15 +2,18 @@ namespace Laravel\Passport\Http\Controllers; -use Illuminate\Contracts\Routing\ResponseFactory; +use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Http\Request; use Illuminate\Support\Str; use Laravel\Passport\Bridge\User; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Contracts\AuthorizationViewResponse; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Passport; use Laravel\Passport\TokenRepository; use Laravel\Passport\Bridge\ScopeRepository; use League\OAuth2\Server\AuthorizationServer; +use League\OAuth2\Server\Exception\OAuthServerException; use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; @@ -26,9 +29,16 @@ class AuthorizationController protected $server; /** - * The response factory implementation. + * The guard implementation. * - * @var \Illuminate\Contracts\Routing\ResponseFactory + * @var \Illuminate\Contracts\Auth\StatefulGuard + */ + protected $guard; + + /** + * The authorization view response implementation. + * + * @var \Laravel\Passport\Contracts\AuthorizationViewResponse */ protected $response; @@ -36,12 +46,16 @@ class AuthorizationController * Create a new controller instance. * * @param \League\OAuth2\Server\AuthorizationServer $server - * @param \Illuminate\Contracts\Routing\ResponseFactory $response + * @param \Illuminate\Contracts\Auth\StatefulGuard $guard + * @param \Laravel\Passport\Contracts\AuthorizationViewResponse $response * @return void */ - public function __construct(AuthorizationServer $server, ResponseFactory $response) + public function __construct(AuthorizationServer $server, + StatefulGuard $guard, + AuthorizationViewResponse $response) { $this->server = $server; + $this->guard = $guard; $this->response = $response; } @@ -52,6 +66,7 @@ public function __construct(AuthorizationServer $server, ResponseFactory $respon * @param \Illuminate\Http\Request $request * @param \Laravel\Passport\ClientRepository $clients * @param \Laravel\Passport\TokenRepository $tokens + * @return \Illuminate\Http\Response|\Laravel\Passport\Contracts\AuthorizationViewResponse * @param \Laravel\Passport\Bridge\ScopeRepository $scopeRepository * * @return \Illuminate\Http\Response @@ -66,27 +81,40 @@ public function authorize(ServerRequestInterface $psrRequest, return $this->server->validateAuthorizationRequest($psrRequest); }); - $scopes = $this->parseScopes($authRequest); + if ($this->guard->guest()) { + return $request->get('prompt') === 'none' + ? $this->denyRequest($authRequest) + : $this->promptForLogin($request); + } - $token = $tokens->findValidToken( - $user = $request->user(), - $client = $clients->find($authRequest->getClient()->getIdentifier()) - ); + if ($request->get('prompt') === 'login' && + ! $request->session()->get('promptedForLogin', false)) { + $this->guard->logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); - $scopeRepository->validateClientScopes( - $authRequest->getScopes(), - $authRequest->getClient() - ); + return $this->promptForLogin($request); + } + + $request->session()->forget('promptedForLogin'); - if (($token && $token->scopes === collect($scopes)->pluck('_id')->all()) || - $client->skipsAuthorization()) { + $scopes = $this->parseScopes($authRequest); + $user = $this->guard->user(); + $client = $clients->find($authRequest->getClient()->getIdentifier()); + + if ($request->get('prompt') !== 'consent' && + ($client->skipsAuthorization() || $this->hasValidToken($tokens, $user, $client, $scopes))) { return $this->approveRequest($authRequest, $user); } + if ($request->get('prompt') === 'none') { + return $this->denyRequest($authRequest, $user); + } + $request->session()->put('authToken', $authToken = Str::random()); $request->session()->put('authRequest', $authRequest); - return $this->response->view('passport::authorize', [ + return $this->response->withParameters([ 'client' => $client, 'user' => $user, 'scopes' => $scopes, @@ -110,11 +138,27 @@ protected function parseScopes($authRequest) ); } + /** + * Determine if a valid token exists for the given user, client, and scopes. + * + * @param \Laravel\Passport\TokenRepository $tokens + * @param \Illuminate\Contracts\Auth\Authenticatable $user + * @param \Laravel\Passport\Client $client + * @param array $scopes + * @return bool + */ + protected function hasValidToken($tokens, $user, $client, $scopes) + { + $token = $tokens->findValidToken($user, $client); + + return $token && $token->scopes === collect($scopes)->pluck('_id')->all(); + } + /** * Approve the authorization request. * * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @param \MongolidLaravel\LegacyMongolidModel $user + * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return \Illuminate\Http\Response */ protected function approveRequest($authRequest, $user) @@ -129,4 +173,53 @@ protected function approveRequest($authRequest, $user) ); }); } + + /** + * Deny the authorization request. + * + * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest + * @param \Illuminate\Contracts\Auth\Authenticatable|null $user + * @return \Illuminate\Http\Response + */ + protected function denyRequest($authRequest, $user = null) + { + if (is_null($user)) { + $uri = $authRequest->getRedirectUri() + ?? (is_array($authRequest->getClient()->getRedirectUri()) + ? $authRequest->getClient()->getRedirectUri()[0] + : $authRequest->getClient()->getRedirectUri()); + + $separator = $authRequest->getGrantTypeId() === 'implicit' ? '#' : '?'; + + $uri = $uri.(str_contains($uri, $separator) ? '&' : $separator).'state='.$authRequest->getState(); + + return $this->withErrorHandling(function () use ($uri) { + throw OAuthServerException::accessDenied('Unauthenticated', $uri); + }); + } + + $authRequest->setUser(new User($user->getAuthIdentifier())); + + $authRequest->setAuthorizationApproved(false); + + return $this->withErrorHandling(function () use ($authRequest) { + return $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + ); + }); + } + + /** + * Prompt the user to login by throwing an AuthenticationException. + * + * @param \Illuminate\Http\Request $request + * + * @throws \Laravel\Passport\Exceptions\AuthenticationException + */ + protected function promptForLogin($request) + { + $request->session()->put('promptedForLogin', true); + + throw new AuthenticationException; + } } diff --git a/src/Http/Controllers/DenyAuthorizationController.php b/src/Http/Controllers/DenyAuthorizationController.php index 613dfd4..3a46e61 100644 --- a/src/Http/Controllers/DenyAuthorizationController.php +++ b/src/Http/Controllers/DenyAuthorizationController.php @@ -2,30 +2,30 @@ namespace Laravel\Passport\Http\Controllers; -use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; -use Illuminate\Support\Arr; +use League\OAuth2\Server\AuthorizationServer; +use Nyholm\Psr7\Response as Psr7Response; class DenyAuthorizationController { - use RetrievesAuthRequestFromSession; + use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession; /** - * The response factory implementation. + * The authorization server. * - * @var \Illuminate\Contracts\Routing\ResponseFactory + * @var \League\OAuth2\Server\AuthorizationServer */ - protected $response; + protected $server; /** * Create a new controller instance. * - * @param \Illuminate\Contracts\Routing\ResponseFactory $response + * @param \League\OAuth2\Server\AuthorizationServer $server * @return void */ - public function __construct(ResponseFactory $response) + public function __construct(AuthorizationServer $server) { - $this->response = $response; + $this->server = $server; } /** @@ -40,16 +40,12 @@ public function deny(Request $request) $authRequest = $this->getAuthRequestFromSession($request); - $clientUris = Arr::wrap($authRequest->getClient()->getRedirectUri()); + $authRequest->setAuthorizationApproved(false); - if (! in_array($uri = $authRequest->getRedirectUri(), $clientUris)) { - $uri = Arr::first($clientUris); - } - - $separator = $authRequest->getGrantTypeId() === 'implicit' ? '#' : (strstr($uri, '?') ? '&' : '?'); - - return $this->response->redirectTo( - $uri.$separator.'error=access_denied&state='.$request->input('state') - ); + return $this->withErrorHandling(function () use ($authRequest) { + return $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + ); + }); } } diff --git a/src/Http/Controllers/RetrievesAuthRequestFromSession.php b/src/Http/Controllers/RetrievesAuthRequestFromSession.php index b129627..0a23e1e 100644 --- a/src/Http/Controllers/RetrievesAuthRequestFromSession.php +++ b/src/Http/Controllers/RetrievesAuthRequestFromSession.php @@ -42,8 +42,6 @@ protected function getAuthRequestFromSession(Request $request) } $authRequest->setUser(new User($request->user()->getAuthIdentifier())); - - $authRequest->setAuthorizationApproved(true); }); } } diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index fc6e049..25644dd 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Http\Middleware; -use Illuminate\Auth\AuthenticationException; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; class CheckClientCredentials extends CheckCredentials @@ -13,7 +13,7 @@ class CheckClientCredentials extends CheckCredentials * @param \Laravel\Passport\Token $token * @return void * - * @throws \Illuminate\Auth\AuthenticationException + * @throws \Laravel\Passport\Exceptions\AuthenticationException */ protected function validateCredentials($token) { diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index 7c63de9..8da32bf 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Http\Middleware; -use Illuminate\Auth\AuthenticationException; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; class CheckClientCredentialsForAnyScope extends CheckCredentials @@ -13,7 +13,7 @@ class CheckClientCredentialsForAnyScope extends CheckCredentials * @param \Laravel\Passport\Token $token * @return void * - * @throws \Illuminate\Auth\AuthenticationException + * @throws \Laravel\Passport\Exceptions\AuthenticationException */ protected function validateCredentials($token) { diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 20a9376..4ece0e2 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -3,7 +3,7 @@ namespace Laravel\Passport\Http\Middleware; use Closure; -use Illuminate\Auth\AuthenticationException; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; @@ -47,7 +47,7 @@ public function __construct(ResourceServer $server, TokenRepository $repository) * @param mixed ...$scopes * @return mixed * - * @throws \Illuminate\Auth\AuthenticationException + * @throws \Laravel\Passport\Exceptions\AuthenticationException */ public function handle($request, Closure $next, ...$scopes) { @@ -93,7 +93,7 @@ protected function validate($psr, $scopes) * @param \Laravel\Passport\Token $token * @return void * - * @throws \Illuminate\Auth\AuthenticationException + * @throws \Laravel\Passport\Exceptions\AuthenticationException */ abstract protected function validateCredentials($token); diff --git a/src/Http/Middleware/CheckForAnyScope.php b/src/Http/Middleware/CheckForAnyScope.php index 0bb9653..9223dfe 100644 --- a/src/Http/Middleware/CheckForAnyScope.php +++ b/src/Http/Middleware/CheckForAnyScope.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Http\Middleware; -use Illuminate\Auth\AuthenticationException; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; class CheckForAnyScope @@ -15,7 +15,7 @@ class CheckForAnyScope * @param mixed ...$scopes * @return \Illuminate\Http\Response * - * @throws \Illuminate\Auth\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException + * @throws \Laravel\Passport\Exceptions\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException */ public function handle($request, $next, ...$scopes) { diff --git a/src/Http/Middleware/CheckScopes.php b/src/Http/Middleware/CheckScopes.php index e19f109..af9f859 100644 --- a/src/Http/Middleware/CheckScopes.php +++ b/src/Http/Middleware/CheckScopes.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Http\Middleware; -use Illuminate\Auth\AuthenticationException; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; class CheckScopes @@ -15,7 +15,7 @@ class CheckScopes * @param mixed ...$scopes * @return \Illuminate\Http\Response * - * @throws \Illuminate\Auth\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException + * @throws \Laravel\Passport\Exceptions\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException */ public function handle($request, $next, ...$scopes) { diff --git a/src/Http/Responses/AuthorizationViewResponse.php b/src/Http/Responses/AuthorizationViewResponse.php new file mode 100644 index 0000000..36761d4 --- /dev/null +++ b/src/Http/Responses/AuthorizationViewResponse.php @@ -0,0 +1,68 @@ +view = $view; + } + + /** + * Add parameters to response. + * + * @param array $parameters + * @return $this + */ + public function withParameters($parameters = []) + { + $this->parameters = $parameters; + + return $this; + } + + /** + * Create an HTTP response that represents the object. + * + * @param \Illuminate\Http\Request $request + * @return \Symfony\Component\HttpFoundation\Response + */ + public function toResponse($request) + { + if (! is_callable($this->view) || is_string($this->view)) { + return response()->view($this->view, $this->parameters); + } + + $response = call_user_func($this->view, $this->parameters); + + if ($response instanceof Responsable) { + return $response->toResponse($request); + } + + return $response; + } +} diff --git a/src/Passport.php b/src/Passport.php index caac8ca..874bdd8 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -6,7 +6,8 @@ use DateInterval; use DateTimeInterface; use Illuminate\Contracts\Encryption\Encrypter; -use Illuminate\Support\Facades\Route; +use Laravel\Passport\Contracts\AuthorizationViewResponse as AuthorizationViewResponseContract; +use Laravel\Passport\Http\Responses\AuthorizationViewResponse; use League\OAuth2\Server\ResourceServer; use Mockery; use Psr\Http\Message\ServerRequestInterface; @@ -36,15 +37,6 @@ class Passport // ]; - /** - * The date when access tokens expire. - * - * @var \DateTimeInterface|null - * - * @deprecated Will be removed in the next major Passport release. - */ - public static $tokensExpireAt; - /** * The interval when access tokens expire. * @@ -52,15 +44,6 @@ class Passport */ public static $tokensExpireIn; - /** - * The date when refresh tokens expire. - * - * @var \DateTimeInterface|null - * - * @deprecated Will be removed in the next major Passport release. - */ - public static $refreshTokensExpireAt; - /** * The date when refresh tokens expire. * @@ -68,15 +51,6 @@ class Passport */ public static $refreshTokensExpireIn; - /** - * The date when personal access tokens expire. - * - * @var \DateTimeInterface|null - * - * @deprecated Will be removed in the next major Passport release. - */ - public static $personalAccessTokensExpireAt; - /** * The date when personal access tokens expire. * @@ -105,6 +79,13 @@ class Passport */ public static $keyPath; + /** + * The access token entity class name. + * + * @var string + */ + public static $accessTokenEntity = 'Laravel\Passport\Bridge\AccessToken'; + /** * The auth code model class name. * @@ -154,6 +135,13 @@ class Passport */ public static $unserializesCookies = false; + /** + * Indicates if Passport should decrypt cookies. + * + * @var bool + */ + public static $decryptsCookies = true; + /** * Indicates if client secrets will be hashed. * @@ -182,6 +170,13 @@ class Passport */ public static $authorizationServerResponseType; + /** + * Indicates if Passport routes will be registered. + * + * @var bool + */ + public static $registersRoutes = true; + /** * Enable the implicit grant type. * @@ -194,31 +189,6 @@ public static function enableImplicitGrant() return new static; } - /** - * Binds the Passport routes into the controller. - * - * @param callable|null $callback - * @param array $options - * @return void - */ - public static function routes($callback = null, array $options = []) - { - $callback = $callback ?: function ($router) { - $router->all(); - }; - - $defaultOptions = [ - 'prefix' => 'oauth', - 'namespace' => '\Laravel\Passport\Http\Controllers', - ]; - - $options = array_merge($defaultOptions, $options); - - Route::group($options, function ($router) use ($callback) { - $callback(new RouteRegistrar($router)); - }); - } - /** * Set the default scope(s). Multiple scopes may be an array or specified delimited by spaces. * @@ -301,7 +271,6 @@ public static function tokensExpireIn(DateTimeInterface $date = null) return static::$tokensExpireIn ?? new DateInterval('P1Y'); } - static::$tokensExpireAt = $date; static::$tokensExpireIn = Carbon::now()->diff($date); return new static; @@ -319,7 +288,6 @@ public static function refreshTokensExpireIn(DateTimeInterface $date = null) return static::$refreshTokensExpireIn ?? new DateInterval('P1Y'); } - static::$refreshTokensExpireAt = $date; static::$refreshTokensExpireIn = Carbon::now()->diff($date); return new static; @@ -337,7 +305,6 @@ public static function personalAccessTokensExpireIn(DateTimeInterface $date = nu return static::$personalAccessTokensExpireIn ?? new DateInterval('P1Y'); } - static::$personalAccessTokensExpireAt = $date; static::$personalAccessTokensExpireIn = Carbon::now()->diff($date); return new static; @@ -383,11 +350,9 @@ public static function ignoreCsrfToken($ignoreCsrfToken = true) */ public static function actingAs($user, $scopes = [], $guard = 'api') { - $token = Mockery::mock(self::tokenModel())->shouldIgnoreMissing(false); + $token = app(self::tokenModel()); - foreach ($scopes as $scope) { - $token->shouldReceive('can')->with($scope)->andReturn(true); - } + $token->scopes = $scopes; $user->withAccessToken($token); @@ -407,9 +372,10 @@ public static function actingAs($user, $scopes = [], $guard = 'api') * * @param \Laravel\Passport\Client $client * @param array $scopes + * @param string $guard * @return \Laravel\Passport\Client */ - public static function actingAsClient($client, $scopes = []) + public static function actingAsClient($client, $scopes = [], $guard = 'api') { $token = app(self::tokenModel()); @@ -419,8 +385,8 @@ public static function actingAsClient($client, $scopes = []) $mock = Mockery::mock(ResourceServer::class); $mock->shouldReceive('validateAuthenticatedRequest') ->andReturnUsing(function (ServerRequestInterface $request) use ($token) { - return $request->withAttribute('oauth_client_id', $token->client->id) - ->withAttribute('oauth_access_token_id', $token->id) + return $request->withAttribute('oauth_client_id', $token->client->_id) + ->withAttribute('oauth_access_token_id', $token->_id) ->withAttribute('oauth_scopes', $token->scopes); }); @@ -431,6 +397,10 @@ public static function actingAsClient($client, $scopes = []) app()->instance(TokenRepository::class, $mock); + app('auth')->guard($guard)->setClient($client); + + app('auth')->shouldUse($guard); + return $client; } @@ -460,6 +430,17 @@ public static function keyPath($file) : storage_path($file); } + /** + * Set the access token entity class name. + * + * @param string $accessTokenEntity + * @return void + */ + public static function useAccessTokenEntity($accessTokenEntity) + { + static::$accessTokenEntity = $accessTokenEntity; + } + /** * Set the auth code model class name. * @@ -653,6 +634,31 @@ public static function tokenEncryptionKey(Encrypter $encrypter) $encrypter->getKey(); } + /** + * Specify which view should be used as the authorization view. + * + * @param callable|string $view + * @return void + */ + public static function authorizationView($view) + { + app()->singleton(AuthorizationViewResponseContract::class, function ($app) use ($view) { + return new AuthorizationViewResponse($view); + }); + } + + /** + * Configure Passport to not register its routes. + * + * @return static + */ + public static function ignoreRoutes() + { + static::$registersRoutes = false; + + return new static; + } + /** * Configure Passport to not register its migrations. * @@ -688,4 +694,28 @@ public static function withoutCookieSerialization() return new static; } + + /** + * Instruct Passport to enable cookie encryption. + * + * @return static + */ + public static function withCookieEncryption() + { + static::$decryptsCookies = true; + + return new static; + } + + /** + * Instruct Passport to disable cookie encryption. + * + * @return static + */ + public static function withoutCookieEncryption() + { + static::$decryptsCookies = false; + + return new static; + } } diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 87da1b4..393e0ae 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -4,16 +4,18 @@ use DateInterval; use Illuminate\Auth\Events\Logout; -use Illuminate\Auth\RequestGuard; use Illuminate\Config\Repository as Config; +use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cookie; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Request; +use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; use Laravel\Passport\Bridge\PersonalAccessGrant; use Laravel\Passport\Bridge\RefreshTokenRepository; use Laravel\Passport\Guards\TokenGuard; +use Laravel\Passport\Http\Controllers\AuthorizationController; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Parser; use League\OAuth2\Server\AuthorizationServer; @@ -34,13 +36,50 @@ class PassportServiceProvider extends ServiceProvider */ public function boot() { - $this->loadViewsFrom(__DIR__.'/../resources/views', 'passport'); + $this->registerRoutes(); + $this->registerResources(); + $this->registerPublishing(); + $this->registerCommands(); $this->deleteCookieOnLogout(); + } - if ($this->app->runningInConsole()) { - $this->registerMigrations(); + /** + * Register the Passport routes. + * + * @return void + */ + protected function registerRoutes() + { + if (Passport::$registersRoutes) { + Route::group([ + 'as' => 'passport.', + 'prefix' => config('passport.path', 'oauth'), + 'namespace' => 'Laravel\Passport\Http\Controllers', + ], function () { + $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); + }); + } + } + /** + * Register the Passport resources. + * + * @return void + */ + protected function registerResources() + { + $this->loadViewsFrom(__DIR__.'/../resources/views', 'passport'); + } + + /** + * Register the package's publishable resources. + * + * @return void + */ + protected function registerPublishing() + { + if ($this->app->runningInConsole()) { $this->publishes([ __DIR__.'/../database/migrations' => database_path('migrations'), ], 'passport-migrations'); @@ -52,26 +91,24 @@ public function boot() $this->publishes([ __DIR__.'/../config/passport.php' => config_path('passport.php'), ], 'passport-config'); - - $this->commands([ - Console\InstallCommand::class, - Console\ClientCommand::class, - Console\HashCommand::class, - Console\KeysCommand::class, - Console\PurgeCommand::class, - ]); } } /** - * Register Passport's migration files. + * Register the Passport Artisan commands. * * @return void */ - protected function registerMigrations() + protected function registerCommands() { - if (Passport::$runsMigrations) { - return $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + if ($this->app->runningInConsole()) { + $this->commands([ + Console\InstallCommand::class, + Console\ClientCommand::class, + Console\HashCommand::class, + Console\KeysCommand::class, + Console\PurgeCommand::class, + ]); } } @@ -82,11 +119,19 @@ protected function registerMigrations() */ public function register() { + $this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport'); + + $this->app->when(AuthorizationController::class) + ->needs(StatefulGuard::class) + ->give(fn () => Auth::guard(config('passport.guard', null))); + $this->registerAuthorizationServer(); $this->registerClientRepository(); $this->registerJWTParser(); $this->registerResourceServer(); $this->registerGuard(); + + Passport::authorizationView('passport::authorize'); } /** @@ -227,6 +272,18 @@ protected function registerClientRepository() }); } + /** + * Register the JWT Parser. + * + * @return void + */ + protected function registerJWTParser() + { + $this->app->singleton(Parser::class, function () { + return Configuration::forUnsecuredSigner()->parser(); + }); + } + /** * Register the resource server. * @@ -259,18 +316,6 @@ protected function makeCryptKey($type) return new CryptKey($key, null, false); } - /** - * Register the JWT Parser. - * - * @return void - */ - protected function registerJWTParser() - { - $this->app->singleton(Parser::class, function () { - return Configuration::forUnsecuredSigner()->parser(); - }); - } - /** * Register the token guard. * @@ -291,19 +336,18 @@ protected function registerGuard() * Make an instance of the token guard. * * @param array $config - * @return \Illuminate\Auth\RequestGuard + * @return \Laravel\Passport\Guards\TokenGuard */ protected function makeGuard(array $config) { - return new RequestGuard(function ($request) use ($config) { - return (new TokenGuard( - $this->app->make(ResourceServer::class), - new PassportUserProvider(Auth::createUserProvider($config['provider']), $config['provider']), - $this->app->make(TokenRepository::class), - $this->app->make(ClientRepository::class), - $this->app->make('encrypter') - ))->user($request); - }, $this->app['request']); + return new TokenGuard( + $this->app->make(ResourceServer::class), + new PassportUserProvider(Auth::createUserProvider($config['provider']), $config['provider']), + $this->app->make(TokenRepository::class), + $this->app->make(ClientRepository::class), + $this->app->make('encrypter'), + $this->app->make('request') + ); } /** diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index 37b868a..271262a 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -35,8 +35,6 @@ class PersonalAccessTokenFactory * The JWT token parser instance. * * @var \Lcobucci\JWT\Parser - * - * @deprecated This property will be removed in a future Passport version. */ protected $jwt; @@ -128,7 +126,7 @@ protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $ * @param array $response * @return \Laravel\Passport\Token */ - protected function findAccessToken(array $response) + public function findAccessToken(array $response) { return $this->tokens->find( $this->jwt->parse($response['access_token'])->claims()->get('jti') diff --git a/src/RefreshToken.php b/src/RefreshToken.php index a327416..2ca52f8 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -1,4 +1,5 @@ router = $router; - } - - /** - * Register routes for transient tokens, clients, and personal access tokens. - * - * @return void - */ - public function all() - { - $this->forAuthorization(); - $this->forAccessTokens(); - $this->forTransientTokens(); - $this->forClients(); - $this->forPersonalAccessTokens(); - } - - /** - * Register the routes needed for authorization. - * - * @return void - */ - public function forAuthorization() - { - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/authorize', [ - 'uses' => 'AuthorizationController@authorize', - 'as' => 'passport.authorizations.authorize', - ]); - - $router->post('/authorize', [ - 'uses' => 'ApproveAuthorizationController@approve', - 'as' => 'passport.authorizations.approve', - ]); - - $router->delete('/authorize', [ - 'uses' => 'DenyAuthorizationController@deny', - 'as' => 'passport.authorizations.deny', - ]); - }); - } - - /** - * Register the routes for retrieving and issuing access tokens. - * - * @return void - */ - public function forAccessTokens() - { - $this->router->post('/token', [ - 'uses' => 'AccessTokenController@issueToken', - 'as' => 'passport.token', - 'middleware' => 'throttle', - ]); - - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/tokens', [ - 'uses' => 'AuthorizedAccessTokenController@forUser', - 'as' => 'passport.tokens.index', - ]); - - $router->delete('/tokens/{token_id}', [ - 'uses' => 'AuthorizedAccessTokenController@destroy', - 'as' => 'passport.tokens.destroy', - ]); - }); - } - - /** - * Register the routes needed for refreshing transient tokens. - * - * @return void - */ - public function forTransientTokens() - { - $this->router->post('/token/refresh', [ - 'middleware' => ['web', 'auth'], - 'uses' => 'TransientTokenController@refresh', - 'as' => 'passport.token.refresh', - ]); - } - - /** - * Register the routes needed for managing clients. - * - * @return void - */ - public function forClients() - { - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/clients', [ - 'uses' => 'ClientController@forUser', - 'as' => 'passport.clients.index', - ]); - - $router->post('/clients', [ - 'uses' => 'ClientController@store', - 'as' => 'passport.clients.store', - ]); - - $router->put('/clients/{client_id}', [ - 'uses' => 'ClientController@update', - 'as' => 'passport.clients.update', - ]); - - $router->delete('/clients/{client_id}', [ - 'uses' => 'ClientController@destroy', - 'as' => 'passport.clients.destroy', - ]); - }); - } - - /** - * Register the routes needed for managing personal access tokens. - * - * @return void - */ - public function forPersonalAccessTokens() - { - $this->router->group(['middleware' => ['web', 'auth']], function ($router) { - $router->get('/scopes', [ - 'uses' => 'ScopeController@all', - 'as' => 'passport.scopes.index', - ]); - - $router->get('/personal-access-tokens', [ - 'uses' => 'PersonalAccessTokenController@forUser', - 'as' => 'passport.personal.tokens.index', - ]); - - $router->post('/personal-access-tokens', [ - 'uses' => 'PersonalAccessTokenController@store', - 'as' => 'passport.personal.tokens.store', - ]); - - $router->delete('/personal-access-tokens/{token_id}', [ - 'uses' => 'PersonalAccessTokenController@destroy', - 'as' => 'passport.personal.tokens.destroy', - ]); - }); - } -} diff --git a/src/TokenRepository.php b/src/TokenRepository.php index d99f898..eccc7ef 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -4,7 +4,6 @@ use MongoDB\BSON\UTCDateTime; use Mongolid\Cursor\CursorInterface; -use Mongolid\Model\ModelInterface; class TokenRepository { @@ -70,9 +69,8 @@ public function forUser($userId) /** * Get a valid token instance for the given user and client. * - * @param ModelInterface $user - * @param \Laravel\Passport\Client $client - * + * @param \Illuminate\Contracts\Auth\Authenticatable $user + * @param \Laravel\Passport\Client $client * @return \Laravel\Passport\Token|null */ public function getValidToken($user, $client) @@ -134,9 +132,8 @@ public function isAccessTokenRevoked($id) /** * Find a valid token for the given user and client. * - * @param ModelInterface $user - * @param \Laravel\Passport\Client $client - * + * @param \Illuminate\Contracts\Auth\Authenticatable $user + * @param \Laravel\Passport\Client $client * @return \Laravel\Passport\Token|null */ public function findValidToken($user, $client) diff --git a/tests/Feature/AccessTokenControllerTest.php b/tests/Feature/AccessTokenControllerTest.php index e56c554..cbe881c 100644 --- a/tests/Feature/AccessTokenControllerTest.php +++ b/tests/Feature/AccessTokenControllerTest.php @@ -9,6 +9,7 @@ use Laravel\Passport\ClientRepository; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Passport; +use Laravel\Passport\PersonalAccessTokenFactory; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; use Lcobucci\JWT\Configuration; @@ -57,19 +58,16 @@ public function testGettingAccessTokenWithClientCredentialsGrant() $response->assertHeader('cache-control', 'no-store, private'); $response->assertHeader('content-type', 'application/json; charset=UTF-8'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayHasKey('token_type', $decodedResponse); $this->assertArrayHasKey('expires_in', $decodedResponse); $this->assertArrayHasKey('access_token', $decodedResponse); $this->assertSame('Bearer', $decodedResponse['token_type']); - $expiresInSeconds = 31536000; + $expiresInSeconds = 31622400; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); - $jwtAccessToken = Configuration::forUnsecuredSigner()->parser()->parse($decodedResponse['access_token']); - $this->assertEquals($client, $this->app->make(ClientRepository::class)->findActive(current($jwtAccessToken->claims()->get('aud')))); - - $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->claims()->get('jti')); + $token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse); $this->assertInstanceOf(Token::class, $token); $this->assertEquals($client, $token->client()); $this->assertFalse($token->revoked); @@ -111,7 +109,7 @@ public function testGettingAccessTokenWithClientCredentialsGrantInvalidClientSec $response->assertHeader('cache-control', 'no-cache, private'); $response->assertHeader('content-type', 'application/json'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayNotHasKey('token_type', $decodedResponse); $this->assertArrayNotHasKey('expires_in', $decodedResponse); @@ -167,21 +165,17 @@ public function testGettingAccessTokenWithPasswordGrant() $response->assertHeader('cache-control', 'no-store, private'); $response->assertHeader('content-type', 'application/json; charset=UTF-8'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayHasKey('token_type', $decodedResponse); $this->assertArrayHasKey('expires_in', $decodedResponse); $this->assertArrayHasKey('access_token', $decodedResponse); $this->assertArrayHasKey('refresh_token', $decodedResponse); $this->assertSame('Bearer', $decodedResponse['token_type']); - $expiresInSeconds = 31536000; + $expiresInSeconds = 31622400; $this->assertEqualsWithDelta($expiresInSeconds, $decodedResponse['expires_in'], 5); - $jwtAccessToken = Configuration::forUnsecuredSigner()->parser()->parse($decodedResponse['access_token']); - $this->assertEquals($client, $this->app->make(ClientRepository::class)->findActive(current($jwtAccessToken->claims()->get('aud')))); - $this->assertEquals($user, $this->app->make('auth')->createUserProvider()->retrieveById($jwtAccessToken->claims()->get('sub'))); - - $token = $this->app->make(TokenRepository::class)->find($jwtAccessToken->claims()->get('jti')); + $token = $this->app->make(PersonalAccessTokenFactory::class)->findAccessToken($decodedResponse); $this->assertInstanceOf(Token::class, $token); $this->assertFalse($token->revoked); $this->assertEquals($user, $token->user()); @@ -226,7 +220,7 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidPassword() $response->assertHeader('cache-control', 'no-cache, private'); $response->assertHeader('content-type', 'application/json'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayNotHasKey('token_type', $decodedResponse); $this->assertArrayNotHasKey('expires_in', $decodedResponse); @@ -278,7 +272,7 @@ public function testGettingAccessTokenWithPasswordGrantWithInvalidClientSecret() $response->assertHeader('cache-control', 'no-cache, private'); $response->assertHeader('content-type', 'application/json'); - $decodedResponse = $response->decodeResponseJson(); + $decodedResponse = $response->decodeResponseJson()->json(); $this->assertArrayNotHasKey('token_type', $decodedResponse); $this->assertArrayNotHasKey('expires_in', $decodedResponse); diff --git a/tests/Feature/ActingAsClientTest.php b/tests/Feature/ActingAsClientTest.php index 8fc99b7..f0a92c7 100644 --- a/tests/Feature/ActingAsClientTest.php +++ b/tests/Feature/ActingAsClientTest.php @@ -7,9 +7,8 @@ use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\Passport; -use Orchestra\Testbench\TestCase; -class ActingAsClientTest extends TestCase +class ActingAsClientTest extends PassportTestCase { public function testActingAsClientWhenTheRouteIsProtectedByCheckClientCredentialsMiddleware() { @@ -46,4 +45,11 @@ public function testActingAsClientWhenTheRouteIsProtectedByCheckClientCredential $response->assertSuccessful(); $response->assertSee('bar'); } + + public function testActingAsClientSetsTheClientOnTheGuard() + { + Passport::actingAsClient($client = new Client()); + + $this->assertSame($client, app('auth')->client()); + } } diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php index aa1b3ec..bf0b953 100644 --- a/tests/Feature/ActingAsTest.php +++ b/tests/Feature/ActingAsTest.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Routing\Registrar; use Illuminate\Foundation\Auth\User; +use Illuminate\Support\Facades\Route; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Http\Middleware\CheckForAnyScope; use Laravel\Passport\Http\Middleware\CheckScopes; @@ -64,6 +65,40 @@ public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware( $response->assertSuccessful(); $response->assertSee('bar'); } + + public function testActingAsWhenTheRouteIsProtectedByCheckScopesMiddlewareWithInheritance() + { + Passport::$withInheritedScopes = true; + + $this->withoutExceptionHandling(); + + Route::middleware(CheckScopes::class.':foo:bar,baz:qux')->get('/foo', function () { + return 'bar'; + }); + + Passport::actingAs(new PassportUser(), ['foo', 'baz']); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } + + public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddlewareWithInheritance() + { + Passport::$withInheritedScopes = true; + + $this->withoutExceptionHandling(); + + Route::middleware(CheckForAnyScope::class.':foo:baz,baz:qux')->get('/foo', function () { + return 'bar'; + }); + + Passport::actingAs(new PassportUser(), ['foo']); + + $response = $this->get('/foo'); + $response->assertSuccessful(); + $response->assertSee('bar'); + } } class PassportUser extends User diff --git a/tests/Feature/PassportTestCase.php b/tests/Feature/PassportTestCase.php index 28dda3e..c0b3f48 100644 --- a/tests/Feature/PassportTestCase.php +++ b/tests/Feature/PassportTestCase.php @@ -22,8 +22,6 @@ protected function setUp(): void $this->dropDatabase(); - Passport::routes(); - Passport::loadKeysFrom(self::KEYS); @unlink(self::PUBLIC_KEY); @@ -81,5 +79,6 @@ protected function getPackageProviders($app) */ protected function getUserClass() { + return \Laravel\Passport\Tests\Stubs\User::class; } } diff --git a/tests/Stubs/User.php b/tests/Stubs/User.php new file mode 100644 index 0000000..1eeacd4 --- /dev/null +++ b/tests/Stubs/User.php @@ -0,0 +1,10 @@ +getBody()->write(json_encode(['access_token' => 'access-token'])); @@ -36,7 +34,7 @@ public function test_a_token_can_be_issued() ->with($request, $response) ->andReturn($psrResponse); - $controller = new AccessTokenController($server, $tokens, $jwt); + $controller = new AccessTokenController($server, $tokens); $this->assertSame('{"access_token":"access-token"}', $controller->issueToken($request)->getContent()); } @@ -44,14 +42,13 @@ public function test_a_token_can_be_issued() public function test_exceptions_are_handled() { $tokens = m::mock(TokenRepository::class); - $jwt = m::mock(Parser::class); $server = m::mock(AuthorizationServer::class); $server->shouldReceive('respondToAccessTokenRequest')->with( m::type(ServerRequestInterface::class), m::type(ResponseInterface::class) )->andThrow(LeagueException::invalidCredentials()); - $controller = new AccessTokenController($server, $tokens, $jwt); + $controller = new AccessTokenController($server, $tokens); $this->expectException(OAuthServerException::class); diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index cf7e495..6892ed2 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -2,14 +2,16 @@ namespace Laravel\Passport\Tests\Unit; -use Illuminate\Contracts\Routing\ResponseFactory; +use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Http\Request; use Laravel\Passport\Bridge\Scope; use Laravel\Passport\Bridge\ScopeRepository; use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\OAuthServerException; use Laravel\Passport\Http\Controllers\AuthorizationController; +use Laravel\Passport\Http\Responses\AuthorizationViewResponse; use Laravel\Passport\Passport; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -37,17 +39,21 @@ public function test_authorization_view_is_presented() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $guard, $response); + $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $server->shouldReceive('validateAuthorizationRequest')->andReturn($authRequest = m::mock()); $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $session->shouldReceive('put')->withSomeOfArgs('authToken'); $session->shouldReceive('put')->with('authRequest', $authRequest); - $request->shouldReceive('user')->andReturn($user = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); + $request->shouldReceive('get')->with('prompt')->andReturn(null); $authRequest->shouldReceive('getClient')->andReturn($clientEntity = m::mock(ClientEntityInterface::class)); $authRequest->shouldReceive('getScopes')->andReturn($scopes = [new Scope('scope-1')]); @@ -56,21 +62,20 @@ public function test_authorization_view_is_presented() $clients = m::mock(ClientRepository::class); $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); - $client->shouldReceive('skipsAuthorization')->andReturn(false); - $response->shouldReceive('view')->once()->andReturnUsing(function ($view, $data) use ($client, $user) { - $this->assertSame('passport::authorize', $view); + $tokens = m::mock(TokenRepository::class); + $tokens->shouldReceive('findValidToken')->with($user, $client)->andReturnNull(); + + $response->shouldReceive('withParameters')->once()->andReturnUsing(function ($data) use ($client, $user, $request) { $this->assertEquals($client, $data['client']); $this->assertEquals($user, $data['user']); + $this->assertEquals($request, $data['request']); $this->assertSame('description', $data['scopes'][0]->description); return 'view'; }); - $tokens = m::mock(TokenRepository::class); - $tokens->shouldReceive('findValidToken')->with($user, $client)->andReturnNull(); - $scopeRepository = m::mock(ScopeRepository::class); $scopeRepository->shouldReceive('validateClientScopes')->with($scopes, $clientEntity)->andReturn(true); @@ -82,10 +87,12 @@ public function test_authorization_view_is_presented() public function test_authorization_exceptions_are_handled() { $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $guard, $response); + $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->andThrow(LeagueException::invalidCredentials()); $request = m::mock(Request::class); @@ -109,9 +116,13 @@ public function test_request_is_approved_if_valid_token_exists() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $psrResponse = new Response(); $psrResponse->getBody()->write('approved'); $server->shouldReceive('validateAuthorizationRequest') @@ -121,12 +132,14 @@ public function test_request_is_approved_if_valid_token_exists() ->andReturn($psrResponse); $request = m::mock(Request::class); - $request->shouldReceive('user')->once()->andReturn($user = m::mock()); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); + $request->shouldReceive('get')->with('prompt')->andReturn(null); - $authRequest->shouldReceive('getClient')->twice()->andReturn($clientEntity = m::mock(ClientEntityInterface::class)); - $authRequest->shouldReceive('getScopes')->twice()->andReturn($scopes = [new Scope('scope-1')]); + $authRequest->shouldReceive('getClient')->once()->andReturn($clientEntity = m::mock(ClientEntityInterface::class)); + $authRequest->shouldReceive('getScopes')->once()->andReturn($scopes = [new Scope('scope-1')]); $authRequest->shouldReceive('setUser')->once()->andReturnNull(); $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); @@ -134,12 +147,13 @@ public function test_request_is_approved_if_valid_token_exists() $clientEntity->shouldReceive('getIdentifier')->andReturn(1); $clients = m::mock(ClientRepository::class); - $clients->shouldReceive('find')->with(1)->andReturn($clientEntity); + $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); + + $client->shouldReceive('skipsAuthorization')->andReturn(false); $tokens = m::mock(TokenRepository::class); $tokens->shouldReceive('findValidToken') - ->once() - ->with($user, $clientEntity) + ->with($user, $client) ->andReturn($token = m::mock(Token::class)); $token->shouldReceive('getAttribute')->with('scopes')->andReturn(['scope-1']); @@ -158,9 +172,13 @@ public function test_request_is_approved_if_client_can_skip_authorization() ]); $server = m::mock(AuthorizationServer::class); - $response = m::mock(ResponseFactory::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $response); + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); $psrResponse = new Response(); $psrResponse->getBody()->write('approved'); $server->shouldReceive('validateAuthorizationRequest') @@ -170,12 +188,14 @@ public function test_request_is_approved_if_client_can_skip_authorization() ->andReturn($psrResponse); $request = m::mock(Request::class); - $request->shouldReceive('user')->once()->andReturn($user = m::mock()); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); $user->shouldReceive('getAuthIdentifier')->andReturn(1); $request->shouldNotReceive('session'); + $request->shouldReceive('get')->with('prompt')->andReturn(null); - $authRequest->shouldReceive('getClient')->twice()->andReturn($clientEntity = m::mock(ClientEntityInterface::class)); - $authRequest->shouldReceive('getScopes')->twice()->andReturn($scopes = [new Scope('scope-1')]); + $authRequest->shouldReceive('getClient')->once()->andReturn($clientEntity = m::mock(ClientEntityInterface::class)); + $authRequest->shouldReceive('getScopes')->once()->andReturn($scopes = [new Scope('scope-1')]); $authRequest->shouldReceive('setUser')->once()->andReturnNull(); $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); @@ -198,4 +218,205 @@ public function test_request_is_approved_if_client_can_skip_authorization() m::mock(ServerRequestInterface::class), $request, $clients, $tokens, $scopeRepository )->getContent()); } + + public function test_authorization_view_is_presented_if_request_has_prompt_equals_to_consent() + { + Passport::tokensCan([ + 'scope-1' => 'description', + ]); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); + $server->shouldReceive('validateAuthorizationRequest') + ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + + $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('put')->withSomeOfArgs('authToken'); + $session->shouldReceive('put')->with('authRequest', $authRequest); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); + $request->shouldReceive('get')->with('prompt')->andReturn('consent'); + + $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); + $authRequest->shouldReceive('getScopes')->once()->andReturn([new Scope('scope-1')]); + + $clients = m::mock(ClientRepository::class); + $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); + $client->shouldReceive('skipsAuthorization')->andReturn(false); + + $tokens = m::mock(TokenRepository::class); + $tokens->shouldNotReceive('findValidToken'); + + $response->shouldReceive('withParameters')->once()->andReturnUsing(function ($data) use ($client, $user, $request) { + $this->assertEquals($client, $data['client']); + $this->assertEquals($user, $data['user']); + $this->assertEquals($request, $data['request']); + $this->assertSame('description', $data['scopes'][0]->description); + + return 'view'; + }); + + $scopeRepository = m::mock(ScopeRepository::class); + + $this->assertSame('view', $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens, $scopeRepository + )); + } + + public function test_authorization_denied_if_request_has_prompt_equals_to_none() + { + $this->expectException('Laravel\Passport\Exceptions\OAuthServerException'); + + Passport::tokensCan([ + 'scope-1' => 'description', + ]); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(false); + $guard->shouldReceive('user')->andReturn($user = m::mock()); + $server->shouldReceive('validateAuthorizationRequest') + ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + $server->shouldReceive('completeAuthorizationRequest') + ->with($authRequest, m::type(ResponseInterface::class)) + ->once() + ->andThrow('League\OAuth2\Server\Exception\OAuthServerException'); + + $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('forget')->with('promptedForLogin')->once(); + $user->shouldReceive('getAuthIdentifier')->andReturn(1); + $request->shouldReceive('get')->with('prompt')->andReturn('none'); + + $authRequest->shouldReceive('getClient->getIdentifier')->once()->andReturn(1); + $authRequest->shouldReceive('getScopes')->once()->andReturn([new Scope('scope-1')]); + $authRequest->shouldReceive('setUser')->once()->andReturnNull(); + $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(false); + + $clients = m::mock(ClientRepository::class); + $clients->shouldReceive('find')->with(1)->andReturn($client = m::mock(Client::class)); + $client->shouldReceive('skipsAuthorization')->andReturn(false); + + $tokens = m::mock(TokenRepository::class); + $tokens->shouldReceive('findValidToken') + ->with($user, $client) + ->andReturnNull(); + + $scopeRepository = m::mock(ScopeRepository::class); + + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens, $scopeRepository + ); + } + + public function test_authorization_denied_if_unauthenticated_and_request_has_prompt_equals_to_none() + { + $server = m::mock(AuthorizationServer::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(true); + $server->shouldReceive('validateAuthorizationRequest') + ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); + $server->shouldNotReceive('completeAuthorizationRequest'); + + $request = m::mock(Request::class); + $request->shouldNotReceive('user'); + $request->shouldReceive('get')->with('prompt')->andReturn('none'); + + $authRequest->shouldNotReceive('setUser'); + $authRequest->shouldReceive('setAuthorizationApproved')->with(false); + $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); + $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost'); + $authRequest->shouldReceive('getState')->andReturn('state'); + $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + $scopeRepository = m::mock(ScopeRepository::class); + + try { + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens, $scopeRepository + ); + } catch (\Laravel\Passport\Exceptions\OAuthServerException $e) { + $this->assertStringStartsWith( + 'http://localhost?state=state&error=access_denied&error_description=', + $e->render($request)->headers->get('location') + ); + } + } + + public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_login() + { + $this->expectException(AuthenticationException::class); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(false); + $server->shouldReceive('validateAuthorizationRequest')->once(); + $guard->shouldReceive('logout')->once(); + + $request = m::mock(Request::class); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('invalidate')->once(); + $session->shouldReceive('regenerateToken')->once(); + $session->shouldReceive('get')->with('promptedForLogin', false)->once()->andReturn(false); + $session->shouldReceive('put')->with('promptedForLogin', true)->once(); + $session->shouldNotReceive('forget')->with('promptedForLogin'); + $request->shouldReceive('get')->with('prompt')->andReturn('login'); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + $scopeRepository = m::mock(ScopeRepository::class); + + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens, $scopeRepository + ); + } + + public function test_user_should_be_authenticated() + { + $this->expectException(AuthenticationException::class); + + $server = m::mock(AuthorizationServer::class); + $response = m::mock(AuthorizationViewResponse::class); + $guard = m::mock(StatefulGuard::class); + + $controller = new AuthorizationController($server, $guard, $response); + + $guard->shouldReceive('guest')->andReturn(true); + $server->shouldReceive('validateAuthorizationRequest')->once(); + + $request = m::mock(Request::class); + $request->shouldNotReceive('user'); + $request->shouldReceive('session')->andReturn($session = m::mock()); + $session->shouldReceive('put')->with('promptedForLogin', true)->once(); + $session->shouldNotReceive('forget')->with('promptedForLogin'); + $request->shouldReceive('get')->with('prompt')->andReturn(null); + + $clients = m::mock(ClientRepository::class); + $tokens = m::mock(TokenRepository::class); + $scopeRepository = m::mock(ScopeRepository::class); + + $controller->authorize( + m::mock(ServerRequestInterface::class), $request, $clients, $tokens, $scopeRepository + ); + } } diff --git a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php index 035bb32..8e4b91f 100644 --- a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -87,7 +88,7 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckClientCredentialsTest.php b/tests/Unit/CheckClientCredentialsTest.php index 36e410d..0a30b19 100644 --- a/tests/Unit/CheckClientCredentialsTest.php +++ b/tests/Unit/CheckClientCredentialsTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Laravel\Passport\Client; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentials; use Laravel\Passport\Token; use Laravel\Passport\TokenRepository; @@ -84,7 +85,7 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() public function test_exception_is_thrown_when_oauth_throws_exception() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $tokenRepository = m::mock(TokenRepository::class); $resourceServer = m::mock(ResourceServer::class); diff --git a/tests/Unit/CheckForAnyScopeTest.php b/tests/Unit/CheckForAnyScopeTest.php index cf9e04c..e567fee 100644 --- a/tests/Unit/CheckForAnyScopeTest.php +++ b/tests/Unit/CheckForAnyScopeTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckForAnyScope as CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -47,7 +48,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); @@ -60,7 +61,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); diff --git a/tests/Unit/CheckScopesTest.php b/tests/Unit/CheckScopesTest.php index 3eb172b..21e8b40 100644 --- a/tests/Unit/CheckScopesTest.php +++ b/tests/Unit/CheckScopesTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckScopes; use Mockery as m; use PHPUnit\Framework\TestCase; @@ -46,7 +47,7 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() public function test_exception_is_thrown_if_no_authenticated_user() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); @@ -59,7 +60,7 @@ public function test_exception_is_thrown_if_no_authenticated_user() public function test_exception_is_thrown_if_no_token() { - $this->expectException('Illuminate\Auth\AuthenticationException'); + $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; $request = m::mock(); diff --git a/tests/Unit/DenyAuthorizationControllerTest.php b/tests/Unit/DenyAuthorizationControllerTest.php index 437d332..bca52fb 100644 --- a/tests/Unit/DenyAuthorizationControllerTest.php +++ b/tests/Unit/DenyAuthorizationControllerTest.php @@ -2,12 +2,13 @@ namespace Laravel\Passport\Tests\Unit; -use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; use Laravel\Passport\Http\Controllers\DenyAuthorizationController; +use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\RequestTypes\AuthorizationRequest; use Mockery as m; use PHPUnit\Framework\TestCase; +use Psr\Http\Message\ResponseInterface; class DenyAuthorizationControllerTest extends TestCase { @@ -18,130 +19,34 @@ protected function tearDown(): void public function test_authorization_can_be_denied() { - $response = m::mock(ResponseFactory::class); + $this->expectException('Laravel\Passport\Exceptions\OAuthServerException'); - $controller = new DenyAuthorizationController($response); + $server = m::mock(AuthorizationServer::class); + $controller = new DenyAuthorizationController($server); $request = m::mock(Request::class); $request->shouldReceive('session')->andReturn($session = m::mock()); $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); $request->shouldReceive('has')->with('auth_token')->andReturn(true); $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); + $session->shouldReceive('get') + ->once() + ->with('authRequest') + ->andReturn($authRequest = m::mock( + AuthorizationRequest::class + )); $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost'); + $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(false); - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); + $server->shouldReceive('completeAuthorizationRequest') + ->with($authRequest, m::type(ResponseInterface::class)) + ->andThrow('League\OAuth2\Server\Exception\OAuthServerException'); - $this->assertSame('http://localhost?error=access_denied&state=state', $controller->deny($request)); - } - - public function test_authorization_can_be_denied_with_multiple_redirect_uris() - { - $response = m::mock(ResponseFactory::class); - - $controller = new DenyAuthorizationController($response); - - $request = m::mock(Request::class); - - $request->shouldReceive('session')->andReturn($session = m::mock()); - $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); - $request->shouldReceive('has')->with('auth_token')->andReturn(true); - $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); - - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); - - $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn(['http://localhost.localdomain', 'http://localhost']); - - $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); - - $this->assertSame('http://localhost?error=access_denied&state=state', $controller->deny($request)); - } - - public function test_authorization_can_be_denied_implicit() - { - $response = m::mock(ResponseFactory::class); - - $controller = new DenyAuthorizationController($response); - - $request = m::mock(Request::class); - - $request->shouldReceive('session')->andReturn($session = m::mock()); - $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); - $request->shouldReceive('has')->with('auth_token')->andReturn(true); - $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); - - $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); - - $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('implicit'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost'); - - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); - - $this->assertSame('http://localhost#error=access_denied&state=state', $controller->deny($request)); - } - - public function test_authorization_can_be_denied_with_existing_query_string() - { - $response = m::mock(ResponseFactory::class); - - $controller = new DenyAuthorizationController($response); - - $request = m::mock(Request::class); - - $request->shouldReceive('session')->andReturn($session = m::mock()); - $request->shouldReceive('user')->andReturn(new DenyAuthorizationControllerFakeUser); - $request->shouldReceive('input')->with('state')->andReturn('state'); - $request->shouldReceive('has')->with('auth_token')->andReturn(true); - $request->shouldReceive('get')->with('auth_token')->andReturn('foo'); - - $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); - $session->shouldReceive('get')->once()->with('authRequest')->andReturn($authRequest = m::mock( - AuthorizationRequest::class - )); - - $authRequest->shouldReceive('setUser')->once(); - $authRequest->shouldReceive('getGrantTypeId')->andReturn('authorization_code'); - $authRequest->shouldReceive('setAuthorizationApproved')->once()->with(true); - $authRequest->shouldReceive('getRedirectUri')->andReturn('http://localhost?action=some_action'); - $authRequest->shouldReceive('getClient->getRedirectUri')->andReturn('http://localhost?action=some_action'); - - $response->shouldReceive('redirectTo')->once()->andReturnUsing(function ($url) { - return $url; - }); - - $this->assertSame('http://localhost?action=some_action&error=access_denied&state=state', $controller->deny($request)); + $controller->deny($request); } public function test_auth_request_should_exist() @@ -149,9 +54,9 @@ public function test_auth_request_should_exist() $this->expectException('Exception'); $this->expectExceptionMessage('Authorization request was not present in the session.'); - $response = m::mock(ResponseFactory::class); + $server = m::mock(AuthorizationServer::class); - $controller = new DenyAuthorizationController($response); + $controller = new DenyAuthorizationController($server); $request = m::mock(Request::class); @@ -164,7 +69,7 @@ public function test_auth_request_should_exist() $session->shouldReceive('get')->once()->with('authToken')->andReturn('foo'); $session->shouldReceive('get')->once()->with('authRequest')->andReturnNull(); - $response->shouldReceive('redirectTo')->never(); + $server->shouldReceive('completeAuthorizationRequest')->never(); $controller->deny($request); } diff --git a/tests/Unit/PersonalAccessTokenFactoryTest.php b/tests/Unit/PersonalAccessTokenFactoryTest.php index 49cf029..99368b6 100644 --- a/tests/Unit/PersonalAccessTokenFactoryTest.php +++ b/tests/Unit/PersonalAccessTokenFactoryTest.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Tests\Unit; +use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; use Laravel\Passport\PersonalAccessTokenFactory; use Laravel\Passport\PersonalAccessTokenResult; @@ -56,7 +57,7 @@ public function test_access_token_can_be_created() } } -class PersonalAccessTokenFactoryTestClientStub +class PersonalAccessTokenFactoryTestClientStub extends Client { public $_id = 1; diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index 83608d8..6143938 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -37,11 +37,40 @@ public function test_user_can_be_pulled_via_bearer_token() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); + $request = Request::create('/'); + $request->headers->set('Authorization', 'Bearer token'); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); + $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $psr->shouldReceive('getAttribute')->with('oauth_access_token_id')->andReturn('token'); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); + $tokens->shouldReceive('find')->once()->with('token')->andReturn($token = m::mock()); + $clients->shouldReceive('revoked')->with(1)->andReturn(false); + $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); + + $user = $guard->user(); + + $this->assertInstanceOf(TokenGuardTestUser::class, $user); + $this->assertEquals($token, $user->token()); + } + + public function test_user_is_resolved_only_once() + { + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = m::mock(Encrypter::class); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); @@ -52,10 +81,15 @@ public function test_user_can_be_pulled_via_bearer_token() $clients->shouldReceive('revoked')->with(1)->andReturn(false); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); - $user = $guard->user($request); + $user = $guard->user(); + + $userProvider->shouldReceive('retrieveById')->never(); + + $user2 = $guard->user(); $this->assertInstanceOf(TokenGuardTestUser::class, $user); $this->assertEquals($token, $user->token()); + $this->assertSame($user, $user2); } public function test_no_user_is_returned_when_oauth_throws_exception() @@ -71,19 +105,19 @@ public function test_no_user_is_returned_when_oauth_throws_exception() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); // Assert that `validateAuthenticatedRequest` isn't called twice on failure. - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_null_is_returned_if_no_user_is_found() @@ -98,18 +132,18 @@ public function test_null_is_returned_if_no_user_is_found() ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_user_id')->andReturn(1); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $userProvider->shouldReceive('retrieveById')->with(1)->andReturn(null); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header() @@ -124,8 +158,6 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', @@ -137,10 +169,12 @@ public function test_users_may_be_retrieved_from_cookies_with_csrf_token_header( ], str_repeat('a', 16), 'HS256'), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); } @@ -157,8 +191,6 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); $request->cookies->set('laravel_token', @@ -170,10 +202,12 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header( ], str_repeat('a', 16), 'HS256'), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); } @@ -186,8 +220,6 @@ public function test_cookie_xsrf_is_verified_against_csrf_token_header() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'wrong_token'); $request->cookies->set('laravel_token', @@ -199,9 +231,11 @@ public function test_cookie_xsrf_is_verified_against_csrf_token_header() ], str_repeat('a', 16), 'HS256')) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_cookie_xsrf_is_verified_against_xsrf_token_header() @@ -212,8 +246,6 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt('wrong_token', false)); $request->cookies->set('laravel_token', @@ -225,9 +257,11 @@ public function test_cookie_xsrf_is_verified_against_xsrf_token_header() ], str_repeat('a', 16), 'HS256')) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_when_using_a_custom_encryption_key() @@ -246,8 +280,6 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); $request->cookies->set('laravel_token', @@ -259,10 +291,12 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ ], Passport::tokenEncryptionKey($encrypter), 'HS256'), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); @@ -270,15 +304,55 @@ public function test_users_may_be_retrieved_from_cookies_with_xsrf_token_header_ Passport::encryptTokensUsing(null); } - public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() + public function test_users_may_be_retrieved_from_cookies_without_encryption() { + Passport::withoutCookieEncryption(); + Passport::encryptTokensUsing(function (EncrypterContract $encrypter) { + return $encrypter->getKey().'.mykey'; + }); + $resourceServer = m::mock(ResourceServer::class); $userProvider = m::mock(PassportUserProvider::class); $tokens = m::mock(TokenRepository::class); $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); + $clients->shouldReceive('findActive') + ->with(1) + ->andReturn(new TokenGuardTestClient); + + $request = Request::create('/'); + $request->headers->set('X-XSRF-TOKEN', $encrypter->encrypt(CookieValuePrefix::create('X-XSRF-TOKEN', $encrypter->getKey()).'token', false)); + $request->cookies->set('laravel_token', + JWT::encode([ + 'sub' => 1, + 'aud' => 1, + 'csrf' => 'token', + 'expiry' => Carbon::now()->addMinutes(10)->getTimestamp(), + ], Passport::tokenEncryptionKey($encrypter), 'HS256') + ); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); + $userProvider->shouldReceive('getProviderName')->andReturn(null); + + $user = $guard->user(); + + $this->assertEquals($expectedUser, $user); + + // Revert to the default encryption method + Passport::withCookieEncryption(); + Passport::encryptTokensUsing(null); + } + + public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() + { + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = new Encrypter(str_repeat('a', 16)); $request = Request::create('/'); $request->cookies->set('XSRF-TOKEN', $encrypter->encrypt('token', false)); @@ -291,9 +365,11 @@ public function test_xsrf_token_cookie_without_a_token_header_is_not_accepted() ], str_repeat('a', 16), 'HS256')) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_expired_cookies_may_not_be_used() @@ -304,8 +380,6 @@ public function test_expired_cookies_may_not_be_used() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', @@ -317,9 +391,11 @@ public function test_expired_cookies_may_not_be_used() ], str_repeat('a', 16), 'HS256')) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->never(); - $this->assertNull($guard->user($request)); + $this->assertNull($guard->user()); } public function test_csrf_check_can_be_disabled() @@ -334,8 +410,6 @@ public function test_csrf_check_can_be_disabled() ->with(1) ->andReturn(new TokenGuardTestClient); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - Passport::ignoreCsrfToken(); $request = Request::create('/'); @@ -347,10 +421,12 @@ public function test_csrf_check_can_be_disabled() ], str_repeat('a', 16), 'HS256'), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $userProvider->shouldReceive('retrieveById')->with(1)->andReturn($expectedUser = new TokenGuardTestUser); $userProvider->shouldReceive('getProviderName')->andReturn(null); - $user = $guard->user($request); + $user = $guard->user(); $this->assertEquals($expectedUser, $user); } @@ -363,18 +439,45 @@ public function test_client_can_be_pulled_via_bearer_token() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); + $request = Request::create('/'); + $request->headers->set('Authorization', 'Bearer token'); + + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); + $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); + $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); + + $client = $guard->client(); + + $this->assertInstanceOf(TokenGuardTestClient::class, $client); + } + + public function test_client_is_resolved_only_once() + { + $resourceServer = m::mock(ResourceServer::class); + $userProvider = m::mock(PassportUserProvider::class); + $tokens = m::mock(TokenRepository::class); + $clients = m::mock(ClientRepository::class); + $encrypter = m::mock(Encrypter::class); $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $clients->shouldReceive('findActive')->with(1)->andReturn(new TokenGuardTestClient); - $client = $guard->client($request); + $client = $guard->client(); + + $clients->shouldReceive('findActive')->never(); + + $client2 = $guard->client(); $this->assertInstanceOf(TokenGuardTestClient::class, $client); + $this->assertSame($client, $client2); } public function test_no_client_is_returned_when_oauth_throws_exception() @@ -390,19 +493,19 @@ public function test_no_client_is_returned_when_oauth_throws_exception() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andThrow( new OAuthServerException('message', 500, 'error type') ); - $this->assertNull($guard->client($request)); + $this->assertNull($guard->client()); // Assert that `validateAuthenticatedRequest` isn't called twice on failure. - $this->assertNull($guard->client($request)); + $this->assertNull($guard->client()); } public function test_null_is_returned_if_no_client_is_found() @@ -413,16 +516,16 @@ public function test_null_is_returned_if_no_client_is_found() $clients = m::mock(ClientRepository::class); $encrypter = m::mock(Encrypter::class); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('Authorization', 'Bearer token'); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $resourceServer->shouldReceive('validateAuthenticatedRequest')->andReturn($psr = m::mock()); $psr->shouldReceive('getAttribute')->with('oauth_client_id')->andReturn(1); $clients->shouldReceive('findActive')->with(1)->andReturn(null); - $this->assertNull($guard->client($request)); + $this->assertNull($guard->client()); } public function test_clients_may_be_retrieved_from_cookies() @@ -433,8 +536,6 @@ public function test_clients_may_be_retrieved_from_cookies() $clients = m::mock(ClientRepository::class); $encrypter = new Encrypter(str_repeat('a', 16)); - $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter); - $request = Request::create('/'); $request->headers->set('X-CSRF-TOKEN', 'token'); $request->cookies->set('laravel_token', @@ -446,9 +547,11 @@ public function test_clients_may_be_retrieved_from_cookies() ], str_repeat('a', 16), 'HS256'), false) ); + $guard = new TokenGuard($resourceServer, $userProvider, $tokens, $clients, $encrypter, $request); + $clients->shouldReceive('findActive')->with(1)->andReturn($expectedClient = new TokenGuardTestClient); - $client = $guard->client($request); + $client = $guard->client(); $this->assertEquals($expectedClient, $client); }