Merge branch '2.7'

* 2.7:
  remove short array syntax
  fix session restart on PHP 5.3
  Avoid missing method when using __invoke
  Show the inherited roles in the web profiler
This commit is contained in:
Fabien Potencier 2014-12-13 09:39:06 +01:00
commit dc7237f1d4
9 changed files with 85 additions and 48 deletions

View File

@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle\DataCollector;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -24,10 +25,12 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector;
class SecurityDataCollector extends DataCollector
{
private $context;
private $roleHierarchy;
public function __construct(SecurityContextInterface $context = null)
public function __construct(SecurityContextInterface $context = null, RoleHierarchyInterface $roleHierarchy = null)
{
$this->context = $context;
$this->roleHierarchy = $roleHierarchy;
}
/**
@ -42,6 +45,8 @@ class SecurityDataCollector extends DataCollector
'token_class' => null,
'user' => '',
'roles' => array(),
'inherited_roles' => array(),
'supports_role_hierarchy' => null !== $this->roleHierarchy,
);
} elseif (null === $token = $this->context->getToken()) {
$this->data = array(
@ -50,14 +55,28 @@ class SecurityDataCollector extends DataCollector
'token_class' => null,
'user' => '',
'roles' => array(),
'inherited_roles' => array(),
'supports_role_hierarchy' => null !== $this->roleHierarchy,
);
} else {
$inheritedRoles = array();
$assignedRoles = $token->getRoles();
if (null !== $this->roleHierarchy) {
$allRoles = $this->roleHierarchy->getReachableRoles($assignedRoles);
foreach ($allRoles as $role) {
if (!in_array($role, $assignedRoles)) {
$inheritedRoles[] = $role;
}
}
}
$this->data = array(
'enabled' => true,
'authenticated' => $token->isAuthenticated(),
'token_class' => get_class($token),
'user' => $token->getUsername(),
'roles' => array_map(function ($role) { return $role->getRole();}, $token->getRoles()),
'roles' => array_map(function ($role) { return $role->getRole();}, $assignedRoles),
'inherited_roles' => array_map(function ($role) { return $role->getRole();}, $inheritedRoles),
'supports_role_hierarchy' => null !== $this->roleHierarchy,
);
}
}
@ -92,6 +111,27 @@ class SecurityDataCollector extends DataCollector
return $this->data['roles'];
}
/**
* Gets the inherited roles of the user.
*
* @return string The inherited roles
*/
public function getInheritedRoles()
{
return $this->data['inherited_roles'];
}
/**
* Checks if the data contains information about inherited roles. Still the inherited
* roles can be an empty array.
*
* @return bool true if the profile was contains inherited role information.
*/
public function supportsRoleHierarchy()
{
return $this->data['supports_role_hierarchy'];
}
/**
* Checks if the user is authenticated or not.
*

View File

@ -12,6 +12,7 @@
<service id="data_collector.security" class="%data_collector.security.class%" public="false">
<tag name="data_collector" template="@Security/Collector/security.html.twig" id="security" />
<argument type="service" id="security.context" on-invalid="ignore" />
<argument type="service" id="security.role_hierarchy" />
</service>
</services>
</container>

View File

@ -67,6 +67,12 @@
<th>Roles</th>
<td>{{ collector.roles|yaml_encode }}</td>
</tr>
{% if collector.supportsRoleHierarchy %}
<tr>
<th>Inherited Roles</th>
<td>{{ collector.inheritedRoles|yaml_encode }}</td>
</tr>
{% endif %}
{% if collector.tokenClass != null %}
<tr>
<th>Token class</th>

View File

@ -80,13 +80,13 @@ class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
$container->loadFromExtension('security', array(
'providers' => array(
'my_foo' => array('foo' => []),
'my_foo' => array('foo' => array()),
),
'firewalls' => array(
'some_firewall' => array(
'pattern' => '/.*',
'http_basic' => [],
'http_basic' => array(),
),
),
));

View File

@ -4,10 +4,14 @@
{% set request_handler %}
{% if collector.controller.class is defined %}
{% set link = collector.controller.file|file_link(collector.controller.line) %}
<span class="sf-toolbar-info-class sf-toolbar-info-with-next-pointer">{{ collector.controller.class|abbr_class }}</span>
<span class="sf-toolbar-info-method" onclick="{% if link %}window.location='{{link|e('js')}}';window.event.stopPropagation();return false;{% endif %}">
{{ collector.controller.method }}
</span>
{% if collector.controller.method %}
<span class="sf-toolbar-info-class sf-toolbar-info-with-next-pointer">{{ collector.controller.class|abbr_class }}</span>
<span class="sf-toolbar-info-method" onclick="{% if link %}window.location='{{link|e('js')}}';window.event.stopPropagation();return false;{% endif %}">
{{ collector.controller.method }}
</span>
{% else %}
<span class="sf-toolbar-info-class" onclick="{% if link %}window.location='{{link|e('js')}}';window.event.stopPropagation();return false;{% endif %}">{{ collector.controller.class|abbr_class }}</span>
{% endif %}
{% else %}
<span class="sf-toolbar-info-class">{{ collector.controller }}</span>
{% endif %}

View File

@ -89,7 +89,7 @@ class MockArraySessionStorage implements SessionStorageInterface
*/
public function start()
{
if ($this->started && !$this->closed) {
if ($this->started) {
return true;
}

View File

@ -126,7 +126,7 @@ class NativeSessionStorage implements SessionStorageInterface
*/
public function start()
{
if ($this->started && !$this->closed) {
if ($this->started) {
return true;
}
@ -134,7 +134,7 @@ class NativeSessionStorage implements SessionStorageInterface
throw new \RuntimeException('Failed to start the session: already started by PHP.');
}
if (PHP_VERSION_ID < 50400 && isset($_SESSION) && session_id()) {
if (PHP_VERSION_ID < 50400 && !$this->closed && isset($_SESSION) && session_id()) {
// not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3
throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).');
}
@ -162,10 +162,6 @@ class NativeSessionStorage implements SessionStorageInterface
*/
public function getId()
{
if (!$this->started && !$this->closed) {
return ''; // returning empty is consistent with session_id() behaviour
}
return $this->saveHandler->getId();
}

View File

@ -38,7 +38,7 @@ class PhpBridgeSessionStorage extends NativeSessionStorage
*/
public function start()
{
if ($this->started && !$this->closed) {
if ($this->started) {
return true;
}

View File

@ -85,13 +85,15 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
public function testGetId()
{
$storage = $this->getStorage();
$this->assertEquals('', $storage->getId());
$this->assertSame('', $storage->getId(), 'Empty ID before starting session');
$storage->start();
$this->assertNotEquals('', $storage->getId());
$id = $storage->getId();
$this->assertInternalType('string', $id);
$this->assertNotSame('', $id);
$storage->save();
$this->assertNotEquals('', $storage->getId());
$this->assertSame($id, $storage->getId(), 'ID stays after saving session');
}
public function testRegenerate()
@ -209,35 +211,8 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \RuntimeException
*/
public function testStartedOutside53()
public function testStartedOutside()
{
if (PHP_VERSION_ID >= 50400) {
$this->markTestSkipped('Test skipped, for PHP 5.3 only.');
}
$storage = $this->getStorage();
$this->assertFalse(isset($_SESSION));
session_start();
$this->assertTrue(isset($_SESSION));
// PHP session might have started, but the storage driver has not, so false is correct here
$this->assertFalse($storage->isStarted());
$key = $storage->getMetadataBag()->getStorageKey();
$this->assertFalse(isset($_SESSION[$key]));
$storage->start();
}
/**
* @expectedException \RuntimeException
*/
public function testCanStartOutside54()
{
if (PHP_VERSION_ID < 50400) {
$this->markTestSkipped('Test skipped, for PHP 5.4 only.');
}
$storage = $this->getStorage();
$this->assertFalse(isset($_SESSION));
@ -246,7 +221,10 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
session_start();
$this->assertTrue(isset($_SESSION));
$this->assertTrue($storage->getSaveHandler()->isActive());
if (PHP_VERSION_ID >= 50400) {
// this only works in PHP >= 5.4 where session_status is available
$this->assertTrue($storage->getSaveHandler()->isActive());
}
// PHP session might have started, but the storage driver has not, so false is correct here
$this->assertFalse($storage->isStarted());
@ -254,4 +232,16 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
$this->assertFalse(isset($_SESSION[$key]));
$storage->start();
}
public function testRestart()
{
$storage = $this->getStorage();
$storage->start();
$id = $storage->getId();
$storage->getBag('attributes')->set('lucky', 7);
$storage->save();
$storage->start();
$this->assertSame($id, $storage->getId(), 'Same session ID after restarting');
$this->assertSame(7, $storage->getBag('attributes')->get('lucky'), 'Data still available');
}
}