Compare commits

...

16 commits

Author SHA1 Message Date
9e3d1fd2ac Merge branch 'feature/flow-7.3' into develop
Some checks failed
ci/woodpecker/push/code-style Pipeline failed
2022-08-01 00:23:32 +02:00
aa150cea9f Adding code-style build pipeline
Some checks failed
ci/woodpecker/push/code-style Pipeline failed
2022-08-01 00:18:22 +02:00
287ef82621 note about broken functional tests 2022-08-01 00:17:55 +02:00
9f30b80d39 Marking breaking change 2022-07-31 23:52:38 +02:00
7c13ff8e71 PHPCBF fixes 2022-07-31 23:51:35 +02:00
0ae4ab9269 do not use static class name as key in proxied classes (changes after compile run to "_Original") 2022-06-01 00:25:02 +02:00
28c6c8ef59 [WIP] migrates SessionLockRequestComponent to new MiddlewareInterface 2022-05-19 11:53:26 +02:00
d7dbff9fc2 TASK: Apply migration Neos.Flow-20201207104500
Adjust code to deprecation of ComponentContext/ComponentParameters

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
e58a157037 TASK: Apply migration Neos.Flow-20201205172733
This migration does not actually change any code. It just displays a
warning if a PHP file still refers to the no longer existing
ComponentInterface

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
5d8e93084b TASK: Apply migration Neos.Flow-20201109224100
Adjust DB migrations to Doctrine Migrations 3.0

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
4dfb3b8568 TASK: Apply migration Neos.Flow-20201003165200
Make default ValueObjects embedded=false

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
7306320814 TASK: Apply migration Neos.Flow-20200813181400
Adjust "Settings.yaml" to new naming of settings (see
https://github.com/neos/flow-development-collection/pull/2051)

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
5ed22d20f0 TASK: Apply migration Neos.Flow-20190515215000
Adjust "Settings.yaml" to new PSR-3 logging settings (see
https://github.com/neos/flow-development-collection/pull/1574)

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
d3714249e5 TASK: Apply migration Neos.Flow-20190425144900
Adjusts code to FlashMessageContainer renaming from "\Neos\Flow\Mvc" to
"\Neos\Flow\Mvc\FlashMessage".

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
abfb8332b3 TASK: Apply migration Neos.Flow-20180415105700
Add scalar type hint to CacheAwareInterface implementations.

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
f7914f7a4b TASK: Apply migration Neos.SwiftMailer-20161130105617
Adjusts code to package renaming from "TYPO3.SwiftMailer" to
"Neos.SwiftMailer".

Note: This migration did not produce any changes, so the commit simply
marks the migration as applied. This makes sure it will not be applied
again.
2022-05-19 11:51:43 +02:00
6 changed files with 52 additions and 30 deletions

View file

@ -0,0 +1,7 @@
pipeline:
code-style:
image: composer
commands:
- composer global config repositories.repo-name vcs https://git.digital-competence.de/Packages/php-codesniffer
- composer global require digicomp/php-codesniffer:@dev
- composer global exec -- phpcs --runtime-set ignore_warnings_on_exit 1 --standard=DigiComp Classes/ Tests/

View file

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace DigiComp\FlowSessionLock\Aspects; namespace DigiComp\FlowSessionLock\Aspects;
use DigiComp\FlowSessionLock\Http\SessionLockRequestComponent; use DigiComp\FlowSessionLock\Http\SessionLockRequestMiddleware;
use Neos\Flow\Annotations as Flow; use Neos\Flow\Annotations as Flow;
use Neos\Flow\Aop\JoinPointInterface; use Neos\Flow\Aop\JoinPointInterface;
use Neos\Flow\Core\Bootstrap; use Neos\Flow\Core\Bootstrap;
@ -52,9 +52,8 @@ class ReadOnlyAspect
$this->readOnly = true; $this->readOnly = true;
/** @var Lock|null $lock */ /** @var Lock|null $lock */
$lock = $activeRequestHandler->getComponentContext()->getParameter( $lock = $activeRequestHandler->getHttpRequest()->getAttribute(
SessionLockRequestComponent::class, SessionLockRequestMiddleware::class . '.' . SessionLockRequestMiddleware::PARAMETER_NAME
SessionLockRequestComponent::PARAMETER_NAME
); );
if ($lock !== null) { if ($lock !== null) {
$this->logger->debug('SessionLock: Release, as this is marked read only.'); $this->logger->debug('SessionLock: Release, as this is marked read only.');

View file

@ -5,14 +5,16 @@ declare(strict_types=1);
namespace DigiComp\FlowSessionLock\Http; namespace DigiComp\FlowSessionLock\Http;
use Neos\Flow\Annotations as Flow; use Neos\Flow\Annotations as Flow;
use Neos\Flow\Http\Component\ComponentContext; use Psr\Http\Message\ResponseInterface;
use Neos\Flow\Http\Component\ComponentInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\Lock\Exception\LockAcquiringException; use Symfony\Component\Lock\Exception\LockAcquiringException;
use Symfony\Component\Lock\Key; use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\LockFactory; use Symfony\Component\Lock\LockFactory;
class SessionLockRequestComponent implements ComponentInterface class SessionLockRequestMiddleware implements MiddlewareInterface
{ {
public const PARAMETER_NAME = 'sessionLock'; public const PARAMETER_NAME = 'sessionLock';
@ -55,13 +57,13 @@ class SessionLockRequestComponent implements ComponentInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function handle(ComponentContext $componentContext): void public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{ {
$sessionCookieName = $this->sessionSettings['name']; $sessionCookieName = $this->sessionSettings['name'];
$cookies = $componentContext->getHttpRequest()->getCookieParams(); $cookies = $request->getCookieParams();
if (!isset($cookies[$sessionCookieName])) { if (!isset($cookies[$sessionCookieName])) {
return; return $handler->handle($request);
} }
// TODO: sessionIdentifier might be wrong, probably it should probably be storage identifier // TODO: sessionIdentifier might be wrong, probably it should probably be storage identifier
@ -69,7 +71,7 @@ class SessionLockRequestComponent implements ComponentInterface
$lock = $this->lockFactory->createLockFromKey($key, $this->timeToLive, $this->autoRelease); $lock = $this->lockFactory->createLockFromKey($key, $this->timeToLive, $this->autoRelease);
$componentContext->setParameter(SessionLockRequestComponent::class, static::PARAMETER_NAME, $lock); $request = $request->withAttribute(SessionLockRequestMiddleware::class . '.' . static::PARAMETER_NAME, $lock);
$this->logger->debug('SessionLock: Try to get "' . $key . '"'); $this->logger->debug('SessionLock: Try to get "' . $key . '"');
$timedOut = \time() + $this->secondsToWait; $timedOut = \time() + $this->secondsToWait;
@ -83,5 +85,6 @@ class SessionLockRequestComponent implements ComponentInterface
\usleep(100000); \usleep(100000);
} }
$this->logger->debug('SessionLock: Acquired "' . $key . '"'); $this->logger->debug('SessionLock: Acquired "' . $key . '"');
return $handler->handle($request);
} }
} }

View file

@ -9,9 +9,7 @@ DigiComp:
Neos: Neos:
Flow: Flow:
http: http:
chain: middlewares:
preprocess: lockSession:
chain: position: "before session"
lockSession: middleware: "DigiComp\\FlowSessionLock\\Http\\SessionLockRequestMiddleware"
position: "before getSessionCookieFromRequest"
component: "DigiComp\\FlowSessionLock\\Http\\SessionLockRequestComponent"

View file

@ -4,6 +4,7 @@ namespace DigiComp\FlowSessionLock\Tests\Functional;
use DigiComp\FlowSessionLock\Tests\Functional\Fixtures\Controller\ExampleController; use DigiComp\FlowSessionLock\Tests\Functional\Fixtures\Controller\ExampleController;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
use Neos\Flow\Composer\ComposerUtility;
use Neos\Flow\Http\Cookie; use Neos\Flow\Http\Cookie;
use Neos\Flow\Mvc\Routing\Route; use Neos\Flow\Mvc\Routing\Route;
use Neos\Flow\Tests\FunctionalTestCase; use Neos\Flow\Tests\FunctionalTestCase;
@ -43,16 +44,16 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
function ($allRequests, $oneRequest) { function ($allRequests, $oneRequest) {
self::assertGreaterThan(ExampleController::CONTROLLER_TIME, $oneRequest * 1000); self::assertGreaterThan(ExampleController::CONTROLLER_TIME, $oneRequest * 1000);
self::assertGreaterThan(ExampleController::CONTROLLER_TIME * 4, $allRequests * 1000); self::assertGreaterThan(ExampleController::CONTROLLER_TIME * 4, $allRequests * 1000);
} },
], ],
[ [
'http://localhost/test/sessionlock/unprotectedbyannotation', 'http://localhost/test/sessionlock/unprotectedbyannotation',
$parallelChecker $parallelChecker,
], ],
[ [
'http://localhost/test/sessionlock/unprotectedbyconfiguration', 'http://localhost/test/sessionlock/unprotectedbyconfiguration',
$parallelChecker $parallelChecker,
] ],
]; ];
} }
@ -62,18 +63,21 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
*/ */
public function itDoesNotAllowToEnterMoreThanOneWithTheSameSession(string $url, \Closure $checker): void public function itDoesNotAllowToEnterMoreThanOneWithTheSameSession(string $url, \Closure $checker): void
{ {
// Functional tests are currently broken, until a version containing
// https://github.com/neos/flow-development-collection/commit/bebfc4e6566bc4ba2ba28330344105adb2d6ada0
// gets released
$request = $this->serverRequestFactory $request = $this->serverRequestFactory
->createServerRequest('GET', new Uri($url)); ->createServerRequest('GET', new Uri($url));
$start = microtime(true); $start = \microtime(true);
$response = $this->browser->sendRequest($request); $response = $this->browser->sendRequest($request);
$neededForOne = microtime(true) - $start; $neededForOne = \microtime(true) - $start;
$sessionCookies = array_map(static function ($cookie) { $sessionCookies = \array_map(static function ($cookie) {
return Cookie::createFromRawSetCookieHeader($cookie); return Cookie::createFromRawSetCookieHeader($cookie);
}, $response->getHeader('Set-Cookie')); }, $response->getHeader('Set-Cookie'));
self::assertNotEmpty($sessionCookies); self::assertNotEmpty($sessionCookies);
$cookies = array_reduce($sessionCookies, static function ($out, $cookie) { $cookies = \array_reduce($sessionCookies, static function ($out, $cookie) {
$out[$cookie->getName()] = $cookie->getValue(); $out[$cookie->getName()] = $cookie->getValue();
return $out; return $out;
}, []); }, []);
@ -81,7 +85,7 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
->createServerRequest('GET', new Uri($url)) ->createServerRequest('GET', new Uri($url))
->withCookieParams($cookies); ->withCookieParams($cookies);
$childs = []; $childs = [];
$start = microtime(true); $start = \microtime(true);
for ($i = 0; $i < 4; $i++) { for ($i = 0; $i < 4; $i++) {
$child = \pcntl_fork(); $child = \pcntl_fork();
if ($child === 0) { if ($child === 0) {
@ -93,7 +97,7 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
foreach ($childs as $child) { foreach ($childs as $child) {
\pcntl_waitpid($child, $status); \pcntl_waitpid($child, $status);
} }
$neededForAll = microtime(true) - $start; $neededForAll = \microtime(true) - $start;
$checker($neededForAll, $neededForOne); $checker($neededForAll, $neededForOne);
} }

View file

@ -3,7 +3,7 @@
"description": "Session locking for Neos Flow - it secures the session becoming corrupted by concurrent access to the same session by different requests", "description": "Session locking for Neos Flow - it secures the session becoming corrupted by concurrent access to the same session by different requests",
"type": "neos-package", "type": "neos-package",
"require": { "require": {
"neos/flow": "^6.3.0", "neos/flow": "^7.3.0",
"php": ">=7.4", "php": ">=7.4",
"symfony/lock": "^5.2.0" "symfony/lock": "^5.2.0"
}, },
@ -20,8 +20,19 @@
"package-key": "DigiComp.FlowSessionLock" "package-key": "DigiComp.FlowSessionLock"
}, },
"branch-alias": { "branch-alias": {
"dev-develop": "2.0.x-dev" "dev-develop": "3.0.x-dev"
} },
"applied-flow-migrations": [
"Neos.SwiftMailer-20161130105617",
"Neos.Flow-20180415105700",
"Neos.Flow-20190425144900",
"Neos.Flow-20190515215000",
"Neos.Flow-20200813181400",
"Neos.Flow-20201003165200",
"Neos.Flow-20201109224100",
"Neos.Flow-20201205172733",
"Neos.Flow-20201207104500"
]
}, },
"authors": [ "authors": [
{ {