diff --git a/Dockerfile b/Dockerfile index ca34646..2beee0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,6 @@ RUN apt-get update && \ ENV APP_DEBUG=0 ENV APP_ENV=prod ENV APP_SHARE_DIR=/data/preauth -ENV DEFAULT_URI='http://' # load application into build image RUN mkdir -p /data/preauth @@ -42,7 +41,6 @@ RUN pecl install apcu && \ ENV APP_DEBUG=0 ENV APP_ENV=prod ENV APP_SHARE_DIR=/data/preauth -ENV DEFAULT_URI='http://' # load application into final image WORKDIR /app diff --git a/composer.json b/composer.json index 993884a..91c1fa0 100644 --- a/composer.json +++ b/composer.json @@ -7,12 +7,12 @@ "php": ">=8.2", "ext-ctype": "*", "ext-iconv": "*", - "bacon/bacon-qr-code": "^3.0", + "bacon/bacon-qr-code": "^3.0.3", "runtime/frankenphp-symfony": "^0.2.0", - "spomky-labs/otphp": "^11.3", + "spomky-labs/otphp": "^11.4.2", "symfony/cache": "7.4.*", "symfony/console": "7.4.*", - "symfony/flex": "^2", + "symfony/flex": "^2.10", "symfony/framework-bundle": "7.4.*", "symfony/mime": "7.4.*", "symfony/runtime": "7.4.*", @@ -34,11 +34,6 @@ "App\\": "src/" } }, - "autoload-dev": { - "psr-4": { - "App\\Tests\\": "tests/" - } - }, "replace": { "symfony/polyfill-ctype": "*", "symfony/polyfill-iconv": "*", diff --git a/composer.lock b/composer.lock index 3145d4e..69fad7c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0347dfc31af034e9753433409f0f2a48", + "content-hash": "fc72cd4e297780175a284feb4d27063a", "packages": [ { "name": "bacon/bacon-qr-code", @@ -484,38 +484,26 @@ }, { "name": "spomky-labs/otphp", - "version": "11.3.0", + "version": "11.4.2", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/otphp.git", - "reference": "2d8ccb5fc992b9cc65ef321fa4f00fefdb3f4b33" + "reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/2d8ccb5fc992b9cc65ef321fa4f00fefdb3f4b33", - "reference": "2d8ccb5fc992b9cc65ef321fa4f00fefdb3f4b33", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad", + "reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad", "shasum": "" }, "require": { - "ext-mbstring": "*", "paragonie/constant_time_encoding": "^2.0 || ^3.0", "php": ">=8.1", "psr/clock": "^1.0", "symfony/deprecation-contracts": "^3.2" }, "require-dev": { - "ekino/phpstan-banned-code": "^1.0", - "infection/infection": "^0.26|^0.27|^0.28|^0.29", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5.26|^10.0|^11.0", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^1.0", - "symfony/phpunit-bridge": "^6.1|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/error-handler": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -550,7 +538,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/otphp/issues", - "source": "https://github.com/Spomky-Labs/otphp/tree/11.3.0" + "source": "https://github.com/Spomky-Labs/otphp/tree/11.4.2" }, "funding": [ { @@ -562,20 +550,20 @@ "type": "patreon" } ], - "time": "2024-06-12T11:22:32+00:00" + "time": "2026-01-23T10:53:01+00:00" }, { "name": "symfony/cache", - "version": "v7.4.1", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "21e0755783bbbab58f2bb6a7a57896d21d27a366" + "reference": "665522ec357540e66c294c08583b40ee576574f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/21e0755783bbbab58f2bb6a7a57896d21d27a366", - "reference": "21e0755783bbbab58f2bb6a7a57896d21d27a366", + "url": "https://api.github.com/repos/symfony/cache/zipball/665522ec357540e66c294c08583b40ee576574f0", + "reference": "665522ec357540e66c294c08583b40ee576574f0", "shasum": "" }, "require": { @@ -646,7 +634,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.1" + "source": "https://github.com/symfony/cache/tree/v7.4.7" }, "funding": [ { @@ -666,7 +654,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:11:45+00:00" + "time": "2026-03-06T08:14:57+00:00" }, { "name": "symfony/cache-contracts", @@ -746,16 +734,16 @@ }, { "name": "symfony/config", - "version": "v7.4.1", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "2c323304c354a43a48b61c5fa760fc4ed60ce495" + "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/2c323304c354a43a48b61c5fa760fc4ed60ce495", - "reference": "2c323304c354a43a48b61c5fa760fc4ed60ce495", + "url": "https://api.github.com/repos/symfony/config/zipball/6c17162555bfb58957a55bb0e43e00035b6ae3d5", + "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5", "shasum": "" }, "require": { @@ -801,7 +789,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/v7.4.1" + "source": "https://github.com/symfony/config/tree/v7.4.7" }, "funding": [ { @@ -821,20 +809,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T07:52:08+00:00" + "time": "2026-03-06T10:41:14+00:00" }, { "name": "symfony/console", - "version": "v7.4.1", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e" + "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", - "reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", + "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d", + "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d", "shasum": "" }, "require": { @@ -899,7 +887,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.1" + "source": "https://github.com/symfony/console/tree/v7.4.7" }, "funding": [ { @@ -919,20 +907,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T15:23:39+00:00" + "time": "2026-03-06T14:06:20+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.2", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "baf614f7c15b30ba6762d4b1ddabdf83dbf0d29b" + "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/baf614f7c15b30ba6762d4b1ddabdf83dbf0d29b", - "reference": "baf614f7c15b30ba6762d4b1ddabdf83dbf0d29b", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db", + "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db", "shasum": "" }, "require": { @@ -983,7 +971,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.4.2" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.7" }, "funding": [ { @@ -1003,7 +991,7 @@ "type": "tidelift" } ], - "time": "2025-12-08T06:57:04+00:00" + "time": "2026-03-03T07:48:48+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1074,16 +1062,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2" + "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2", - "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8da531f364ddfee53e36092a7eebbbd0b775f6b8", + "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8", "shasum": "" }, "require": { @@ -1132,7 +1120,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/v7.4.0" + "source": "https://github.com/symfony/error-handler/tree/v7.4.4" }, "funding": [ { @@ -1152,20 +1140,20 @@ "type": "tidelift" } ], - "time": "2025-11-05T14:29:59+00:00" + "time": "2026-01-20T16:42:42+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d" + "reference": "dc2c0eba1af673e736bb851d747d266108aea746" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d", - "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746", + "reference": "dc2c0eba1af673e736bb851d747d266108aea746", "shasum": "" }, "require": { @@ -1217,7 +1205,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/v7.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.4" }, "funding": [ { @@ -1237,7 +1225,7 @@ "type": "tidelift" } ], - "time": "2025-10-28T09:38:46+00:00" + "time": "2026-01-05T11:45:34+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -1317,16 +1305,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a" + "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a", - "reference": "d551b38811096d0be9c4691d406991b47c0c630a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e", + "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e", "shasum": "" }, "require": { @@ -1363,7 +1351,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.0" + "source": "https://github.com/symfony/filesystem/tree/v7.4.6" }, "funding": [ { @@ -1383,20 +1371,20 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2026-02-25T16:50:00+00:00" }, { "name": "symfony/finder", - "version": "v7.4.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "340b9ed7320570f319028a2cbec46d40535e94bd" + "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/340b9ed7320570f319028a2cbec46d40535e94bd", - "reference": "340b9ed7320570f319028a2cbec46d40535e94bd", + "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", "shasum": "" }, "require": { @@ -1431,7 +1419,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.0" + "source": "https://github.com/symfony/finder/tree/v7.4.6" }, "funding": [ { @@ -1451,7 +1439,7 @@ "type": "tidelift" } ], - "time": "2025-11-05T05:42:40+00:00" + "time": "2026-01-29T09:40:50+00:00" }, { "name": "symfony/flex", @@ -1528,16 +1516,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v7.4.1", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "2fa3b3ad6ed75ce0cc8cad8a5027b4f25b990bc3" + "reference": "c94bc78c85d76af67918404a95d44940f66a7c2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/2fa3b3ad6ed75ce0cc8cad8a5027b4f25b990bc3", - "reference": "2fa3b3ad6ed75ce0cc8cad8a5027b4f25b990bc3", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c94bc78c85d76af67918404a95d44940f66a7c2f", + "reference": "c94bc78c85d76af67918404a95d44940f66a7c2f", "shasum": "" }, "require": { @@ -1545,8 +1533,8 @@ "ext-xml": "*", "php": ">=8.2", "symfony/cache": "^6.4.12|^7.0|^8.0", - "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", + "symfony/config": "^7.4.4|^8.0.4", + "symfony/dependency-injection": "^7.4.4|^8.0.4", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^7.3|^8.0", "symfony/event-dispatcher": "^6.4|^7.0|^8.0", @@ -1560,8 +1548,8 @@ }, "conflict": { "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", "symfony/asset": "<6.4", "symfony/asset-mapper": "<6.4", "symfony/clock": "<6.4", @@ -1593,7 +1581,7 @@ "require-dev": { "doctrine/persistence": "^1.3|^2|^3", "dragonmantank/cron-expression": "^3.1", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", "seld/jsonlint": "^1.10", "symfony/asset": "^6.4|^7.0|^8.0", "symfony/asset-mapper": "^6.4|^7.0|^8.0", @@ -1662,7 +1650,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/v7.4.1" + "source": "https://github.com/symfony/framework-bundle/tree/v7.4.7" }, "funding": [ { @@ -1682,20 +1670,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T14:04:53+00:00" + "time": "2026-03-06T15:39:55+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.1", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "bd1af1e425811d6f077db240c3a588bdb405cd27" + "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bd1af1e425811d6f077db240c3a588bdb405cd27", - "reference": "bd1af1e425811d6f077db240c3a588bdb405cd27", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f94b3e7b7dafd40e666f0c9ff2084133bae41e81", + "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81", "shasum": "" }, "require": { @@ -1744,7 +1732,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.1" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.7" }, "funding": [ { @@ -1764,20 +1752,20 @@ "type": "tidelift" } ], - "time": "2025-12-07T11:13:10+00:00" + "time": "2026-03-06T13:15:18+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.2", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f" + "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6e6f0a5fa8763f75a504b930163785fb6dd055f", - "reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3b3fcf386c809be990c922e10e4c620d6367cab1", + "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1", "shasum": "" }, "require": { @@ -1819,7 +1807,7 @@ "symfony/config": "^6.4|^7.0|^8.0", "symfony/console": "^6.4|^7.0|^8.0", "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4.1|^7.0.1|^8.0", "symfony/dom-crawler": "^6.4|^7.0|^8.0", "symfony/expression-language": "^6.4|^7.0|^8.0", "symfony/finder": "^6.4|^7.0|^8.0", @@ -1863,7 +1851,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/v7.4.2" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.7" }, "funding": [ { @@ -1883,20 +1871,20 @@ "type": "tidelift" } ], - "time": "2025-12-08T07:43:37+00:00" + "time": "2026-03-06T16:33:18+00:00" }, { "name": "symfony/mime", - "version": "v7.4.0", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a" + "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a", - "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a", + "url": "https://api.github.com/repos/symfony/mime/zipball/da5ab4fde3f6c88ab06e96185b9922f48b677cd1", + "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1", "shasum": "" }, "require": { @@ -1907,15 +1895,15 @@ }, "conflict": { "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", "symfony/mailer": "<6.4", "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", "symfony/dependency-injection": "^6.4|^7.0|^8.0", "symfony/process": "^6.4|^7.0|^8.0", "symfony/property-access": "^6.4|^7.0|^8.0", @@ -1952,7 +1940,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.0" + "source": "https://github.com/symfony/mime/tree/v7.4.7" }, "funding": [ { @@ -1972,7 +1960,7 @@ "type": "tidelift" } ], - "time": "2025-11-16T10:14:42+00:00" + "time": "2026-03-05T15:24:09+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -2478,16 +2466,16 @@ }, { "name": "symfony/routing", - "version": "v7.4.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "4720254cb2644a0b876233d258a32bf017330db7" + "reference": "238d749c56b804b31a9bf3e26519d93b65a60938" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/4720254cb2644a0b876233d258a32bf017330db7", - "reference": "4720254cb2644a0b876233d258a32bf017330db7", + "url": "https://api.github.com/repos/symfony/routing/zipball/238d749c56b804b31a9bf3e26519d93b65a60938", + "reference": "238d749c56b804b31a9bf3e26519d93b65a60938", "shasum": "" }, "require": { @@ -2539,7 +2527,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.0" + "source": "https://github.com/symfony/routing/tree/v7.4.6" }, "funding": [ { @@ -2559,7 +2547,7 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2026-02-25T16:50:00+00:00" }, { "name": "symfony/runtime", @@ -2733,16 +2721,16 @@ }, { "name": "symfony/string", - "version": "v7.4.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003" + "reference": "9f209231affa85aa930a5e46e6eb03381424b30b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003", + "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b", + "reference": "9f209231affa85aa930a5e46e6eb03381424b30b", "shasum": "" }, "require": { @@ -2800,7 +2788,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.0" + "source": "https://github.com/symfony/string/tree/v7.4.6" }, "funding": [ { @@ -2820,7 +2808,7 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2026-02-09T09:33:46+00:00" }, { "name": "symfony/translation-contracts", @@ -2906,16 +2894,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v7.4.1", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "9103559ef3e9f06708d8bff6810f6335b8f1eee8" + "reference": "c67219ca6b79a57b64e36bbb2cd8ba741286587e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9103559ef3e9f06708d8bff6810f6335b8f1eee8", - "reference": "9103559ef3e9f06708d8bff6810f6335b8f1eee8", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/c67219ca6b79a57b64e36bbb2cd8ba741286587e", + "reference": "c67219ca6b79a57b64e36bbb2cd8ba741286587e", "shasum": "" }, "require": { @@ -2925,10 +2913,10 @@ "twig/twig": "^3.21" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", "symfony/console": "<6.4", - "symfony/form": "<6.4", + "symfony/form": "<6.4.32|>7,<7.3.10|>7.4,<7.4.4|>8.0,<8.0.4", "symfony/http-foundation": "<6.4", "symfony/http-kernel": "<6.4", "symfony/mime": "<6.4", @@ -2939,7 +2927,7 @@ "require-dev": { "egulias/email-validator": "^2.1.10|^3|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", "symfony/asset": "^6.4|^7.0|^8.0", "symfony/asset-mapper": "^6.4|^7.0|^8.0", "symfony/console": "^6.4|^7.0|^8.0", @@ -2947,7 +2935,7 @@ "symfony/emoji": "^7.1|^8.0", "symfony/expression-language": "^6.4|^7.0|^8.0", "symfony/finder": "^6.4|^7.0|^8.0", - "symfony/form": "^6.4.30|~7.3.8|^7.4.1|^8.0.1", + "symfony/form": "^6.4.32|~7.3.10|^7.4.4|^8.0.4", "symfony/html-sanitizer": "^6.4|^7.0|^8.0", "symfony/http-foundation": "^7.3|^8.0", "symfony/http-kernel": "^6.4|^7.0|^8.0", @@ -2997,7 +2985,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.4.1" + "source": "https://github.com/symfony/twig-bridge/tree/v7.4.7" }, "funding": [ { @@ -3017,20 +3005,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T14:04:53+00:00" + "time": "2026-03-04T15:37:05+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "f83f530d00d1bbc6f7fafeb433077887c83326ef" + "reference": "e8829e02ff96a391ed0703bac9e7ff0537480b6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/f83f530d00d1bbc6f7fafeb433077887c83326ef", - "reference": "f83f530d00d1bbc6f7fafeb433077887c83326ef", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/e8829e02ff96a391ed0703bac9e7ff0537480b6b", + "reference": "e8829e02ff96a391ed0703bac9e7ff0537480b6b", "shasum": "" }, "require": { @@ -3038,6 +3026,7 @@ "php": ">=8.2", "symfony/config": "^7.4|^8.0", "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-foundation": "^6.4|^7.0|^8.0", "symfony/http-kernel": "^6.4.13|^7.1.6|^8.0", "symfony/twig-bridge": "^7.3|^8.0", @@ -3086,7 +3075,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.4.0" + "source": "https://github.com/symfony/twig-bundle/tree/v7.4.4" }, "funding": [ { @@ -3106,20 +3095,20 @@ "type": "tidelift" } ], - "time": "2025-10-02T07:41:02+00:00" + "time": "2026-01-06T12:34:24+00:00" }, { "name": "symfony/uid", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "2498e9f81b7baa206f44de583f2f48350b90142c" + "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/2498e9f81b7baa206f44de583f2f48350b90142c", - "reference": "2498e9f81b7baa206f44de583f2f48350b90142c", + "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", + "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", "shasum": "" }, "require": { @@ -3164,7 +3153,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.0" + "source": "https://github.com/symfony/uid/tree/v7.4.4" }, "funding": [ { @@ -3184,20 +3173,20 @@ "type": "tidelift" } ], - "time": "2025-09-25T11:02:55+00:00" + "time": "2026-01-03T23:30:35+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.0", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "41fd6c4ae28c38b294b42af6db61446594a0dece" + "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41fd6c4ae28c38b294b42af6db61446594a0dece", - "reference": "41fd6c4ae28c38b294b42af6db61446594a0dece", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/045321c440ac18347b136c63d2e9bf28a2dc0291", + "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291", "shasum": "" }, "require": { @@ -3251,7 +3240,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.6" }, "funding": [ { @@ -3271,7 +3260,7 @@ "type": "tidelift" } ], - "time": "2025-10-27T20:36:44+00:00" + "time": "2026-02-15T10:53:20+00:00" }, { "name": "symfony/var-exporter", @@ -3356,16 +3345,16 @@ }, { "name": "symfony/yaml", - "version": "v7.4.1", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" + "reference": "58751048de17bae71c5aa0d13cb19d79bca26391" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", + "url": "https://api.github.com/repos/symfony/yaml/zipball/58751048de17bae71c5aa0d13cb19d79bca26391", + "reference": "58751048de17bae71c5aa0d13cb19d79bca26391", "shasum": "" }, "require": { @@ -3408,7 +3397,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.1" + "source": "https://github.com/symfony/yaml/tree/v7.4.6" }, "funding": [ { @@ -3428,20 +3417,20 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:11:45+00:00" + "time": "2026-02-09T09:33:46+00:00" }, { "name": "twig/twig", - "version": "v3.22.1", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "1de2ec1fc43ab58a4b7e80b214b96bfc895750f3" + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/1de2ec1fc43ab58a4b7e80b214b96bfc895750f3", - "reference": "1de2ec1fc43ab58a4b7e80b214b96bfc895750f3", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", "shasum": "" }, "require": { @@ -3495,7 +3484,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.22.1" + "source": "https://github.com/twigphp/Twig/tree/v3.23.0" }, "funding": [ { @@ -3507,7 +3496,7 @@ "type": "tidelift" } ], - "time": "2025-11-16T16:01:12+00:00" + "time": "2026-01-23T21:00:41+00:00" } ], "packages-dev": [], diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml index e30690c..307fc05 100644 --- a/config/packages/cache.yaml +++ b/config/packages/cache.yaml @@ -2,38 +2,16 @@ framework: cache: app: cache.adapter.filesystem pools: - noncePool: - adapters: - - cache.adapter.apcu - sessionPool: - adapters: - - cache.adapter.apcu - requestPool: - adapters: - - cache.adapter.apcu - persistSessionPool: - adapters: - - cache.adapter.filesystem - persistRequestPool: - adapters: - - cache.adapter.filesystem + nonceCache: + adapters: cache.adapter.apcu + sessionCache: + adapters: cache.adapter.apcu + requestCache: + adapters: cache.adapter.apcu + sessionStorage: + adapters: cache.adapter.filesystem + requestStorage: + adapters: cache.adapter.filesystem - # Unique name of your app: used to compute - # stable namespaces for cache keys. + # Unique name of your app: used to compute stable namespaces for cache keys. prefix_seed: digitaladapt/preauth - - # The "app" cache stores to the filesystem by default. - # The data in this cache should persist between deploys. - # Other options include: - - # Redis - #app: cache.adapter.redis - #default_redis_provider: redis://localhost - - # APCu (not recommended with heavy random-write workloads - # as memory fragmentation can cause perf issues) - #app: cache.adapter.apcu - - # Namespaced pools use the above "app" backend by default - #pools: - #my.dedicated.cache: null diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 40f464c..ecfd1d5 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -7,12 +7,3 @@ framework: # Note that the session will be started ONLY if you read or write from it. session: true - - #esi: true - #fragments: true - -when@test: - framework: - test: true - session: - storage_factory_id: session.storage.factory.mock_file diff --git a/config/packages/routing.yaml b/config/packages/routing.yaml index 0401e13..f2c6665 100644 --- a/config/packages/routing.yaml +++ b/config/packages/routing.yaml @@ -1,10 +1,6 @@ framework: router: - # Configure how to generate URLs in non-HTTP contexts, - # such as CLI commands. See - # https://symfony.com/doc/current/routing.html - # #generating-urls-in-commands - default_uri: '%env(DEFAULT_URI)%' + default_uri: 'http://localhost' when@prod: framework: diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 7b5e99e..e59ef5b 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -3,7 +3,6 @@ twig: strict_variables: true globals: env: - allow_password: '%env(STATIC_SECRET_ENABLED)%' title: '%env(TITLE)%' bg_color: '%env(BG_COLOR)%' fg_color: '%env(FG_COLOR)%' diff --git a/config/reference.php b/config/reference.php index e0e1448..7c49104 100644 --- a/config/reference.php +++ b/config/reference.php @@ -4,6 +4,8 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; +use Symfony\Component\Config\Loader\ParamConfigurator as Param; + /** * This class provides array-shapes for configuring the services and bundles of an application. * @@ -31,11 +33,11 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * type?: string|null, * ignore_errors?: bool, * }> - * @psalm-type ParametersConfig = array|null>|null> + * @psalm-type ParametersConfig = array|Param|null>|Param|null> * @psalm-type ArgumentsType = list|array * @psalm-type CallType = array|array{0:string, 1?:ArgumentsType, 2?:bool}|array{method:string, arguments?:ArgumentsType, returns_clone?:bool} * @psalm-type TagsType = list>> // arrays inside the list must have only one element, with the tag name as the key - * @psalm-type CallbackType = string|array{0:string|ReferenceConfigurator,1:string}|\Closure|ReferenceConfigurator|ExpressionConfigurator + * @psalm-type CallbackType = string|array{0:string|ReferenceConfigurator,1:string}|\Closure|ReferenceConfigurator * @psalm-type DeprecationType = array{package: string, version: string, message?: string} * @psalm-type DefaultsType = array{ * public?: bool, @@ -124,601 +126,601 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * } * @psalm-type ExtensionType = array * @psalm-type FrameworkConfig = array{ - * secret?: scalar|null, - * http_method_override?: bool, // Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. // Default: false - * allowed_http_method_override?: list|null, - * trust_x_sendfile_type_header?: scalar|null, // Set true to enable support for xsendfile in binary file responses. // Default: "%env(bool:default::SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER)%" - * ide?: scalar|null, // Default: "%env(default::SYMFONY_IDE)%" - * test?: bool, - * default_locale?: scalar|null, // Default: "en" - * set_locale_from_accept_language?: bool, // Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed). // Default: false - * set_content_language_from_locale?: bool, // Whether to set the Content-Language HTTP header on the Response using the Request locale. // Default: false - * enabled_locales?: list, - * trusted_hosts?: list, + * secret?: scalar|Param|null, + * http_method_override?: bool|Param, // Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. // Default: false + * allowed_http_method_override?: list|null, + * trust_x_sendfile_type_header?: scalar|Param|null, // Set true to enable support for xsendfile in binary file responses. // Default: "%env(bool:default::SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER)%" + * ide?: scalar|Param|null, // Default: "%env(default::SYMFONY_IDE)%" + * test?: bool|Param, + * default_locale?: scalar|Param|null, // Default: "en" + * set_locale_from_accept_language?: bool|Param, // Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed). // Default: false + * set_content_language_from_locale?: bool|Param, // Whether to set the Content-Language HTTP header on the Response using the Request locale. // Default: false + * enabled_locales?: list, + * trusted_hosts?: list, * trusted_proxies?: mixed, // Default: ["%env(default::SYMFONY_TRUSTED_PROXIES)%"] - * trusted_headers?: list, - * error_controller?: scalar|null, // Default: "error_controller" - * handle_all_throwables?: bool, // HttpKernel will handle all kinds of \Throwable. // Default: true + * trusted_headers?: list, + * error_controller?: scalar|Param|null, // Default: "error_controller" + * handle_all_throwables?: bool|Param, // HttpKernel will handle all kinds of \Throwable. // Default: true * csrf_protection?: bool|array{ - * enabled?: scalar|null, // Default: null - * stateless_token_ids?: list, - * check_header?: scalar|null, // Whether to check the CSRF token in a header in addition to a cookie when using stateless protection. // Default: false - * cookie_name?: scalar|null, // The name of the cookie to use when using stateless protection. // Default: "csrf-token" + * enabled?: scalar|Param|null, // Default: null + * stateless_token_ids?: list, + * check_header?: scalar|Param|null, // Whether to check the CSRF token in a header in addition to a cookie when using stateless protection. // Default: false + * cookie_name?: scalar|Param|null, // The name of the cookie to use when using stateless protection. // Default: "csrf-token" * }, * form?: bool|array{ // Form configuration - * enabled?: bool, // Default: false - * csrf_protection?: array{ - * enabled?: scalar|null, // Default: null - * token_id?: scalar|null, // Default: null - * field_name?: scalar|null, // Default: "_token" - * field_attr?: array, + * enabled?: bool|Param, // Default: false + * csrf_protection?: bool|array{ + * enabled?: scalar|Param|null, // Default: null + * token_id?: scalar|Param|null, // Default: null + * field_name?: scalar|Param|null, // Default: "_token" + * field_attr?: array, * }, * }, * http_cache?: bool|array{ // HTTP cache configuration - * enabled?: bool, // Default: false - * debug?: bool, // Default: "%kernel.debug%" - * trace_level?: "none"|"short"|"full", - * trace_header?: scalar|null, - * default_ttl?: int, - * private_headers?: list, - * skip_response_headers?: list, - * allow_reload?: bool, - * allow_revalidate?: bool, - * stale_while_revalidate?: int, - * stale_if_error?: int, - * terminate_on_cache_hit?: bool, + * enabled?: bool|Param, // Default: false + * debug?: bool|Param, // Default: "%kernel.debug%" + * trace_level?: "none"|"short"|"full"|Param, + * trace_header?: scalar|Param|null, + * default_ttl?: int|Param, + * private_headers?: list, + * skip_response_headers?: list, + * allow_reload?: bool|Param, + * allow_revalidate?: bool|Param, + * stale_while_revalidate?: int|Param, + * stale_if_error?: int|Param, + * terminate_on_cache_hit?: bool|Param, * }, * esi?: bool|array{ // ESI configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, * ssi?: bool|array{ // SSI configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, * fragments?: bool|array{ // Fragments configuration - * enabled?: bool, // Default: false - * hinclude_default_template?: scalar|null, // Default: null - * path?: scalar|null, // Default: "/_fragment" + * enabled?: bool|Param, // Default: false + * hinclude_default_template?: scalar|Param|null, // Default: null + * path?: scalar|Param|null, // Default: "/_fragment" * }, * profiler?: bool|array{ // Profiler configuration - * enabled?: bool, // Default: false - * collect?: bool, // Default: true - * collect_parameter?: scalar|null, // The name of the parameter to use to enable or disable collection on a per request basis. // Default: null - * only_exceptions?: bool, // Default: false - * only_main_requests?: bool, // Default: false - * dsn?: scalar|null, // Default: "file:%kernel.cache_dir%/profiler" - * collect_serializer_data?: bool, // Enables the serializer data collector and profiler panel. // Default: false + * enabled?: bool|Param, // Default: false + * collect?: bool|Param, // Default: true + * collect_parameter?: scalar|Param|null, // The name of the parameter to use to enable or disable collection on a per request basis. // Default: null + * only_exceptions?: bool|Param, // Default: false + * only_main_requests?: bool|Param, // Default: false + * dsn?: scalar|Param|null, // Default: "file:%kernel.cache_dir%/profiler" + * collect_serializer_data?: bool|Param, // Enables the serializer data collector and profiler panel. // Default: false * }, * workflows?: bool|array{ - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * workflows?: array, - * definition_validators?: list, - * support_strategy?: scalar|null, - * initial_marking?: list, - * events_to_dispatch?: list|null, + * supports?: list, + * definition_validators?: list, + * support_strategy?: scalar|Param|null, + * initial_marking?: list, + * events_to_dispatch?: list|null, * places?: list, + * name?: scalar|Param|null, + * metadata?: array, * }>, - * transitions: list, * to?: list, - * weight?: int, // Default: 1 - * metadata?: list, + * weight?: int|Param, // Default: 1 + * metadata?: array, * }>, - * metadata?: list, + * metadata?: array, * }>, * }, * router?: bool|array{ // Router configuration - * enabled?: bool, // Default: false - * resource: scalar|null, - * type?: scalar|null, - * cache_dir?: scalar|null, // Deprecated: Setting the "framework.router.cache_dir.cache_dir" configuration option is deprecated. It will be removed in version 8.0. // Default: "%kernel.build_dir%" - * default_uri?: scalar|null, // The default URI used to generate URLs in a non-HTTP context. // Default: null - * http_port?: scalar|null, // Default: 80 - * https_port?: scalar|null, // Default: 443 - * strict_requirements?: scalar|null, // set to true to throw an exception when a parameter does not match the requirements set to false to disable exceptions when a parameter does not match the requirements (and return null instead) set to null to disable parameter checks against requirements 'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production // Default: true - * utf8?: bool, // Default: true + * enabled?: bool|Param, // Default: false + * resource?: scalar|Param|null, + * type?: scalar|Param|null, + * cache_dir?: scalar|Param|null, // Deprecated: Setting the "framework.router.cache_dir.cache_dir" configuration option is deprecated. It will be removed in version 8.0. // Default: "%kernel.build_dir%" + * default_uri?: scalar|Param|null, // The default URI used to generate URLs in a non-HTTP context. // Default: null + * http_port?: scalar|Param|null, // Default: 80 + * https_port?: scalar|Param|null, // Default: 443 + * strict_requirements?: scalar|Param|null, // set to true to throw an exception when a parameter does not match the requirements set to false to disable exceptions when a parameter does not match the requirements (and return null instead) set to null to disable parameter checks against requirements 'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production // Default: true + * utf8?: bool|Param, // Default: true * }, * session?: bool|array{ // Session configuration - * enabled?: bool, // Default: false - * storage_factory_id?: scalar|null, // Default: "session.storage.factory.native" - * handler_id?: scalar|null, // Defaults to using the native session handler, or to the native *file* session handler if "save_path" is not null. - * name?: scalar|null, - * cookie_lifetime?: scalar|null, - * cookie_path?: scalar|null, - * cookie_domain?: scalar|null, - * cookie_secure?: true|false|"auto", // Default: "auto" - * cookie_httponly?: bool, // Default: true - * cookie_samesite?: null|"lax"|"strict"|"none", // Default: "lax" - * use_cookies?: bool, - * gc_divisor?: scalar|null, - * gc_probability?: scalar|null, - * gc_maxlifetime?: scalar|null, - * save_path?: scalar|null, // Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null. - * metadata_update_threshold?: int, // Seconds to wait between 2 session metadata updates. // Default: 0 - * sid_length?: int, // Deprecated: Setting the "framework.session.sid_length.sid_length" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. - * sid_bits_per_character?: int, // Deprecated: Setting the "framework.session.sid_bits_per_character.sid_bits_per_character" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. + * enabled?: bool|Param, // Default: false + * storage_factory_id?: scalar|Param|null, // Default: "session.storage.factory.native" + * handler_id?: scalar|Param|null, // Defaults to using the native session handler, or to the native *file* session handler if "save_path" is not null. + * name?: scalar|Param|null, + * cookie_lifetime?: scalar|Param|null, + * cookie_path?: scalar|Param|null, + * cookie_domain?: scalar|Param|null, + * cookie_secure?: true|false|"auto"|Param, // Default: "auto" + * cookie_httponly?: bool|Param, // Default: true + * cookie_samesite?: null|"lax"|"strict"|"none"|Param, // Default: "lax" + * use_cookies?: bool|Param, + * gc_divisor?: scalar|Param|null, + * gc_probability?: scalar|Param|null, + * gc_maxlifetime?: scalar|Param|null, + * save_path?: scalar|Param|null, // Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null. + * metadata_update_threshold?: int|Param, // Seconds to wait between 2 session metadata updates. // Default: 0 + * sid_length?: int|Param, // Deprecated: Setting the "framework.session.sid_length.sid_length" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. + * sid_bits_per_character?: int|Param, // Deprecated: Setting the "framework.session.sid_bits_per_character.sid_bits_per_character" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option. * }, * request?: bool|array{ // Request configuration - * enabled?: bool, // Default: false - * formats?: array>, + * enabled?: bool|Param, // Default: false + * formats?: array>, * }, * assets?: bool|array{ // Assets configuration - * enabled?: bool, // Default: false - * strict_mode?: bool, // Throw an exception if an entry is missing from the manifest.json. // Default: false - * version_strategy?: scalar|null, // Default: null - * version?: scalar|null, // Default: null - * version_format?: scalar|null, // Default: "%%s?%%s" - * json_manifest_path?: scalar|null, // Default: null - * base_path?: scalar|null, // Default: "" - * base_urls?: list, + * enabled?: bool|Param, // Default: false + * strict_mode?: bool|Param, // Throw an exception if an entry is missing from the manifest.json. // Default: false + * version_strategy?: scalar|Param|null, // Default: null + * version?: scalar|Param|null, // Default: null + * version_format?: scalar|Param|null, // Default: "%%s?%%s" + * json_manifest_path?: scalar|Param|null, // Default: null + * base_path?: scalar|Param|null, // Default: "" + * base_urls?: list, * packages?: array, + * strict_mode?: bool|Param, // Throw an exception if an entry is missing from the manifest.json. // Default: false + * version_strategy?: scalar|Param|null, // Default: null + * version?: scalar|Param|null, + * version_format?: scalar|Param|null, // Default: null + * json_manifest_path?: scalar|Param|null, // Default: null + * base_path?: scalar|Param|null, // Default: "" + * base_urls?: list, * }>, * }, * asset_mapper?: bool|array{ // Asset Mapper configuration - * enabled?: bool, // Default: false - * paths?: array, - * excluded_patterns?: list, - * exclude_dotfiles?: bool, // If true, any files starting with "." will be excluded from the asset mapper. // Default: true - * server?: bool, // If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default). // Default: true - * public_prefix?: scalar|null, // The public path where the assets will be written to (and served from when "server" is true). // Default: "/assets/" - * missing_import_mode?: "strict"|"warn"|"ignore", // Behavior if an asset cannot be found when imported from JavaScript or CSS files - e.g. "import './non-existent.js'". "strict" means an exception is thrown, "warn" means a warning is logged, "ignore" means the import is left as-is. // Default: "warn" - * extensions?: array, - * importmap_path?: scalar|null, // The path of the importmap.php file. // Default: "%kernel.project_dir%/importmap.php" - * importmap_polyfill?: scalar|null, // The importmap name that will be used to load the polyfill. Set to false to disable. // Default: "es-module-shims" - * importmap_script_attributes?: array, - * vendor_dir?: scalar|null, // The directory to store JavaScript vendors. // Default: "%kernel.project_dir%/assets/vendor" + * enabled?: bool|Param, // Default: false + * paths?: array, + * excluded_patterns?: list, + * exclude_dotfiles?: bool|Param, // If true, any files starting with "." will be excluded from the asset mapper. // Default: true + * server?: bool|Param, // If true, a "dev server" will return the assets from the public directory (true in "debug" mode only by default). // Default: true + * public_prefix?: scalar|Param|null, // The public path where the assets will be written to (and served from when "server" is true). // Default: "/assets/" + * missing_import_mode?: "strict"|"warn"|"ignore"|Param, // Behavior if an asset cannot be found when imported from JavaScript or CSS files - e.g. "import './non-existent.js'". "strict" means an exception is thrown, "warn" means a warning is logged, "ignore" means the import is left as-is. // Default: "warn" + * extensions?: array, + * importmap_path?: scalar|Param|null, // The path of the importmap.php file. // Default: "%kernel.project_dir%/importmap.php" + * importmap_polyfill?: scalar|Param|null, // The importmap name that will be used to load the polyfill. Set to false to disable. // Default: "es-module-shims" + * importmap_script_attributes?: array, + * vendor_dir?: scalar|Param|null, // The directory to store JavaScript vendors. // Default: "%kernel.project_dir%/assets/vendor" * precompress?: bool|array{ // Precompress assets with Brotli, Zstandard and gzip. - * enabled?: bool, // Default: false - * formats?: list, - * extensions?: list, + * enabled?: bool|Param, // Default: false + * formats?: list, + * extensions?: list, * }, * }, * translator?: bool|array{ // Translator configuration - * enabled?: bool, // Default: false - * fallbacks?: list, - * logging?: bool, // Default: false - * formatter?: scalar|null, // Default: "translator.formatter.default" - * cache_dir?: scalar|null, // Default: "%kernel.cache_dir%/translations" - * default_path?: scalar|null, // The default path used to load translations. // Default: "%kernel.project_dir%/translations" - * paths?: list, + * enabled?: bool|Param, // Default: false + * fallbacks?: list, + * logging?: bool|Param, // Default: false + * formatter?: scalar|Param|null, // Default: "translator.formatter.default" + * cache_dir?: scalar|Param|null, // Default: "%kernel.cache_dir%/translations" + * default_path?: scalar|Param|null, // The default path used to load translations. // Default: "%kernel.project_dir%/translations" + * paths?: list, * pseudo_localization?: bool|array{ - * enabled?: bool, // Default: false - * accents?: bool, // Default: true - * expansion_factor?: float, // Default: 1.0 - * brackets?: bool, // Default: true - * parse_html?: bool, // Default: false - * localizable_html_attributes?: list, + * enabled?: bool|Param, // Default: false + * accents?: bool|Param, // Default: true + * expansion_factor?: float|Param, // Default: 1.0 + * brackets?: bool|Param, // Default: true + * parse_html?: bool|Param, // Default: false + * localizable_html_attributes?: list, * }, * providers?: array, - * locales?: list, + * dsn?: scalar|Param|null, + * domains?: list, + * locales?: list, * }>, * globals?: array, - * domain?: string, + * message?: string|Param, + * parameters?: array, + * domain?: string|Param, * }>, * }, * validation?: bool|array{ // Validation configuration - * enabled?: bool, // Default: false - * cache?: scalar|null, // Deprecated: Setting the "framework.validation.cache.cache" configuration option is deprecated. It will be removed in version 8.0. - * enable_attributes?: bool, // Default: true - * static_method?: list, - * translation_domain?: scalar|null, // Default: "validators" - * email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|"loose", // Default: "html5" + * enabled?: bool|Param, // Default: false + * cache?: scalar|Param|null, // Deprecated: Setting the "framework.validation.cache.cache" configuration option is deprecated. It will be removed in version 8.0. + * enable_attributes?: bool|Param, // Default: true + * static_method?: list, + * translation_domain?: scalar|Param|null, // Default: "validators" + * email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|"loose"|Param, // Default: "html5" * mapping?: array{ - * paths?: list, + * paths?: list, * }, * not_compromised_password?: bool|array{ - * enabled?: bool, // When disabled, compromised passwords will be accepted as valid. // Default: true - * endpoint?: scalar|null, // API endpoint for the NotCompromisedPassword Validator. // Default: null + * enabled?: bool|Param, // When disabled, compromised passwords will be accepted as valid. // Default: true + * endpoint?: scalar|Param|null, // API endpoint for the NotCompromisedPassword Validator. // Default: null * }, - * disable_translation?: bool, // Default: false + * disable_translation?: bool|Param, // Default: false * auto_mapping?: array, + * services?: list, * }>, * }, * annotations?: bool|array{ - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, * serializer?: bool|array{ // Serializer configuration - * enabled?: bool, // Default: false - * enable_attributes?: bool, // Default: true - * name_converter?: scalar|null, - * circular_reference_handler?: scalar|null, - * max_depth_handler?: scalar|null, + * enabled?: bool|Param, // Default: false + * enable_attributes?: bool|Param, // Default: true + * name_converter?: scalar|Param|null, + * circular_reference_handler?: scalar|Param|null, + * max_depth_handler?: scalar|Param|null, * mapping?: array{ - * paths?: list, + * paths?: list, * }, - * default_context?: list, + * default_context?: array, * named_serializers?: array, - * include_built_in_normalizers?: bool, // Whether to include the built-in normalizers // Default: true - * include_built_in_encoders?: bool, // Whether to include the built-in encoders // Default: true + * name_converter?: scalar|Param|null, + * default_context?: array, + * include_built_in_normalizers?: bool|Param, // Whether to include the built-in normalizers // Default: true + * include_built_in_encoders?: bool|Param, // Whether to include the built-in encoders // Default: true * }>, * }, * property_access?: bool|array{ // Property access configuration - * enabled?: bool, // Default: false - * magic_call?: bool, // Default: false - * magic_get?: bool, // Default: true - * magic_set?: bool, // Default: true - * throw_exception_on_invalid_index?: bool, // Default: false - * throw_exception_on_invalid_property_path?: bool, // Default: true + * enabled?: bool|Param, // Default: false + * magic_call?: bool|Param, // Default: false + * magic_get?: bool|Param, // Default: true + * magic_set?: bool|Param, // Default: true + * throw_exception_on_invalid_index?: bool|Param, // Default: false + * throw_exception_on_invalid_property_path?: bool|Param, // Default: true * }, * type_info?: bool|array{ // Type info configuration - * enabled?: bool, // Default: false - * aliases?: array, + * enabled?: bool|Param, // Default: false + * aliases?: array, * }, * property_info?: bool|array{ // Property info configuration - * enabled?: bool, // Default: false - * with_constructor_extractor?: bool, // Registers the constructor extractor. + * enabled?: bool|Param, // Default: false + * with_constructor_extractor?: bool|Param, // Registers the constructor extractor. * }, * cache?: array{ // Cache configuration - * prefix_seed?: scalar|null, // Used to namespace cache keys when using several apps with the same shared backend. // Default: "_%kernel.project_dir%.%kernel.container_class%" - * app?: scalar|null, // App related cache pools configuration. // Default: "cache.adapter.filesystem" - * system?: scalar|null, // System related cache pools configuration. // Default: "cache.adapter.system" - * directory?: scalar|null, // Default: "%kernel.share_dir%/pools/app" - * default_psr6_provider?: scalar|null, - * default_redis_provider?: scalar|null, // Default: "redis://localhost" - * default_valkey_provider?: scalar|null, // Default: "valkey://localhost" - * default_memcached_provider?: scalar|null, // Default: "memcached://localhost" - * default_doctrine_dbal_provider?: scalar|null, // Default: "database_connection" - * default_pdo_provider?: scalar|null, // Default: null + * prefix_seed?: scalar|Param|null, // Used to namespace cache keys when using several apps with the same shared backend. // Default: "_%kernel.project_dir%.%kernel.container_class%" + * app?: scalar|Param|null, // App related cache pools configuration. // Default: "cache.adapter.filesystem" + * system?: scalar|Param|null, // System related cache pools configuration. // Default: "cache.adapter.system" + * directory?: scalar|Param|null, // Default: "%kernel.share_dir%/pools/app" + * default_psr6_provider?: scalar|Param|null, + * default_redis_provider?: scalar|Param|null, // Default: "redis://localhost" + * default_valkey_provider?: scalar|Param|null, // Default: "valkey://localhost" + * default_memcached_provider?: scalar|Param|null, // Default: "memcached://localhost" + * default_doctrine_dbal_provider?: scalar|Param|null, // Default: "database_connection" + * default_pdo_provider?: scalar|Param|null, // Default: null * pools?: array, - * tags?: scalar|null, // Default: null - * public?: bool, // Default: false - * default_lifetime?: scalar|null, // Default lifetime of the pool. - * provider?: scalar|null, // Overwrite the setting from the default provider for this adapter. - * early_expiration_message_bus?: scalar|null, - * clearer?: scalar|null, + * adapters?: list, + * tags?: scalar|Param|null, // Default: null + * public?: bool|Param, // Default: false + * default_lifetime?: scalar|Param|null, // Default lifetime of the pool. + * provider?: scalar|Param|null, // Overwrite the setting from the default provider for this adapter. + * early_expiration_message_bus?: scalar|Param|null, + * clearer?: scalar|Param|null, * }>, * }, * php_errors?: array{ // PHP errors handling configuration * log?: mixed, // Use the application logger instead of the PHP logger for logging PHP errors. // Default: true - * throw?: bool, // Throw PHP errors as \ErrorException instances. // Default: true + * throw?: bool|Param, // Throw PHP errors as \ErrorException instances. // Default: true * }, * exceptions?: array, * web_link?: bool|array{ // Web links configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, * lock?: bool|string|array{ // Lock configuration - * enabled?: bool, // Default: false - * resources?: array>, + * enabled?: bool|Param, // Default: false + * resources?: array>, * }, * semaphore?: bool|string|array{ // Semaphore configuration - * enabled?: bool, // Default: false - * resources?: array, + * enabled?: bool|Param, // Default: false + * resources?: array, * }, * messenger?: bool|array{ // Messenger configuration - * enabled?: bool, // Default: false - * routing?: array, + * enabled?: bool|Param, // Default: false + * routing?: array, * }>, * serializer?: array{ - * default_serializer?: scalar|null, // Service id to use as the default serializer for the transports. // Default: "messenger.transport.native_php_serializer" + * default_serializer?: scalar|Param|null, // Service id to use as the default serializer for the transports. // Default: "messenger.transport.native_php_serializer" * symfony_serializer?: array{ - * format?: scalar|null, // Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default). // Default: "json" + * format?: scalar|Param|null, // Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default). // Default: "json" * context?: array, * }, * }, * transports?: array, - * failure_transport?: scalar|null, // Transport name to send failed messages to (after all retries have failed). // Default: null + * dsn?: scalar|Param|null, + * serializer?: scalar|Param|null, // Service id of a custom serializer to use. // Default: null + * options?: array, + * failure_transport?: scalar|Param|null, // Transport name to send failed messages to (after all retries have failed). // Default: null * retry_strategy?: string|array{ - * service?: scalar|null, // Service id to override the retry strategy entirely. // Default: null - * max_retries?: int, // Default: 3 - * delay?: int, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 - * multiplier?: float, // If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries)). // Default: 2 - * max_delay?: int, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 - * jitter?: float, // Randomness to apply to the delay (between 0 and 1). // Default: 0.1 + * service?: scalar|Param|null, // Service id to override the retry strategy entirely. // Default: null + * max_retries?: int|Param, // Default: 3 + * delay?: int|Param, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 + * multiplier?: float|Param, // If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries)). // Default: 2 + * max_delay?: int|Param, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 + * jitter?: float|Param, // Randomness to apply to the delay (between 0 and 1). // Default: 0.1 * }, - * rate_limiter?: scalar|null, // Rate limiter name to use when processing messages. // Default: null + * rate_limiter?: scalar|Param|null, // Rate limiter name to use when processing messages. // Default: null * }>, - * failure_transport?: scalar|null, // Transport name to send failed messages to (after all retries have failed). // Default: null - * stop_worker_on_signals?: list, - * default_bus?: scalar|null, // Default: null + * failure_transport?: scalar|Param|null, // Transport name to send failed messages to (after all retries have failed). // Default: null + * stop_worker_on_signals?: list, + * default_bus?: scalar|Param|null, // Default: null * buses?: array, * }>, * }>, * }, * scheduler?: bool|array{ // Scheduler configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, - * disallow_search_engine_index?: bool, // Enabled by default when debug is enabled. // Default: true + * disallow_search_engine_index?: bool|Param, // Enabled by default when debug is enabled. // Default: true * http_client?: bool|array{ // HTTP Client configuration - * enabled?: bool, // Default: false - * max_host_connections?: int, // The maximum number of connections to a single host. + * enabled?: bool|Param, // Default: false + * max_host_connections?: int|Param, // The maximum number of connections to a single host. * default_options?: array{ * headers?: array, * vars?: array, - * max_redirects?: int, // The maximum number of redirects to follow. - * http_version?: scalar|null, // The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. - * resolve?: array, - * proxy?: scalar|null, // The URL of the proxy to pass requests through or null for automatic detection. - * no_proxy?: scalar|null, // A comma separated list of hosts that do not require a proxy to be reached. - * timeout?: float, // The idle timeout, defaults to the "default_socket_timeout" ini parameter. - * max_duration?: float, // The maximum execution time for the request+response as a whole. - * bindto?: scalar|null, // A network interface name, IP address, a host name or a UNIX socket to bind to. - * verify_peer?: bool, // Indicates if the peer should be verified in a TLS context. - * verify_host?: bool, // Indicates if the host should exist as a certificate common name. - * cafile?: scalar|null, // A certificate authority file. - * capath?: scalar|null, // A directory that contains multiple certificate authority files. - * local_cert?: scalar|null, // A PEM formatted certificate file. - * local_pk?: scalar|null, // A private key file. - * passphrase?: scalar|null, // The passphrase used to encrypt the "local_pk" file. - * ciphers?: scalar|null, // A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...) + * max_redirects?: int|Param, // The maximum number of redirects to follow. + * http_version?: scalar|Param|null, // The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. + * resolve?: array, + * proxy?: scalar|Param|null, // The URL of the proxy to pass requests through or null for automatic detection. + * no_proxy?: scalar|Param|null, // A comma separated list of hosts that do not require a proxy to be reached. + * timeout?: float|Param, // The idle timeout, defaults to the "default_socket_timeout" ini parameter. + * max_duration?: float|Param, // The maximum execution time for the request+response as a whole. + * bindto?: scalar|Param|null, // A network interface name, IP address, a host name or a UNIX socket to bind to. + * verify_peer?: bool|Param, // Indicates if the peer should be verified in a TLS context. + * verify_host?: bool|Param, // Indicates if the host should exist as a certificate common name. + * cafile?: scalar|Param|null, // A certificate authority file. + * capath?: scalar|Param|null, // A directory that contains multiple certificate authority files. + * local_cert?: scalar|Param|null, // A PEM formatted certificate file. + * local_pk?: scalar|Param|null, // A private key file. + * passphrase?: scalar|Param|null, // The passphrase used to encrypt the "local_pk" file. + * ciphers?: scalar|Param|null, // A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...) * peer_fingerprint?: array{ // Associative array: hashing algorithm => hash(es). * sha1?: mixed, * pin-sha256?: mixed, * md5?: mixed, * }, - * crypto_method?: scalar|null, // The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. + * crypto_method?: scalar|Param|null, // The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. * extra?: array, - * rate_limiter?: scalar|null, // Rate limiter name to use for throttling requests. // Default: null + * rate_limiter?: scalar|Param|null, // Rate limiter name to use for throttling requests. // Default: null * caching?: bool|array{ // Caching configuration. - * enabled?: bool, // Default: false - * cache_pool?: string, // The taggable cache pool to use for storing the responses. // Default: "cache.http_client" - * shared?: bool, // Indicates whether the cache is shared (public) or private. // Default: true - * max_ttl?: int, // The maximum TTL (in seconds) allowed for cached responses. Null means no cap. // Default: null + * enabled?: bool|Param, // Default: false + * cache_pool?: string|Param, // The taggable cache pool to use for storing the responses. // Default: "cache.http_client" + * shared?: bool|Param, // Indicates whether the cache is shared (public) or private. // Default: true + * max_ttl?: int|Param, // The maximum TTL (in seconds) allowed for cached responses. Null means no cap. // Default: null * }, * retry_failed?: bool|array{ - * enabled?: bool, // Default: false - * retry_strategy?: scalar|null, // service id to override the retry strategy. // Default: null + * enabled?: bool|Param, // Default: false + * retry_strategy?: scalar|Param|null, // service id to override the retry strategy. // Default: null * http_codes?: array, + * code?: int|Param, + * methods?: list, * }>, - * max_retries?: int, // Default: 3 - * delay?: int, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 - * multiplier?: float, // If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries). // Default: 2 - * max_delay?: int, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 - * jitter?: float, // Randomness in percent (between 0 and 1) to apply to the delay. // Default: 0.1 + * max_retries?: int|Param, // Default: 3 + * delay?: int|Param, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 + * multiplier?: float|Param, // If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries). // Default: 2 + * max_delay?: int|Param, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 + * jitter?: float|Param, // Randomness in percent (between 0 and 1) to apply to the delay. // Default: 0.1 * }, * }, - * mock_response_factory?: scalar|null, // The id of the service that should generate mock responses. It should be either an invokable or an iterable. + * mock_response_factory?: scalar|Param|null, // The id of the service that should generate mock responses. It should be either an invokable or an iterable. * scoped_clients?: array, + * scope?: scalar|Param|null, // The regular expression that the request URL must match before adding the other options. When none is provided, the base URI is used instead. + * base_uri?: scalar|Param|null, // The URI to resolve relative URLs, following rules in RFC 3985, section 2. + * auth_basic?: scalar|Param|null, // An HTTP Basic authentication "username:password". + * auth_bearer?: scalar|Param|null, // A token enabling HTTP Bearer authorization. + * auth_ntlm?: scalar|Param|null, // A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension). + * query?: array, * headers?: array, - * max_redirects?: int, // The maximum number of redirects to follow. - * http_version?: scalar|null, // The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. - * resolve?: array, - * proxy?: scalar|null, // The URL of the proxy to pass requests through or null for automatic detection. - * no_proxy?: scalar|null, // A comma separated list of hosts that do not require a proxy to be reached. - * timeout?: float, // The idle timeout, defaults to the "default_socket_timeout" ini parameter. - * max_duration?: float, // The maximum execution time for the request+response as a whole. - * bindto?: scalar|null, // A network interface name, IP address, a host name or a UNIX socket to bind to. - * verify_peer?: bool, // Indicates if the peer should be verified in a TLS context. - * verify_host?: bool, // Indicates if the host should exist as a certificate common name. - * cafile?: scalar|null, // A certificate authority file. - * capath?: scalar|null, // A directory that contains multiple certificate authority files. - * local_cert?: scalar|null, // A PEM formatted certificate file. - * local_pk?: scalar|null, // A private key file. - * passphrase?: scalar|null, // The passphrase used to encrypt the "local_pk" file. - * ciphers?: scalar|null, // A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...). + * max_redirects?: int|Param, // The maximum number of redirects to follow. + * http_version?: scalar|Param|null, // The default HTTP version, typically 1.1 or 2.0, leave to null for the best version. + * resolve?: array, + * proxy?: scalar|Param|null, // The URL of the proxy to pass requests through or null for automatic detection. + * no_proxy?: scalar|Param|null, // A comma separated list of hosts that do not require a proxy to be reached. + * timeout?: float|Param, // The idle timeout, defaults to the "default_socket_timeout" ini parameter. + * max_duration?: float|Param, // The maximum execution time for the request+response as a whole. + * bindto?: scalar|Param|null, // A network interface name, IP address, a host name or a UNIX socket to bind to. + * verify_peer?: bool|Param, // Indicates if the peer should be verified in a TLS context. + * verify_host?: bool|Param, // Indicates if the host should exist as a certificate common name. + * cafile?: scalar|Param|null, // A certificate authority file. + * capath?: scalar|Param|null, // A directory that contains multiple certificate authority files. + * local_cert?: scalar|Param|null, // A PEM formatted certificate file. + * local_pk?: scalar|Param|null, // A private key file. + * passphrase?: scalar|Param|null, // The passphrase used to encrypt the "local_pk" file. + * ciphers?: scalar|Param|null, // A list of TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...). * peer_fingerprint?: array{ // Associative array: hashing algorithm => hash(es). * sha1?: mixed, * pin-sha256?: mixed, * md5?: mixed, * }, - * crypto_method?: scalar|null, // The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. + * crypto_method?: scalar|Param|null, // The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants. * extra?: array, - * rate_limiter?: scalar|null, // Rate limiter name to use for throttling requests. // Default: null + * rate_limiter?: scalar|Param|null, // Rate limiter name to use for throttling requests. // Default: null * caching?: bool|array{ // Caching configuration. - * enabled?: bool, // Default: false - * cache_pool?: string, // The taggable cache pool to use for storing the responses. // Default: "cache.http_client" - * shared?: bool, // Indicates whether the cache is shared (public) or private. // Default: true - * max_ttl?: int, // The maximum TTL (in seconds) allowed for cached responses. Null means no cap. // Default: null + * enabled?: bool|Param, // Default: false + * cache_pool?: string|Param, // The taggable cache pool to use for storing the responses. // Default: "cache.http_client" + * shared?: bool|Param, // Indicates whether the cache is shared (public) or private. // Default: true + * max_ttl?: int|Param, // The maximum TTL (in seconds) allowed for cached responses. Null means no cap. // Default: null * }, * retry_failed?: bool|array{ - * enabled?: bool, // Default: false - * retry_strategy?: scalar|null, // service id to override the retry strategy. // Default: null + * enabled?: bool|Param, // Default: false + * retry_strategy?: scalar|Param|null, // service id to override the retry strategy. // Default: null * http_codes?: array, + * code?: int|Param, + * methods?: list, * }>, - * max_retries?: int, // Default: 3 - * delay?: int, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 - * multiplier?: float, // If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries). // Default: 2 - * max_delay?: int, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 - * jitter?: float, // Randomness in percent (between 0 and 1) to apply to the delay. // Default: 0.1 + * max_retries?: int|Param, // Default: 3 + * delay?: int|Param, // Time in ms to delay (or the initial value when multiplier is used). // Default: 1000 + * multiplier?: float|Param, // If greater than 1, delay will grow exponentially for each retry: delay * (multiple ^ retries). // Default: 2 + * max_delay?: int|Param, // Max time in ms that a retry should ever be delayed (0 = infinite). // Default: 0 + * jitter?: float|Param, // Randomness in percent (between 0 and 1) to apply to the delay. // Default: 0.1 * }, * }>, * }, * mailer?: bool|array{ // Mailer configuration - * enabled?: bool, // Default: false - * message_bus?: scalar|null, // The message bus to use. Defaults to the default bus if the Messenger component is installed. // Default: null - * dsn?: scalar|null, // Default: null - * transports?: array, + * enabled?: bool|Param, // Default: false + * message_bus?: scalar|Param|null, // The message bus to use. Defaults to the default bus if the Messenger component is installed. // Default: null + * dsn?: scalar|Param|null, // Default: null + * transports?: array, * envelope?: array{ // Mailer Envelope configuration - * sender?: scalar|null, - * recipients?: list, - * allowed_recipients?: list, + * sender?: scalar|Param|null, + * recipients?: list, + * allowed_recipients?: list, * }, * headers?: array, * dkim_signer?: bool|array{ // DKIM signer configuration - * enabled?: bool, // Default: false - * key?: scalar|null, // Key content, or path to key (in PEM format with the `file://` prefix) // Default: "" - * domain?: scalar|null, // Default: "" - * select?: scalar|null, // Default: "" - * passphrase?: scalar|null, // The private key passphrase // Default: "" + * enabled?: bool|Param, // Default: false + * key?: scalar|Param|null, // Key content, or path to key (in PEM format with the `file://` prefix) // Default: "" + * domain?: scalar|Param|null, // Default: "" + * select?: scalar|Param|null, // Default: "" + * passphrase?: scalar|Param|null, // The private key passphrase // Default: "" * options?: array, * }, * smime_signer?: bool|array{ // S/MIME signer configuration - * enabled?: bool, // Default: false - * key?: scalar|null, // Path to key (in PEM format) // Default: "" - * certificate?: scalar|null, // Path to certificate (in PEM format without the `file://` prefix) // Default: "" - * passphrase?: scalar|null, // The private key passphrase // Default: null - * extra_certificates?: scalar|null, // Default: null - * sign_options?: int, // Default: null + * enabled?: bool|Param, // Default: false + * key?: scalar|Param|null, // Path to key (in PEM format) // Default: "" + * certificate?: scalar|Param|null, // Path to certificate (in PEM format without the `file://` prefix) // Default: "" + * passphrase?: scalar|Param|null, // The private key passphrase // Default: null + * extra_certificates?: scalar|Param|null, // Default: null + * sign_options?: int|Param, // Default: null * }, * smime_encrypter?: bool|array{ // S/MIME encrypter configuration - * enabled?: bool, // Default: false - * repository?: scalar|null, // S/MIME certificate repository service. This service shall implement the `Symfony\Component\Mailer\EventListener\SmimeCertificateRepositoryInterface`. // Default: "" - * cipher?: int, // A set of algorithms used to encrypt the message // Default: null + * enabled?: bool|Param, // Default: false + * repository?: scalar|Param|null, // S/MIME certificate repository service. This service shall implement the `Symfony\Component\Mailer\EventListener\SmimeCertificateRepositoryInterface`. // Default: "" + * cipher?: int|Param, // A set of algorithms used to encrypt the message // Default: null * }, * }, * secrets?: bool|array{ - * enabled?: bool, // Default: true - * vault_directory?: scalar|null, // Default: "%kernel.project_dir%/config/secrets/%kernel.runtime_environment%" - * local_dotenv_file?: scalar|null, // Default: "%kernel.project_dir%/.env.%kernel.runtime_environment%.local" - * decryption_env_var?: scalar|null, // Default: "base64:default::SYMFONY_DECRYPTION_SECRET" + * enabled?: bool|Param, // Default: true + * vault_directory?: scalar|Param|null, // Default: "%kernel.project_dir%/config/secrets/%kernel.runtime_environment%" + * local_dotenv_file?: scalar|Param|null, // Default: "%kernel.project_dir%/.env.%kernel.environment%.local" + * decryption_env_var?: scalar|Param|null, // Default: "base64:default::SYMFONY_DECRYPTION_SECRET" * }, * notifier?: bool|array{ // Notifier configuration - * enabled?: bool, // Default: false - * message_bus?: scalar|null, // The message bus to use. Defaults to the default bus if the Messenger component is installed. // Default: null - * chatter_transports?: array, - * texter_transports?: array, - * notification_on_failed_messages?: bool, // Default: false - * channel_policy?: array>, + * enabled?: bool|Param, // Default: false + * message_bus?: scalar|Param|null, // The message bus to use. Defaults to the default bus if the Messenger component is installed. // Default: null + * chatter_transports?: array, + * texter_transports?: array, + * notification_on_failed_messages?: bool|Param, // Default: false + * channel_policy?: array>, * admin_recipients?: list, * }, * rate_limiter?: bool|array{ // Rate limiter configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * limiters?: array, - * limit?: int, // The maximum allowed hits in a fixed interval or burst. - * interval?: scalar|null, // Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). + * lock_factory?: scalar|Param|null, // The service ID of the lock factory used by this limiter (or null to disable locking). // Default: "auto" + * cache_pool?: scalar|Param|null, // The cache pool to use for storing the current limiter state. // Default: "cache.rate_limiter" + * storage_service?: scalar|Param|null, // The service ID of a custom storage implementation, this precedes any configured "cache_pool". // Default: null + * policy?: "fixed_window"|"token_bucket"|"sliding_window"|"compound"|"no_limit"|Param, // The algorithm to be used by this limiter. + * limiters?: list, + * limit?: int|Param, // The maximum allowed hits in a fixed interval or burst. + * interval?: scalar|Param|null, // Configures the fixed interval if "policy" is set to "fixed_window" or "sliding_window". The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). * rate?: array{ // Configures the fill rate if "policy" is set to "token_bucket". - * interval?: scalar|null, // Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). - * amount?: int, // Amount of tokens to add each interval. // Default: 1 + * interval?: scalar|Param|null, // Configures the rate interval. The value must be a number followed by "second", "minute", "hour", "day", "week" or "month" (or their plural equivalent). + * amount?: int|Param, // Amount of tokens to add each interval. // Default: 1 * }, * }>, * }, * uid?: bool|array{ // Uid configuration - * enabled?: bool, // Default: true - * default_uuid_version?: 7|6|4|1, // Default: 7 - * name_based_uuid_version?: 5|3, // Default: 5 - * name_based_uuid_namespace?: scalar|null, - * time_based_uuid_version?: 7|6|1, // Default: 7 - * time_based_uuid_node?: scalar|null, + * enabled?: bool|Param, // Default: true + * default_uuid_version?: 7|6|4|1|Param, // Default: 7 + * name_based_uuid_version?: 5|3|Param, // Default: 5 + * name_based_uuid_namespace?: scalar|Param|null, + * time_based_uuid_version?: 7|6|1|Param, // Default: 7 + * time_based_uuid_node?: scalar|Param|null, * }, * html_sanitizer?: bool|array{ // HtmlSanitizer configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * sanitizers?: array, - * block_elements?: list, - * drop_elements?: list, + * block_elements?: list, + * drop_elements?: list, * allow_attributes?: array, * drop_attributes?: array, - * force_attributes?: array>, - * force_https_urls?: bool, // Transforms URLs using the HTTP scheme to use the HTTPS scheme instead. // Default: false - * allowed_link_schemes?: list, - * allowed_link_hosts?: list|null, - * allow_relative_links?: bool, // Allows relative URLs to be used in links href attributes. // Default: false - * allowed_media_schemes?: list, - * allowed_media_hosts?: list|null, - * allow_relative_medias?: bool, // Allows relative URLs to be used in media source attributes (img, audio, video, ...). // Default: false - * with_attribute_sanitizers?: list, - * without_attribute_sanitizers?: list, - * max_input_length?: int, // The maximum length allowed for the sanitized input. // Default: 0 + * force_attributes?: array>, + * force_https_urls?: bool|Param, // Transforms URLs using the HTTP scheme to use the HTTPS scheme instead. // Default: false + * allowed_link_schemes?: list, + * allowed_link_hosts?: list|null, + * allow_relative_links?: bool|Param, // Allows relative URLs to be used in links href attributes. // Default: false + * allowed_media_schemes?: list, + * allowed_media_hosts?: list|null, + * allow_relative_medias?: bool|Param, // Allows relative URLs to be used in media source attributes (img, audio, video, ...). // Default: false + * with_attribute_sanitizers?: list, + * without_attribute_sanitizers?: list, + * max_input_length?: int|Param, // The maximum length allowed for the sanitized input. // Default: 0 * }>, * }, * webhook?: bool|array{ // Webhook configuration - * enabled?: bool, // Default: false - * message_bus?: scalar|null, // The message bus to use. // Default: "messenger.default_bus" + * enabled?: bool|Param, // Default: false + * message_bus?: scalar|Param|null, // The message bus to use. // Default: "messenger.default_bus" * routing?: array, * }, * remote-event?: bool|array{ // RemoteEvent configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, * json_streamer?: bool|array{ // JSON streamer configuration - * enabled?: bool, // Default: false + * enabled?: bool|Param, // Default: false * }, * } * @psalm-type TwigConfig = array{ - * form_themes?: list, + * form_themes?: list, * globals?: array, - * autoescape_service?: scalar|null, // Default: null - * autoescape_service_method?: scalar|null, // Default: null - * base_template_class?: scalar|null, // Deprecated: The child node "base_template_class" at path "twig.base_template_class" is deprecated. - * cache?: scalar|null, // Default: true - * charset?: scalar|null, // Default: "%kernel.charset%" - * debug?: bool, // Default: "%kernel.debug%" - * strict_variables?: bool, // Default: "%kernel.debug%" - * auto_reload?: scalar|null, - * optimizations?: int, - * default_path?: scalar|null, // The default path used to load templates. // Default: "%kernel.project_dir%/templates" - * file_name_pattern?: list, + * autoescape_service?: scalar|Param|null, // Default: null + * autoescape_service_method?: scalar|Param|null, // Default: null + * base_template_class?: scalar|Param|null, // Deprecated: The child node "base_template_class" at path "twig.base_template_class" is deprecated. + * cache?: scalar|Param|null, // Default: true + * charset?: scalar|Param|null, // Default: "%kernel.charset%" + * debug?: bool|Param, // Default: "%kernel.debug%" + * strict_variables?: bool|Param, // Default: "%kernel.debug%" + * auto_reload?: scalar|Param|null, + * optimizations?: int|Param, + * default_path?: scalar|Param|null, // The default path used to load templates. // Default: "%kernel.project_dir%/templates" + * file_name_pattern?: list, * paths?: array, * date?: array{ // The default format options used by the date filter. - * format?: scalar|null, // Default: "F j, Y H:i" - * interval_format?: scalar|null, // Default: "%d days" - * timezone?: scalar|null, // The timezone used when formatting dates, when set to null, the timezone returned by date_default_timezone_get() is used. // Default: null + * format?: scalar|Param|null, // Default: "F j, Y H:i" + * interval_format?: scalar|Param|null, // Default: "%d days" + * timezone?: scalar|Param|null, // The timezone used when formatting dates, when set to null, the timezone returned by date_default_timezone_get() is used. // Default: null * }, * number_format?: array{ // The default format options for the number_format filter. - * decimals?: int, // Default: 0 - * decimal_point?: scalar|null, // Default: "." - * thousands_separator?: scalar|null, // Default: "," + * decimals?: int|Param, // Default: 0 + * decimal_point?: scalar|Param|null, // Default: "." + * thousands_separator?: scalar|Param|null, // Default: "," * }, * mailer?: array{ - * html_to_text_converter?: scalar|null, // A service implementing the "Symfony\Component\Mime\HtmlToTextConverter\HtmlToTextConverterInterface". // Default: null + * html_to_text_converter?: scalar|Param|null, // A service implementing the "Symfony\Component\Mime\HtmlToTextConverter\HtmlToTextConverterInterface". // Default: null * }, * } * @psalm-type ConfigType = array{ @@ -741,13 +743,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * framework?: FrameworkConfig, * twig?: TwigConfig, * }, - * "when@test"?: array{ - * imports?: ImportsConfig, - * parameters?: ParametersConfig, - * services?: ServicesConfig, - * framework?: FrameworkConfig, - * twig?: TwigConfig, - * }, * ..., * "when@prod"?: array, - * "when@test"?: array, * ... * } */ diff --git a/config/routes.yaml b/config/routes.yaml deleted file mode 100644 index cef258c..0000000 --- a/config/routes.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# yaml-language-server: $schema=../vendor/symfony/routing/Loader/schema/routing.schema.json - -# This file is the entry point to configure the routes of your app. -# Methods with the #[Route] attribute are automatically imported. -# See also https://symfony.com/doc/current/routing.html - -# To list all registered routes, run the following command: -# bin/console debug:router - -controllers: - resource: routing.controllers diff --git a/config/routes/framework.yaml b/config/routes/framework.yaml deleted file mode 100644 index bc1feac..0000000 --- a/config/routes/framework.yaml +++ /dev/null @@ -1,4 +0,0 @@ -when@dev: - _errors: - resource: '@FrameworkBundle/Resources/config/routing/errors.php' - prefix: /_error diff --git a/config/services.yaml b/config/services.yaml index f3fd291..ea3fbd1 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -29,10 +29,6 @@ parameters: # how long do we allow all traffic from an ip address after successful login # could be useful if you have a system which does not handle cookies env(IP_TTL): '0' # default disabled, time in seconds - # if desired, in addition to supporting a TOTP, you can set a static password - env(STATIC_SECRET_ENABLED): '0' # boolean - env(STATIC_SECRET): '' # default disabled - env(LOOKUP_TOTP): '' # default disabled # once blocked, do we respond with "I'm a teapot", false to use "Too many requests" env(TEAPOT): '1' # boolean @@ -61,9 +57,6 @@ parameters: app.totp_uri: '%env(TOTP_URI)%' app.ip_ttl: '%env(IP_TTL)%' - app.static_secret_enabled: '%env(STATIC_SECRET_ENABLED)%' - app.static_secret: '%env(STATIC_SECRET)%' - app.lookup_totp: '%env(LOOKUP_TOTP)%' app.teapot: '%env(TEAPOT)%' app.error_message: '%env(ERROR_MESSAGE)%' diff --git a/docs/env.example b/docs/env.example index 73cd315..e3fae0f 100644 --- a/docs/env.example +++ b/docs/env.example @@ -26,14 +26,6 @@ # could be useful if you have a system which does not handle cookies #IP_TTL=0 # default disabled, time in seconds -# if desired, in addition to supporting a TOTP, you can set a static password -# if you enable a static secret, you may choose to also enable a totp-lookup, -# which contains a special path, when successfully authenticated, -# instead of returning "hi " it returns "code ". -#STATIC_SECRET_ENABLED='0' # boolean, disabled by default -#STATIC_SECRET='' # default disabled -#LOOKUP_TOTP='' # default disabled - # once blocked, do we respond with "I'm a teapot", false to use "Too many requests" #TEAPOT=true # default enabled, boolean diff --git a/readme.md b/readme.md index aa334be..700f076 100644 --- a/readme.md +++ b/readme.md @@ -19,11 +19,11 @@ There is an example Caddyfile in /docs/ and env.example file to get you started. When someone tries to reach your protected web service, Caddy will check with preauth if they are allowed, if their preauth cookie is missing, invalid, or expired, we will show them to a login screen. -I say login, but it's really just a TOTP code (6 digit code which changes every 30 second). But once they enter the right code,they'll get their cookie and be shown the protected service. It is also possible to allow all requests from an approved IP address, but that is disabled by default. +I say login, but it's really just a TOTP code (6-digit code which changes every 30 second). But once they enter the right code,they'll get their cookie and be shown the protected service. It is also possible to allow all requests from an approved IP address, but that is disabled by default. First time you spin up the docker container it will generate a TOTP secret (which you'll load into your authenticator app); or generate you own. -Be sure to save that TOTP secret to your docker environment, so that it persistents beyond removing the container. +Be sure to save that TOTP secret to your docker environment, so that it persists beyond removing the container. ### History #### v0.4.1 (Dec 26th, 2025) diff --git a/src/ConfigBag.php b/src/ConfigBag.php index d759cbb..ee77d81 100644 --- a/src/ConfigBag.php +++ b/src/ConfigBag.php @@ -16,8 +16,6 @@ final readonly class ConfigBag { private string $queryPrefix; private string $totpUri; private ?int $ipTtl; - private ?string $lookupTotp; - private ?string $staticSecret; private bool $teapot; private string $errorMessage; private string $teapotTitle; @@ -34,9 +32,6 @@ final readonly class ConfigBag { #[Autowire('%app.query_prefix%')] string $queryPrefix, #[Autowire('%app.totp_uri%')] string $totpUri, #[Autowire('%app.ip_ttl%')] ?int $ipTtl, - #[Autowire('%app.lookup_totp%')] ?string $lookupTotp, - #[Autowire('%app.static_secret_enabled%')] bool $staticSecretEnabled, - #[Autowire('%app.static_secret%')] ?string $staticSecret, #[Autowire('%app.teapot%')] bool $teapot, #[Autowire('%app.error_message%')] string $errorMessage, #[Autowire('%app.teapot_title%')] string $teapotTitle, @@ -50,8 +45,6 @@ final readonly class ConfigBag { $this->queryPrefix = $queryPrefix; $this->totpUri = $totpUri ?: $utilities->loadTotp(); $this->ipTtl = $ipTtl ?: null; - $this->staticSecret = $staticSecretEnabled ? ($staticSecret ?: null) : null; - $this->lookupTotp = $this->staticSecret ? ($lookupTotp ?: null) : null; $this->teapot = $teapot; $this->errorMessage = $errorMessage; $this->teapotTitle = $teapotTitle; @@ -90,14 +83,6 @@ final readonly class ConfigBag { return $this->ipTtl; } - public function lookupTotp(): ?string { - return $this->lookupTotp; - } - - public function staticSecret(): ?string { - return $this->staticSecret; - } - public function teapot(): bool { return $this->teapot; } diff --git a/src/Data/Payload.php b/src/Data/Payload.php index 373dc52..39feced 100644 --- a/src/Data/Payload.php +++ b/src/Data/Payload.php @@ -8,12 +8,11 @@ use App\Enum\Scope; /* When scope is Ip but ip-access is disabled, scope is to be considered Cookie. */ /* When using password but password is disabled, request will always fail. */ final class Payload { - public string $id; /* session name, identifying who is logging in */ - public ?string $token; /* totp, typically six digits */ - public ?string $password; /* static secret, alternative to token, if enabled */ - public string $nonce; /* random unique string, to block duplicate submissions */ - public bool $json; /* should we return json (for the login page) */ - public Scope $scope; /* type of access being requested */ + public string $id; /* session name, identifying who is logging in */ + public string $token; /* totp, typically six digits */ + public string $nonce; /* random unique string, to block duplicate submissions */ + public bool $json; /* should we return json (for the login page) */ + public Scope $scope; /* type of access being requested */ public static function decode(string $base64url): ?Payload { /* convert the base64url into json string */ @@ -31,12 +30,10 @@ final class Payload { } public static function create(object $data): ?Payload { - /* if missing required fields id or nonce */ + /* if missing required fields id, nonce, or token */ if (strlen($data->id ?? '') < 1 || strlen($data->nonce ?? '') < 1 || - /* if missing both token and password (we require one of them) */ - (strlen($data->token ?? '') < 1 && - strlen($data->password ?? '') < 1) + strlen($data->token ?? '') < 1 ) { /* returns null as the input is invalid */ return null; @@ -47,25 +44,12 @@ final class Payload { $payload->nonce = $data->nonce; $payload->json = ($data->json ?? true); $payload->scope = Scope::tryFrom($data->scope ?? '') ?? Scope::Cookie; - - /* we accept either a token or a password, not both */ - if (strlen($data->token ?? '') > 0) { - $payload->token = $data->token; - $payload->password = null; - } else { - $payload->token = null; - $payload->password = $data->password; - } + $payload->token = $data->token; return Payload::constrict($payload); } public static function constrict(Payload $payload): Payload { - /* When using password, scope will be considered None. */ - if ($payload->password) { - $payload->scope = Scope::None; - } - /* When scope is None, json will be considered false. */ if ($payload->scope === Scope::None) { $payload->json = false; diff --git a/src/Listener/AcceptListener.php b/src/Listener/AcceptListener.php index 62202c4..7a222fb 100644 --- a/src/Listener/AcceptListener.php +++ b/src/Listener/AcceptListener.php @@ -17,7 +17,7 @@ final readonly class AcceptListener { use StringTrait; public function __construct( - private CacheItemPoolInterface $sessionPool, + private CacheItemPoolInterface $sessionCache, private LoggerInterface $logger, ) {} @@ -28,9 +28,9 @@ final readonly class AcceptListener { if ($event->getRequest()->cookies->has($this->cookieName())) { $cookie = $event->getRequest()->cookies->get($this->cookieName()); $cookieKey = $this->makeCacheKey("cookie_$cookie"); - if ($this->sessionPool->hasItem($cookieKey)) { + if ($this->sessionCache->hasItem($cookieKey)) { /* cookie sent corresponds to valid existing session */ - $id = $this->sessionPool->getItem($cookieKey)->get(); + $id = $this->sessionCache->getItem($cookieKey)->get(); $this->logger->debug("has valid cookie-session: $id"); $event->setResponse(new Response("hi $id", headers: ['Content-Type' => 'text/plain'] diff --git a/src/Listener/AllowListener.php b/src/Listener/AllowListener.php index 6d4f8a8..bd6633f 100644 --- a/src/Listener/AllowListener.php +++ b/src/Listener/AllowListener.php @@ -16,7 +16,7 @@ final readonly class AllowListener { use StringTrait; public function __construct( - private CacheItemPoolInterface $sessionPool, + private CacheItemPoolInterface $sessionCache, private ConfigBag $config, private LoggerInterface $logger, ) {} @@ -26,9 +26,9 @@ final readonly class AllowListener { public function onKernelRequest(RequestEvent $event): void { if ($this->config->ipTtl() > 0) { $ipKey = $this->makeCacheKey("ip_{$event->getRequest()->getClientIp()}"); - if ($this->sessionPool->hasItem($ipKey)) { + if ($this->sessionCache->hasItem($ipKey)) { /* ip address corresponds to valid existing session */ - $id = $this->sessionPool->getItem($ipKey)->get(); + $id = $this->sessionCache->getItem($ipKey)->get(); $this->logger->debug("has valid ip-session: $id"); $event->setResponse(new Response("hi $id", headers: ['Content-Type' => 'text/plain'] diff --git a/src/Listener/InterceptListener.php b/src/Listener/InterceptListener.php index aab53e9..7ffc1f3 100644 --- a/src/Listener/InterceptListener.php +++ b/src/Listener/InterceptListener.php @@ -4,10 +4,10 @@ declare(strict_types=1); namespace App\Listener; use App\ConfigBag; +use App\Trait\HasLoggerTrait; use App\Trait\MakeNonceTrait; use Psr\Cache\CacheItemPoolInterface; use Psr\Cache\InvalidArgumentException; -use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\RequestEvent; @@ -17,18 +17,14 @@ use Twig\Error\RuntimeError; use Twig\Error\SyntaxError; final readonly class InterceptListener { + use HasLoggerTrait; use MakeNonceTrait; public function __construct( - private CacheItemPoolInterface $requestPool, + private CacheItemPoolInterface $requestCache, private ConfigBag $config, private Environment $twig, - CacheItemPoolInterface $noncePool, - LoggerInterface $logger, - ) { - $this->logger = $logger; - $this->noncePool = $noncePool; - } + ) {} /** @throws InvalidArgumentException|RuntimeError|SyntaxError|LoaderError */ #[AsEventListener(priority: 55)] diff --git a/src/Listener/LoginListener.php b/src/Listener/LoginListener.php index 3d288f0..5e42588 100644 --- a/src/Listener/LoginListener.php +++ b/src/Listener/LoginListener.php @@ -3,17 +3,16 @@ declare(strict_types=1); namespace App\Listener; -use App\ConfigBag; use App\Data\Payload; use App\Enum\Scope; use App\MonitorCacheKeys; use App\Trait\CookieNameTrait; use App\Trait\GetTotpTrait; +use App\Trait\HasLoggerTrait; use App\Trait\MakeNonceTrait; use App\Trait\StringTrait; use Psr\Cache\CacheItemPoolInterface; use Psr\Cache\InvalidArgumentException; -use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; @@ -28,27 +27,22 @@ use Twig\Error\SyntaxError; final readonly class LoginListener { use CookieNameTrait; + use HasLoggerTrait; use MakeNonceTrait; use StringTrait; use GetTotpTrait; - private CacheItemPoolInterface $requestPool; - private CacheItemPoolInterface $sessionPool; + private CacheItemPoolInterface $requestCache; + private CacheItemPoolInterface $sessionCache; /** @throws InvalidArgumentException */ public function __construct( - ConfigBag $config, private Environment $twig, - CacheItemPoolInterface $noncePool, - CacheItemPoolInterface $requestPool, - CacheItemPoolInterface $sessionPool, - LoggerInterface $logger, + CacheItemPoolInterface $requestCache, + CacheItemPoolInterface $sessionCache, ) { - $this->config = $config; - $this->requestPool = new MonitorCacheKeys($requestPool); - $this->sessionPool = new MonitorCacheKeys($sessionPool); - $this->noncePool = $noncePool; - $this->logger = $logger; + $this->requestCache = new MonitorCacheKeys($requestCache); + $this->sessionCache = new MonitorCacheKeys($sessionCache); } /** @throws InvalidArgumentException|LoaderError|RuntimeError|SyntaxError */ @@ -58,13 +52,8 @@ final readonly class LoginListener { $data = $event->getRequest()->headers->get($this->headerName()); $payload = Payload::decode($data); $response = null; - if ($payload) { - /* if using token */ - if ($payload->token) { - $response = $this->checkToken($payload, $event->getRequest()); - } else if ($this->config->staticSecret()) { - $response = $this->checkPassword($payload); - } + if ($payload && $payload->token) { + $response = $this->checkToken($payload, $event->getRequest()); } /* token or password authentication was successful */ @@ -95,12 +84,12 @@ final readonly class LoginListener { /* token is correct */ /* if server nonce is found and is valid */ - $nonceItem = $this->noncePool->getItem($payload->nonce); + $nonceItem = $this->nonceCache->getItem($payload->nonce); if ($nonceItem->isHit() && $nonceItem->get()) { /* mark nonce as spent */ $nonceItem->set(false); /* invalid */ $nonceItem->expiresAfter(LoginListener::NONCE_TTL); /* keep briefly */ - $this->noncePool->save($nonceItem); + $this->nonceCache->save($nonceItem); /* token authentication successful, grant access and set response */ $cleanId = $this->makeCacheKey($payload->id); @@ -144,42 +133,11 @@ final readonly class LoginListener { return null; } - /** @throws InvalidArgumentException */ - private function checkPassword(Payload $payload): ?Response { - /* When using password but password is disabled, request will always fail. */ - - /* if password is correct */ - - if (hash_equals($this->config->staticSecret(), $payload->password)) { - /* password is correct */ - - /* nonce *may* be client provided, but must still be unique */ - - /* if server/client nonce is acceptable (valid server or unused client) */ - $nonceItem = $this->noncePool->getItem($payload->nonce); - if (($nonceItem->isHit() && $nonceItem->get()) || ! $nonceItem->isHit()) { - /* mark nonce as spent */ - $nonceItem->set(false); /* invalid */ - $nonceItem->expiresAfter(LoginListener::NONCE_TTL); /* keep briefly */ - $this->noncePool->save($nonceItem); - - /* password authentication successful, grant access and set response */ - $cleanId = $this->makeCacheKey($payload->id); - $this->logger->debug("successful login for: $cleanId"); - return new Response("hi $cleanId", - Response::HTTP_OK, - ['Content-Type' => 'text/plain'] - ); - } - } - return null; - } - /** @throws InvalidArgumentException */ private function setCookie(string $id): Cookie { /* successful auth with token, store session and set the cookie */ $ulid = new Ulid(); - $sessionCookie = $this->sessionPool->getItem( + $sessionCookie = $this->sessionCache->getItem( $this->makeCacheKey("cookie_$ulid") ); if ($sessionCookie->isHit()) { @@ -189,7 +147,7 @@ final readonly class LoginListener { } $sessionCookie->set($id); $sessionCookie->expiresAfter($this->config->cookieTtl()); - $this->sessionPool->save($sessionCookie); + $this->sessionCache->save($sessionCookie); return Cookie::create( name: $this->cookieName(), @@ -205,10 +163,10 @@ final readonly class LoginListener { /* successful auth with token, requested scope of ip (and ip access enabled) */ $ipKey = $this->makeCacheKey("ip_$ip"); - $sessionIp = $this->sessionPool->getItem($ipKey); + $sessionIp = $this->sessionCache->getItem($ipKey); $sessionIp->set($id); $sessionIp->expiresAfter($this->config->ipTtl()); - $this->sessionPool->save($sessionIp); + $this->sessionCache->save($sessionIp); } /** @throws InvalidArgumentException */ @@ -218,7 +176,7 @@ final readonly class LoginListener { /* hash the data and timeframe, so we do not count duplicates in the same timeframe * hitting refresh a few times should not lock you out */ $ipKey = $this->makeCacheKey("ip_{$request->getClientIp()}"); - $failuresItem = $this->requestPool->getItem($ipKey); + $failuresItem = $this->requestCache->getItem($ipKey); $failures = $failuresItem->get() ?? []; $failures[hash('xxh3', "$timeframe-$data")] = true; $limitReached = count($failures) >= $this->config->limit(); @@ -226,7 +184,7 @@ final readonly class LoginListener { $failuresItem->expiresAfter($limitReached ? $this->config->limitTtl() : $this->config->limitTimeout() ); - $this->requestPool->save($failuresItem); + $this->requestCache->save($failuresItem); return $limitReached; } diff --git a/src/Listener/LookupListener.php b/src/Listener/LookupListener.php deleted file mode 100644 index 0b5526e..0000000 --- a/src/Listener/LookupListener.php +++ /dev/null @@ -1,41 +0,0 @@ -config = $config; - } - - #[AsEventListener(priority: 44)] - public function onKernelResponse(ResponseEvent $event): void { - /* if you enable a static secret, you may choose to also enable - * a totp-lookup, which contains a special path, when successfully - * authenticated, instead of returning "hi " it returns - * "code " */ - if ($this->config->staticSecret() && $this->config->lookupTotp()) { - if (str_contains($event->getRequest()->getPathInfo(), - $this->config->lookupTotp()) && - $event->getResponse()->getStatusCode() === Response::HTTP_OK - ) { - $totp = $this->getTotp(); - $next = $totp->at(time() + $totp->getPeriod()); - $event->setResponse(new Response( - "next {$next}", - Response::HTTP_OK, - ['Content-Type' => 'text/plain'] - )); - } - } - } -} diff --git a/src/Listener/RejectListener.php b/src/Listener/RejectListener.php index cdd50ed..e8876c2 100644 --- a/src/Listener/RejectListener.php +++ b/src/Listener/RejectListener.php @@ -20,7 +20,7 @@ final readonly class RejectListener { use StringTrait; public function __construct( - private CacheItemPoolInterface $requestPool, + private CacheItemPoolInterface $requestCache, private ConfigBag $config, private Environment $twig, private LoggerInterface $logger, @@ -32,7 +32,7 @@ final readonly class RejectListener { $ipKey = $this->makeCacheKey("ip_{$event->getRequest()->getClientIp()}"); /* check if they have made too many failed login attempts */ - $failuresItem = $this->requestPool->getItem($ipKey); + $failuresItem = $this->requestCache->getItem($ipKey); if ($failuresItem->isHit()) { $failures = $failuresItem->get() ?? []; if (count($failures) >= $this->config->limit()) { diff --git a/src/MonitorCacheKeys.php b/src/MonitorCacheKeys.php index e04c064..10be8d4 100644 --- a/src/MonitorCacheKeys.php +++ b/src/MonitorCacheKeys.php @@ -11,6 +11,9 @@ use Psr\Cache\InvalidArgumentException; /* We must not store the key-list item or values within this object, * because it can change from outside this object instance. */ final readonly class MonitorCacheKeys implements CacheItemPoolInterface { + /* TODO store clean/dirty status in the key-list, so that in PersistCache, + * we can only need to update/remove specific items that changed, + * instead of the full list */ private const KEY_LIST = '__key_list'; private const IS_DIRTY = '__is_dirty'; diff --git a/src/PersistCache.php b/src/PersistCache.php index dcf354a..14bae22 100644 --- a/src/PersistCache.php +++ b/src/PersistCache.php @@ -9,67 +9,67 @@ use Symfony\Component\DependencyInjection\Attribute\Autoconfigure; #[Autoconfigure(public: true)] final readonly class PersistCache { - private MonitorCacheKeys $requestPool; - private MonitorCacheKeys $persistRequestPool; - private MonitorCacheKeys $sessionPool; - private MonitorCacheKeys $persistSessionPool; + private MonitorCacheKeys $requestCache; + private MonitorCacheKeys $requestStorage; + private MonitorCacheKeys $sessionCache; + private MonitorCacheKeys $sessionStorage; /** @throws InvalidArgumentException */ public function __construct( - CacheItemPoolInterface $requestPool, - CacheItemPoolInterface $persistRequestPool, - CacheItemPoolInterface $sessionPool, - CacheItemPoolInterface $persistSessionPool + CacheItemPoolInterface $requestCache, + CacheItemPoolInterface $requestStorage, + CacheItemPoolInterface $sessionCache, + CacheItemPoolInterface $sessionStorage, ) { - $this->requestPool = new MonitorCacheKeys($requestPool); - $this->persistRequestPool = new MonitorCacheKeys($persistRequestPool); - $this->sessionPool = new MonitorCacheKeys($sessionPool); - $this->persistSessionPool = new MonitorCacheKeys($persistSessionPool); + $this->requestCache = new MonitorCacheKeys($requestCache); + $this->requestStorage = new MonitorCacheKeys($requestStorage); + $this->sessionCache = new MonitorCacheKeys($sessionCache); + $this->sessionStorage = new MonitorCacheKeys($sessionStorage); } /** @throws InvalidArgumentException */ public function boot(): void { /* the caches are considered warm as soon as they are not empty */ - if (empty($this->requestPool->getKeys())) { - $items = $this->persistRequestPool->getItems($this->persistRequestPool->getKeys()); + if (empty($this->requestCache->getKeys())) { + $items = $this->requestStorage->getItems($this->requestStorage->getKeys()); foreach ($items as $item) { - $this->requestPool->saveDeferred($item); + $this->requestCache->saveDeferred($item); } - $this->requestPool->markClean(); - $this->requestPool->commit(); + $this->requestCache->markClean(); + $this->requestCache->commit(); } - if (empty($this->sessionPool->getKeys())) { - $items = $this->persistSessionPool->getItems($this->persistSessionPool->getKeys()); + if (empty($this->sessionCache->getKeys())) { + $items = $this->sessionStorage->getItems($this->sessionStorage->getKeys()); foreach ($items as $item) { - $this->sessionPool->saveDeferred($item); + $this->sessionCache->saveDeferred($item); } - $this->sessionPool->markClean(); - $this->sessionPool->commit(); + $this->sessionCache->markClean(); + $this->sessionCache->commit(); } } /** @throws InvalidArgumentException */ public function persist(): void { /* we only need to persist the caches if they contain changes */ - if ($this->requestPool->isDirty()) { - $this->requestPool->markClean(); - $items = $this->requestPool->getItems($this->requestPool->getKeys()); - $this->persistRequestPool->clear(); + if ($this->requestCache->isDirty()) { + $this->requestCache->markClean(); + $items = $this->requestCache->getItems($this->requestCache->getKeys()); + $this->requestStorage->clear(); foreach ($items as $item) { - $this->persistRequestPool->saveDeferred($item); + $this->requestStorage->saveDeferred($item); } - $this->persistRequestPool->commit(); + $this->requestStorage->commit(); } - if ($this->sessionPool->isDirty()) { - $this->sessionPool->markClean(); - $items = $this->sessionPool->getItems($this->sessionPool->getKeys()); - $this->persistSessionPool->clear(); + if ($this->sessionCache->isDirty()) { + $this->sessionCache->markClean(); + $items = $this->sessionCache->getItems($this->sessionCache->getKeys()); + $this->sessionStorage->clear(); foreach ($items as $item) { - $this->persistSessionPool->saveDeferred($item); + $this->sessionStorage->saveDeferred($item); } - $this->persistSessionPool->commit(); + $this->sessionStorage->commit(); } } } diff --git a/src/Trait/GetTotpTrait.php b/src/Trait/GetTotpTrait.php index 1a51526..bfd5614 100644 --- a/src/Trait/GetTotpTrait.php +++ b/src/Trait/GetTotpTrait.php @@ -6,10 +6,16 @@ use App\ConfigBag; use OTPHP\Factory; use OTPHP\TOTPInterface; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Contracts\Service\Attribute\Required; trait GetTotpTrait { protected readonly ConfigBag $config; + #[Required] + public function setConfig(ConfigBag $config): void { + $this->config = $config; + } + protected function getTotp(): TOTPInterface { $otp = Factory::loadFromProvisioningUri( $this->config->totpUri(), $this->config->clock() diff --git a/src/Trait/HasLoggerTrait.php b/src/Trait/HasLoggerTrait.php new file mode 100644 index 0000000..57344e4 --- /dev/null +++ b/src/Trait/HasLoggerTrait.php @@ -0,0 +1,16 @@ +logger = $logger; + } +} diff --git a/src/Trait/MakeNonceTrait.php b/src/Trait/MakeNonceTrait.php index 1a1f6cf..51f2816 100644 --- a/src/Trait/MakeNonceTrait.php +++ b/src/Trait/MakeNonceTrait.php @@ -6,17 +6,23 @@ namespace App\Trait; use Exception; use Psr\Cache\CacheItemPoolInterface; use Psr\Cache\InvalidArgumentException; -use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Contracts\Service\Attribute\Required; trait MakeNonceTrait { + use HasLoggerTrait; + /* 15 bytes neatly fits in base64 */ private const NONCE_LENGTH = 15; private const NONCE_TTL = 120; - protected readonly CacheItemPoolInterface $noncePool; - protected readonly LoggerInterface $logger; + protected readonly CacheItemPoolInterface $nonceCache; + + #[Required] + public function setNonceCache(CacheItemPoolInterface $nonceCache): void { + $this->nonceCache = $nonceCache; + } /** @throws InvalidArgumentException|Exception */ protected function makeNonce(int $retries = 3): string { @@ -24,7 +30,7 @@ trait MakeNonceTrait { $nonce = rtrim(strtr(base64_encode(random_bytes( static::NONCE_LENGTH )), '+/', '-_'), '='); - $nonceItem = $this->noncePool->getItem($nonce); + $nonceItem = $this->nonceCache->getItem($nonce); if ($nonceItem->isHit()) { if ($retries < 1) { @@ -41,7 +47,7 @@ trait MakeNonceTrait { $nonceItem->set(true); /* valid */ $nonceItem->expiresAfter(static::NONCE_TTL); $this->logger->debug("added nonce: $nonce"); - $this->noncePool->save($nonceItem); + $this->nonceCache->save($nonceItem); return $nonce; } } diff --git a/src/var/share/dev/pools/app/0xQxY0ZxZl/F/Q/la0V391yRRJD5n7Vs43Q b/src/var/share/dev/pools/app/0xQxY0ZxZl/F/Q/la0V391yRRJD5n7Vs43Q deleted file mode 100644 index e149522..0000000 --- a/src/var/share/dev/pools/app/0xQxY0ZxZl/F/Q/la0V391yRRJD5n7Vs43Q +++ /dev/null @@ -1,3 +0,0 @@ -0 -__key_list -a:0:{} \ No newline at end of file diff --git a/src/var/share/dev/pools/app/0xQxY0ZxZl/J/6/nbmeIrZtxdzW+dKt5xUA b/src/var/share/dev/pools/app/0xQxY0ZxZl/J/6/nbmeIrZtxdzW+dKt5xUA deleted file mode 100644 index 52416aa..0000000 --- a/src/var/share/dev/pools/app/0xQxY0ZxZl/J/6/nbmeIrZtxdzW+dKt5xUA +++ /dev/null @@ -1,3 +0,0 @@ -0 -__is_dirty -b:0; \ No newline at end of file diff --git a/src/var/share/dev/pools/app/joE1VFKE34/F/Q/la0V391yRRJD5n7Vs43Q b/src/var/share/dev/pools/app/joE1VFKE34/F/Q/la0V391yRRJD5n7Vs43Q deleted file mode 100644 index e149522..0000000 --- a/src/var/share/dev/pools/app/joE1VFKE34/F/Q/la0V391yRRJD5n7Vs43Q +++ /dev/null @@ -1,3 +0,0 @@ -0 -__key_list -a:0:{} \ No newline at end of file diff --git a/src/var/share/dev/pools/app/joE1VFKE34/J/6/nbmeIrZtxdzW+dKt5xUA b/src/var/share/dev/pools/app/joE1VFKE34/J/6/nbmeIrZtxdzW+dKt5xUA deleted file mode 100644 index 52416aa..0000000 --- a/src/var/share/dev/pools/app/joE1VFKE34/J/6/nbmeIrZtxdzW+dKt5xUA +++ /dev/null @@ -1,3 +0,0 @@ -0 -__is_dirty -b:0; \ No newline at end of file diff --git a/src/var/share/dev/pools/app/w4RrgZ2XdW/-/G/9VLlX+puJPGpzbQLnVHA b/src/var/share/dev/pools/app/w4RrgZ2XdW/-/G/9VLlX+puJPGpzbQLnVHA deleted file mode 100644 index 848cd60..0000000 --- a/src/var/share/dev/pools/app/w4RrgZ2XdW/-/G/9VLlX+puJPGpzbQLnVHA +++ /dev/null @@ -1,3 +0,0 @@ -1766103213 -suppress -N; \ No newline at end of file diff --git a/src/var/share/dev/pools/app/w4RrgZ2XdW/I/V/EI-b-M3ArgfEx5Vkhckw b/src/var/share/dev/pools/app/w4RrgZ2XdW/I/V/EI-b-M3ArgfEx5Vkhckw deleted file mode 100644 index a2e179e..0000000 --- a/src/var/share/dev/pools/app/w4RrgZ2XdW/I/V/EI-b-M3ArgfEx5Vkhckw +++ /dev/null @@ -1,3 +0,0 @@ -32503594112 -totp -s:138:"otpauth://totp/Preauth-TOTP?secret=5RL5FOJGV4XRKGT74ZVN4725OAM244SU7JYXYX4SHQDTJI4P3YKBYAFUVBBOCLI5XSOLERNB6IQQ54SIGY6QHJ26JM4OP3ZJVBUUBIY"; \ No newline at end of file diff --git a/templates/login.html.twig b/templates/login.html.twig index dda8099..7fcae01 100644 --- a/templates/login.html.twig +++ b/templates/login.html.twig @@ -8,82 +8,25 @@
- {% if env.allow_password %} -
-
- 🔃 {{ env.password_name }}
-
- - - - {% else %}
- {% endif %}