diff --git a/.env b/.env index 47afb85..11c6cdf 100644 --- a/.env +++ b/.env @@ -29,8 +29,8 @@ BASE_URL='http://localhost:8080' # connexion hydra HYDRA_ADMIN_BASE_URL='http://hydra:4445' APP_LOCALES="fr,en" - - +SECURITY_PATTERN= +HASH_ALGO_LEGACY="sha256" ###> symfony/lock ### # Choose one of the stores below # postgresql+advisory://db_user:db_password@localhost/db_name diff --git a/.gitignore b/.gitignore index 52b996a..4f06bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,21 @@ - -###> symfony/framework-bundle ### /.env.local /.env.local.php /.env.*.local /config/secrets/prod/prod.decrypt.private.php /public/bundles/ /var/ -###< symfony/framework-bundle ### -supervisord.log -supervisord.pid + /vendor /tools/php-cs-fixer/vendor -###> symfony/webpack-encore-bundle ### /node_modules/ /public/build/ npm-debug.log yarn-error.log -###< symfony/webpack-encore-bundle ### /.vscode -/.cache +/.cache/ /.config /.npm /.local -supervisord.log -supervisord.pid \ No newline at end of file +/supervisord.log +/supervisord.pid +.cache \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index b2b4283..69e458d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,4 +4,4 @@ // Utilisation du pipeline partagé pour les applications Symfony de Cadoles // Le nom de l'image Docker passée en paramètre vous permet de préciser l'environnement de test // de votre application Symfony -symfonyAppPipeline("ubuntu:20.04") \ No newline at end of file +symfonyAppPipeline("ubuntu:22.04") \ No newline at end of file diff --git a/composer.lock b/composer.lock index 3572ea1..35e5ab9 100644 --- a/composer.lock +++ b/composer.lock @@ -74,30 +74,34 @@ }, { "name": "doctrine/annotations", - "version": "1.13.2", + "version": "1.14.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "5b668aef16090008790395c02c893b1ba13f7e08" + "reference": "9e034d7a70032d422169f27d8759e8d84abb4f51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08", - "reference": "5b668aef16090008790395c02c893b1ba13f7e08", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/9e034d7a70032d422169f27d8759e8d84abb4f51", + "reference": "9e034d7a70032d422169f27d8759e8d84abb4f51", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", + "doctrine/lexer": "^1 || ^2", "ext-tokenizer": "*", "php": "^7.1 || ^8.0", "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2" + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, "type": "library", "autoload": { @@ -140,37 +144,82 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.13.2" + "source": "https://github.com/doctrine/annotations/tree/1.14.1" }, - "time": "2021-08-05T19:00:23+00:00" + "time": "2022-12-12T12:46:12+00:00" }, { - "name": "doctrine/lexer", - "version": "1.2.3", + "name": "doctrine/deprecations", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.1|^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "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.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "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 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -202,7 +251,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": [ { @@ -218,7 +267,7 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "guzzlehttp/promises", @@ -931,20 +980,20 @@ }, { "name": "psr/cache", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { @@ -964,7 +1013,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for caching libraries", @@ -974,9 +1023,9 @@ "psr-6" ], "support": { - "source": "https://github.com/php-fig/cache/tree/master" + "source": "https://github.com/php-fig/cache/tree/2.0.0" }, - "time": "2016-08-06T20:24:11+00:00" + "time": "2021-02-03T23:23:37+00:00" }, { "name": "psr/container", @@ -1238,30 +1287,30 @@ }, { "name": "psr/log", - "version": "1.1.4", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" }, "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/ef29f6d262798707a9edd554e2b82517ef3a9376", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1282,9 +1331,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/2.0.0" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2021-07-14T16:41:46+00:00" }, { "name": "ralouphie/getallheaders", @@ -1709,16 +1758,16 @@ }, { "name": "symfony/cache", - "version": "v5.4.7", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "ba06841ed293fcaf79a592f59fdaba471f7c756c" + "reference": "60e87188abbacd29ccde44d69c5392a33e888e98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/ba06841ed293fcaf79a592f59fdaba471f7c756c", - "reference": "ba06841ed293fcaf79a592f59fdaba471f7c756c", + "url": "https://api.github.com/repos/symfony/cache/zipball/60e87188abbacd29ccde44d69c5392a33e888e98", + "reference": "60e87188abbacd29ccde44d69c5392a33e888e98", "shasum": "" }, "require": { @@ -1779,14 +1828,14 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an extended PSR-6, PSR-16 (and tags) implementation", + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", "homepage": "https://symfony.com", "keywords": [ "caching", "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v5.4.7" + "source": "https://github.com/symfony/cache/tree/v5.4.15" }, "funding": [ { @@ -1802,11 +1851,11 @@ "type": "tidelift" } ], - "time": "2022-03-22T15:31:03+00:00" + "time": "2022-10-27T07:55:40+00:00" }, { "name": "symfony/cache-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", @@ -1865,7 +1914,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/cache-contracts/tree/v2.5.2" }, "funding": [ { @@ -1885,16 +1934,16 @@ }, { "name": "symfony/config", - "version": "v5.4.7", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "05624c386afa1b4ccc1357463d830fade8d9d404" + "reference": "ec79e03125c1d2477e43dde8528535d90cc78379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/05624c386afa1b4ccc1357463d830fade8d9d404", - "reference": "05624c386afa1b4ccc1357463d830fade8d9d404", + "url": "https://api.github.com/repos/symfony/config/zipball/ec79e03125c1d2477e43dde8528535d90cc78379", + "reference": "ec79e03125c1d2477e43dde8528535d90cc78379", "shasum": "" }, "require": { @@ -1944,7 +1993,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.7" + "source": "https://github.com/symfony/config/tree/v5.4.11" }, "funding": [ { @@ -1960,20 +2009,20 @@ "type": "tidelift" } ], - "time": "2022-03-21T13:42:03+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/console", - "version": "v5.4.7", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6" + "reference": "8e9b9c8dfb33af6057c94e1b44846bee700dc5ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/900275254f0a1a2afff1ab0e11abd5587a10e1d6", - "reference": "900275254f0a1a2afff1ab0e11abd5587a10e1d6", + "url": "https://api.github.com/repos/symfony/console/zipball/8e9b9c8dfb33af6057c94e1b44846bee700dc5ef", + "reference": "8e9b9c8dfb33af6057c94e1b44846bee700dc5ef", "shasum": "" }, "require": { @@ -2043,7 +2092,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.7" + "source": "https://github.com/symfony/console/tree/v5.4.16" }, "funding": [ { @@ -2059,7 +2108,7 @@ "type": "tidelift" } ], - "time": "2022-03-31T17:09:19+00:00" + "time": "2022-11-25T14:09:27+00:00" }, { "name": "symfony/dependency-injection", @@ -2152,25 +2201,25 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.1", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" }, "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/1ee04c65529dea5d8744774d474e7cbd2f1206d3", + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -2199,7 +2248,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.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" }, "funding": [ { @@ -2215,7 +2264,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/dotenv", @@ -2290,16 +2339,16 @@ }, { "name": "symfony/error-handler", - "version": "v5.4.7", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "060bc01856a1846e3e4385261bc9ed11a1dd7b6a" + "reference": "539cf1428b8442303c6e876ad7bf5a7babd91091" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/060bc01856a1846e3e4385261bc9ed11a1dd7b6a", - "reference": "060bc01856a1846e3e4385261bc9ed11a1dd7b6a", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/539cf1428b8442303c6e876ad7bf5a7babd91091", + "reference": "539cf1428b8442303c6e876ad7bf5a7babd91091", "shasum": "" }, "require": { @@ -2341,7 +2390,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.7" + "source": "https://github.com/symfony/error-handler/tree/v5.4.15" }, "funding": [ { @@ -2357,20 +2406,20 @@ "type": "tidelift" } ], - "time": "2022-03-18T16:21:29+00:00" + "time": "2022-10-27T06:32:25+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.3", + "version": "v5.4.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d" + "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dec8a9f58d20df252b9cd89f1c6c1530f747685d", - "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", + "reference": "8e6ce1cc0279e3ff3c8ff0f43813bc88d21ca1bc", "shasum": "" }, "require": { @@ -2426,7 +2475,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.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.9" }, "funding": [ { @@ -2442,24 +2491,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-05-05T16:45:39+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.1", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae" }, "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/0782b0b52a737a05b4383d0df35a474303cabdae", + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, "suggest": { @@ -2468,7 +2517,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -2505,7 +2554,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.0" }, "funding": [ { @@ -2521,20 +2570,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/filesystem", - "version": "v5.4.7", + "version": "v5.4.13", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f" + "reference": "ac09569844a9109a5966b9438fc29113ce77cf51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3a4442138d80c9f7b600fb297534ac718b61d37f", - "reference": "3a4442138d80c9f7b600fb297534ac718b61d37f", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/ac09569844a9109a5966b9438fc29113ce77cf51", + "reference": "ac09569844a9109a5966b9438fc29113ce77cf51", "shasum": "" }, "require": { @@ -2569,7 +2618,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.7" + "source": "https://github.com/symfony/filesystem/tree/v5.4.13" }, "funding": [ { @@ -2585,20 +2634,20 @@ "type": "tidelift" } ], - "time": "2022-04-01T12:33:59+00:00" + "time": "2022-09-21T19:53:16+00:00" }, { "name": "symfony/finder", - "version": "v5.4.3", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d" + "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/231313534dded84c7ecaa79d14bc5da4ccb69b7d", - "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d", + "url": "https://api.github.com/repos/symfony/finder/zipball/7872a66f57caffa2916a584db1aa7f12adc76f8c", + "reference": "7872a66f57caffa2916a584db1aa7f12adc76f8c", "shasum": "" }, "require": { @@ -2632,7 +2681,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.3" + "source": "https://github.com/symfony/finder/tree/v5.4.11" }, "funding": [ { @@ -2648,32 +2697,32 @@ "type": "tidelift" } ], - "time": "2022-01-26T16:34:36+00:00" + "time": "2022-07-29T07:37:50+00:00" }, { "name": "symfony/flex", - "version": "v1.18.5", + "version": "v2.2.3", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "10e438f53a972439675dc720706f0cd5c0ed94f1" + "reference": "0763da1bdcce1d48c06778d48249905c26d34a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/10e438f53a972439675dc720706f0cd5c0ed94f1", - "reference": "10e438f53a972439675dc720706f0cd5c0ed94f1", + "url": "https://api.github.com/repos/symfony/flex/zipball/0763da1bdcce1d48c06778d48249905c26d34a72", + "reference": "0763da1bdcce1d48c06778d48249905c26d34a72", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0|^2.0", - "php": ">=7.1" + "composer-plugin-api": "^2.1", + "php": ">=8.0" }, "require-dev": { - "composer/composer": "^1.0.2|^2.0", - "symfony/dotenv": "^4.4|^5.0|^6.0", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/phpunit-bridge": "^4.4.12|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0" + "composer/composer": "^2.1", + "symfony/dotenv": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0", + "symfony/phpunit-bridge": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0" }, "type": "composer-plugin", "extra": { @@ -2697,7 +2746,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v1.18.5" + "source": "https://github.com/symfony/flex/tree/v2.2.3" }, "funding": [ { @@ -2713,20 +2762,20 @@ "type": "tidelift" } ], - "time": "2022-02-16T17:26:46+00:00" + "time": "2022-08-07T09:39:47+00:00" }, { "name": "symfony/form", - "version": "v5.4.8", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "7d1bd919be530e8071314a54bd5ae786452a81bf" + "reference": "5d3790b31935deff2506b2687ae18b3cf8f50405" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/7d1bd919be530e8071314a54bd5ae786452a81bf", - "reference": "7d1bd919be530e8071314a54bd5ae786452a81bf", + "url": "https://api.github.com/repos/symfony/form/zipball/5d3790b31935deff2506b2687ae18b3cf8f50405", + "reference": "5d3790b31935deff2506b2687ae18b3cf8f50405", "shasum": "" }, "require": { @@ -2755,7 +2804,7 @@ "symfony/twig-bridge": "<4.4" }, "require-dev": { - "doctrine/collections": "~1.0", + "doctrine/collections": "^1.0|^2.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/console": "^5.4|^6.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", @@ -2800,7 +2849,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v5.4.8" + "source": "https://github.com/symfony/form/tree/v5.4.16" }, "funding": [ { @@ -2816,20 +2865,20 @@ "type": "tidelift" } ], - "time": "2022-04-23T15:25:10+00:00" + "time": "2022-11-25T18:56:07+00:00" }, { "name": "symfony/framework-bundle", - "version": "v5.4.7", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "7520f553c7a7721652c1b7ac95c09dae62a1676e" + "reference": "70bfb2e76b8d97b2b19058bd65046b4cc1f04e3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/7520f553c7a7721652c1b7ac95c09dae62a1676e", - "reference": "7520f553c7a7721652c1b7ac95c09dae62a1676e", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/70bfb2e76b8d97b2b19058bd65046b4cc1f04e3d", + "reference": "70bfb2e76b8d97b2b19058bd65046b4cc1f04e3d", "shasum": "" }, "require": { @@ -2883,11 +2932,11 @@ "require-dev": { "doctrine/annotations": "^1.13.1", "doctrine/cache": "^1.11|^2.0", - "doctrine/persistence": "^1.3|^2.0", + "doctrine/persistence": "^1.3|^2|^3", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/asset": "^5.3|^6.0", "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", + "symfony/console": "^5.4.9|^6.0.9", "symfony/css-selector": "^4.4|^5.0|^6.0", "symfony/dom-crawler": "^4.4.30|^5.3.7|^6.0", "symfony/dotenv": "^5.1|^6.0", @@ -2951,7 +3000,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v5.4.7" + "source": "https://github.com/symfony/framework-bundle/tree/v5.4.16" }, "funding": [ { @@ -2967,20 +3016,20 @@ "type": "tidelift" } ], - "time": "2022-04-01T06:09:41+00:00" + "time": "2022-11-25T14:26:10+00:00" }, { "name": "symfony/http-client", - "version": "v5.4.8", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "0dabec4e3898d3e00451dd47b5ef839168f9bbf5" + "reference": "0f43af12a27733a060b92396b7bde84a4376da0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/0dabec4e3898d3e00451dd47b5ef839168f9bbf5", - "reference": "0dabec4e3898d3e00451dd47b5ef839168f9bbf5", + "url": "https://api.github.com/repos/symfony/http-client/zipball/0f43af12a27733a060b92396b7bde84a4376da0a", + "reference": "0f43af12a27733a060b92396b7bde84a4376da0a", "shasum": "" }, "require": { @@ -3038,7 +3087,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v5.4.8" + "source": "https://github.com/symfony/http-client/tree/v5.4.16" }, "funding": [ { @@ -3054,20 +3103,20 @@ "type": "tidelift" } ], - "time": "2022-04-12T16:02:29+00:00" + "time": "2022-11-09T11:27:39+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5" + "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1a4f708e4e87f335d1b1be6148060739152f0bd5", - "reference": "1a4f708e4e87f335d1b1be6148060739152f0bd5", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70", + "reference": "ba6a9f0e8f3edd190520ee3b9a958596b6ca2e70", "shasum": "" }, "require": { @@ -3116,7 +3165,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/http-client-contracts/tree/v2.5.2" }, "funding": [ { @@ -3132,20 +3181,20 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:07:29+00:00" + "time": "2022-04-12T15:48:08+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.4.6", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "34e89bc147633c0f9dd6caaaf56da3b806a21465" + "reference": "5032c5849aef24741e1970cb03511b0dd131d838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/34e89bc147633c0f9dd6caaaf56da3b806a21465", - "reference": "34e89bc147633c0f9dd6caaaf56da3b806a21465", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5032c5849aef24741e1970cb03511b0dd131d838", + "reference": "5032c5849aef24741e1970cb03511b0dd131d838", "shasum": "" }, "require": { @@ -3157,8 +3206,11 @@ "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0" + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" }, "suggest": { "symfony/mime": "To use the file extension guesser" @@ -3189,7 +3241,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.6" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.16" }, "funding": [ { @@ -3205,20 +3257,20 @@ "type": "tidelift" } ], - "time": "2022-03-05T21:03:43+00:00" + "time": "2022-11-07T08:06:40+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.4.7", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "509243b9b3656db966284c45dffce9316c1ecc5c" + "reference": "b432c57c5de73634b1859093c1f58e3cd84455a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/509243b9b3656db966284c45dffce9316c1ecc5c", - "reference": "509243b9b3656db966284c45dffce9316c1ecc5c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b432c57c5de73634b1859093c1f58e3cd84455a1", + "reference": "b432c57c5de73634b1859093c1f58e3cd84455a1", "shasum": "" }, "require": { @@ -3301,7 +3353,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.7" + "source": "https://github.com/symfony/http-kernel/tree/v5.4.16" }, "funding": [ { @@ -3317,7 +3369,7 @@ "type": "tidelift" } ], - "time": "2022-04-02T06:04:20+00:00" + "time": "2022-11-28T18:08:58+00:00" }, { "name": "symfony/lock", @@ -3400,16 +3452,16 @@ }, { "name": "symfony/options-resolver", - "version": "v5.4.3", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8" + "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/cc1147cb11af1b43f503ac18f31aa3bec213aba8", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/54f14e36aa73cb8f7261d7686691fd4d75ea2690", + "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690", "shasum": "" }, "require": { @@ -3449,7 +3501,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.3" + "source": "https://github.com/symfony/options-resolver/tree/v5.4.11" }, "funding": [ { @@ -3465,20 +3517,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/password-hasher", - "version": "v5.4.8", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "bc9c982b25c0292aa4e009b3e9cc9835e4d1e94f" + "reference": "b0169ed8f09a4ae39eb119218ea1685079a9b179" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/bc9c982b25c0292aa4e009b3e9cc9835e4d1e94f", - "reference": "bc9c982b25c0292aa4e009b3e9cc9835e4d1e94f", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/b0169ed8f09a4ae39eb119218ea1685079a9b179", + "reference": "b0169ed8f09a4ae39eb119218ea1685079a9b179", "shasum": "" }, "require": { @@ -3522,7 +3574,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v5.4.8" + "source": "https://github.com/symfony/password-hasher/tree/v5.4.11" }, "funding": [ { @@ -3538,20 +3590,20 @@ "type": "tidelift" } ], - "time": "2022-04-15T13:57:25+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", "shasum": "" }, "require": { @@ -3563,7 +3615,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3603,7 +3655,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" }, "funding": [ { @@ -3619,20 +3671,20 @@ "type": "tidelift" } ], - "time": "2021-11-23T21:10:46+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "c023a439b8551e320cc3c8433b198e408a623af1" + "reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/c023a439b8551e320cc3c8433b198e408a623af1", - "reference": "c023a439b8551e320cc3c8433b198e408a623af1", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/a3d9148e2c363588e05abbdd4ee4f971f0a5330c", + "reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c", "shasum": "" }, "require": { @@ -3644,7 +3696,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3690,7 +3742,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.27.0" }, "funding": [ { @@ -3706,20 +3758,20 @@ "type": "tidelift" } ], - "time": "2021-10-26T17:16:04+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", "shasum": "" }, "require": { @@ -3731,7 +3783,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3774,7 +3826,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" }, "funding": [ { @@ -3790,20 +3842,20 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", "shasum": "" }, "require": { @@ -3818,7 +3870,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3857,7 +3909,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" }, "funding": [ { @@ -3873,20 +3925,20 @@ "type": "tidelift" } ], - "time": "2021-11-30T18:21:41+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", "shasum": "" }, "require": { @@ -3895,7 +3947,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3936,7 +3988,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" }, "funding": [ { @@ -3952,20 +4004,20 @@ "type": "tidelift" } ], - "time": "2021-06-05T21:20:04+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", - "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "shasum": "" }, "require": { @@ -3974,7 +4026,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4019,7 +4071,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" }, "funding": [ { @@ -4035,20 +4087,20 @@ "type": "tidelift" } ], - "time": "2022-03-04T08:16:47+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.25.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f" + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", - "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", "shasum": "" }, "require": { @@ -4057,7 +4109,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4098,7 +4150,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" }, "funding": [ { @@ -4114,20 +4166,20 @@ "type": "tidelift" } ], - "time": "2021-09-13T13:58:11+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/property-access", - "version": "v5.4.8", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "fe501d498d6ec7e9efe928c90fabedf629116495" + "reference": "0f3e8f40a1d3da90f674b3dd772e4777ccde4273" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/fe501d498d6ec7e9efe928c90fabedf629116495", - "reference": "fe501d498d6ec7e9efe928c90fabedf629116495", + "url": "https://api.github.com/repos/symfony/property-access/zipball/0f3e8f40a1d3da90f674b3dd772e4777ccde4273", + "reference": "0f3e8f40a1d3da90f674b3dd772e4777ccde4273", "shasum": "" }, "require": { @@ -4179,7 +4231,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v5.4.8" + "source": "https://github.com/symfony/property-access/tree/v5.4.15" }, "funding": [ { @@ -4195,20 +4247,20 @@ "type": "tidelift" } ], - "time": "2022-04-12T15:48:08+00:00" + "time": "2022-10-27T07:55:40+00:00" }, { "name": "symfony/property-info", - "version": "v5.4.7", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "0fc07795712972b9792f203d0fe0e77c26c3281d" + "reference": "9dd148c4fbfc231fa4bff00def8dc16a2cd89944" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/0fc07795712972b9792f203d0fe0e77c26c3281d", - "reference": "0fc07795712972b9792f203d0fe0e77c26c3281d", + "url": "https://api.github.com/repos/symfony/property-info/zipball/9dd148c4fbfc231fa4bff00def8dc16a2cd89944", + "reference": "9dd148c4fbfc231fa4bff00def8dc16a2cd89944", "shasum": "" }, "require": { @@ -4270,7 +4322,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v5.4.7" + "source": "https://github.com/symfony/property-info/tree/v5.4.16" }, "funding": [ { @@ -4286,7 +4338,7 @@ "type": "tidelift" } ], - "time": "2022-03-30T13:40:48+00:00" + "time": "2022-11-19T17:41:50+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -4448,16 +4500,16 @@ }, { "name": "symfony/routing", - "version": "v5.4.3", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "44b29c7a94e867ccde1da604792f11a469958981" + "reference": "5c9b129efe9abce9470e384bf65d8a7e262eee69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/44b29c7a94e867ccde1da604792f11a469958981", - "reference": "44b29c7a94e867ccde1da604792f11a469958981", + "url": "https://api.github.com/repos/symfony/routing/zipball/5c9b129efe9abce9470e384bf65d8a7e262eee69", + "reference": "5c9b129efe9abce9470e384bf65d8a7e262eee69", "shasum": "" }, "require": { @@ -4518,7 +4570,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.4.3" + "source": "https://github.com/symfony/routing/tree/v5.4.15" }, "funding": [ { @@ -4534,20 +4586,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-10-13T14:10:41+00:00" }, { "name": "symfony/runtime", - "version": "v5.4.7", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "dc22a2876de3a3dc26b686570d9e638d443b575e" + "reference": "c32ac27a8abebe4e6375cd12a4f78ba78e9c742f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/dc22a2876de3a3dc26b686570d9e638d443b575e", - "reference": "dc22a2876de3a3dc26b686570d9e638d443b575e", + "url": "https://api.github.com/repos/symfony/runtime/zipball/c32ac27a8abebe4e6375cd12a4f78ba78e9c742f", + "reference": "c32ac27a8abebe4e6375cd12a4f78ba78e9c742f", "shasum": "" }, "require": { @@ -4595,7 +4647,7 @@ "description": "Enables decoupling PHP applications from global state", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/runtime/tree/v5.4.7" + "source": "https://github.com/symfony/runtime/tree/v5.4.11" }, "funding": [ { @@ -4611,20 +4663,20 @@ "type": "tidelift" } ], - "time": "2022-03-08T15:36:36+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "symfony/security-bundle", - "version": "v5.4.8", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "9806c9d491584e14a4444ea861a15428ab4b00be" + "reference": "86b49feb056b840f2b79a03fcfa2d378d6d34234" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/9806c9d491584e14a4444ea861a15428ab4b00be", - "reference": "9806c9d491584e14a4444ea861a15428ab4b00be", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/86b49feb056b840f2b79a03fcfa2d378d6d34234", + "reference": "86b49feb056b840f2b79a03fcfa2d378d6d34234", "shasum": "" }, "require": { @@ -4697,7 +4749,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v5.4.8" + "source": "https://github.com/symfony/security-bundle/tree/v5.4.11" }, "funding": [ { @@ -4713,20 +4765,20 @@ "type": "tidelift" } ], - "time": "2022-04-15T11:48:31+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/security-core", - "version": "v5.4.8", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "4540ecb8ae82cc46d9580672888597f481ff0440" + "reference": "4ef922cd626a43b570522cb1616e3d678664c9a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/4540ecb8ae82cc46d9580672888597f481ff0440", - "reference": "4540ecb8ae82cc46d9580672888597f481ff0440", + "url": "https://api.github.com/repos/symfony/security-core/zipball/4ef922cd626a43b570522cb1616e3d678664c9a0", + "reference": "4ef922cd626a43b570522cb1616e3d678664c9a0", "shasum": "" }, "require": { @@ -4790,7 +4842,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v5.4.8" + "source": "https://github.com/symfony/security-core/tree/v5.4.15" }, "funding": [ { @@ -4806,20 +4858,20 @@ "type": "tidelift" } ], - "time": "2022-04-15T08:07:45+00:00" + "time": "2022-10-23T10:30:41+00:00" }, { "name": "symfony/security-csrf", - "version": "v5.4.3", + "version": "v5.4.11", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "57c1c252ca756289c2b61327e08fb10be3936956" + "reference": "b97ab244b6dda80abb84a4a236d682871695db4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/57c1c252ca756289c2b61327e08fb10be3936956", - "reference": "57c1c252ca756289c2b61327e08fb10be3936956", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/b97ab244b6dda80abb84a4a236d682871695db4a", + "reference": "b97ab244b6dda80abb84a4a236d682871695db4a", "shasum": "" }, "require": { @@ -4862,7 +4914,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v5.4.3" + "source": "https://github.com/symfony/security-csrf/tree/v5.4.11" }, "funding": [ { @@ -4878,20 +4930,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-07-20T13:00:38+00:00" }, { "name": "symfony/security-guard", - "version": "v5.4.3", + "version": "v5.4.13", "source": { "type": "git", "url": "https://github.com/symfony/security-guard.git", - "reference": "3d68d9f8e162f6655eb0a0237b9f333a82a19da9" + "reference": "83f647fcdc17aa14908f0e02a302d3d9d0f63fbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-guard/zipball/3d68d9f8e162f6655eb0a0237b9f333a82a19da9", - "reference": "3d68d9f8e162f6655eb0a0237b9f333a82a19da9", + "url": "https://api.github.com/repos/symfony/security-guard/zipball/83f647fcdc17aa14908f0e02a302d3d9d0f63fbc", + "reference": "83f647fcdc17aa14908f0e02a302d3d9d0f63fbc", "shasum": "" }, "require": { @@ -4929,7 +4981,7 @@ "description": "Symfony Security Component - Guard", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-guard/tree/v5.4.3" + "source": "https://github.com/symfony/security-guard/tree/v5.4.13" }, "funding": [ { @@ -4945,20 +4997,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-09-28T13:19:49+00:00" }, { "name": "symfony/security-http", - "version": "v5.4.8", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "3d4b612da3a278285e6fd16fc2e5233820eeba0d" + "reference": "142d48153a453dbd49e880eef6bc77e4ba162dff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/3d4b612da3a278285e6fd16fc2e5233820eeba0d", - "reference": "3d4b612da3a278285e6fd16fc2e5233820eeba0d", + "url": "https://api.github.com/repos/symfony/security-http/zipball/142d48153a453dbd49e880eef6bc77e4ba162dff", + "reference": "142d48153a453dbd49e880eef6bc77e4ba162dff", "shasum": "" }, "require": { @@ -5014,7 +5066,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v5.4.8" + "source": "https://github.com/symfony/security-http/tree/v5.4.15" }, "funding": [ { @@ -5030,20 +5082,20 @@ "type": "tidelift" } ], - "time": "2022-04-16T13:32:04+00:00" + "time": "2022-10-23T10:30:41+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { @@ -5097,7 +5149,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -5113,20 +5165,20 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:07:29+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", - "version": "v5.4.3", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" + "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", - "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", + "url": "https://api.github.com/repos/symfony/string/zipball/571334ce9f687e3e6af72db4d3b2a9431e4fd9ed", + "reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed", "shasum": "" }, "require": { @@ -5183,7 +5235,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.3" + "source": "https://github.com/symfony/string/tree/v5.4.15" }, "funding": [ { @@ -5199,7 +5251,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-10-05T15:16:54+00:00" }, { "name": "symfony/translation", @@ -5300,16 +5352,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07" + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1211df0afa701e45a04253110e959d4af4ef0f07", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", "shasum": "" }, "require": { @@ -5358,7 +5410,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" }, "funding": [ { @@ -5374,20 +5426,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "symfony/twig-bridge", - "version": "v5.4.8", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "f68dbdb80c9ce425f503512dfa8c8c01cf789e43" + "reference": "227d5030714c024bf4bc760b5762224070d4288c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/f68dbdb80c9ce425f503512dfa8c8c01cf789e43", - "reference": "f68dbdb80c9ce425f503512dfa8c8c01cf789e43", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/227d5030714c024bf4bc760b5762224070d4288c", + "reference": "227d5030714c024bf4bc760b5762224070d4288c", "shasum": "" }, "require": { @@ -5479,7 +5531,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v5.4.8" + "source": "https://github.com/symfony/twig-bridge/tree/v5.4.16" }, "funding": [ { @@ -5495,7 +5547,7 @@ "type": "tidelift" } ], - "time": "2022-04-12T15:48:08+00:00" + "time": "2022-11-04T07:37:26+00:00" }, { "name": "symfony/twig-bundle", @@ -5588,16 +5640,16 @@ }, { "name": "symfony/validator", - "version": "v5.4.8", + "version": "v5.4.15", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "bdc6d04ba95c73ccbf906b4ad9b8775c738d83ad" + "reference": "0fb0c50f18f4517a8ea59d1cc87bff231402a7e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/bdc6d04ba95c73ccbf906b4ad9b8775c738d83ad", - "reference": "bdc6d04ba95c73ccbf906b4ad9b8775c738d83ad", + "url": "https://api.github.com/repos/symfony/validator/zipball/0fb0c50f18f4517a8ea59d1cc87bff231402a7e3", + "reference": "0fb0c50f18f4517a8ea59d1cc87bff231402a7e3", "shasum": "" }, "require": { @@ -5681,7 +5733,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v5.4.8" + "source": "https://github.com/symfony/validator/tree/v5.4.15" }, "funding": [ { @@ -5697,20 +5749,20 @@ "type": "tidelift" } ], - "time": "2022-04-15T08:07:45+00:00" + "time": "2022-10-27T08:04:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.4.6", + "version": "v5.4.14", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "294e9da6e2e0dd404e983daa5aa74253d92c05d0" + "reference": "6894d06145fefebd9a4c7272baa026a1c394a430" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/294e9da6e2e0dd404e983daa5aa74253d92c05d0", - "reference": "294e9da6e2e0dd404e983daa5aa74253d92c05d0", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6894d06145fefebd9a4c7272baa026a1c394a430", + "reference": "6894d06145fefebd9a4c7272baa026a1c394a430", "shasum": "" }, "require": { @@ -5770,7 +5822,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.6" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.14" }, "funding": [ { @@ -5786,20 +5838,20 @@ "type": "tidelift" } ], - "time": "2022-03-02T12:42:23+00:00" + "time": "2022-10-07T08:01:20+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.4.7", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "7eacaa588c9b27f2738575adb4a8457a80d9c807" + "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/7eacaa588c9b27f2738575adb4a8457a80d9c807", - "reference": "7eacaa588c9b27f2738575adb4a8457a80d9c807", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/8fc03ee75eeece3d9be1ef47d26d79bea1afb340", + "reference": "8fc03ee75eeece3d9be1ef47d26d79bea1afb340", "shasum": "" }, "require": { @@ -5843,7 +5895,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.7" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.10" }, "funding": [ { @@ -5859,20 +5911,20 @@ "type": "tidelift" } ], - "time": "2022-03-31T17:09:19+00:00" + "time": "2022-05-27T12:56:18+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v5.4.8", + "version": "v5.4.14", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "909c6eea7815066a80d0a362ed41abd7924e376a" + "reference": "e41ebd5411908bc8afdc848ccf68918ecb243c02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/909c6eea7815066a80d0a362ed41abd7924e376a", - "reference": "909c6eea7815066a80d0a362ed41abd7924e376a", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/e41ebd5411908bc8afdc848ccf68918ecb243c02", + "reference": "e41ebd5411908bc8afdc848ccf68918ecb243c02", "shasum": "" }, "require": { @@ -5923,7 +5975,7 @@ "description": "Provides a development tool that gives detailed information about the execution of any request", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v5.4.8" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v5.4.14" }, "funding": [ { @@ -5939,7 +5991,7 @@ "type": "tidelift" } ], - "time": "2022-04-22T08:14:12+00:00" + "time": "2022-10-01T21:59:28+00:00" }, { "name": "symfony/webpack-encore-bundle", @@ -6016,16 +6068,16 @@ }, { "name": "symfony/yaml", - "version": "v5.4.3", + "version": "v5.4.16", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e80f87d2c9495966768310fc531b487ce64237a2" + "reference": "ebd37c71f62d5ec5f6e27de3e06fee492d4c6298" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e80f87d2c9495966768310fc531b487ce64237a2", - "reference": "e80f87d2c9495966768310fc531b487ce64237a2", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ebd37c71f62d5ec5f6e27de3e06fee492d4c6298", + "reference": "ebd37c71f62d5ec5f6e27de3e06fee492d4c6298", "shasum": "" }, "require": { @@ -6071,7 +6123,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.3" + "source": "https://github.com/symfony/yaml/tree/v5.4.16" }, "funding": [ { @@ -6087,20 +6139,20 @@ "type": "tidelift" } ], - "time": "2022-01-26T16:32:32+00:00" + "time": "2022-11-25T16:04:03+00:00" }, { "name": "twig/twig", - "version": "v3.3.10", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "8442df056c51b706793adf80a9fd363406dd3674" + "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/8442df056c51b706793adf80a9fd363406dd3674", - "reference": "8442df056c51b706793adf80a9fd363406dd3674", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58", + "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58", "shasum": "" }, "require": { @@ -6115,7 +6167,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -6151,7 +6203,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.3.10" + "source": "https://github.com/twigphp/Twig/tree/v3.4.3" }, "funding": [ { @@ -6163,7 +6215,7 @@ "type": "tidelift" } ], - "time": "2022-04-06T06:47:41+00:00" + "time": "2022-09-28T08:42:51+00:00" } ], "packages-dev": [], diff --git a/config/packages/security.yaml b/config/packages/security.yaml index f73ccca..81dc52e 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -2,11 +2,16 @@ security: enable_authenticator_manager: true # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords password_hashers: - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' + app_hasher: + # the service ID of your custom hasher (the FQCN using the default services.yaml) + id: 'App\Security\Hasher\PasswordEncoder' + # App\Entity\User: 'sha256' + # Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: + # algorithm: 'sha256' # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: - pdo_user_provider: - id: App\Security\PdoUserProvider + sql_login_provider: + id: App\Security\SQLLoginUserProvider firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ @@ -14,9 +19,9 @@ security: main: # lazy: true stateless: false - provider: pdo_user_provider + provider: sql_login_provider custom_authenticators: - - App\Security\PdoUserAuthenticator + - App\Security\SQLLoginUserAuthenticator entry_point: form_login form_login: diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 91998cd..76c0c44 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -1,9 +1,9 @@ twig: + globals: + locales: "%app.supported_locales%" default_path: '%kernel.project_dir%/templates' form_themes: - 'bootstrap_5_layout.html.twig' - globals: - locales: "%app.supported_locales%" when@test: twig: strict_variables: true diff --git a/config/pdo_configuration/pdo.yaml b/config/pdo_configuration/pdo.yaml deleted file mode 100644 index de6ddf8..0000000 --- a/config/pdo_configuration/pdo.yaml +++ /dev/null @@ -1,8 +0,0 @@ -pdo: - column_login_name: email - column_password_name: password - table_name: usager - data_to_fetch: - - email - - lastname - - firstname \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 0b3885d..cebc5f0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -9,8 +9,9 @@ parameters: database.user: "%env(resolve:DB_USER)%" database.password: "%env(resolve:DB_PASSWORD)%" - # algorythme de hahshage utilisé "md5", "sha256", "haval160,4", etc. - hashAlgo: "sha256" + # algorythme de hashage utilisé "md5", "sha256", "haval160,4", etc. + env(HASH_ALGO_LEGACY): "sha256" + hashAlgoLegacy: '%env(resolve:HASH_ALGO_LEGACY)%' # adresse du site hote issuer_url: '%env(resolve:ISSUER_URL)%' @@ -21,9 +22,13 @@ parameters: default_locale: '%env(DEFAULT_LOCALE)%' env(DEFAULT_LOCALE): 'fr' + security_pattern: '%env(resolve:SECURITY_PATTERN)%' env(APP_LOCALES): "fr,en" locales: '%env(APP_LOCALES)%' app.supported_locales: ~ + + env(PEPPER): "257d62c24cd352c21b51c26dba678c8ff05011a89022aec106185bf67c69aa8b" + pepper: '%env(resolve:PEPPER)%' services: # default configuration for services in *this* file _defaults: @@ -39,11 +44,11 @@ services: - '../src/Entity/' - '../src/Kernel.php' - App\Security\PdoUserAuthenticator: + App\Security\SQLLoginUserAuthenticator: arguments: $baseUrl: '%base_url%' - App\Pdo\PdoRequest: + App\SQLLogin\SQLLoginRequest: arguments: $config: [] $dsn: "%database.dsn%" @@ -58,5 +63,11 @@ services: App\EventListener\LocaleSubscriber: arguments: $defaultLocale: "%default_locale%" + + App\Security\Hasher\PasswordEncoder: + arguments: + $pepper: '%pepper%' + $hashAlgoLegacy: '%hashAlgoLegacy%' + $securityPattern: '%security_pattern%' # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones diff --git a/config/sql_login_configuration/sql_login.yaml b/config/sql_login_configuration/sql_login.yaml new file mode 100644 index 0000000..2a1d5c8 --- /dev/null +++ b/config/sql_login_configuration/sql_login.yaml @@ -0,0 +1,9 @@ +sql_login: + login_column_name: email + password_column_name: password + salt_column_name: salt + table_name: usager + data_to_fetch: + - email + - lastname + - firstname \ No newline at end of file diff --git a/containers/compose/postgres/init-db.d/fill_lasql.sql b/containers/compose/postgres/init-db.d/fill_lasql.sql index 60efa4c..f2d0df4 100644 --- a/containers/compose/postgres/init-db.d/fill_lasql.sql +++ b/containers/compose/postgres/init-db.d/fill_lasql.sql @@ -1,12 +1,15 @@ CREATE TABLE IF NOT EXISTS usager ( email VARCHAR ( 100 ) UNIQUE NOT NULL, password VARCHAR ( 255 ) NOT NULL, + salt VARCHAR (255), lastname VARCHAR ( 255 ) NOT NULL, firstname VARCHAR ( 255 ) NOT NULL ); +INSERT INTO usager (email, password, salt, lastname, firstname) VALUES + ('test1@test.com', '8ad4025044b77ae6a5e3fcf99e53e44b15db9a4ecf468be21cbc6b9fbdae6d9f', 'cesaltestunexemple', 'Locke', 'John'), + ('test3@test.com', '504ae1c3e2f5fdaf41f868164dabcef21e17059f5f388b452718a1ce92692c67', 'cesaltestunautreexemple', 'Dupont', 'Henri'); + INSERT INTO usager (email, password, lastname, firstname) VALUES - ('test1@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Locke', 'John'), - ('test2@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Dubois', 'Angela'), - ('test3@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Dupont', 'Henri'), - ('test4@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Durand', 'Isabelle'); + ('test4@test.com', '$2a$12$91AHN7WFXieeadvUfZ88mO.9N7oS5adeXbdERnRno9oLAbqqDW4IG', 'Durand', 'Isabelle'), + ('test2@test.com', '50626fa21f45a275cea0efff13ff78fd02234cade322da08b7191c7e9150141d', 'Dubois', 'Angela'); GRANT ALL PRIVILEGES ON DATABASE usager TO lasql diff --git a/docker-compose.yml b/docker-compose.yml index 76ae48f..ad59579 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,8 @@ services: - DB_PASSWORD=lasql - DEFAULT_LOCALE=fr - DSN_REMOTE_DATABASE=pgsql:host='postgres';port=5432;dbname=lasql; + - HASH_ALGO_LEGACY=sha256 + - SECURITY_PATTERN=password,salt,pepper oidc-test: diff --git a/readme.md b/readme.md index fbac333..361fbc2 100644 --- a/readme.md +++ b/readme.md @@ -34,8 +34,38 @@ BASE_URL='http://localhost:8080' HYDRA_ADMIN_BASE_URL='http://hydra:4445' DSN_REMOTE_DATABASE="pgsql:host='postgres';port=5432;dbname=lasql" APP_LOCALES="fr,en" +HASH_ALGO_LEGACY="sha256, bcrypt" +SECURITY_PATTERN="password,salt,pepper" +PEPPER= ``` +## Tests password +Dans le cas où plusieurs méthodes de hashage cohabitent (migration de méthode par exemple dans l'application principale), toutes les méthode seront testées pour comparer les hashs jusqu'à un succès + +## Pattern de hashage + +``` +Définir le pattern utilisé avec les mots clés autorisé: password | salt | pepper dans un string, séparé par des virgules pour représenter la séquence à employer pour le hashage du mot de passe. +``` +### Postgres + +``` +Les mot de passe inscrits en bdd sont hachés en tenant compte du salt si non vide (cf données de la bdd plus bas) et du pepper inscrit en variable d'environnement (généré avec : bin2hex(random_bytes(32) pour l'exemple), le pepper peut être vide +Indiquer le nom de la colonne contenant le salt: +Il faut inscrire dans slq_login_configuration salt_column_name: salt +Indiquer le pepper utilisé: +et conserver le pepper dans service.yaml +env(PEPPER): "257d62c24cd352c21b51c26dba678c8ff05011a89022aec106185bf67c69aa8b" + +``` +### mariadb +``` +En plus de tester la connexion à une différente base de donnée, on teste le hashage de password sans salt ni pepper +Il faut mettre dans sql_login_configuration salt_column_name: ~ +et dans service.yaml +env(PEPPER): ~ + +``` ### test connexion mariadb ``` Modifier la variable d'environnement avec cette valeur @@ -45,13 +75,25 @@ DSN_REMOTE_DATABASE="mysql:host=mariadb;port=3306;dbname=lasql;" ## Données de test -un base de données postgres est montée dans l'environnement pour tester la connexion: +### postgres +``` +|email|password|salt|lastname|firstname + |test1@test.com| 8ad4025044b77ae6a5e3fcf99e53e44b15db9a4ecf468be21cbc6b9fbdae6d9f| cesaltestunexemple| Locke|John| + |test2@test.com| 50626fa21f45a275cea0efff13ff78fd02234cade322da08b7191c7e9150141d| NULL| Dubois| Angela| + |test3@test.com| 504ae1c3e2f5fdaf41f868164dabcef21e17059f5f388b452718a1ce92692c67| cesaltestunautreexemple| Dupont| Henri| + |test4@test.com| $2a$12$91AHN7WFXieeadvUfZ88mO.9N7oS5adeXbdERnRno9oLAbqqDW4IG| NULL| Durand|Isabelle| -utilisateurs disponibles au démarage: - ('test1@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Locke', 'John'), - ('test2@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Dubois', 'Angela'), - ('test3@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Dupont', 'Henri'), - ('test4@test.com', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 'Durand', 'Isabelle'); +A noter que le hash de test4 est en bcrypt +``` + +### mariadb (sans salt) +``` +|email|password|lastname|firstname + |test1@test.com| 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92| Sassot|Charles| + |test2@test.com| 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92| Dubois| Angela| + |test3@test.com| 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92| Dupont| Henri| + |test4@test.com| 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92| Durand|Isabelle| +``` Mot de passe = '123456' hashé en par sha256 @@ -60,9 +102,10 @@ Permet d'adapter les requetes SQL en indiquant les noms de colonnes nécessaires pdo_configuration/pdo.yaml ``` -pdo: - column_login_name: email - column_password_name: password +sql_login: + login_column_name: email + password_column_name: password + salt_column_name: ~ table_name: usager data_to_fetch: - email diff --git a/src/Controller/LocaleController.php b/src/Controller/LocaleController.php index ea6bc62..1541780 100644 --- a/src/Controller/LocaleController.php +++ b/src/Controller/LocaleController.php @@ -3,14 +3,25 @@ namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; class LocaleController extends AbstractController { - #[Route(path: 'locale/{locale}', name: 'locale_change')] - public function changeLocal(string $locale, Request $request) + private ParameterBagInterface $params; + + public function __construct(ParameterBagInterface $params) { + $this->params = $params; + } + + #[Route(path: 'locale/{locale?}', name: 'locale_change')] + public function changeLocal(?string $locale, Request $request) + { + if (empty($locale)) { + $locale = $this->params->get('default_locale'); + } // On stocke la langue dans la session $request->getSession()->set('_locale', $locale); diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index b273c25..08a0c76 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -3,7 +3,7 @@ namespace App\Controller; use App\Form\LoginType; -use App\Security\PdoUserAuthenticator; +use App\Security\SQLLoginUserAuthenticator; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\FormError; @@ -28,17 +28,17 @@ class SecurityController extends AbstractController $loginForm = $this->createForm(LoginType::class, null); $error = $authenticationUtils->getLastAuthenticationError(); if ($error) { - if ($request->getSession()->has(PdoUserAuthenticator::ERROR_LOGIN)) { + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_LOGIN)) { $loginForm->get('login')->addError(new FormError($trans->trans('error.login', [], 'messages'))); - $request->getSession()->remove(PdoUserAuthenticator::ERROR_LOGIN); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_LOGIN); } - if ($request->getSession()->has(PdoUserAuthenticator::ERROR_PASSWORD)) { + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_PASSWORD)) { $loginForm->get('password')->addError(new FormError($trans->trans('error.password', [], 'messages'))); - $request->getSession()->remove(PdoUserAuthenticator::ERROR_PASSWORD); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_PASSWORD); } - if ($request->getSession()->has(PdoUserAuthenticator::ERROR_PDO)) { - $loginForm->addError(new FormError($trans->trans('error.pdo', [], 'messages'))); - $request->getSession()->remove(PdoUserAuthenticator::ERROR_PDO); + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_SQL_LOGIN)) { + $loginForm->addError(new FormError($trans->trans('error.sql_login', [], 'messages'))); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_SQL_LOGIN); } } diff --git a/src/DependencyInjection/PdoConfiguration.php b/src/DependencyInjection/PdoConfiguration.php deleted file mode 100644 index b6378a8..0000000 --- a/src/DependencyInjection/PdoConfiguration.php +++ /dev/null @@ -1,25 +0,0 @@ -getRootNode()->children() - ->scalarNode(PdoRequest::COLUMN_LOGIN_NAME)->isRequired()->cannotBeEmpty()->end() - ->scalarNode(PdoRequest::COLUMN_PASSWORD_NAME)->isRequired()->cannotBeEmpty()->end() - ->scalarNode(PdoRequest::TABLE_NAME)->isRequired()->cannotBeEmpty()->end() - ->arrayNode(PdoRequest::DATA_TO_FETCH) - ->scalarPrototype()->end() - ->end() - ->end(); - - return $treeBuilder; - } -} diff --git a/src/DependencyInjection/SQLLoginConfiguration.php b/src/DependencyInjection/SQLLoginConfiguration.php new file mode 100644 index 0000000..8262e2a --- /dev/null +++ b/src/DependencyInjection/SQLLoginConfiguration.php @@ -0,0 +1,26 @@ +getRootNode()->children() + ->scalarNode(SQLLoginRequest::LOGIN_COLUMN_NAME)->isRequired()->cannotBeEmpty()->end() + ->scalarNode(SQLLoginRequest::PASSWORD_COLUMN_NAME)->isRequired()->cannotBeEmpty()->end() + ->scalarNode(SQLLoginRequest::SALT_COLUMN_NAME)->end() + ->scalarNode(SQLLoginRequest::TABLE_NAME)->isRequired()->cannotBeEmpty()->end() + ->arrayNode(SQLLoginRequest::DATA_TO_FETCH) + ->scalarPrototype()->end() + ->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/DependencyInjection/PdoExtension.php b/src/DependencyInjection/SQLLoginExtension.php similarity index 56% rename from src/DependencyInjection/PdoExtension.php rename to src/DependencyInjection/SQLLoginExtension.php index 017c4ca..c1fd858 100644 --- a/src/DependencyInjection/PdoExtension.php +++ b/src/DependencyInjection/SQLLoginExtension.php @@ -2,26 +2,26 @@ namespace App\DependencyInjection; -use App\Pdo\PdoRequest; +use App\SQLLogin\SQLLoginRequest; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; -class PdoExtension extends Extension implements CompilerPassInterface +class SQLLoginExtension extends Extension implements CompilerPassInterface { /** @var array */ - protected $pdoConfig; + protected $sqlLoginConfig; public function load(array $configs, ContainerBuilder $container) { - $configuration = new PdoConfiguration(); + $configuration = new SQLLoginConfiguration(); $config = $this->processConfiguration($configuration, $configs); - $this->pdoConfig = $config; + $this->sqlLoginConfig = $config; } public function process(ContainerBuilder $container) { - $definition = $container->getDefinition(PdoRequest::class); - $definition->replaceArgument('$config', $this->pdoConfig); + $definition = $container->getDefinition(SQLLoginRequest::class); + $definition->replaceArgument('$config', $this->sqlLoginConfig); } } diff --git a/src/Entity/User.php b/src/Entity/User.php index 7550b0b..2ae7689 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -6,8 +6,7 @@ use Symfony\Component\Security\Core\User\UserInterface; class User implements UserInterface { - /** @var array */ - protected $attributes; + protected array $attributes = []; private string $login; private string $password; private bool $rememberMe; diff --git a/src/EventListener/LogoutSubscriber.php b/src/EventListener/LogoutSubscriber.php index 4e76ef8..ece9179 100644 --- a/src/EventListener/LogoutSubscriber.php +++ b/src/EventListener/LogoutSubscriber.php @@ -4,15 +4,16 @@ namespace App\EventListener; use App\Hydra\HydraService; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\Event\LogoutEvent; class LogoutSubscriber implements EventSubscriberInterface { + private HydraService $hydra; + public function __construct( - private UrlGeneratorInterface $urlGenerator, - private HydraService $hydra + HydraService $hydra ) { + $this->hydra = $hydra; } public static function getSubscribedEvents(): array diff --git a/src/Hydra/HydraService.php b/src/Hydra/HydraService.php index 9f5d8e7..6bfad86 100644 --- a/src/Hydra/HydraService.php +++ b/src/Hydra/HydraService.php @@ -3,29 +3,23 @@ namespace App\Hydra; use App\Hydra\Exception\InvalidChallengeException; -use App\Services\PdoService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; class HydraService extends AbstractController { public SessionInterface $session; - public UrlGeneratorInterface $router; public Client $client; - public PdoService $pdoServices; public TokenStorageInterface $tokenStorage; - public function __construct(PdoService $pdoServices, Client $client, SessionInterface $session, UrlGeneratorInterface $router, TokenStorageInterface $tokenStorage) + public function __construct(Client $client, SessionInterface $session, TokenStorageInterface $tokenStorage) { - $this->pdoServices = $pdoServices; $this->session = $session; $this->client = $client; - $this->router = $router; $this->tokenStorage = $tokenStorage; } diff --git a/src/Kernel.php b/src/Kernel.php index b9dd5d4..b7958bf 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -2,7 +2,7 @@ namespace App; -use App\DependencyInjection\PdoExtension; +use App\DependencyInjection\SQLLoginExtension; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -22,10 +22,10 @@ class Kernel extends BaseKernel $this->microKernelConfigureContainer($loader); $loader->load(function (ContainerBuilder $container) use ($loader) { - $envLanguage = \getenv('APP_LOCALES'); + $envLanguage = getenv('APP_LOCALES'); $container->setParameter('app.supported_locales', explode(',', $envLanguage)); - $container->registerExtension(new PdoExtension()); - $loader->load($this->getConfigDir().'/pdo_configuration/*.{yml,yaml}', 'glob'); + $container->registerExtension(new SQLLoginExtension()); + $loader->load($this->getConfigDir().'/sql_login_configuration/*.{yml,yaml}', 'glob'); }); } } diff --git a/src/Pdo/Exception/InvalidLoginException.php b/src/Pdo/Exception/InvalidLoginException.php deleted file mode 100644 index 34a0932..0000000 --- a/src/Pdo/Exception/InvalidLoginException.php +++ /dev/null @@ -1,9 +0,0 @@ -config = $config; - $this->dsn = $dsn; - $this->user = $user; - $this->password = $password; - } - - public function getDatabaseDsn() - { - return $this->dsn; - } - - public function getDbUser() - { - return $this->user; - } - - public function getDbPassword() - { - return $this->password; - } - - public function getNameLogin() - { - return $this->config[self::COLUMN_LOGIN_NAME]; - } - - public function getNamePassword() - { - return $this->config[self::COLUMN_PASSWORD_NAME]; - } - - public function getRequestScope() - { - $scope = ''; - foreach ($this->config[self::DATA_TO_FETCH] as $data) { - $scope .= $data.','; - } - $scope = substr($scope, 0, -1); - $request = 'SELECT '.$scope.' FROM '.$this->config[self::TABLE_NAME].' WHERE '.$this->config[self::COLUMN_LOGIN_NAME].' = :'.$this->config[self::COLUMN_LOGIN_NAME].';'; - - return $request; - } - - public function getRequestLogin() - { - return 'SELECT '.$this->config[self::COLUMN_PASSWORD_NAME].' FROM '.$this->config[self::TABLE_NAME].' WHERE '.$this->config[self::COLUMN_LOGIN_NAME].' = :'.$this->config[self::COLUMN_LOGIN_NAME].';'; - } -} diff --git a/src/SQLLogin/Exception/InvalidSQLLoginAlgoException.php b/src/SQLLogin/Exception/InvalidSQLLoginAlgoException.php new file mode 100644 index 0000000..ee9ac4c --- /dev/null +++ b/src/SQLLogin/Exception/InvalidSQLLoginAlgoException.php @@ -0,0 +1,9 @@ +config = $config; + $this->dsn = $dsn; + $this->user = $user; + $this->password = $password; + } + + public function getDatabaseDsn(): string + { + return $this->dsn; + } + + public function getDbUser(): string + { + return $this->user; + } + + public function getDbPassword(): string + { + return $this->password; + } + + public function getLoginColumnName(): string + { + return $this->config[self::LOGIN_COLUMN_NAME]; + } + + public function getPasswordColumnName(): string + { + return $this->config[self::PASSWORD_COLUMN_NAME]; + } + + public function getSaltColumnName(): ?string + { + return $this->config[self::SALT_COLUMN_NAME]; + } + + public function getTableName(): string + { + return $this->config[self::TABLE_NAME]; + } + + public function getDataToFetch(): array + { + return $this->config[self::DATA_TO_FETCH]; + } + + public function getRequestScope() + { + $scope = ''; + foreach ($this->config[self::DATA_TO_FETCH] as $data) { + $scope .= $data.','; + } + $scope = substr($scope, 0, -1); + + return 'SELECT '.$scope.' FROM '.$this->getTableName().' WHERE '.$this->getLoginColumnName().' = :'.$this->getLoginColumnName().';'; + } + + /** + * Construction de la string pour la requête préparée selon la configuration yaml + * intègre la récupération du mot de passe hashé, du salt et de besoin d'upgrade de la méthode de hashage + */ + public function getRequestPassword() + { + $fields = $this->getPasswordColumnName(); + if (!empty($this->getSaltColumnName())) { + $fields .= ', '.$this->getSaltColumnName(); + } + + return 'SELECT '.$fields.' FROM '.$this->getTableName().' WHERE '.$this->getLoginColumnName().' = :'.$this->getLoginColumnName().';'; + } +} diff --git a/src/Security/Hasher/PasswordEncoder.php b/src/Security/Hasher/PasswordEncoder.php new file mode 100644 index 0000000..be4fbc9 --- /dev/null +++ b/src/Security/Hasher/PasswordEncoder.php @@ -0,0 +1,101 @@ +pepper = $pepper; + $this->hashAlgoLegacy = explode(',', $hashAlgoLegacy); + $this->securityPattern = explode(',', $securityPattern); + } + + /** + * Pas utilisé, mais on doit le garder pour le implements + */ + public function hash(string $plainPassword, string $salt = null): string + { + if ($this->isPasswordTooLong($plainPassword)) { + throw new InvalidPasswordException(); + } + + return hash($plainPassword.$salt, $this->hashAlgoLegacy[0]); + } + + public function verify(string $hashedPassword, string $plainPassword, string $salt = null): bool + { + if ('' === $plainPassword || $this->isPasswordTooLong($plainPassword)) { + return false; + } + + $completedPassword = $this->getPasswordToHash($plainPassword, $salt); + + foreach ($this->hashAlgoLegacy as $algo) { + if ($this->isObsoleteAlgo($algo)) { + if (hash_equals(hash($algo, $completedPassword), $hashedPassword)) { + return true; + } + } else { + if (password_verify($completedPassword, $hashedPassword)) { + return true; + } + } + } + throw new InvalidSQLPasswordException(); + } + + public function needsRehash(string $hashedPassword): bool + { + return false; + } + + public function isObsoleteAlgo($algo): bool + { + return in_array($algo, hash_algos()); + } + + /** + * Retourne la string à hasher en fonction du pattern indiqué + * + * @param mixed $plainTextPassword + * @param mixed $salt + * + * @return string + */ + protected function getPasswordToHash($plainTextPassword, $salt) + { + $arrayRef = [ + self::PASSWORD_PATTERN => $plainTextPassword, + self::SALT_PATTERN => $salt, + self::PEPPER_PATTERN => $this->pepper, + ]; + + foreach ($this->securityPattern as $term) { + if (self::PEPPER_PATTERN !== $term && self::PASSWORD_PATTERN !== $term && self::SALT_PATTERN !== $term) { + throw new InvalidSQLLoginConfigurationException(); + } + } + $completedPlainPassword = ''; + foreach ($this->securityPattern as $term) { + $completedPlainPassword .= $arrayRef[$term]; + } + + return $completedPlainPassword; + } +} diff --git a/src/Security/PdoUserAuthenticator.php b/src/Security/SQLLoginUserAuthenticator.php similarity index 71% rename from src/Security/PdoUserAuthenticator.php rename to src/Security/SQLLoginUserAuthenticator.php index 817c5e1..4d78115 100644 --- a/src/Security/PdoUserAuthenticator.php +++ b/src/Security/SQLLoginUserAuthenticator.php @@ -3,8 +3,9 @@ namespace App\Security; use App\Entity\User; -use App\Pdo\Exception\InvalidPasswordException; -use App\Services\PdoService; +use App\Security\Hasher\PasswordEncoder; +use App\Service\SQLLoginService; +use App\SQLLogin\Exception\InvalidSQLPasswordException; use PDOException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -19,22 +20,24 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\Passport; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; -class PdoUserAuthenticator extends AbstractAuthenticator +class SQLLoginUserAuthenticator extends AbstractAuthenticator { public const LOGIN_ROUTE = 'app_login'; public const ERROR_LOGIN = 'error_login'; public const ERROR_PASSWORD = 'error_password'; - public const ERROR_PDO = 'error_pdo'; + public const ERROR_SQL_LOGIN = 'error_sql_login'; protected string $baseUrl; - private PdoService $pdoService; + private SQLLoginService $sqlLoginService; private UrlGeneratorInterface $router; + private PasswordEncoder $passwordHasher; - public function __construct(string $baseUrl, PdoService $pdoService, UrlGeneratorInterface $router) + public function __construct(string $baseUrl, SQLLoginService $sqlLoginService, UrlGeneratorInterface $router, PasswordEncoder $passwordHasher) { $this->baseUrl = $baseUrl; - $this->pdoService = $pdoService; + $this->sqlLoginService = $sqlLoginService; $this->router = $router; + $this->passwordHasher = $passwordHasher; } /** @@ -65,20 +68,22 @@ class PdoUserAuthenticator extends AbstractAuthenticator { $form = $request->request->get('login'); $login = $form['login']; - $password = $form['password']; + $plaintextPassword = $form['password']; $rememberMe = isset($form['_remember_me']) ? true : false; try { // requête préparée - $remoteHashedPassword = $this->pdoService->fetchPassword($login); + list($remoteHashedPassword, $remoteSalt) = $this->sqlLoginService->fetchPassword($login); } catch (PDOException $e) { - $request->getSession()->set(self::ERROR_PDO, true); + $request->getSession()->set(self::ERROR_SQL_LOGIN, true); throw new AuthenticationException(); } if ($remoteHashedPassword) { try { - $this->pdoService->verifyPassword($password, $remoteHashedPassword); - $attributes = $this->pdoService->fetchDatas($login); - $user = new User($login, $password, $attributes, $rememberMe); + // Comparaison remote hash et hash du input password + salt + $this->passwordHasher->verify($remoteHashedPassword, $plaintextPassword, $remoteSalt); + $attributes = $this->sqlLoginService->fetchDatas($login); + $user = new User($login, $remoteHashedPassword, $attributes, $rememberMe); + $loader = function (string $userIdentifier) use ($user) { return $user->getLogin() == $userIdentifier ? $user : null; }; @@ -89,11 +94,11 @@ class PdoUserAuthenticator extends AbstractAuthenticator $passport->setAttribute('attributes', $user->getAttributes()); return $passport; - } catch (InvalidPasswordException $e) { + } catch (InvalidSQLPasswordException $e) { $request->getSession()->set(self::ERROR_PASSWORD, true); throw new AuthenticationException(); } catch (PDOException $e) { - $request->getSession()->set(self::ERROR_PDO, true); + $request->getSession()->set(self::ERROR_SQL_LOGIN, true); throw new AuthenticationException(); } } diff --git a/src/Security/PdoUserProvider.php b/src/Security/SQLLoginUserProvider.php similarity index 83% rename from src/Security/PdoUserProvider.php rename to src/Security/SQLLoginUserProvider.php index 3110498..e5bef7d 100644 --- a/src/Security/PdoUserProvider.php +++ b/src/Security/SQLLoginUserProvider.php @@ -4,19 +4,17 @@ namespace App\Security; use App\Entity\User; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; -class PdoUserProvider implements UserProviderInterface +class SQLLoginUserProvider implements UserProviderInterface { protected RequestStack $requestStack; - public function __construct(RequestStack $requestStack, SessionInterface $session) + public function __construct(RequestStack $requestStack) { $this->requestStack = $requestStack; - $this->session = $session; } public function loadUserByIdentifier(string $identifier, ?User $user): ?UserInterface diff --git a/src/Service/SQLLoginService.php b/src/Service/SQLLoginService.php new file mode 100644 index 0000000..db1c957 --- /dev/null +++ b/src/Service/SQLLoginService.php @@ -0,0 +1,73 @@ +sqlLoginRequest = $sqlLoginRequest; + } + + public function fetchDatas($login) + { + try { + $dbh = $this->getConnection(); + // forge de la requête + $request = $this->sqlLoginRequest->getRequestScope(); + // Préparation de la requête + $query = $dbh->prepare($request); + $query->execute([$this->sqlLoginRequest->getLoginColumnName() => $login]); + $datas = $query->fetch(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + \Sentry\captureException($e); + + throw new PDOException(); + } + + return $datas; + } + + /** + * @param mixed $login + * + * @return bool + */ + public function fetchPassword($login) + { + try { + $dbh = $this->getConnection(); + $request = $this->sqlLoginRequest->getRequestPassword(); + $query = $dbh->prepare($request); + $query->execute([$this->sqlLoginRequest->getLoginColumnName() => $login]); + $password = $query->fetch(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + \Sentry\captureException($e); + throw new PDOException(); + } + if ($password) { + return [ + $password[$this->sqlLoginRequest->getPasswordColumnName()], + isset($password[$this->sqlLoginRequest->getSaltColumnName()]) ? $password[$this->sqlLoginRequest->getSaltColumnName()] : null, + ]; + } + + return false; + } + + public function getConnection() + { + // Appel du singleton + $sqlLogin = SQLLoginConnect::getInstance(); + // Connection bdd + return $sqlLogin->connect($this->sqlLoginRequest->getDatabaseDsn(), $this->sqlLoginRequest->getDbUser(), $this->sqlLoginRequest->getDbPassword()); + } +} diff --git a/src/Services/PdoService.php b/src/Services/PdoService.php deleted file mode 100644 index ee8994d..0000000 --- a/src/Services/PdoService.php +++ /dev/null @@ -1,89 +0,0 @@ -params = $params; - $this->pdoRequest = $pdoRequest; - } - - public function fetchDatas($login) - { - try { - $dbh = $this->getConnection(); - - // forge de la requête - $request = $this->pdoRequest->getRequestScope(); - - // Préparation de la requête - $query = $dbh->prepare($request); - $query->execute([$this->pdoRequest->getNameLogin() => $login]); - $datas = $query->fetch(PDO::FETCH_ASSOC); - } catch (PDOException $e) { - \Sentry\captureException($e); - - throw new PDOException(); - } - - return $datas; - } - - /** - * @param mixed $login - * - * @return bool - */ - public function fetchPassword($login) - { - try { - $dbh = $this->getConnection(); - $request = $this->pdoRequest->getRequestLogin(); - $query = $dbh->prepare($request); - $query->execute([$this->pdoRequest->getNameLogin() => $login]); - $password = $query->fetch(PDO::FETCH_ASSOC); - } catch (PDOException $e) { - \Sentry\captureException($e); - dd($e); - throw new PDOException(); - } - if ($password) { - return $password[$this->pdoRequest->getNamePassword()]; - } - - return false; - } - - public function getConnection() - { - // Appel du singleton - $pdo = PdoConnect::getInstance(); - // Connection bdd - return $pdo->connect($this->pdoRequest->getDatabaseDsn(), $this->pdoRequest->getDbUser(), $this->pdoRequest->getDbPassword()); - } - - public function verifyPassword($password, $hashedPassword) - { - $hashAlgo = $this->params->get('hashAlgo') ?? 'sha256'; - - if ($hashedPassword === hash($hashAlgo, $password)) { - return true; - } else { - throw new InvalidPasswordException(); - } - } -} diff --git a/supervisord.pid b/supervisord.pid index 190a180..405e2af 100644 --- a/supervisord.pid +++ b/supervisord.pid @@ -1 +1 @@ -123 +134 diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index 7908f71..cfcf961 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -1,4 +1,4 @@ error: login: 'Incorrect login' password: 'Incorrect password' - pdo: 'Connection to database encountered a problem' \ No newline at end of file + sql_login: 'Connection to database encountered a problem' \ No newline at end of file diff --git a/translations/messages.fr.yaml b/translations/messages.fr.yaml index 6128d20..d9410e2 100644 --- a/translations/messages.fr.yaml +++ b/translations/messages.fr.yaml @@ -1,4 +1,4 @@ error: login: 'Login incorrect ou inconnu' password: 'Mot de passe incorrect' - pdo: 'La connexion à la base de données a rencontré un problème' \ No newline at end of file + sql_login: 'La connexion à la base de données a rencontré un problème' \ No newline at end of file