Don't save sessions permanently on api and metrics paths
closes #530 (Session on API calls)
This commit is contained in:
parent
7b3901211a
commit
491ee37651
|
@ -24,6 +24,7 @@ return [
|
|||
\Engelsystem\Renderer\TwigServiceProvider::class,
|
||||
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
|
||||
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
|
||||
\Engelsystem\Middleware\SessionHandlerServiceProvider::class,
|
||||
|
||||
// Additional services
|
||||
\Engelsystem\Mail\MailerServiceProvider::class,
|
||||
|
@ -43,6 +44,7 @@ return [
|
|||
\Engelsystem\Middleware\ErrorHandler::class,
|
||||
\Engelsystem\Middleware\VerifyCsrfToken::class,
|
||||
\Engelsystem\Middleware\RouteDispatcher::class,
|
||||
\Engelsystem\Middleware\SessionHandler::class,
|
||||
|
||||
// Handle request
|
||||
\Engelsystem\Middleware\RequestHandler::class,
|
||||
|
|
|
@ -50,7 +50,8 @@ class RouteDispatcher implements MiddlewareInterface
|
|||
$path = $request->getPathInfo();
|
||||
}
|
||||
|
||||
$route = $this->dispatcher->dispatch($request->getMethod(), urldecode($path));
|
||||
$path = urldecode($path);
|
||||
$route = $this->dispatcher->dispatch($request->getMethod(), $path);
|
||||
|
||||
$status = $route[0];
|
||||
if ($status == FastRouteDispatcher::NOT_FOUND) {
|
||||
|
@ -70,6 +71,7 @@ class RouteDispatcher implements MiddlewareInterface
|
|||
|
||||
$routeHandler = $route[1];
|
||||
$request = $request->withAttribute('route-request-handler', $routeHandler);
|
||||
$request = $request->withAttribute('route-request-path', $path);
|
||||
|
||||
$vars = $route[2];
|
||||
foreach ($vars as $name => $value) {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
|
||||
|
||||
class SessionHandler implements MiddlewareInterface
|
||||
{
|
||||
/** @var SessionStorageInterface */
|
||||
protected $session;
|
||||
|
||||
/** @var string[] */
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* @param SessionStorageInterface $session
|
||||
* @param array $paths
|
||||
*/
|
||||
public function __construct(SessionStorageInterface $session, array $paths = [])
|
||||
{
|
||||
$this->paths = $paths;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$return = $handler->handle($request);
|
||||
|
||||
$cookies = $request->getCookieParams();
|
||||
if (
|
||||
$this->session instanceof NativeSessionStorage
|
||||
&& in_array($request->getAttribute('route-request-path'), $this->paths)
|
||||
&& !isset($cookies[$this->session->getName()])
|
||||
) {
|
||||
$this->destroyNative();
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function destroyNative()
|
||||
{
|
||||
return session_destroy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
|
||||
class SessionHandlerServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
$this->app
|
||||
->when(SessionHandler::class)
|
||||
->needs('$paths')
|
||||
->give(function () {
|
||||
return [
|
||||
'/api',
|
||||
'/ical',
|
||||
'/metrics',
|
||||
'/shifts-json-export',
|
||||
'/stats',
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
|
@ -32,10 +32,11 @@ class RouteDispatcherTest extends TestCase
|
|||
->with('HEAD', '/foo!bar')
|
||||
->willReturn([FastRouteDispatcher::FOUND, $handler, ['foo' => 'bar', 'lorem' => 'ipsum']]);
|
||||
|
||||
$request->expects($this->exactly(3))
|
||||
$request->expects($this->exactly(4))
|
||||
->method('withAttribute')
|
||||
->withConsecutive(
|
||||
['route-request-handler', $handler],
|
||||
['route-request-path', '/foo!bar'],
|
||||
['foo', 'bar'],
|
||||
['lorem', 'ipsum']
|
||||
)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Middleware\SessionHandler;
|
||||
use Engelsystem\Middleware\SessionHandlerServiceProvider;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use Illuminate\Contracts\Container\ContextualBindingBuilder;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class SessionHandlerServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\SessionHandlerServiceProvider::register()
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var ContextualBindingBuilder|MockObject $bindingBuilder */
|
||||
$bindingBuilder = $this->createMock(ContextualBindingBuilder::class);
|
||||
$app = $this->getApp(['when']);
|
||||
|
||||
$app->expects($this->once())
|
||||
->method('when')
|
||||
->with(SessionHandler::class)
|
||||
->willReturn($bindingBuilder);
|
||||
|
||||
$bindingBuilder->expects($this->once())
|
||||
->method('needs')
|
||||
->with('$paths')
|
||||
->willReturn($bindingBuilder);
|
||||
|
||||
$bindingBuilder->expects($this->once())
|
||||
->method('give')
|
||||
->willReturnCallback(function (callable $callable) {
|
||||
$paths = $callable();
|
||||
|
||||
$this->assertTrue(is_array($paths));
|
||||
$this->assertTrue(in_array('/metrics', $paths));
|
||||
});
|
||||
|
||||
$serviceProvider = new SessionHandlerServiceProvider($app);
|
||||
$serviceProvider->register();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Middleware\SessionHandler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
|
||||
class SessionHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\SessionHandler::__construct
|
||||
* @covers \Engelsystem\Middleware\SessionHandler::process
|
||||
*/
|
||||
public function testProcess()
|
||||
{
|
||||
/** @var NativeSessionStorage|MockObject $sessionStorage */
|
||||
$sessionStorage = $this->createMock(NativeSessionStorage::class);
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||
|
||||
$handler->expects($this->exactly(2))
|
||||
->method('handle')
|
||||
->with($request)
|
||||
->willReturn($response);
|
||||
|
||||
$request->expects($this->exactly(2))
|
||||
->method('getCookieParams')
|
||||
->willReturnOnConsecutiveCalls([], ['SESSION' => 'BlaFoo']);
|
||||
|
||||
$request->expects($this->exactly(2))
|
||||
->method('getAttribute')
|
||||
->with('route-request-path')
|
||||
->willReturn('/foo');
|
||||
|
||||
$sessionStorage->expects($this->exactly(2))
|
||||
->method('getName')
|
||||
->willReturn('SESSION');
|
||||
|
||||
/** @var SessionHandler|MockObject $middleware */
|
||||
$middleware = $this->getMockBuilder(SessionHandler::class)
|
||||
->setConstructorArgs([$sessionStorage, ['/foo']])
|
||||
->setMethods(['destroyNative'])
|
||||
->getMock();
|
||||
|
||||
$middleware->expects($this->once())
|
||||
->method('destroyNative')
|
||||
->willReturn(true);
|
||||
|
||||
$middleware->process($request, $handler);
|
||||
$middleware->process($request, $handler);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue