11
11
12
12
namespace Symfony \Component \Security \Core \Authorization ;
13
13
14
+ use Symfony \Component \Security \Core \Authorization \Strategy \DecideAffirmativeStrategy ;
15
+ use Symfony \Component \Security \Core \Authorization \Strategy \DecideConsensusStrategy ;
16
+ use Symfony \Component \Security \Core \Authorization \Strategy \DecideHighestNotAbstainedVoterStrategy ;
17
+ use Symfony \Component \Security \Core \Authorization \Strategy \DecideUnanimousStrategy ;
14
18
use Symfony \Component \Security \Core \Authorization \Voter \VoterInterface ;
15
19
use Symfony \Component \Security \Core \Authentication \Token \TokenInterface ;
16
20
@@ -25,8 +29,10 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
25
29
const STRATEGY_AFFIRMATIVE = 'affirmative ' ;
26
30
const STRATEGY_CONSENSUS = 'consensus ' ;
27
31
const STRATEGY_UNANIMOUS = 'unanimous ' ;
32
+ const STRATEGY_HIGHEST_NOT_ABSTAINED = 'highest ' ;
28
33
29
34
private $ voters ;
35
+ private $ strategies ;
30
36
private $ strategy ;
31
37
private $ allowIfAllAbstainDecisions ;
32
38
private $ allowIfEqualGrantedDeniedDecisions ;
@@ -43,13 +49,9 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
43
49
*/
44
50
public function __construct (array $ voters = array (), $ strategy = self ::STRATEGY_AFFIRMATIVE , $ allowIfAllAbstainDecisions = false , $ allowIfEqualGrantedDeniedDecisions = true )
45
51
{
46
- $ strategyMethod = 'decide ' .ucfirst ($ strategy );
47
- if (!is_callable (array ($ this , $ strategyMethod ))) {
48
- throw new \InvalidArgumentException (sprintf ('The strategy "%s" is not supported. ' , $ strategy ));
49
- }
50
-
52
+ $ this ->strategies = array ();
51
53
$ this ->voters = $ voters ;
52
- $ this ->strategy = $ strategyMethod ;
54
+ $ this ->strategy = $ strategy ;
53
55
$ this ->allowIfAllAbstainDecisions = (bool ) $ allowIfAllAbstainDecisions ;
54
56
$ this ->allowIfEqualGrantedDeniedDecisions = (bool ) $ allowIfEqualGrantedDeniedDecisions ;
55
57
}
@@ -65,155 +67,74 @@ public function setVoters(array $voters)
65
67
}
66
68
67
69
/**
68
- * {@inheritdoc}
70
+ * @param mixed $strategies
69
71
*/
70
- public function decide ( TokenInterface $ token , array $ attributes , $ object = null )
72
+ public function addStrategy ( $ name , $ strategy )
71
73
{
72
- return $ this ->{ $ this -> strategy }( $ token , $ attributes , $ object ) ;
74
+ $ this ->strategies [ $ name ] = $ strategy ;
73
75
}
74
76
75
- /**
76
- * {@inheritdoc}
77
- */
78
- public function supportsAttribute ($ attribute )
77
+ private function getStrategy ($ strategyName )
79
78
{
80
- foreach ($ this ->voters as $ voter ) {
81
- if ($ voter ->supportsAttribute ($ attribute )) {
82
- return true ;
79
+ if (!array_key_exists ($ strategyName ,$ this ->strategies ))
80
+ {
81
+ switch ($ strategyName ){
82
+ case self ::STRATEGY_UNANIMOUS :
83
+ return new DecideUnanimousStrategy ();
84
+ case self ::STRATEGY_CONSENSUS :
85
+ return new DecideConsensusStrategy ();
86
+ case self ::STRATEGY_AFFIRMATIVE :
87
+ return new DecideAffirmativeStrategy ();
88
+ case self ::STRATEGY_HIGHEST_NOT_ABSTAINED :
89
+ return new DecideHighestNotAbstainedVoterStrategy ();
90
+ default :
91
+ break ;
83
92
}
93
+ } elseif ($ this ->strategies [$ strategyName ] instanceof AccessDecisionStrategyInterface) {
94
+ return $ this ->strategies [$ strategyName ];
84
95
}
85
96
86
- return false ;
97
+ throw new \ InvalidArgumentException ( sprintf ( ' The strategy "%s" is not supported. ' , $ strategyName )) ;
87
98
}
88
99
89
100
/**
90
101
* {@inheritdoc}
91
102
*/
92
- public function supportsClass ( $ class )
103
+ public function decide ( TokenInterface $ token , array $ attributes , $ object = null )
93
104
{
94
- foreach ($ this ->voters as $ voter ) {
95
- if ($ voter ->supportsClass ($ class )) {
96
- return true ;
97
- }
98
- }
105
+ $ strategy = $ this ->getStrategy ($ this ->strategy );
106
+ $ strategy ->setVoters ($ this ->voters );
107
+ $ strategy ->setAllowIfAllAbstainDecisions ($ this ->allowIfAllAbstainDecisions );
108
+ $ strategy ->setAllowIfEqualGrantedDeniedDecisions ($ this ->allowIfEqualGrantedDeniedDecisions );
99
109
100
- return false ;
110
+ return $ strategy -> decide ( $ token , $ attributes , $ object ) ;
101
111
}
102
112
103
113
/**
104
- * Grants access if any voter returns an affirmative response.
105
- *
106
- * If all voters abstained from voting, the decision will be based on the
107
- * allowIfAllAbstainDecisions property value (defaults to false).
114
+ * {@inheritdoc}
108
115
*/
109
- private function decideAffirmative ( TokenInterface $ token , array $ attributes , $ object = null )
116
+ public function supportsAttribute ( $ attribute )
110
117
{
111
- $ deny = 0 ;
112
118
foreach ($ this ->voters as $ voter ) {
113
- $ result = $ voter ->vote ($ token , $ object , $ attributes );
114
- switch ($ result ) {
115
- case VoterInterface::ACCESS_GRANTED :
116
- return true ;
117
-
118
- case VoterInterface::ACCESS_DENIED :
119
- ++$ deny ;
120
-
121
- break ;
122
-
123
- default :
124
- break ;
119
+ if ($ voter ->supportsAttribute ($ attribute )) {
120
+ return true ;
125
121
}
126
122
}
127
123
128
- if ($ deny > 0 ) {
129
- return false ;
130
- }
131
-
132
- return $ this ->allowIfAllAbstainDecisions ;
124
+ return false ;
133
125
}
134
126
135
127
/**
136
- * Grants access if there is consensus of granted against denied responses.
137
- *
138
- * Consensus means majority-rule (ignoring abstains) rather than unanimous
139
- * agreement (ignoring abstains). If you require unanimity, see
140
- * UnanimousBased.
141
- *
142
- * If there were an equal number of grant and deny votes, the decision will
143
- * be based on the allowIfEqualGrantedDeniedDecisions property value
144
- * (defaults to true).
145
- *
146
- * If all voters abstained from voting, the decision will be based on the
147
- * allowIfAllAbstainDecisions property value (defaults to false).
128
+ * {@inheritdoc}
148
129
*/
149
- private function decideConsensus ( TokenInterface $ token , array $ attributes , $ object = null )
130
+ public function supportsClass ( $ class )
150
131
{
151
- $ grant = 0 ;
152
- $ deny = 0 ;
153
132
foreach ($ this ->voters as $ voter ) {
154
- $ result = $ voter ->vote ($ token , $ object , $ attributes );
155
-
156
- switch ($ result ) {
157
- case VoterInterface::ACCESS_GRANTED :
158
- ++$ grant ;
159
-
160
- break ;
161
-
162
- case VoterInterface::ACCESS_DENIED :
163
- ++$ deny ;
164
-
165
- break ;
166
- }
167
- }
168
-
169
- if ($ grant > $ deny ) {
170
- return true ;
171
- }
172
-
173
- if ($ deny > $ grant ) {
174
- return false ;
175
- }
176
-
177
- if ($ grant > 0 ) {
178
- return $ this ->allowIfEqualGrantedDeniedDecisions ;
179
- }
180
-
181
- return $ this ->allowIfAllAbstainDecisions ;
182
- }
183
-
184
- /**
185
- * Grants access if only grant (or abstain) votes were received.
186
- *
187
- * If all voters abstained from voting, the decision will be based on the
188
- * allowIfAllAbstainDecisions property value (defaults to false).
189
- */
190
- private function decideUnanimous (TokenInterface $ token , array $ attributes , $ object = null )
191
- {
192
- $ grant = 0 ;
193
- foreach ($ attributes as $ attribute ) {
194
- foreach ($ this ->voters as $ voter ) {
195
- $ result = $ voter ->vote ($ token , $ object , array ($ attribute ));
196
-
197
- switch ($ result ) {
198
- case VoterInterface::ACCESS_GRANTED :
199
- ++$ grant ;
200
-
201
- break ;
202
-
203
- case VoterInterface::ACCESS_DENIED :
204
- return false ;
205
-
206
- default :
207
- break ;
208
- }
133
+ if ($ voter ->supportsClass ($ class )) {
134
+ return true ;
209
135
}
210
136
}
211
137
212
- // no deny votes
213
- if ($ grant > 0 ) {
214
- return true ;
215
- }
216
-
217
- return $ this ->allowIfAllAbstainDecisions ;
138
+ return false ;
218
139
}
219
140
}
0 commit comments