Skip to content

Commit eedfa9e

Browse files
Merge branch '4.4'
* 4.4: [Security/Http] fix typo in deprecation message [Security] Deprecate isGranted()/decide() on more than one attribute Fixed a minor typo in the UPGRADE to 5.0 guide Various tweaks 3.4 Various tweaks 4.3 [Security] Make stateful firewalls turn responses private only when needed [PhpUnit] Fix usleep mock return value Revert \"feature #33507 [WebProfiler] Deprecated intercept_redirects in 4.4 (dorumd)\" [TwigBundle] typo [TwigBundle] fix test case [Lock] use Predis\ClientInterface instead of Predis\Client Allow Twig 3 Minor tweaks Fix version typo in deprecation notice [Form][SubmitType] Add "validate" option hint to the --parse-tags when parsing tags fails Make legacy "wrong" RFC2047 encoding apply only to one header
2 parents fdb7141 + 217f469 commit eedfa9e

File tree

6 files changed

+138
-2
lines changed

6 files changed

+138
-2
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Core\Authentication\Token\Storage;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
16+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
17+
use Symfony\Contracts\Service\ServiceSubscriberInterface;
18+
19+
/**
20+
* A token storage that increments the session usage index when the token is accessed.
21+
*
22+
* @author Nicolas Grekas <[email protected]>
23+
*/
24+
final class UsageTrackingTokenStorage implements TokenStorageInterface, ServiceSubscriberInterface
25+
{
26+
private $storage;
27+
private $sessionLocator;
28+
private $enableUsageTracking = false;
29+
30+
public function __construct(TokenStorageInterface $storage, ContainerInterface $sessionLocator)
31+
{
32+
$this->storage = $storage;
33+
$this->sessionLocator = $sessionLocator;
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function getToken(): ?TokenInterface
40+
{
41+
if ($this->enableUsageTracking) {
42+
// increments the internal session usage index
43+
$this->sessionLocator->get('session')->getMetadataBag();
44+
}
45+
46+
return $this->storage->getToken();
47+
}
48+
49+
/**
50+
* {@inheritdoc}
51+
*/
52+
public function setToken(TokenInterface $token = null): void
53+
{
54+
$this->storage->setToken($token);
55+
}
56+
57+
public function enableUsageTracking(): void
58+
{
59+
$this->enableUsageTracking = true;
60+
}
61+
62+
public function disableUsageTracking(): void
63+
{
64+
$this->enableUsageTracking = false;
65+
}
66+
67+
public static function getSubscribedServices(): array
68+
{
69+
return [
70+
'session' => SessionInterface::class,
71+
];
72+
}
73+
}

Authorization/AccessDecisionManager.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ public function __construct(iterable $voters = [], string $strategy = self::STRA
5757
*/
5858
public function decide(TokenInterface $token, array $attributes, $object = null)
5959
{
60+
if (\count($attributes) > 1) {
61+
@trigger_error('Passing more than one Security attribute to '.__METHOD__.' is deprecated since Symfony 4.4. Use multiple decide() calls or the expression language (e.g. "has_role(...) or has_role(...)") instead.', \E_USER_DEPRECATED);
62+
}
63+
6064
return $this->{$this->strategy}($token, $attributes, $object);
6165
}
6266

Authorization/AuthorizationChecker.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ final public function isGranted($attributes, $subject = null): bool
5555

5656
if (!\is_array($attributes)) {
5757
$attributes = [$attributes];
58+
} else {
59+
@trigger_error('Passing an array of Security attributes to '.__METHOD__.' is deprecated since Symfony 4.4. Use multiple isGranted() calls or the expression language (e.g. "has_role(...) or has_role(...)") instead.', \E_USER_DEPRECATED);
5860
}
5961

6062
return $this->accessDecisionManager->decide($token, $attributes, $subject);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Core\Tests\Authentication\Token\Storage;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Psr\Container\ContainerInterface;
16+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
17+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
18+
use Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage;
19+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
20+
use Symfony\Contracts\Service\ServiceLocatorTrait;
21+
22+
class UsageTrackingTokenStorageTest extends TestCase
23+
{
24+
public function testGetSetToken()
25+
{
26+
$sessionAccess = 0;
27+
$sessionLocator = new class(['session' => function () use (&$sessionAccess) {
28+
++$sessionAccess;
29+
30+
$session = $this->createMock(SessionInterface::class);
31+
$session->expects($this->once())
32+
->method('getMetadataBag');
33+
34+
return $session;
35+
}]) implements ContainerInterface {
36+
use ServiceLocatorTrait;
37+
};
38+
$tokenStorage = new TokenStorage();
39+
$trackingStorage = new UsageTrackingTokenStorage($tokenStorage, $sessionLocator);
40+
41+
$this->assertNull($trackingStorage->getToken());
42+
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
43+
44+
$trackingStorage->setToken($token);
45+
$this->assertSame($token, $trackingStorage->getToken());
46+
$this->assertSame($token, $tokenStorage->getToken());
47+
$this->assertSame(0, $sessionAccess);
48+
49+
$trackingStorage->enableUsageTracking();
50+
$this->assertSame($token, $trackingStorage->getToken());
51+
$this->assertSame(1, $sessionAccess);
52+
53+
$trackingStorage->disableUsageTracking();
54+
$this->assertSame($token, $trackingStorage->getToken());
55+
$this->assertSame(1, $sessionAccess);
56+
}
57+
}

Tests/Authorization/AccessDecisionManagerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function testStrategies($strategy, $voters, $allowIfAllAbstainDecisions,
3737
/**
3838
* @dataProvider getStrategiesWith2RolesTests
3939
*/
40-
public function testStrategiesWith2Roles($token, $strategy, $voter, $expected)
40+
public function testLegacyStrategiesWith2Roles($token, $strategy, $voter, $expected)
4141
{
4242
$manager = new AccessDecisionManager([$voter], $strategy);
4343

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": "^7.2.9",
2020
"symfony/event-dispatcher-contracts": "^1.1|^2",
21-
"symfony/service-contracts": "^1.1|^2"
21+
"symfony/service-contracts": "^1.1.6|^2"
2222
},
2323
"require-dev": {
2424
"psr/container": "^1.0",

0 commit comments

Comments
 (0)