| --Copyright 2021 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. |
| |
| local CoreEnforcer = require("src/main/CoreEnforcer") |
| |
| -- InternalEnforcer = CoreEnforcer + Internal API. |
| local InternalEnforcer = {} |
| setmetatable(InternalEnforcer, CoreEnforcer) |
| InternalEnforcer.__index = InternalEnforcer |
| |
| function InternalEnforcer:shouldPersist() |
| return self.adapter and self.autoSave |
| end |
| |
| --[[ |
| * addPolicy adds a rule to the current policy. |
| ]] |
| function InternalEnforcer:addPolicy(sec, ptype, rule) |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:addPolicies(sec, ptype,{rule}) |
| return true |
| end |
| |
| if self.model:hasPolicy(sec, ptype, rule) then |
| return false |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () self.adapter:addPolicy(sec, ptype, rule) end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| self.model:addPolicy(sec, ptype, rule) |
| |
| if sec == "g" then |
| local rules = {} |
| table.insert(rules, rule) |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_ADD, ptype, rules) |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForAddPolicy then |
| self.watcher:updateForAddPolicy(sec, ptype, rule) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| --[[ |
| * addPolicies adds rules to the current policy. |
| ]] |
| function InternalEnforcer:addPolicies(sec, ptype, rules) |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:addPolicies(sec, ptype,rules) |
| return true |
| end |
| |
| if self.model:hasPolicies(sec, ptype, rules) then |
| return false |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () |
| if self.adapter.addPolicies then |
| self.adapter:addPolicies(sec, ptype, rules) |
| end |
| end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| self.model:addPolicies(sec, ptype, rules) |
| |
| if sec == "g" then |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_ADD, ptype, rules) |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForAddPolicies then |
| self.watcher:updateForAddPolicies(sec, ptype, rules) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| --[[ |
| * buildIncrementalRoleLinks provides incremental build the role inheritance relations. |
| * @param op Policy operations. |
| * @param ptype policy type. |
| * @param rules the rules. |
| ]] |
| function InternalEnforcer:buildIncrementalRoleLinks(op, ptype, rules) |
| self.model:buildIncrementalRoleLinks(self.rmMap[ptype], op, "g", ptype, rules) |
| end |
| |
| --[[ |
| * removePolicy removes a rule from the current policy. |
| ]] |
| function InternalEnforcer:removePolicy(sec, ptype, rule) |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:removePolicies(sec, ptype,{rule}) |
| return true |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () self.adapter:removePolicy(sec, ptype, rule) end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| local ruleRemoved = self.model:removePolicy(sec, ptype, rule) |
| |
| if not ruleRemoved then |
| return false |
| end |
| |
| if sec == "g" then |
| local rules = {} |
| table.insert(rules, rule) |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_REMOVE, ptype, rules) |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForRemovePolicy then |
| self.watcher:updateForRemovePolicy(sec, ptype, rule) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| --[[ |
| * updatePolicy updates an authorization rule from the current policy. |
| * @param sec the section, "p" or "g". |
| * @param ptype the policy type, "p", "p2", .. or "g", "g2", .. |
| * @param oldRule the old rule. |
| * @param newRule the new rule. |
| * @return succeeds or not. |
| ]] |
| function InternalEnforcer:updatePolicy(sec, ptype, oldRule, newRule) |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:updatePolicy(sec, ptype,oldRule, newRule) |
| return true |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () self.adapter:updatePolicy(sec, ptype, oldRule, newRule) end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| local ruleUpdated = self.model:updatePolicy(sec, ptype, oldRule, newRule) |
| |
| if not ruleUpdated then |
| return false |
| end |
| |
| if sec == "g" then |
| local status, err = pcall(function () |
| local oldRules = {} |
| table.insert(oldRules, oldRule) |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_REMOVE, ptype, oldRules) |
| end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| |
| status, err = pcall(function () |
| local newRules = {} |
| table.insert(newRules, newRule) |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_ADD, ptype, newRules) |
| end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForUpdatePolicy then |
| self.watcher:updateForUpdatePolicy(sec, ptype, oldRule, newRule) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| function InternalEnforcer:updatePolicies(sec, ptype, oldRules, newRules) |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:updatePolicies(sec, ptype,oldRules, newRules) |
| return true |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () self.adapter:updatePolicies(sec, ptype, oldRules, newRules) end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| local ruleUpdated = self.model:updatePolicies(sec, ptype, oldRules, newRules) |
| |
| if not ruleUpdated then |
| return false |
| end |
| |
| if sec == "g" then |
| local status, err = pcall(function () |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_REMOVE, ptype, oldRules) |
| end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| |
| status, err = pcall(function () |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_ADD, ptype, newRules) |
| end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForUpdatePolicies then |
| self.watcher:updateForUpdatePolicies(sec, ptype, oldRules, newRules) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| --[[ |
| * removePolicies removes rules from the current policy. |
| ]] |
| function InternalEnforcer:removePolicies(sec, ptype, rules) |
| if not self.model:hasPolicies(sec, ptype, rules) then |
| return false |
| end |
| |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:removePolicies(sec, ptype,rules) |
| return true |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () |
| if self.adapter.removePolicies then |
| self.adapter:removePolicies(sec, ptype, rules) |
| end |
| end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| local rulesRemoved = self.model:removePolicies(sec, ptype, rules) |
| |
| if not rulesRemoved then |
| return false |
| end |
| |
| if sec == "g" then |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_REMOVE, ptype, rules) |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForRemovePolicies then |
| self.watcher:updateForRemovePolicies(sec, ptype, rules) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| --[[ |
| * removeFilteredPolicy removes rules based on field filters from the current policy. |
| ]] |
| function InternalEnforcer:removeFilteredPolicy(sec, ptype, fieldIndex, fieldValues) |
| if fieldValues == nil or #fieldValues == 0 then |
| return false |
| end |
| |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:removeFilteredPolicy(sec, ptype, fieldIndex, fieldValues) |
| return true |
| end |
| |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () self.adapter:removeFilteredPolicy(sec, ptype, fieldIndex, fieldValues) end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| local isRuleRemoved, effects = self.model:removeFilteredPolicy(sec, ptype, fieldIndex, fieldValues) |
| |
| if not isRuleRemoved then |
| return false |
| end |
| |
| if sec == "g" then |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_REMOVE, ptype, effects) |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForRemoveFilteredPolicy then |
| self.watcher:updateForRemoveFilteredPolicy(sec, ptype, fieldIndex, fieldValues) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| function InternalEnforcer:updateFilteredPolicies(sec, ptype, newRules, fieldIndex, fieldValues) |
| if fieldValues == nil or #fieldValues == 0 then |
| return false |
| end |
| |
| local oldRules = self.model:getFilteredPolicy(sec, ptype, fieldIndex, fieldValues) |
| if self:shouldPersist() then |
| |
| local status, err = pcall(function () self.adapter:updateFilteredPolicies(sec, ptype, newRules, fieldIndex, fieldValues) end) |
| if status == false and string.sub(err, -15) == "not implemented" then |
| -- log, continue |
| elseif status == false then |
| return false |
| end |
| end |
| |
| if self.dispatcher~=nil and self.autoNotifyDispatcher then |
| self.dispatcher:updateFilteredPolicies(sec, ptype, oldRules, newRules) |
| return true |
| end |
| |
| local ruleChanged = self.model:removePolicies(sec, ptype, oldRules) |
| self.model:addPolicies(sec, ptype, newRules) |
| ruleChanged = ruleChanged and #newRules ~= 0 |
| if ruleChanged==false then |
| return ruleChanged |
| end |
| |
| if sec == "g" then |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_REMOVE, ptype, oldRules) |
| self:buildIncrementalRoleLinks(self.model.PolicyOperations.POLICY_ADD, ptype, newRules) |
| end |
| |
| if self.watcher and self.autoNotifyWatcher then |
| if self.watcher.updateForUpdatePolicies then |
| self.watcher:updateForUpdatePolicies(oldRules, newRules) |
| else |
| self.watcher:update() |
| end |
| end |
| |
| return true |
| end |
| |
| function InternalEnforcer:getDomainIndex(ptype) |
| if not self.model.model["p"] then return end |
| if not self.model.model["p"][ptype] then return end |
| |
| local p = self.model.model["p"][ptype] |
| local pattern = ptype .. "_dom" |
| local index = #p.tokens + 1 |
| for i, token in pairs(p.tokens) do |
| if token == pattern then |
| index = i |
| break |
| end |
| end |
| return index |
| end |
| |
| return InternalEnforcer |