blob: 78bd56810d6acab15d061589b9297f323e2ae95a [file] [log] [blame]
/*
* Copyright 2020 The casbin Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "casbin/pch.h"
#ifndef DEFAULT_EFFECTOR_CPP
#define DEFAULT_EFFECTOR_CPP
#include "casbin/effect/default_effector.h"
#include "casbin/exception/unsupported_operation_exception.h"
namespace casbin {
/**
* MergeEffects merges all matching results collected by the enforcer into a single decision.
*/
Effect DefaultEffector::MergeEffects(const std::string& expr, const std::vector<Effect>& effects, const std::vector<float>& matches, int policyIndex, int policyLength, int& explainIndex) {
Effect result = Effect::Indeterminate;
explainIndex = -1;
if (expr == "some(where (p.eft == allow))") { // AllowOverrideEffect
if (matches[policyIndex] == 0) {
return result;
}
// only check the current policyIndex
if (effects[policyIndex] == Effect::Allow) {
result = Effect::Allow;
explainIndex = policyIndex;
return result;
}
} else if (expr == "!some(where (p.eft == deny))") { // DenyOverrideEffect
// only check the current policyIndex
if (matches[policyIndex] != 0 && effects[policyIndex] == Effect::Deny) {
result = Effect::Deny;
explainIndex = policyIndex;
return result;
}
// if no deny rules are matched at last, then allow
if (policyIndex == policyLength - 1) {
result = Effect::Allow;
return result;
}
} else if (expr == "some(where (p.eft == allow)) && !some(where (p.eft == deny))") { // AllowAndDenyEffect
// short-circuit if matched deny rule
if (matches[policyIndex] != 0 && effects[policyIndex] == Effect::Deny) {
result = Effect::Deny;
// set hit rule to the (first) matched deny rule
explainIndex = policyIndex;
return result;
}
// short-circuit some effects in the middle
if (policyIndex < policyLength - 1) {
// choose not to short-circuit
return result;
}
// merge all effects at last
for (int i = 0; i < effects.size(); ++i) {
if (matches[i] == 0) {
continue;
}
if (effects[i] == Effect::Allow) {
result = Effect::Allow;
// set hit rule to first matched allow rule
explainIndex = i;
return result;
}
}
} else if (expr == "priority(p.eft) || deny") { // PriorityEffect
// reverse merge, short-circuit may be earlier
for (int i = effects.size() - 1; i >= 0; --i) {
if (matches[i] == 0) {
continue;
}
if (effects[i] != Effect::Indeterminate) {
if (effects[i] == Effect::Allow) {
result = Effect::Allow;
} else {
result = Effect::Deny;
}
explainIndex = i;
return result;
}
}
} else {
throw UnsupportedOperationException("unsupported effect");
}
return result;
}
} // namespace casbin
#endif // DEFAULT_EFFECTOR_CPP