From 4f37d7a5d7b8e935439c7c7e7a1fc3b84b149a6a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 22 Feb 2016 16:03:02 +0100 Subject: [PATCH 01/15] Show more information in the security profiler --- .../DataCollector/SecurityDataCollector.php | 57 +++++++++++- .../DependencyInjection/SecurityExtension.php | 6 ++ .../Resources/config/collectors.xml | 1 + .../Resources/config/security_debug.xml | 12 +++ .../views/Collector/security.html.twig | 62 +++++++++++++ .../DebugAccessDecisionManager.php | 92 +++++++++++++++++++ 6 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml create mode 100644 src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 0fff7552e858d..a5d16d046b12f 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; /** * SecurityDataCollector. @@ -29,19 +30,22 @@ class SecurityDataCollector extends DataCollector private $tokenStorage; private $roleHierarchy; private $logoutUrlGenerator; + private $accessDecisionManager; /** * Constructor. * - * @param TokenStorageInterface|null $tokenStorage - * @param RoleHierarchyInterface|null $roleHierarchy - * @param LogoutUrlGenerator|null $logoutUrlGenerator + * @param TokenStorageInterface|null $tokenStorage + * @param RoleHierarchyInterface|null $roleHierarchy + * @param LogoutUrlGenerator|null $logoutUrlGenerator + * @param AccessDecisionManagerInterface|null $accessDecisionManager */ - public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null) + public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null) { $this->tokenStorage = $tokenStorage; $this->roleHierarchy = $roleHierarchy; $this->logoutUrlGenerator = $logoutUrlGenerator; + $this->accessDecisionManager = $accessDecisionManager; } /** @@ -104,6 +108,21 @@ public function collect(Request $request, Response $response, \Exception $except 'supports_role_hierarchy' => null !== $this->roleHierarchy, ); } + + // collect voters and access decision manager information + if (null !== $this->accessDecisionManager) { + $this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy(); + + foreach ($this->accessDecisionManager->getVoters() as $voter) { + $this->data['voters'][] = get_class($voter); + } + + $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog(); + } else { + $this->data['voter_strategy'] = 'unknown'; + $this->data['voters'] = array(); + $this->data['access_decision_log'] = array(); + } } /** @@ -187,6 +206,36 @@ public function getLogoutUrl() return $this->data['logout_url']; } + /** + * Returns the FQCN of the security voters enabled in the application. + * + * @return string[] + */ + public function getVoters() + { + return $this->data['voters']; + } + + /** + * Returns the strategy configured for the security voters. + * + * @return string + */ + public function getVoterStrategy() + { + return $this->data['voter_strategy']; + } + + /** + * Returns the log of the security decisions made by the access decision manager. + * + * @return array + */ + public function getAccessDecisionLog() + { + return $this->data['access_decision_log']; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 6043ed6292089..c63132d8674e7 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -65,6 +65,7 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('templating_twig.xml'); $loader->load('collectors.xml'); $loader->load('guard.xml'); + $loader->load('security_debug.xml'); if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { $container->removeDefinition('security.expression_language'); @@ -97,6 +98,11 @@ public function load(array $configs, ContainerBuilder $container) $this->aclLoad($config['acl'], $container); } + if ($container->getParameter('kernel.debug')) { + $definition = $container->findDefinition('security.authorization_checker'); + $definition->replaceArgument(2, new Reference('debug.security.access.decision_manager')); + } + // add some required classes for compilation $this->addClassesToCompile(array( 'Symfony\Component\Security\Http\Firewall', diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml index 329815fd608a1..738455358b0dd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml @@ -10,6 +10,7 @@ + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml new file mode 100644 index 0000000000000..4312d747417d1 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index dd724682d749e..e656c0c8f4d5c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -119,4 +119,66 @@

The security component is disabled.

{% endif %} + + {% if collector.voters|default([]) is not empty %} +

Security Voters ({{ collector.voters|length }})

+ +
+
+ {{ collector.voterStrategy|default('unknown') }} + Strategy +
+
+ + + + + + + + + + + {% for voter in collector.voters %} + + + + + {% endfor %} + +
#Voter class
{{ loop.index }}{{ voter }}
+ {% endif %} + + {% if collector.accessDecisionLog|default([]) is not empty %} +

Access decision log

+ + + + + + + + + + + + + + {% for decision in collector.accessDecisionLog %} + + + + + + + + {% endfor %} + +
#ResultAttributesObjectToken
{{ loop.index }} + {{ decision.result + ? 'GRANTED' + : 'DENIED' + }} + {{ profiler_dump(decision.attributes) }}{{ profiler_dump(decision.object) }}{{ profiler_dump(decision.token) }}
+ {% endif %} {% endblock %} diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php new file mode 100644 index 0000000000000..1cab477c081ae --- /dev/null +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Authorization; + +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + +/** + * AccessDecisionManager is the base class for all access decision managers + * that use decision voters. + * + * @author Javier Eguiluz + */ +class DebugAccessDecisionManager implements AccessDecisionManagerInterface //extends AccessDecisionManager +{ + private $manager; + private $strategy; + private $voters; + private $decisionLog = array(); + + public function __construct(AccessDecisionManager $manager) + { + $this->manager = $manager; + + // The strategy is stored in a private property of the decorated service + $reflection = new \ReflectionProperty($manager, 'strategy'); + $reflection->setAccessible(true); + $this->strategy = $reflection->getValue($manager); + } + + /** + * {@inheritdoc} + */ + public function decide(TokenInterface $token, array $attributes, $object = null) + { + $result = $this->manager->decide($token, $attributes, $object); + + $this->decisionLog[] = array( + 'token' => $token, + 'attributes' => $attributes, + 'object' => $object, + 'result' => $result, + ); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function setVoters(array $voters) + { + $this->voters = $voters; + } + + /** + * @return string + */ + public function getStrategy() + { + // The $strategy property stores the name of its method, instead of the + // original strategy name. Example: + // method name = 'decideAffirmative', strategy = 'affirmative' + $strategyName = strtolower(substr($this->strategy, 6)); + + return $strategyName; + } + + /** + * @return array + */ + public function getVoters() + { + return $this->voters; + } + + /** + * @return array + */ + public function getDecisionLog() + { + return $this->decisionLog; + } +} From c9bfc30ae96eef83bbdc17dd6df6520c8b9ac4d2 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 23 Feb 2016 11:55:56 +0100 Subject: [PATCH 02/15] Try to fix the test issues --- .../SecurityBundle/DependencyInjection/SecurityExtension.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index c63132d8674e7..8427068727035 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -65,7 +65,6 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('templating_twig.xml'); $loader->load('collectors.xml'); $loader->load('guard.xml'); - $loader->load('security_debug.xml'); if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { $container->removeDefinition('security.expression_language'); @@ -98,7 +97,9 @@ public function load(array $configs, ContainerBuilder $container) $this->aclLoad($config['acl'], $container); } - if ($container->getParameter('kernel.debug')) { + if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) { + $loader->load('security_debug.xml'); + $definition = $container->findDefinition('security.authorization_checker'); $definition->replaceArgument(2, new Reference('debug.security.access.decision_manager')); } From 5e46d238ec4747db6f05cb3e51ca663ce4cab289 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 23 Feb 2016 17:07:52 +0100 Subject: [PATCH 03/15] Minor refactoring --- .../DataCollector/SecurityDataCollector.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index a5d16d046b12f..38bd4ed5a688c 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -110,18 +110,19 @@ public function collect(Request $request, Response $response, \Exception $except } // collect voters and access decision manager information + $this->data['access_decision_log'] = array(); + $this->data['voter_strategy'] = 'unknown'; + $this->data['voters'] = array(); + if (null !== $this->accessDecisionManager) { + $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog(); $this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy(); + } + if (!empty($this->accessDecisionManager->getVoters())) { foreach ($this->accessDecisionManager->getVoters() as $voter) { $this->data['voters'][] = get_class($voter); } - - $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog(); - } else { - $this->data['voter_strategy'] = 'unknown'; - $this->data['voters'] = array(); - $this->data['access_decision_log'] = array(); } } From 879d6717f89301edcd32645048c9231884ad2b71 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 23 Feb 2016 17:28:14 +0100 Subject: [PATCH 04/15] Another refactor to fix tests --- .../DataCollector/SecurityDataCollector.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 38bd4ed5a688c..f78d5aa44d1b3 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -110,19 +110,17 @@ public function collect(Request $request, Response $response, \Exception $except } // collect voters and access decision manager information - $this->data['access_decision_log'] = array(); - $this->data['voter_strategy'] = 'unknown'; - $this->data['voters'] = array(); - if (null !== $this->accessDecisionManager) { $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog(); $this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy(); - } - if (!empty($this->accessDecisionManager->getVoters())) { foreach ($this->accessDecisionManager->getVoters() as $voter) { $this->data['voters'][] = get_class($voter); } + } else { + $this->data['access_decision_log'] = array(); + $this->data['voter_strategy'] = 'unknown'; + $this->data['voters'] = array(); } } From 378db408d38c13b45d54e1773839a25b0f3bfe71 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 25 Feb 2016 09:09:32 +0100 Subject: [PATCH 05/15] Fixed the PHPdoc od the new class --- .../Core/Authorization/DebugAccessDecisionManager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index 1cab477c081ae..25f6d8e2b0b98 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -14,8 +14,8 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** - * AccessDecisionManager is the base class for all access decision managers - * that use decision voters. + * Decorates the original AccessDecisionManager class to log information + * about the security voters and the decisions made by them. * * @author Javier Eguiluz */ From 9349fdf7b2ae0afc63d2e293e2f5b80c3bb85228 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 29 Feb 2016 17:26:58 +0100 Subject: [PATCH 06/15] Made the changes asked for by reviewers --- .../Authorization/DebugAccessDecisionManager.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index 25f6d8e2b0b98..70cd2df9d81a3 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -18,8 +18,10 @@ * about the security voters and the decisions made by them. * * @author Javier Eguiluz + * + * @internal */ -class DebugAccessDecisionManager implements AccessDecisionManagerInterface //extends AccessDecisionManager +class DebugAccessDecisionManager implements AccessDecisionManagerInterface { private $manager; private $strategy; @@ -66,12 +68,10 @@ public function setVoters(array $voters) */ public function getStrategy() { - // The $strategy property stores the name of its method, instead of the - // original strategy name. Example: - // method name = 'decideAffirmative', strategy = 'affirmative' - $strategyName = strtolower(substr($this->strategy, 6)); - - return $strategyName; + // The $strategy property is misleading because it store the name of its + // method (e.g. 'decideAffirmative') instead of the original strategy name + // (e.g. 'affirmative') + return strtolower(substr($this->strategy, 6)); } /** From 597bc48d9fe63d424a7cb494b9ba09bcf74a4b19 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 1 Mar 2016 13:10:56 +0100 Subject: [PATCH 07/15] Improvements after Iltar's review --- .../views/Collector/security.html.twig | 17 ++++++++------- .../views/Profiler/profiler.css.twig | 4 ++++ .../DebugAccessDecisionManager.php | 21 ++++++++++++++++--- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index e656c0c8f4d5c..6aca03861868f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -141,7 +141,7 @@ {% for voter in collector.voters %} - {{ loop.index }} + {{ loop.index }} {{ voter }} {% endfor %} @@ -153,29 +153,32 @@

Access decision log

+ + + + + - {% for decision in collector.accessDecisionLog %} - + - + - {% endfor %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index 6e07edeb3f2a0..67638ec532f96 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -235,6 +235,10 @@ table tbody ul { padding: 3px 7px; white-space: nowrap; } +.label.same-width { + min-width: 70px; + text-align: center; +} .label.status-success { background: {{ colors.success|raw }}; color: #FFF; } .label.status-warning { background: {{ colors.warning|raw }}; color: #FFF; } .label.status-error { background: {{ colors.error|raw }}; color: #FFF; } diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index 70cd2df9d81a3..a6dea108eed11 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -46,9 +46,8 @@ public function decide(TokenInterface $token, array $attributes, $object = null) $result = $this->manager->decide($token, $attributes, $object); $this->decisionLog[] = array( - 'token' => $token, 'attributes' => $attributes, - 'object' => $object, + 'object' => $this->getStringRepresentation($object), 'result' => $result, ); @@ -68,7 +67,7 @@ public function setVoters(array $voters) */ public function getStrategy() { - // The $strategy property is misleading because it store the name of its + // The $strategy property is misleading because it stores the name of its // method (e.g. 'decideAffirmative') instead of the original strategy name // (e.g. 'affirmative') return strtolower(substr($this->strategy, 6)); @@ -89,4 +88,20 @@ public function getDecisionLog() { return $this->decisionLog; } + + /** + * @param mixed $object + * + * @return string + */ + private function getStringRepresentation($object) + { + if (!is_object($object)) { + return gettype($object); + } + + $objectClass = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($object) : get_class($object); + + return method_exists($object, '__toString') ? (string) $object : $objectClass.'@'.spl_object_hash($object); + } } From ca6da1965fb5c3c4430de7bde09191484687674f Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 1 Mar 2016 13:14:34 +0100 Subject: [PATCH 08/15] Fixed fabbot issues --- .../Security/Core/Authorization/DebugAccessDecisionManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index a6dea108eed11..6837ed5c0c6f1 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -90,7 +90,7 @@ public function getDecisionLog() } /** - * @param mixed $object + * @param mixed $object * * @return string */ From e20948eee39861cacb40591a0278d7e87e43413b Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 1 Mar 2016 14:50:49 +0100 Subject: [PATCH 09/15] Fixes and tweaks --- .../DependencyInjection/Compiler/AddSecurityVotersPass.php | 4 ++++ .../Core/Authorization/DebugAccessDecisionManager.php | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php index 992d5a5f7c6f5..e2f8b3c645b61 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php @@ -46,5 +46,9 @@ public function process(ContainerBuilder $container) } $container->getDefinition('security.access.decision_manager')->addMethodCall('setVoters', array(array_values($voters))); + + if ($container->hasDefinition('debug.security.access.decision_manager')) { + $container->getDefinition('debug.security.access.decision_manager')->addMethodCall('setVoters', array(array_values($voters))); + } } } diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index 6837ed5c0c6f1..4f1057b8e0bf6 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Core\Authorization; +use Doctrine\Common\Util\ClassUtils; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** @@ -101,7 +102,8 @@ private function getStringRepresentation($object) } $objectClass = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($object) : get_class($object); + $objectAsString = method_exists($object, '__toString') ? (string) $object : 'object hash: '.spl_object_hash($object); - return method_exists($object, '__toString') ? (string) $object : $objectClass.'@'.spl_object_hash($object); + return sprintf('%s (%s)', $objectClass, $objectAsString); } } From 367f8eacee4afbdf5934c9565b9f8de7b2079237 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 1 Mar 2016 16:36:27 +0100 Subject: [PATCH 10/15] Improved the string representation of the objects --- .../Core/Authorization/DebugAccessDecisionManager.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index 4f1057b8e0bf6..f52eea4597708 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -102,7 +102,14 @@ private function getStringRepresentation($object) } $objectClass = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($object) : get_class($object); - $objectAsString = method_exists($object, '__toString') ? (string) $object : 'object hash: '.spl_object_hash($object); + + if (method_exists($object, 'getId')) { + $objectAsString = sprintf('ID: %s', $object->getId()); + } elseif (method_exists($object, '__toString')) { + $objectAsString = (string) $object; + } else { + $objectAsString = sprintf('object hash: %s', spl_object_hash($object)); + } return sprintf('%s (%s)', $objectClass, $objectAsString); } From 89bc8c0589e7c8be6ce426b4b4a0feca9ff12c07 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 1 Mar 2016 16:42:39 +0100 Subject: [PATCH 11/15] Display the contents when the object is not a true object --- .../Security/Core/Authorization/DebugAccessDecisionManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index f52eea4597708..afcdb8a708320 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -98,7 +98,7 @@ public function getDecisionLog() private function getStringRepresentation($object) { if (!is_object($object)) { - return gettype($object); + return sprintf('%s (%s)', gettype($object), $object); } $objectClass = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($object) : get_class($object); From 97111f3a68ba3a0eb0e7300f94d2f9fb7829e756 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 2 Mar 2016 08:48:13 +0100 Subject: [PATCH 12/15] Made code more robust --- .../SecurityBundle/DataCollector/SecurityDataCollector.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index f78d5aa44d1b3..4d682073d81b4 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -19,6 +19,7 @@ use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; +use Symfony\Component\Security\Core\Authorization\DebugAccessDecisionManager; /** * SecurityDataCollector. @@ -110,7 +111,7 @@ public function collect(Request $request, Response $response, \Exception $except } // collect voters and access decision manager information - if (null !== $this->accessDecisionManager) { + if ($this->accessDecisionManager instance of DebugAccessDecisionManager) { $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog(); $this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy(); From 8b36d15f1618f15646e18fe974b4bb211da68ec6 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 3 Mar 2016 15:41:44 +0100 Subject: [PATCH 13/15] Take care of the null objects --- .../Core/Authorization/DebugAccessDecisionManager.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php index afcdb8a708320..de7ec4d9a25db 100644 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php @@ -97,6 +97,10 @@ public function getDecisionLog() */ private function getStringRepresentation($object) { + if (null === $object) { + return 'NULL'; + } + if (!is_object($object)) { return sprintf('%s (%s)', gettype($object), $object); } From 4864976456c09fec180bc0a310b6d1c9858919ac Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 3 Mar 2016 15:44:33 +0100 Subject: [PATCH 14/15] Fixed a syntax error --- .../SecurityBundle/DataCollector/SecurityDataCollector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 4d682073d81b4..fc798989dec78 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -111,7 +111,7 @@ public function collect(Request $request, Response $response, \Exception $except } // collect voters and access decision manager information - if ($this->accessDecisionManager instance of DebugAccessDecisionManager) { + if ($this->accessDecisionManager instanceof DebugAccessDecisionManager) { $this->data['access_decision_log'] = $this->accessDecisionManager->getDecisionLog(); $this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy(); From f3db034e3745c62419efdcf6469b5ad08172ee2b Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 3 Mar 2016 16:00:37 +0100 Subject: [PATCH 15/15] Minor Twig change --- .../SecurityBundle/Resources/views/Collector/security.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 6aca03861868f..c7c8147002df5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -177,7 +177,7 @@ : 'DENIED' }} - + {% endfor %}
# Result Attributes ObjectToken
{{ loop.index }}{{ loop.index }} {{ decision.result - ? 'GRANTED' - : 'DENIED' + ? 'GRANTED' + : 'DENIED' }} {{ profiler_dump(decision.attributes) }}{{ decision.attributes|length == 1 ? decision.attributes[0] : profiler_dump(decision.attributes) }} {{ profiler_dump(decision.object) }}{{ profiler_dump(decision.token) }}
{{ decision.attributes|length == 1 ? decision.attributes[0] : profiler_dump(decision.attributes) }}{{ decision.attributes|length == 1 ? decision.attributes|first : profiler_dump(decision.attributes) }} {{ profiler_dump(decision.object) }}