Compare commits

..

No commits in common. "9e3d1fd2aca8c5121f3f92e7a5acccaf7a023488" and "aaacd95a065805c6bc35b3b27d10c262d6ab1661" have entirely different histories.

6 changed files with 30 additions and 52 deletions

View file

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

View file

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

View file

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

View file

@ -4,7 +4,6 @@ namespace DigiComp\FlowSessionLock\Tests\Functional;
use DigiComp\FlowSessionLock\Tests\Functional\Fixtures\Controller\ExampleController;
use GuzzleHttp\Psr7\Uri;
use Neos\Flow\Composer\ComposerUtility;
use Neos\Flow\Http\Cookie;
use Neos\Flow\Mvc\Routing\Route;
use Neos\Flow\Tests\FunctionalTestCase;
@ -44,16 +43,16 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
function ($allRequests, $oneRequest) {
self::assertGreaterThan(ExampleController::CONTROLLER_TIME, $oneRequest * 1000);
self::assertGreaterThan(ExampleController::CONTROLLER_TIME * 4, $allRequests * 1000);
},
}
],
[
'http://localhost/test/sessionlock/unprotectedbyannotation',
$parallelChecker,
$parallelChecker
],
[
'http://localhost/test/sessionlock/unprotectedbyconfiguration',
$parallelChecker,
],
$parallelChecker
]
];
}
@ -63,21 +62,18 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
*/
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
->createServerRequest('GET', new Uri($url));
$start = \microtime(true);
$start = microtime(true);
$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);
}, $response->getHeader('Set-Cookie'));
self::assertNotEmpty($sessionCookies);
$cookies = \array_reduce($sessionCookies, static function ($out, $cookie) {
$cookies = array_reduce($sessionCookies, static function ($out, $cookie) {
$out[$cookie->getName()] = $cookie->getValue();
return $out;
}, []);
@ -85,7 +81,7 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
->createServerRequest('GET', new Uri($url))
->withCookieParams($cookies);
$childs = [];
$start = \microtime(true);
$start = microtime(true);
for ($i = 0; $i < 4; $i++) {
$child = \pcntl_fork();
if ($child === 0) {
@ -97,7 +93,7 @@ class SessionLockRequestComponentTest extends FunctionalTestCase
foreach ($childs as $child) {
\pcntl_waitpid($child, $status);
}
$neededForAll = \microtime(true) - $start;
$neededForAll = microtime(true) - $start;
$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",
"type": "neos-package",
"require": {
"neos/flow": "^7.3.0",
"neos/flow": "^6.3.0",
"php": ">=7.4",
"symfony/lock": "^5.2.0"
},
@ -20,19 +20,8 @@
"package-key": "DigiComp.FlowSessionLock"
},
"branch-alias": {
"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"
]
"dev-develop": "2.0.x-dev"
}
},
"authors": [
{