[MonologBridge] Added SwitchUserTokenProcessor to log the impersonator

This commit is contained in:
Igor Timoshenko 2020-07-29 18:40:37 +03:00 committed by Fabien Potencier
parent e983035e1a
commit 2f8651d4ec
4 changed files with 154 additions and 19 deletions

View File

@ -0,0 +1,53 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Monolog\Processor;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* The base class for security token processors.
*
* @author Dany Maillard <danymaillard93b@gmail.com>
* @author Igor Timoshenko <igor.timoshenko@i.ua>
*/
abstract class AbstractTokenProcessor
{
/**
* @var TokenStorageInterface
*/
protected $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
abstract protected function getKey(): string;
abstract protected function getToken(): ?TokenInterface;
public function __invoke(array $record): array
{
$record['extra'][$this->getKey()] = null;
if (null !== $token = $this->getToken()) {
$record['extra'][$this->getKey()] = [
'username' => $token->getUsername(),
'authenticated' => $token->isAuthenticated(),
'roles' => $token->getRoleNames(),
];
}
return $record;
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Monolog\Processor;
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* Adds the original security token to the log entry.
*
* @author Igor Timoshenko <igor.timoshenko@i.ua>
*/
class SwitchUserTokenProcessor extends AbstractTokenProcessor
{
/**
* {@inheritdoc}
*/
protected function getKey(): string
{
return 'impersonator_token';
}
/**
* {@inheritdoc}
*/
protected function getToken(): ?TokenInterface
{
$token = $this->tokenStorage->getToken();
if ($token instanceof SwitchUserToken) {
return $token->getOriginalToken();
}
return null;
}
}

View File

@ -11,35 +11,29 @@
namespace Symfony\Bridge\Monolog\Processor;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* Adds the current security token to the log entry.
*
* @author Dany Maillard <danymaillard93b@gmail.com>
* @author Igor Timoshenko <igor.timoshenko@i.ua>
*/
class TokenProcessor
class TokenProcessor extends AbstractTokenProcessor
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
/**
* {@inheritdoc}
*/
protected function getKey(): string
{
$this->tokenStorage = $tokenStorage;
return 'token';
}
public function __invoke(array $records)
/**
* {@inheritdoc}
*/
protected function getToken(): ?TokenInterface
{
$records['extra']['token'] = null;
if (null !== $token = $this->tokenStorage->getToken()) {
$roles = $token->getRoleNames();
$records['extra']['token'] = [
'username' => $token->getUsername(),
'authenticated' => $token->isAuthenticated(),
'roles' => $roles,
];
}
return $records;
return $this->tokenStorage->getToken();
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Monolog\Tests\Processor;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Monolog\Processor\SwitchUserTokenProcessor;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
/**
* Tests the SwitchUserTokenProcessor.
*
* @author Igor Timoshenko <igor.timoshenko@i.ua>
*/
class SwitchUserTokenProcessorTest extends TestCase
{
public function testProcessor()
{
$originalToken = new UsernamePasswordToken('original_user', 'password', 'provider', ['ROLE_SUPER_ADMIN']);
$switchUserToken = new SwitchUserToken('user', 'passsword', 'provider', ['ROLE_USER'], $originalToken);
$tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock();
$tokenStorage->method('getToken')->willReturn($switchUserToken);
$processor = new SwitchUserTokenProcessor($tokenStorage);
$record = ['extra' => []];
$record = $processor($record);
$this->assertArrayHasKey('original_token', $record['extra']);
$this->assertEquals($originalToken->getUsername(), $record['extra']['original_token']['username']);
$this->assertEquals($originalToken->isAuthenticated(), $record['extra']['original_token']['authenticated']);
$this->assertEquals(['ROLE_SUPER_ADMIN'], $record['extra']['original_token']['roles']);
}
}