Skip to content

Commit ab100b3

Browse files
committed
[Security][SecurityBundle] Add voter individual decisions to profiler
1 parent 438de43 commit ab100b3

File tree

5 files changed

+432
-19
lines changed

5 files changed

+432
-19
lines changed

Authorization/TraceableAccessDecisionManager.php

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class TraceableAccessDecisionManager implements AccessDecisionManagerInterface
2727
private $manager;
2828
private $strategy;
2929
private $voters = array();
30-
private $decisionLog = array();
30+
private $decisionLog = array(); // All decision logs
31+
private $currentLog = array(); // Logs being filled in
3132

3233
public function __construct(AccessDecisionManagerInterface $manager)
3334
{
@@ -49,17 +50,40 @@ public function __construct(AccessDecisionManagerInterface $manager)
4950
*/
5051
public function decide(TokenInterface $token, array $attributes, $object = null)
5152
{
52-
$result = $this->manager->decide($token, $attributes, $object);
53-
54-
$this->decisionLog[] = array(
53+
$currentDecisionLog = array(
5554
'attributes' => $attributes,
5655
'object' => $object,
57-
'result' => $result,
56+
'voterDetails' => array(),
5857
);
5958

59+
$this->currentLog[] = &$currentDecisionLog;
60+
61+
$result = $this->manager->decide($token, $attributes, $object);
62+
63+
$currentDecisionLog['result'] = $result;
64+
65+
$this->decisionLog[] = array_pop($this->currentLog); // Using a stack since decide can be called by voters
66+
6067
return $result;
6168
}
6269

70+
/**
71+
* Adds voter vote and class to the voter details.
72+
*
73+
* @param VoterInterface $voter voter
74+
* @param array $attributes attributes used for the vote
75+
* @param int $vote vote of the voter
76+
*/
77+
public function addVoterVote(VoterInterface $voter, array $attributes, int $vote)
78+
{
79+
$currentLogIndex = \count($this->currentLog) - 1;
80+
$this->currentLog[$currentLogIndex]['voterDetails'][] = array(
81+
'voter' => $voter,
82+
'attributes' => $attributes,
83+
'vote' => $vote,
84+
);
85+
}
86+
6387
/**
6488
* @return string
6589
*/
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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\Authorization\Voter;
13+
14+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
16+
use Symfony\Component\Security\Core\Event\VoteEvent;
17+
18+
/**
19+
* Decorates voter classes to send result events.
20+
*
21+
* @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
22+
*
23+
* @internal
24+
*/
25+
class TraceableVoter implements VoterInterface
26+
{
27+
private $voter;
28+
private $eventDispatcher;
29+
30+
public function __construct(VoterInterface $voter, EventDispatcherInterface $eventDispatcher)
31+
{
32+
$this->voter = $voter;
33+
$this->eventDispatcher = $eventDispatcher;
34+
}
35+
36+
public function vote(TokenInterface $token, $subject, array $attributes)
37+
{
38+
$result = $this->voter->vote($token, $subject, $attributes);
39+
40+
$this->eventDispatcher->dispatch('debug.security.authorization.vote', new VoteEvent($this->voter, $subject, $attributes, $result));
41+
42+
return $result;
43+
}
44+
45+
public function getDecoratedVoter(): VoterInterface
46+
{
47+
return $this->voter;
48+
}
49+
}

Event/VoteEvent.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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\Event;
13+
14+
use Symfony\Component\EventDispatcher\Event;
15+
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
16+
17+
/**
18+
* This event is dispatched on voter vote.
19+
*
20+
* @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
21+
*
22+
* @internal
23+
*/
24+
class VoteEvent extends Event
25+
{
26+
private $voter;
27+
private $subject;
28+
private $attributes;
29+
private $vote;
30+
31+
public function __construct(VoterInterface $voter, $subject, array $attributes, int $vote)
32+
{
33+
$this->voter = $voter;
34+
$this->subject = $subject;
35+
$this->attributes = $attributes;
36+
$this->vote = $vote;
37+
}
38+
39+
public function getVoter(): VoterInterface
40+
{
41+
return $this->voter;
42+
}
43+
44+
public function getSubject()
45+
{
46+
return $this->subject;
47+
}
48+
49+
public function getAttributes(): array
50+
{
51+
return $this->attributes;
52+
}
53+
54+
public function getVote(): int
55+
{
56+
return $this->vote;
57+
}
58+
}

0 commit comments

Comments
 (0)