diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7ff4f67..3739f454 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,21 +7,24 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache Composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: /tmp/composer-cache key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} - - uses: php-actions/composer@v6 + - name: Composer + uses: php-actions/composer@v6 + with: + php_version: 8.1 - name: Archive build run: mkdir /tmp/github-actions/ && tar -cvf /tmp/github-actions/build.tar ./ - name: Upload build archive for test runners - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: build-artifact path: /tmp/github-actions @@ -52,7 +55,7 @@ jobs: needs: [composer] steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: build-artifact path: /tmp/github-actions @@ -64,3 +67,4 @@ jobs: uses: php-actions/phpstan@v3 with: path: src/ + php_version: 8.1 diff --git a/composer.json b/composer.json index fc861b5f..06a0ccb5 100644 --- a/composer.json +++ b/composer.json @@ -14,17 +14,17 @@ "ext-json": "*", "php": ">=8.1", - "phpgt/config": "^v1.0", + "phpgt/config": "^1.0", + "phpgt/csrf": "^v1.9", "phpgt/dom": "^v4.0", "phpgt/domtemplate": "^v3.1", - "phpgt/database": "^v1.4", - "phpgt/http": "^v1.1", - "phpgt/logger": "^v1.0", - "phpgt/protectedglobal": "^v1.0", - "phpgt/routing": "^v1.0", - "phpgt/servicecontainer": "^v1.1", - "phpgt/session": "^v1.1", - "phpgt/sync": "^v1.2", + "phpgt/database": "^1.4", + "phpgt/http": "^1.1", + "phpgt/logger": "^1.0", + "phpgt/routing": "^1.0", + "phpgt/servicecontainer": "^1.1", + "phpgt/session": "^1.1", + "phpgt/sync": "^1.2", "phpgt/ulid": "^v1.0.0", "psr/http-server-middleware": "^1.0", @@ -32,8 +32,8 @@ }, "require-dev": { - "phpstan/phpstan": "^v1.8", - "phpunit/phpunit": "^v9.5" + "phpstan/phpstan": "v1.8.0", + "phpunit/phpunit": "v9.5.21" }, "autoload": { diff --git a/composer.lock b/composer.lock index 40577f3a..be24cec9 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": "8d3a97a219abb0a78f4d48b0e34819fe", + "content-hash": "b1fb79f4fc1286b820e47716f4085ff7", "packages": [ { "name": "magicalex/write-ini-file", @@ -171,6 +171,64 @@ ], "time": "2021-01-30T14:24:07+00:00" }, + { + "name": "phpgt/csrf", + "version": "v1.9.0", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/Csrf.git", + "reference": "30d67a65466976c90e94c571834d041cc4d8fb5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/Csrf/zipball/30d67a65466976c90e94c571834d041cc4d8fb5e", + "reference": "30d67a65466976c90e94c571834d041cc4d8fb5e", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "phpgt/dom": "^v4.0", + "phpgt/session": "^v1.1" + }, + "require-dev": { + "phpstan/phpstan": "^v1.8", + "phpunit/phpunit": "^v9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\Csrf\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "James Fellows", + "email": "mrfellows@gmail.com", + "role": "Developer" + }, + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com", + "role": "Developer" + } + ], + "description": "Automatic protection from Cross-Site Request Forgery.", + "support": { + "issues": "https://github.com/PhpGt/Csrf/issues", + "source": "https://github.com/PhpGt/Csrf/tree/v1.9.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/PhpGt", + "type": "github" + } + ], + "time": "2022-09-23T12:03:51+00:00" + }, { "name": "phpgt/cssxpath", "version": "v1.1.4", @@ -669,44 +727,6 @@ ], "time": "2021-03-23T12:46:44+00:00" }, - { - "name": "phpgt/protectedglobal", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/PhpGt/ProtectedGlobal.git", - "reference": "4e909c44a0e1c3c2b4b9eedb1a61ee247cc19635" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PhpGt/ProtectedGlobal/zipball/4e909c44a0e1c3c2b4b9eedb1a61ee247cc19635", - "reference": "4e909c44a0e1c3c2b4b9eedb1a61ee247cc19635", - "shasum": "" - }, - "require": { - "php": ">7.4" - }, - "require-dev": { - "phpstan/phpstan": "^v1.8", - "phpunit/phpunit": "^v9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Gt\\ProtectedGlobal\\": "./src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Protect against accidental use of superglobals.", - "support": { - "issues": "https://github.com/PhpGt/ProtectedGlobal/issues", - "source": "https://github.com/PhpGt/ProtectedGlobal/tree/v1.1.0" - }, - "time": "2022-09-22T14:44:46+00:00" - }, { "name": "phpgt/routing", "version": "v1.1.0", @@ -977,24 +997,24 @@ }, { "name": "phpgt/ulid", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/PhpGt/Ulid.git", - "reference": "17edd130b29fc4ca70d457d9758ac6208ceaa6ab" + "reference": "6fdbf83672c98013d530d2fb469768602b505aff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PhpGt/Ulid/zipball/17edd130b29fc4ca70d457d9758ac6208ceaa6ab", - "reference": "17edd130b29fc4ca70d457d9758ac6208ceaa6ab", + "url": "https://api.github.com/repos/PhpGt/Ulid/zipball/6fdbf83672c98013d530d2fb469768602b505aff", + "reference": "6fdbf83672c98013d530d2fb469768602b505aff", "shasum": "" }, "require": { "php": ">=8.0" }, "require-dev": { - "phpstan/phpstan": "v1.8.0", - "phpunit/phpunit": "v9.5.21" + "phpstan/phpstan": "^v1.8", + "phpunit/phpunit": "^v9.5" }, "type": "library", "autoload": { @@ -1017,7 +1037,7 @@ "description": "Unique, lexicographically sortable identifiers.", "support": { "issues": "https://github.com/PhpGt/Ulid/issues", - "source": "https://github.com/PhpGt/Ulid/tree/v1.1.0" + "source": "https://github.com/PhpGt/Ulid/tree/v1.1.1" }, "funding": [ { @@ -1025,7 +1045,7 @@ "type": "github" } ], - "time": "2022-07-30T19:02:35+00:00" + "time": "2022-09-24T17:38:47+00:00" }, { "name": "psr/container", @@ -1760,18 +1780,245 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "77a32518733312af16a44300404e945338981de3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", + "reference": "77a32518733312af16a44300404e945338981de3", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + }, + "time": "2022-03-15T21:29:03+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.15.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", + "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.2", + "php": "^7.2 || ~8.0, <8.2", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^6.0 || ^7.0", + "phpunit/phpunit": "^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" + }, + "time": "2021-12-08T12:19:24+00:00" + }, { "name": "phpstan/phpstan", - "version": "1.8.5", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20" + "reference": "b7648d4ee9321665acaf112e49da9fd93df8fbd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f6598a5ff12ca4499a836815e08b4d77a2ddeb20", - "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b7648d4ee9321665acaf112e49da9fd93df8fbd5", + "reference": "b7648d4ee9321665acaf112e49da9fd93df8fbd5", "shasum": "" }, "require": { @@ -1795,13 +2042,9 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.5" + "source": "https://github.com/phpstan/phpstan/tree/1.8.0" }, "funding": [ { @@ -1812,12 +2055,16 @@ "url": "https://github.com/phpstan", "type": "github" }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, { "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", "type": "tidelift" } ], - "time": "2022-09-07T16:05:32+00:00" + "time": "2022-06-29T08:53:31+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2139,16 +2386,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.24", + "version": "9.5.21", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5" + "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d0aa6097bef9fd42458a9b3c49da32c6ce6129c5", - "reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1", + "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1", "shasum": "" }, "require": { @@ -2163,6 +2410,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", + "phpspec/prophecy": "^1.12.1", "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", @@ -2177,9 +2425,12 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.1", + "sebastian/type": "^3.0", "sebastian/version": "^3.0.2" }, + "require-dev": { + "phpspec/prophecy-phpunit": "^2.0.1" + }, "suggest": { "ext-soap": "*", "ext-xdebug": "*" @@ -2221,7 +2472,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21" }, "funding": [ { @@ -2233,7 +2484,7 @@ "type": "github" } ], - "time": "2022-08-30T07:42:16+00:00" + "time": "2022-06-19T12:14:25+00:00" }, { "name": "sebastian/cli-parser", diff --git a/src/Middleware/RequestHandler.php b/src/Middleware/RequestHandler.php index ed6f3821..5a8eea2e 100644 --- a/src/Middleware/RequestHandler.php +++ b/src/Middleware/RequestHandler.php @@ -4,6 +4,8 @@ use Gt\Config\Config; use Gt\Config\ConfigFactory; use Gt\Config\ConfigSection; +use Gt\Csrf\HTMLDocumentProtector; +use Gt\Csrf\SessionTokenStore; use Gt\Dom\HTMLDocument; use Gt\DomTemplate\ComponentExpander; use Gt\DomTemplate\DocumentBinder; @@ -184,7 +186,6 @@ public function handle( $viewModel->body->classList->add($bodyDirClass); } -// ini_set('session.serialize_handler', 'php_serialize'); $sessionConfig = $this->config->getSection("session"); $sessionId = $_COOKIE[$sessionConfig["name"]] ?? null; $sessionHandler = SessionSetup::attachHandler( @@ -197,35 +198,37 @@ public function handle( ); $serviceContainer->set($session); -// TODO: Complete CSRF implementation - maybe use its own cookie? -// /** @var Session $session */ -// $session = $serviceContainer->get(Session::class); -// $csrfTokenStore = new SessionTokenStore($session->getStore("csrf", true)); -// -// if($request->getMethod() === "POST") { -// $csrfTokenStore->processAndVerify($_POST); -// } -// -// $protector = new HTMLDocumentProtector($viewModel, $csrfTokenStore); -// $protector->protectAndInject(); + $session = $serviceContainer->get(Session::class); + $csrfTokenStore = new SessionTokenStore( + $session->getStore("csrf", true) + ); + + if($request->getMethod() === "POST") { + $csrfTokenStore->verify($_POST); + } + + $protector = new HTMLDocumentProtector($viewModel, $csrfTokenStore); + $tokens = $protector->protect(HTMLDocumentProtector::ONE_TOKEN_PER_FORM); + $response = $response->withHeader("x-csrf", $tokens); } $input = new Input($_GET, $_POST, $_FILES); $serviceContainer->set($input); - Protection::removeGlobals($GLOBALS, [ - "_GET" => ["xdebug"], - ]); - Protection::overrideInternals( - $GLOBALS, - $_ENV, - $_SERVER, - $_GET, - $_POST, - $_FILES, - $_COOKIE, - $_SESSION, - ); +// TODO: Re-enable protected globals +// Protection::removeGlobals($GLOBALS, [ +// "_GET" => ["xdebug"], +// ]); +// Protection::overrideInternals( +// $GLOBALS, +// $_ENV, +// $_SERVER, +// $_GET, +// $_POST, +// $_FILES, +// $_COOKIE, +// $_SESSION, +// ); $injector = new Injector($serviceContainer);