@@ -27,47 +27,81 @@ namespace casbin {
2727/* *
2828 * MergeEffects merges all matching results collected by the enforcer into a single decision.
2929 */
30- bool DefaultEffector ::MergeEffects (std::string expr, std::vector<Effect> effects, std::vector<float > results) {
31- bool result;
32-
33- if (!expr.compare (" some(where (p.eft == allow))" )) {
34- result = false ;
35- for (unsigned int index = 0 ; index < effects.size (); index++) {
36- if (effects[index] == Effect::Allow) {
37- result = true ;
38- break ;
39- }
30+ Effect DefaultEffector::MergeEffects (const std::string& expr, const std::vector<Effect>& effects, const std::vector<float >& matches, int policyIndex, int policyLength, int & explainIndex) {
31+ Effect result = Effect::Indeterminate;
32+ explainIndex = -1 ;
33+
34+ if (expr == " some(where (p.eft == allow))" ) { // AllowOverrideEffect
35+ if (matches[policyIndex] == 0 ) {
36+ return result;
4037 }
41- } else if (!expr.compare (" !some(where (p.eft == deny))" )) {
42- result = true ;
43- for (unsigned int index = 0 ; index < effects.size (); index++) {
44- if (effects[index] == Effect::Deny) {
45- result = false ;
46- break ;
47- }
38+
39+ // only check the current policyIndex
40+ if (effects[policyIndex] == Effect::Allow) {
41+ result = Effect::Allow;
42+ explainIndex = policyIndex;
43+ return result;
44+ }
45+ } else if (expr == " !some(where (p.eft == deny))" ) { // DenyOverrideEffect
46+ // only check the current policyIndex
47+ if (matches[policyIndex] != 0 && effects[policyIndex] == Effect::Deny) {
48+ result = Effect::Deny;
49+ explainIndex = policyIndex;
50+ return result;
4851 }
49- } else if (!expr.compare (" some(where (p.eft == allow)) && !some(where (p.eft == deny))" )) {
50- result = false ;
51- for (unsigned int index = 0 ; index < effects.size (); index++) {
52- if (effects[index] == Effect::Allow) {
53- result = true ;
54- } else if (effects[index] == Effect::Deny) {
55- result = false ;
56- break ;
52+
53+ // if no deny rules are matched at last, then allow
54+ if (policyIndex == policyLength - 1 ) {
55+ result = Effect::Allow;
56+ return result;
57+ }
58+ } else if (expr == " some(where (p.eft == allow)) && !some(where (p.eft == deny))" ) { // AllowAndDenyEffect
59+ // short-circuit if matched deny rule
60+ if (matches[policyIndex] != 0 && effects[policyIndex] == Effect::Deny) {
61+ result = Effect::Deny;
62+ // set hit rule to the (first) matched deny rule
63+ explainIndex = policyIndex;
64+ return result;
65+ }
66+
67+ // short-circuit some effects in the middle
68+ if (policyIndex < policyLength - 1 ) {
69+ // choose not to short-circuit
70+ return result;
71+ }
72+
73+ // merge all effects at last
74+ for (int i = 0 ; i < effects.size (); ++i) {
75+ if (matches[i] == 0 ) {
76+ continue ;
77+ }
78+
79+ if (effects[i] == Effect::Allow) {
80+ result = Effect::Allow;
81+ // set hit rule to first matched allow rule
82+ explainIndex = i;
83+ return result;
5784 }
5885 }
59- } else if (!expr.compare (" priority(p.eft) || deny" )) {
60- result = false ;
61- for (unsigned int index = 0 ; index < effects.size (); index++) {
62- if (effects[index] != Effect::Indeterminate) {
63- if (effects[index] == Effect::Allow) {
64- result = true ;
86+
87+ } else if (expr == " priority(p.eft) || deny" ) { // PriorityEffect
88+ // reverse merge, short-circuit may be earlier
89+ for (int i = effects.size () - 1 ; i >= 0 ; --i) {
90+ if (matches[i] == 0 ) {
91+ continue ;
92+ }
93+
94+ if (effects[i] != Effect::Indeterminate) {
95+ if (effects[i] == Effect::Allow) {
96+ result = Effect::Allow;
6597 } else {
66- result = false ;
98+ result = Effect::Deny ;
6799 }
68- break ;
100+ explainIndex = i;
101+ return result;
69102 }
70103 }
104+
71105 } else {
72106 throw UnsupportedOperationException (" unsupported effect" );
73107 }
0 commit comments