Skip to content

Commit 04c774d

Browse files
committed
Adding a shortcut for the main security functionality
1 parent 250d56b commit 04c774d

File tree

10 files changed

+238
-1
lines changed

10 files changed

+238
-1
lines changed

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ CHANGELOG
44
3.4.0
55
-----
66

7+
* Added new `security.helper` service that is an instance of `Symfony\Component\Security\Core\Security`
8+
and provides shortcuts for common security tasks.
79
* Tagging voters with the `security.voter` tag without implementing the
810
`VoterInterface` on the class is now deprecated and will be removed in 4.0.
911
* [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array`

src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@
2626
</service>
2727
<service id="Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface" alias="security.token_storage" />
2828

29+
<service id="security.helper" class="Symfony\Component\Security\Core\Security">
30+
<argument type="service">
31+
<service class="Symfony\Component\DependencyInjection\ServiceLocator">
32+
<tag name="container.service_locator" />
33+
<argument type="collection">
34+
<argument key="security.token_storage" type="service" id="security.token_storage" />
35+
<argument key="security.authorization_checker" type="service" id="security.authorization_checker" />
36+
</argument>
37+
</service>
38+
</argument>
39+
</service>
40+
<service id="Symfony\Component\Security\Core\Security" alias="security.helper" />
41+
2942
<service id="security.user_value_resolver" class="Symfony\Bundle\SecurityBundle\SecurityUserValueResolver">
3043
<argument type="service" id="security.token_storage" />
3144
<tag name="controller.argument_value_resolver" priority="40" />
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Bundle\SecurityBundle\Tests\Functional;
13+
14+
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
15+
use Symfony\Component\Security\Core\User\User;
16+
17+
class SecurityTest extends WebTestCase
18+
{
19+
public function testServiceIsFunctional()
20+
{
21+
$kernel = self::createKernel(array('test_case' => 'SecurityHelper', 'root_config' => 'config.yml'));
22+
$kernel->boot();
23+
$container = $kernel->getContainer();
24+
25+
// put a token into the storage so the final calls can function
26+
$user = new User('foo', 'pass');
27+
$token = new UsernamePasswordToken($user, '', 'provider', array('ROLE_USER'));
28+
$container->get('security.token_storage')->setToken($token);
29+
30+
$security = $container->get('functional_test.security.helper');
31+
$this->assertTrue($security->isGranted('ROLE_USER'));
32+
$this->assertSAme($token, $security->getToken());
33+
}
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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+
use Symfony\Bundle\TwigBundle\TwigBundle;
13+
use Symfony\Bundle\SecurityBundle\SecurityBundle;
14+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
15+
16+
return array(
17+
new FrameworkBundle(),
18+
new SecurityBundle(),
19+
new TwigBundle(),
20+
);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
imports:
2+
- { resource: ./../config/default.yml }
3+
4+
services:
5+
# alias the service so we can access it in the tests
6+
functional_test.security.helper:
7+
alias: security.helper
8+
public: true
9+
10+
security:
11+
providers:
12+
in_memory:
13+
memory:
14+
users: []
15+
16+
firewalls:
17+
default:
18+
anonymous: ~

src/Symfony/Component/Security/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
3.4.0
55
-----
66

7+
* Added `getUser`, `getToken` and `isGranted` methods to `Security`.
78
* added a `setToken()` method to the `SwitchUserEvent` class to allow to replace the created token while switching users
89
when custom token generation is required by application.
910
* Using voters that do not implement the `VoterInterface`is now deprecated in

src/Symfony/Component/Security/Core/Security.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111

1212
namespace Symfony\Component\Security\Core;
1313

14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
16+
use Symfony\Component\Security\Core\User\UserInterface;
17+
1418
/**
15-
* This class holds security information.
19+
* Helper class for commonly-needed security tasks.
1620
*
1721
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
1822
*/
@@ -22,4 +26,50 @@ final class Security
2226
const AUTHENTICATION_ERROR = '_security.last_error';
2327
const LAST_USERNAME = '_security.last_username';
2428
const MAX_USERNAME_LENGTH = 4096;
29+
30+
private $container;
31+
32+
public function __construct(ContainerInterface $container)
33+
{
34+
$this->container = $container;
35+
}
36+
37+
/**
38+
* @return UserInterface|null
39+
*/
40+
public function getUser()
41+
{
42+
if (!$token = $this->getToken()) {
43+
return null;
44+
}
45+
46+
$user = $token->getUser();
47+
if (!is_object($user)) {
48+
return null;
49+
}
50+
51+
return $user;
52+
}
53+
54+
/**
55+
* Checks if the attributes are granted against the current authentication token and optionally supplied subject.
56+
*
57+
* @param mixed $attributes
58+
* @param mixed $subject
59+
*
60+
* @return bool
61+
*/
62+
public function isGranted($attributes, $subject = null)
63+
{
64+
return $this->container->get('security.authorization_checker')
65+
->isGranted($attributes, $subject);
66+
}
67+
68+
/**
69+
* @return TokenInterface|null
70+
*/
71+
public function getToken()
72+
{
73+
return $this->container->get('security.token_storage')->getToken();
74+
}
2575
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Role;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Psr\Container\ContainerInterface;
16+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
17+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
18+
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
19+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
20+
use Symfony\Component\Security\Core\Security;
21+
use Symfony\Component\Security\Core\User\User;
22+
23+
class SecurityTest extends TestCase
24+
{
25+
public function testGetToken()
26+
{
27+
$token = new UsernamePasswordToken('foo', 'bar', 'provider');
28+
$tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock();
29+
30+
$tokenStorage->expects($this->once())
31+
->method('getToken')
32+
->will($this->returnValue($token));
33+
34+
$container = $this->createContainer('security.token_storage', $tokenStorage);
35+
36+
$security = new Security($container);
37+
$this->assertSame($token, $security->getToken());
38+
}
39+
40+
/**
41+
* @dataProvider getUserTests
42+
*/
43+
public function testGetUser($userInToken, $expectedUser)
44+
{
45+
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
46+
$token->expects($this->any())
47+
->method('getUser')
48+
->will($this->returnValue($userInToken));
49+
$tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock();
50+
51+
$tokenStorage->expects($this->once())
52+
->method('getToken')
53+
->will($this->returnValue($token));
54+
55+
$container = $this->createContainer('security.token_storage', $tokenStorage);
56+
57+
$security = new Security($container);
58+
$this->assertSame($expectedUser, $security->getUser());
59+
}
60+
61+
public function getUserTests()
62+
{
63+
yield array(null, null);
64+
65+
yield array('string_username', null);
66+
67+
$user = new User('nice_user', 'foo');
68+
yield array($user, $user);
69+
}
70+
71+
public function testIsGranted()
72+
{
73+
$authorizationChecker = $this->getMockBuilder(AuthorizationCheckerInterface::class)->getMock();
74+
75+
$authorizationChecker->expects($this->once())
76+
->method('isGranted')
77+
->with('SOME_ATTRIBUTE', 'SOME_SUBJECT')
78+
->will($this->returnValue(true));
79+
80+
$container = $this->createContainer('security.authorization_checker', $authorizationChecker);
81+
82+
$security = new Security($container);
83+
$this->assertTrue($security->isGranted('SOME_ATTRIBUTE', 'SOME_SUBJECT'));
84+
}
85+
86+
private function createContainer($serviceId, $serviceObject)
87+
{
88+
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
89+
90+
$container->expects($this->atLeastOnce())
91+
->method('get')
92+
->with($serviceId)
93+
->will($this->returnValue($serviceObject));
94+
95+
return $container;
96+
}
97+
}

src/Symfony/Component/Security/Core/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
],
1818
"require": {
1919
"php": "^5.5.9|>=7.0.8",
20+
"psr/container": "^1.0",
2021
"symfony/polyfill-php56": "~1.0"
2122
},
2223
"require-dev": {

src/Symfony/Component/Security/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
],
1818
"require": {
1919
"php": "^5.5.9|>=7.0.8",
20+
"psr/container": "^1.0",
2021
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
2122
"symfony/http-foundation": "~2.8|~3.0|~4.0",
2223
"symfony/http-kernel": "~3.3|~4.0",

0 commit comments

Comments
 (0)