From 1f7d811b5dde1e6a4502a661750a3dec36625ba4 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Wed, 9 Jun 2021 03:44:05 +0530 Subject: [PATCH 1/7] feat: added model implementation Signed-off-by: Yash Pandey (YP) --- .gitignore | 1 + README.md | 3 ++- casbin/CMakeLists.txt | 13 +++++++++--- casbin/internal_api.cpp | 1 + casbin/ip_parser/parser/Print.h | 2 -- casbin/{ => log}/logger.cpp | 5 ++--- casbin/model/model.cpp | 36 +++++++++++++++++++++++++++++---- casbin/model/model.h | 3 +++ casbin/pch.h | 13 ++++++++++++ casbin/util/ticker.h | 9 --------- 10 files changed, 64 insertions(+), 22 deletions(-) rename casbin/{ => log}/logger.cpp (87%) diff --git a/.gitignore b/.gitignore index 7b14ee16..fd90e1d1 100644 --- a/.gitignore +++ b/.gitignore @@ -354,6 +354,7 @@ MigrationBackup/ .idea/ *.iml .vscode +.DS_Store # CMake work directory cmake-build/ diff --git a/README.md b/README.md index 84b27717..77bb6cef 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ Casbin-CPP Operating Systems | Availability status ----------------- | ------------------- Windows (VS C++) | :heavy_check_mark: Available -Linux and MacOS | :heavy_check_mark: Available +Linux | :heavy_check_mark: Available +macOS | :heavy_check_mark: Available ![casbin Logo](casbin-logo.png) diff --git a/casbin/CMakeLists.txt b/casbin/CMakeLists.txt index 83861d8e..37ca1be3 100644 --- a/casbin/CMakeLists.txt +++ b/casbin/CMakeLists.txt @@ -1,8 +1,15 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) -FILE(GLOB_RECURSE SC_FILES "*.cpp" "*.h") +FILE(GLOB_RECURSE SRC_FILES "*.cpp" "*.h") -add_library(casbin ${SC_FILES}) +add_library(casbin ${SRC_FILES}) +include_directories(${CMAKE_SOURCE_DIR}/casbin) + +target_precompile_headers(casbin PUBLIC "pch.h") set_target_properties(casbin PROPERTIES PREFIX "") -set_target_properties(casbin PROPERTIES SUFFIX ".o") +if(WIN32 OR MSVC) + set_target_properties(casbin PROPERTIES SUFFIX ".lib") +elseif(UNIX) + set_target_properties(casbin PROPERTIES SUFFIX ".a") +endif() diff --git a/casbin/internal_api.cpp b/casbin/internal_api.cpp index 73cb5647..7c4e1f4d 100644 --- a/casbin/internal_api.cpp +++ b/casbin/internal_api.cpp @@ -167,6 +167,7 @@ bool Enforcer :: removeFilteredPolicy(const std::string& sec, const std::string& } bool Enforcer :: updatePolicy(const std::string& sec, const std::string& p_type, const std::vector& oldRule, const std::vector& newRule) { + bool is_model_policy_updated = m_model->UpdatePolicy(sec, p_type, oldRule, newRule); return true; } diff --git a/casbin/ip_parser/parser/Print.h b/casbin/ip_parser/parser/Print.h index b0cfb859..98772cd8 100644 --- a/casbin/ip_parser/parser/Print.h +++ b/casbin/ip_parser/parser/Print.h @@ -1,8 +1,6 @@ #ifndef IP_PARSER_PARSER_PRINT #define IP_PARSER_PARSER_PRINT -#include - #include "./IP.h" namespace casbin { diff --git a/casbin/logger.cpp b/casbin/log/logger.cpp similarity index 87% rename from casbin/logger.cpp rename to casbin/log/logger.cpp index a60566a1..a347c618 100644 --- a/casbin/logger.cpp +++ b/casbin/log/logger.cpp @@ -3,9 +3,8 @@ #ifndef LOGGER_CPP #define LOGGER_CPP -#include -#include "log/Logger.h" -#include "log/log_util.h" +#include "Logger.h" +#include "log_util.h" namespace casbin { diff --git a/casbin/model/model.cpp b/casbin/model/model.cpp index 198a792b..6ff97e2c 100644 --- a/casbin/model/model.cpp +++ b/casbin/model/model.cpp @@ -260,15 +260,43 @@ bool Model :: AddPolicies(std::string sec, std::string p_type, std::vector& oldRule, const std::vector& newRule) { + // Caching policy by reference for the scope of this function + auto& policy = m[sec].assertion_map[p_type]->policy; + bool is_oldRule_deleted = false, is_newRule_added = false; + + for (auto it = policy.begin(); it != policy.end(); ++it) { + if(ArrayEquals(oldRule, *it)) { + policy.erase(it); + is_oldRule_deleted = true; + break; + } + } + + if(!is_oldRule_deleted) + return false; + + if(!this->HasPolicy(sec, p_type, newRule)) { + policy.push_back(newRule); + is_newRule_added = true; + } + + if(!is_newRule_added) + return false; + + return is_oldRule_deleted && is_newRule_added; +} + // RemovePolicy removes a policy rule from the model. bool Model :: RemovePolicy(std::string sec, std::string p_type, std::vector rule) { - for (int i = 0 ; i < m[sec].assertion_map[p_type]->policy.size() ; i++) { - if (ArrayEquals(rule, m[sec].assertion_map[p_type]->policy[i])) { - m[sec].assertion_map[p_type]->policy.erase(m[sec].assertion_map[p_type]->policy.begin() + i); + // Caching policy by reference for the scope of this function + auto& policy = m[sec].assertion_map[p_type]->policy; + for (auto it = policy.begin(); it != policy.end(); ++it) { + if(ArrayEquals(rule, *it)) { + policy.erase(it); return true; } } - return false; } diff --git a/casbin/model/model.h b/casbin/model/model.h index fc1d2361..0b3f3454 100644 --- a/casbin/model/model.h +++ b/casbin/model/model.h @@ -105,6 +105,9 @@ class Model{ // AddPolicies adds policy rules to the model. bool AddPolicies(std::string sec, std::string p_type, std::vector> rules); + // UpdatePolicy updates a policy rule from the model. + bool UpdatePolicy(const std::string& sec, const std::string p_type, const std::vector& oldRule, const std::vector& newRule); + // RemovePolicy removes a policy rule from the model. bool RemovePolicy(std::string sec, std::string p_type, std::vector rule); diff --git a/casbin/pch.h b/casbin/pch.h index 787a37c4..d8fd4627 100644 --- a/casbin/pch.h +++ b/casbin/pch.h @@ -25,5 +25,18 @@ // add headers that you want to pre-compile here // #include "framework.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #endif //PCH_H diff --git a/casbin/util/ticker.h b/casbin/util/ticker.h index f1889268..2854a17a 100644 --- a/casbin/util/ticker.h +++ b/casbin/util/ticker.h @@ -17,15 +17,6 @@ #ifndef TICKER_H #define TICKER_H -#include -#include -#include -#include -#include -#include -#include -#include -#include namespace casbin { From ae0f3472b435df04d4eb2ff2d3e0f27233472626 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Wed, 9 Jun 2021 22:06:30 +0530 Subject: [PATCH 2/7] feat: Missing implementations in internal API Signed-off-by: Yash Pandey (YP) --- casbin/internal_api.cpp | 54 ++++++++-- casbin/model/model.cpp | 171 ++++++++++++++++++++------------ casbin/model/model.h | 47 +++++---- casbin/persist/watcher_update.h | 50 ++++++++++ 4 files changed, 229 insertions(+), 93 deletions(-) create mode 100644 casbin/persist/watcher_update.h diff --git a/casbin/internal_api.cpp b/casbin/internal_api.cpp index 7c4e1f4d..31258a0b 100644 --- a/casbin/internal_api.cpp +++ b/casbin/internal_api.cpp @@ -25,11 +25,12 @@ #include "./util/util.h" #include "./persist/watcher_ex.h" #include "./exception/unsupported_operation_exception.h" +#include "./persist/watcher_update.h" namespace casbin { // addPolicy adds a rule to the current policy. -bool Enforcer :: addPolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { +bool Enforcer::addPolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { bool rule_added = m_model->AddPolicy(sec, p_type, rule); if(!rule_added) return rule_added; @@ -59,7 +60,7 @@ bool Enforcer :: addPolicy(const std::string& sec, const std::string& p_type, co } // addPolicies adds rules to the current policy. -bool Enforcer :: addPolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules) { +bool Enforcer::addPolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules) { bool rules_added = m_model->AddPolicies(sec, p_type, rules); if (!rules_added) return rules_added; @@ -83,7 +84,7 @@ bool Enforcer :: addPolicies(const std::string& sec, const std::string& p_type, } // removePolicy removes a rule from the current policy. -bool Enforcer :: removePolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { +bool Enforcer::removePolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { bool rule_removed = m_model->RemovePolicy(sec, p_type, rule); if(!rule_removed) return rule_removed; @@ -113,7 +114,7 @@ bool Enforcer :: removePolicy(const std::string& sec, const std::string& p_type, } // removePolicies removes rules from the current policy. -bool Enforcer :: removePolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules) { +bool Enforcer::removePolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules) { bool rules_removed = m_model->AddPolicies(sec, p_type, rules); if (!rules_removed) return rules_removed; @@ -136,7 +137,7 @@ bool Enforcer :: removePolicies(const std::string& sec, const std::string& p_typ } // removeFilteredPolicy removes rules based on field filters from the current policy. -bool Enforcer :: removeFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector& field_values){ +bool Enforcer::removeFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector& field_values){ std::pair>> p = m_model->RemoveFilteredPolicy(sec, p_type, field_index, field_values); bool rule_removed = p.first; std::vector> effects = p.second; @@ -166,13 +167,46 @@ bool Enforcer :: removeFilteredPolicy(const std::string& sec, const std::string& return rule_removed; } -bool Enforcer :: updatePolicy(const std::string& sec, const std::string& p_type, const std::vector& oldRule, const std::vector& newRule) { - bool is_model_policy_updated = m_model->UpdatePolicy(sec, p_type, oldRule, newRule); - return true; +bool Enforcer::updatePolicy(const std::string& sec, const std::string& p_type, const std::vector& oldRule, const std::vector& newRule) { + bool is_rule_updated = m_model->UpdatePolicy(sec, p_type, oldRule, newRule); + if(!is_rule_updated) + return false; + + if(sec == "g") { + this->BuildIncrementalRoleLinks(policy_remove, p_type, { oldRule }); + this->BuildIncrementalRoleLinks(policy_add, p_type, { newRule }); + } + if (m_watcher && m_auto_notify_watcher) { + if(IsInstanceOf(m_watcher.get())) { + std::dynamic_pointer_cast(m_watcher)->UpdateForUpdatePolicy(oldRule, newRule); + } + else { + m_watcher->Update(); + } + } + return is_rule_updated; } -bool Enforcer :: updatePolicies(const std::string& sec, const std::string& p_type, const std::vector>& p1, const std::vector>& p2) { - return true; +bool Enforcer::updatePolicies(const std::string& sec, const std::string& p_type, const std::vector>& oldRules, const std::vector>& newRules) { + bool is_rules_updated = m_model->UpdatePolicies(sec, p_type, oldRules, newRules); + if(!is_rules_updated) + return false; + + if(sec == "g") { + this->BuildIncrementalRoleLinks(policy_remove, p_type, oldRules); + this->BuildIncrementalRoleLinks(policy_add, p_type, newRules); + } + + if (m_watcher && m_auto_notify_watcher) { + if(IsInstanceOf(m_watcher.get())) { + std::dynamic_pointer_cast(m_watcher)->UpdateForUpdatePolicies(oldRules, newRules); + } + else { + m_watcher->Update(); + } + } + + return is_rules_updated; } } // namespace casbin diff --git a/casbin/model/model.cpp b/casbin/model/model.cpp index 6ff97e2c..ff366795 100644 --- a/casbin/model/model.cpp +++ b/casbin/model/model.cpp @@ -29,7 +29,7 @@ namespace casbin { -std::unordered_map Model :: section_name_map = { +std::unordered_map Model::section_name_map = { {"r", "request_definition"}, {"p", "policy_definition"}, {"g", "role_definition"}, @@ -37,9 +37,9 @@ std::unordered_map Model :: section_name_map = { {"m", "matchers"} }; -std::vector Model :: required_sections{"r","p","e","m"}; +std::vector Model::required_sections{"r","p","e","m"}; -void Model :: LoadModelFromConfig(std::shared_ptr cfg) { +void Model::LoadModelFromConfig(std::shared_ptr cfg) { for (std::unordered_map::iterator it = section_name_map.begin(); it != section_name_map.end(); it++) LoadSection(this, cfg, it->first); @@ -52,11 +52,11 @@ void Model :: LoadModelFromConfig(std::shared_ptr cfg) { throw MissingRequiredSections("missing required sections: " + Join(ms, ",")); } -bool Model :: HasSection(std::string sec) { +bool Model::HasSection(const std::string& sec) { return this->m.find(sec) != this->m.end(); } -void Model :: LoadSection(Model* model, std::shared_ptr cfg, std::string sec) { +void Model::LoadSection(Model* model, std::shared_ptr cfg, const std::string& sec) { int i = 1; while(true) { if (!LoadAssertion(model, cfg, sec, sec+GetKeySuffix(i))){ @@ -77,17 +77,17 @@ std::string Model ::GetKeySuffix(int i) { return s; } -bool Model :: LoadAssertion(Model* model, std::shared_ptr cfg, std::string sec, std::string key) { +bool Model::LoadAssertion(Model* model, std::shared_ptr cfg, const std::string& sec, const std::string& key) { std::string value = cfg->GetString(section_name_map[sec] + "::" + key); return model->AddDef(sec, key, value); } // AddDef adds an assertion to the model. -bool Model :: AddDef(std::string sec, std::string key, std::string value) { +bool Model::AddDef(const std::string& sec, const std::string& key, const std::string& value) { if(value == "") return false; - std::shared_ptr ast(new Assertion()); + std::shared_ptr ast = std::make_shared(); ast->key = key; ast->value = value; if (sec == "r" || sec == "p") { @@ -100,7 +100,7 @@ bool Model :: AddDef(std::string sec, std::string key, std::string value) { if (m.find(sec) == m.end()) m[sec] = AssertionMap(); - ast->policy = std::vector>{}; + ast->policy = {}; m[sec].assertion_map[key] = ast; @@ -108,19 +108,20 @@ bool Model :: AddDef(std::string sec, std::string key, std::string value) { } // LoadModel loads the model from model CONF file. -void Model :: LoadModel(std::string path) { +void Model::LoadModel(const std::string& path) { std::shared_ptr cfg = Config::NewConfig(path); LoadModelFromConfig(cfg); } // LoadModelFromText loads the model from the text. -void Model :: LoadModelFromText(std::string text) { +void Model::LoadModelFromText(const std::string& text) { std::shared_ptr cfg = Config::NewConfigFromText(text); LoadModelFromConfig(cfg); } // PrintModel prints the model to the log. -void Model :: PrintModel() { +void Model::PrintModel() { + // ------TODO------ // DefaultLogger df_logger; // df_logger.EnableLog(true); @@ -128,52 +129,53 @@ void Model :: PrintModel() { // LogUtil::SetLogger(*logger); // LogUtil::LogPrint("Model:"); - // for (unordered_map :: iterator it1 = M.begin() ; it1 != M.end() ; it1++){ - // for(unordered_map :: iterator it2 = (it1->second).AMap.begin() ; it2 != (it1->second).AMap.end() ; it2++){ + // for (unordered_map ::iterator it1 = M.begin() ; it1 != M.end() ; it1++){ + // for(unordered_map ::iterator it2 = (it1->second).AMap.begin() ; it2 != (it1->second).AMap.end() ; it2++){ // LogUtil::LogPrintf("%s.%s: %s", it1->first, it2->first, it2->second->Value); // } // } } -Model :: Model(){ +Model::Model(){ } -Model :: Model(std::string path){ +Model::Model(const std::string& path){ LoadModel(path); } // NewModel creates an empty model. -Model* Model :: NewModel() { +Model* Model::NewModel() { return new Model(); } // NewModel creates a model from a .CONF file. -Model* Model :: NewModelFromFile(std::string path) { +Model* Model::NewModelFromFile(const std::string& path) { Model* m = NewModel(); m->LoadModel(path); return m; } // NewModel creates a model from a std::string which contains model text. -Model* Model :: NewModelFromString(std::string text) { +Model* Model::NewModelFromString(const std::string& text) { Model* m = NewModel(); m->LoadModelFromText(text); return m; } -void Model :: BuildIncrementalRoleLinks(std::shared_ptr rm, policy_op op, std::string sec, std::string p_type, std::vector> rules) { +void Model::BuildIncrementalRoleLinks(std::shared_ptr rm, policy_op op, const std::string& sec, const std::string& p_type, const std::vector>& rules) { if (sec == "g") this->m[sec].assertion_map[p_type]->BuildIncrementalRoleLinks(rm, op, rules); } // BuildRoleLinks initializes the roles in RBAC. -void Model :: BuildRoleLinks(std::shared_ptr rm) { - for (std::unordered_map> :: iterator it = this->m["g"].assertion_map.begin() ; it != this->m["g"].assertion_map.end() ; it++) +void Model::BuildRoleLinks(std::shared_ptr rm) { + for (std::unordered_map>::iterator it = this->m["g"].assertion_map.begin() ; it != this->m["g"].assertion_map.end() ; it++) (it->second)->BuildRoleLinks(rm); } // PrintPolicy prints the policy to log. -void Model :: PrintPolicy() { +void Model::PrintPolicy() { + // ------TODO------ // DefaultLogger df_logger; // df_logger.EnableLog(true); @@ -182,35 +184,39 @@ void Model :: PrintPolicy() { // LogUtil::LogPrint("Policy:"); - // for (std::unordered_map :: iterator it = this->m["p"].assertion_map.begin() ; it != this->m["p"].assertion_map.end() ; it++) { + // for (std::unordered_map::iterator it = this->m["p"].assertion_map.begin() ; it != this->m["p"].assertion_map.end() ; it++) { // LogUtil::LogPrint(it->first, ": ", (it->second)->Value, ": ", (it->second)->policy); // } - // for (std::unordered_map :: iterator it = this->m["g"].assertion_map.begin() ; it != this->m["g"].assertion_map.end() ; it++) { + // for (std::unordered_map::iterator it = this->m["g"].assertion_map.begin() ; it != this->m["g"].assertion_map.end() ; it++) { // LogUtil::LogPrint(it->first, ": ", (it->second)->Value, ": ", (it->second)->policy); // } } // ClearPolicy clears all current policy. -void Model :: ClearPolicy() { - for (std::unordered_map> :: iterator it = this->m["p"].assertion_map.begin() ; it != this->m["p"].assertion_map.end() ; it++){ - if((it->second)->policy.size() > 0) - (it->second)->policy.clear(); +void Model::ClearPolicy() { + // Caching "p" assertion map by reference for the scope of this function + auto& p_assertion_map = this->m["p"].assertion_map; + for (auto it : p_assertion_map) { + if((it.second)->policy.size() > 0) + (it.second)->policy.clear(); } - for (std::unordered_map> :: iterator it = this->m["g"].assertion_map.begin() ; it != this->m["g"].assertion_map.end() ; it++){ - if((it->second)->policy.size() > 0) - (it->second)->policy.clear(); + // Caching "g" assertion map by reference for the scope of this function + auto& g_assertion_map = this->m["g"].assertion_map; + for (auto it : g_assertion_map){ + if((it.second)->policy.size() > 0) + (it.second)->policy.clear(); } } // GetPolicy gets all rules in a policy. -std::vector> Model :: GetPolicy(std::string sec, std::string p_type) { - return (this->m)[sec].assertion_map[p_type]->policy; +std::vector> Model::GetPolicy(const std::string& sec, const std::string& p_type) { + return this->m[sec].assertion_map[p_type]->policy; } // GetFilteredPolicy gets rules based on field filters from a policy. -std::vector> Model :: GetFilteredPolicy(std::string sec, std::string p_type, int field_index, std::vector field_values) { +std::vector> Model::GetFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector& field_values) { std::vector> res; std::vector> policy(m[sec].assertion_map[p_type]->policy); for(int i = 0 ; i < policy.size() ; i++){ @@ -229,17 +235,17 @@ std::vector> Model :: GetFilteredPolicy(std::string sec } // HasPolicy determines whether a model has the specified policy rule. -bool Model :: HasPolicy(std::string sec, std::string p_type, std::vector rule) { - std::vector> policy = m[sec].assertion_map[p_type]->policy; - for(int i=0 ; i < policy.size() ; i++) - if (ArrayEquals(rule, policy[i])) +bool Model::HasPolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { + auto& policy = this->m[sec].assertion_map[p_type]->policy; + for(auto policy_it : policy) + if (ArrayEquals(rule, policy_it)) return true; return false; } // AddPolicy adds a policy rule to the model. -bool Model :: AddPolicy(std::string sec, std::string p_type, std::vector rule) { +bool Model::AddPolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { if(!this->HasPolicy(sec, p_type, rule)) { m[sec].assertion_map[p_type]->policy.push_back(rule); return true; @@ -249,20 +255,22 @@ bool Model :: AddPolicy(std::string sec, std::string p_type, std::vector> rules) { - for (int i = 0; i < rules.size(); i++) - if (this->HasPolicy(sec, p_type, rules[i])) +bool Model::AddPolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules) { + for (auto rule : rules) + if (this->HasPolicy(sec, p_type, rule)) return false; - for (int i = 0; i < rules.size(); i++) - this->m[sec].assertion_map[p_type]->policy.push_back(rules[i]); + for (auto rule : rules) + this->m[sec].assertion_map[p_type]->policy.push_back(rule); return true; } -bool Model :: UpdatePolicy(const std::string& sec, const std::string p_type, const std::vector& oldRule, const std::vector& newRule) { +bool Model::UpdatePolicy(const std::string& sec, const std::string& p_type, const std::vector& oldRule, const std::vector& newRule) { // Caching policy by reference for the scope of this function auto& policy = m[sec].assertion_map[p_type]->policy; + + // Status flags bool is_oldRule_deleted = false, is_newRule_added = false; for (auto it = policy.begin(); it != policy.end(); ++it) { @@ -276,6 +284,7 @@ bool Model :: UpdatePolicy(const std::string& sec, const std::string p_type, con if(!is_oldRule_deleted) return false; + // Prevents duplicate policies if(!this->HasPolicy(sec, p_type, newRule)) { policy.push_back(newRule); is_newRule_added = true; @@ -287,8 +296,42 @@ bool Model :: UpdatePolicy(const std::string& sec, const std::string p_type, con return is_oldRule_deleted && is_newRule_added; } +bool Model::UpdatePolicies(const std::string& sec, const std::string& p_type, const std::vector>& oldRules, const std::vector>& newRules) { + // Caching policy by reference for the scope of this function + auto& policy = this->m[sec].assertion_map[p_type]->policy; + + // Deleting old rules + bool is_oldRule_deleted; + for (auto oldRule : oldRules) { + is_oldRule_deleted = false; + for (auto it = policy.begin(); it != policy.end(); ++it) { + if(ArrayEquals(oldRule, *it)) { + policy.erase(it); + is_oldRule_deleted = true; + break; + } + } + if(!is_oldRule_deleted) + return false; + } + + // Checking if the policy already contains newRule + for(auto newRule : newRules) { + if(!this->HasPolicy(sec, p_type, newRule)) + continue; + else + return false; + } + + for(auto newRule : newRules) { + policy.push_back(newRule); + } + + return true; +} + // RemovePolicy removes a policy rule from the model. -bool Model :: RemovePolicy(std::string sec, std::string p_type, std::vector rule) { +bool Model::RemovePolicy(const std::string& sec, const std::string& p_type, const std::vector& rule) { // Caching policy by reference for the scope of this function auto& policy = m[sec].assertion_map[p_type]->policy; for (auto it = policy.begin(); it != policy.end(); ++it) { @@ -301,19 +344,25 @@ bool Model :: RemovePolicy(std::string sec, std::string p_type, std::vector> rules) { - OUTER: for (int j = 0; j < rules.size(); j++) { - for (int i = 0; i < this->m[sec].assertion_map[p_type]->policy.size(); i++){ - if (ArrayEquals(rules[j], this->m[sec].assertion_map[p_type]->policy[i])) - goto OUTER; +bool Model::RemovePolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules) { + // Caching policy by reference for the scope of this function + auto& policy = this->m[sec].assertion_map[p_type]->policy; + + bool is_equal; + for (auto rule : rules) { + is_equal = false; + for (auto policy_it : policy) { + if (ArrayEquals(rule, policy_it)) + is_equal = true; } - return false; + if(!is_equal) + return false; } - for (int j = 0; j < rules.size(); j++){ - for (int i = 0; i < this->m[sec].assertion_map[p_type]->policy.size(); i++){ - if (ArrayEquals(rules[j], this->m[sec].assertion_map[p_type]->policy[i])) - this->m[sec].assertion_map[p_type]->policy.erase(this->m[sec].assertion_map[p_type]->policy.begin() + i); + for (auto rule : rules) { + for (auto policy_it = policy.begin(); policy_it != policy.end(); ++policy_it) { + if (ArrayEquals(rule, *policy_it)) + policy.erase(policy_it); } } @@ -321,7 +370,7 @@ bool Model :: RemovePolicies(std::string sec, std::string p_type, std::vector>> Model :: RemoveFilteredPolicy(std::string sec, std::string p_type, int field_index, std::vector field_values) { +std::pair>> Model::RemoveFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector& field_values) { std::vector> tmp; std::vector> effects; std::vector> policy(m[sec].assertion_map[p_type]->policy); @@ -348,7 +397,7 @@ std::pair>> Model :: RemoveFilteredPo } // GetValuesForFieldInPolicy gets all values for a field for all rules in a policy, duplicated values are removed. -std::vector Model :: GetValuesForFieldInPolicy(std::string sec, std::string p_type, int field_index) { +std::vector Model::GetValuesForFieldInPolicy(const std::string& sec, const std::string& p_type, int field_index) { std::vector values; std::vector> policy(m[sec].assertion_map[p_type]->policy); for(int i = 0 ; i < policy.size() ; i++) @@ -360,10 +409,10 @@ std::vector Model :: GetValuesForFieldInPolicy(std::string sec, std } // GetValuesForFieldInPolicyAllTypes gets all values for a field for all rules in a policy of all p_types, duplicated values are removed. -std::vector Model :: GetValuesForFieldInPolicyAllTypes(std::string sec, int field_index) { +std::vector Model::GetValuesForFieldInPolicyAllTypes(const std::string& sec, int field_index) { std::vector values; - for (std::unordered_map> :: iterator it = m[sec].assertion_map.begin() ; it != m[sec].assertion_map.end() ; it++) { + for (std::unordered_map>::iterator it = m[sec].assertion_map.begin() ; it != m[sec].assertion_map.end() ; it++) { std::vector values_for_field(this->GetValuesForFieldInPolicy(sec, it->first, field_index)); for(int i = 0 ; i < values_for_field.size() ; i++) values.push_back(values_for_field[i]); diff --git a/casbin/model/model.h b/casbin/model/model.h index 0b3f3454..5bfb546f 100644 --- a/casbin/model/model.h +++ b/casbin/model/model.h @@ -32,38 +32,38 @@ class AssertionMap { }; // Model represents the whole access control model. -class Model{ +class Model { private: static std::unordered_map section_name_map; - static void LoadSection(Model* model, std::shared_ptr cfg, std::string sec); + static void LoadSection(Model* model, std::shared_ptr cfg, const std::string& sec); static std::string GetKeySuffix(int i); - static bool LoadAssertion(Model* model, std::shared_ptr cfg, std::string sec, std::string key); + static bool LoadAssertion(Model* model, std::shared_ptr cfg, const std::string& sec, const std::string& key); public: Model(); - Model(std::string path); + Model(const std::string& path); std::unordered_map m; // Minimal required sections for a model to be valid static std::vector required_sections; - bool HasSection(std::string sec); + bool HasSection(const std::string& sec); // AddDef adds an assertion to the model. - bool AddDef(std::string sec, std::string key, std::string value); + bool AddDef(const std::string& sec, const std::string& key, const std::string& value); // LoadModel loads the model from model CONF file. - void LoadModel(std::string path); + void LoadModel(const std::string& path); // LoadModelFromText loads the model from the text. - void LoadModelFromText(std::string text); + void LoadModelFromText(const std::string& text); void LoadModelFromConfig(std::shared_ptr cfg); @@ -74,12 +74,12 @@ class Model{ static Model* NewModel(); // NewModel creates a model from a .CONF file. - static Model* NewModelFromFile(std::string path); + static Model* NewModelFromFile(const std::string& path); // NewModel creates a model from a std::string which contains model text. - static Model* NewModelFromString(std::string text); + static Model* NewModelFromString(const std::string& text); - void BuildIncrementalRoleLinks(std::shared_ptr rm, policy_op op, std::string sec, std::string p_type, std::vector> rules); + void BuildIncrementalRoleLinks(std::shared_ptr rm, policy_op op, const std::string& sec, const std::string& p_type, const std::vector>& rules); // BuildRoleLinks initializes the roles in RBAC. void BuildRoleLinks(std::shared_ptr rm); @@ -91,37 +91,40 @@ class Model{ void ClearPolicy(); // GetPolicy gets all rules in a policy. - std::vector> GetPolicy(std::string sec, std::string p_type); + std::vector> GetPolicy(const std::string& sec, const std::string& p_type); // GetFilteredPolicy gets rules based on field filters from a policy. - std::vector> GetFilteredPolicy(std::string sec, std::string p_type, int field_index, std::vector field_values); + std::vector> GetFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector& field_values); // HasPolicy determines whether a model has the specified policy rule. - bool HasPolicy(std::string sec, std::string p_type, std::vector rule); + bool HasPolicy(const std::string& sec, const std::string& p_type, const std::vector& rule); // AddPolicy adds a policy rule to the model. - bool AddPolicy(std::string sec, std::string p_type, std::vector rule); + bool AddPolicy(const std::string& sec, const std::string& p_type, const std::vector& rule); // AddPolicies adds policy rules to the model. - bool AddPolicies(std::string sec, std::string p_type, std::vector> rules); + bool AddPolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules); // UpdatePolicy updates a policy rule from the model. - bool UpdatePolicy(const std::string& sec, const std::string p_type, const std::vector& oldRule, const std::vector& newRule); + bool UpdatePolicy(const std::string& sec, const std::string& p_type, const std::vector& oldRule, const std::vector& newRule); + + // UpdatePolicies updates a set of policy rules from the model. + bool UpdatePolicies(const std::string& sec, const std::string& p_type, const std::vector>& oldRules, const std::vector>& newRules); // RemovePolicy removes a policy rule from the model. - bool RemovePolicy(std::string sec, std::string p_type, std::vector rule); + bool RemovePolicy(const std::string& sec, const std::string& p_type, const std::vector& rule); // RemovePolicies removes policy rules from the model. - bool RemovePolicies(std::string sec, std::string p_type, std::vector> rules); + bool RemovePolicies(const std::string& sec, const std::string& p_type, const std::vector>& rules); // RemoveFilteredPolicy removes policy rules based on field filters from the model. - std::pair>> RemoveFilteredPolicy(std::string sec, std::string p_type, int field_index, std::vector field_values); + std::pair>> RemoveFilteredPolicy(const std::string& sec, const std::string& p_type, int field_index, const std::vector& field_values); // GetValuesForFieldInPolicy gets all values for a field for all rules in a policy, duplicated values are removed. - std::vector GetValuesForFieldInPolicy(std::string sec, std::string p_type, int field_index); + std::vector GetValuesForFieldInPolicy(const std::string& sec, const std::string& p_type, int field_index); // GetValuesForFieldInPolicyAllTypes gets all values for a field for all rules in a policy of all p_types, duplicated values are removed. - std::vector GetValuesForFieldInPolicyAllTypes(std::string sec, int field_index); + std::vector GetValuesForFieldInPolicyAllTypes(const std::string& sec, int field_index); }; }; // namespace casbin diff --git a/casbin/persist/watcher_update.h b/casbin/persist/watcher_update.h new file mode 100644 index 00000000..c0ea147a --- /dev/null +++ b/casbin/persist/watcher_update.h @@ -0,0 +1,50 @@ +/* +* 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. +*/ + +#ifndef WATCHER_UPDATE_H +#define WATCHER_UPDATE_H + +#include "watcher.h" + +namespace casbin { + +/** + * @brief WatcherUpdatable is the strengthen for Casbin watchers. + * + */ +class WatcherUpdatable : public Watcher { +public: + /** + * @brief UpdateForUpdatePolicy calls the update callback of other instances to synchronize their policy. + * It is called after Enforcer::UpdatePolicy() + * + * @param oldRule Old rule which is to be replaced + * @param newRule New rule which will replace oldRule + */ + virtual void UpdateForUpdatePolicy(const std::vector& oldRule, const std::vector& newRule) = 0; + /** + * @brief UpdateForUpdatePolicies calls the update callback of other instances to synchronize their policy. + * It is called after Enforcer::UpdatePolicies() + * + * @param oldRules Old rules which are to be replaced + * @param newRules New rules which will replace oldRules + */ + virtual void UpdateForUpdatePolicies(const std::vector>& oldRules, const std::vector>& newRules) = 0; +}; + +} + +#endif From 5c684ce676ce7273729c654112a4bc6c71aa6c3b Mon Sep 17 00:00:00 2001 From: EmperorYP7 Date: Thu, 10 Jun 2021 18:22:51 +0530 Subject: [PATCH 3/7] feat: added tests for UpdatePolicy Signed-off-by: EmperorYP7 --- casbin/casbin.vcxproj | 2 + casbin/casbin.vcxproj.filters | 6 ++ casbin/{log => }/logger.cpp | 4 +- casbin/util/is_instance_of.cpp | 2 + casbin/util/ticker.h | 6 ++ test/test_management_api.cpp | 175 ++++++++++++++++++++------------- 6 files changed, 122 insertions(+), 73 deletions(-) rename casbin/{log => }/logger.cpp (90%) diff --git a/casbin/casbin.vcxproj b/casbin/casbin.vcxproj index 78734730..d2cdb9ec 100644 --- a/casbin/casbin.vcxproj +++ b/casbin/casbin.vcxproj @@ -273,6 +273,7 @@ + @@ -286,6 +287,7 @@ + diff --git a/casbin/casbin.vcxproj.filters b/casbin/casbin.vcxproj.filters index b737c515..98977348 100644 --- a/casbin/casbin.vcxproj.filters +++ b/casbin/casbin.vcxproj.filters @@ -494,6 +494,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/casbin/log/logger.cpp b/casbin/logger.cpp similarity index 90% rename from casbin/log/logger.cpp rename to casbin/logger.cpp index a347c618..e4c534bc 100644 --- a/casbin/log/logger.cpp +++ b/casbin/logger.cpp @@ -3,8 +3,8 @@ #ifndef LOGGER_CPP #define LOGGER_CPP -#include "Logger.h" -#include "log_util.h" +#include "./log/Logger.h" +#include "./log/log_util.h" namespace casbin { diff --git a/casbin/util/is_instance_of.cpp b/casbin/util/is_instance_of.cpp index 6395090f..b3a72608 100644 --- a/casbin/util/is_instance_of.cpp +++ b/casbin/util/is_instance_of.cpp @@ -22,6 +22,7 @@ #include "./util.h" #include "../persist/watcher_ex.h" +#include "../persist/watcher_update.h" namespace casbin { @@ -31,6 +32,7 @@ bool IsInstanceOf(const T*) { } template bool IsInstanceOf(class Watcher const*); +template bool IsInstanceOf(class Watcher const*); } // namespace casbin diff --git a/casbin/util/ticker.h b/casbin/util/ticker.h index 2854a17a..3725df06 100644 --- a/casbin/util/ticker.h +++ b/casbin/util/ticker.h @@ -14,9 +14,15 @@ * limitations under the License. */ +#include "pch.h" + #ifndef TICKER_H #define TICKER_H +#include +#include +#include +#include namespace casbin { diff --git a/test/test_management_api.cpp b/test/test_management_api.cpp index fd4037e5..d49da842 100644 --- a/test/test_management_api.cpp +++ b/test/test_management_api.cpp @@ -23,10 +23,10 @@ namespace test_management_api std::string policy = "../../examples/rbac_policy.csv"; Enforcer e = Enforcer(model, policy); - Assert::IsTrue(ArrayEquals(std::vector{ "alice", "bob", "data2_admin" }, e.GetAllSubjects())); - Assert::IsTrue(ArrayEquals(std::vector{ "data1", "data2" }, e.GetAllObjects())); - Assert::IsTrue(ArrayEquals(std::vector{ "read", "write" }, e.GetAllActions())); - Assert::IsTrue(ArrayEquals(std::vector{ "data2_admin" }, e.GetAllRoles())); + Assert::IsTrue(ArrayEquals({ "alice", "bob", "data2_admin" }, e.GetAllSubjects())); + Assert::IsTrue(ArrayEquals({ "data1", "data2" }, e.GetAllObjects())); + Assert::IsTrue(ArrayEquals({ "read", "write" }, e.GetAllActions())); + Assert::IsTrue(ArrayEquals({ "data2_admin" }, e.GetAllRoles())); } void TestGetPolicy(Enforcer e, std::vector> res) { @@ -89,35 +89,35 @@ namespace test_management_api { "data2_admin", "data2", "read" }, { "data2_admin", "data2", "write" }}); - TestGetFilteredPolicy(e, 0, std::vector>{ {"alice", "data1", "read"} }, std::vector{"alice"}); - TestGetFilteredPolicy(e, 0, std::vector>{ {"bob", "data2", "write"}}, std::vector{"bob"}); - TestGetFilteredPolicy(e, 0, std::vector>{ {"data2_admin", "data2", "read"}, { "data2_admin", "data2", "write" }}, std::vector{"data2_admin"}); - TestGetFilteredPolicy(e, 1, std::vector>{ {"alice", "data1", "read"}}, std::vector{"data1"}); - TestGetFilteredPolicy(e, 1, std::vector>{ {"bob", "data2", "write"}, { "data2_admin", "data2", "read" }, { "data2_admin", "data2", "write" }}, std::vector{"data2"}); - TestGetFilteredPolicy(e, 2, std::vector>{ {"alice", "data1", "read"}, { "data2_admin", "data2", "read" }}, std::vector{"read"}); - TestGetFilteredPolicy(e, 2, std::vector>{ {"bob", "data2", "write"}, { "data2_admin", "data2", "write" }}, std::vector{"write"}); + TestGetFilteredPolicy(e, 0, { {"alice", "data1", "read"} }, {"alice"}); + TestGetFilteredPolicy(e, 0, { {"bob", "data2", "write"}}, {"bob"}); + TestGetFilteredPolicy(e, 0, { {"data2_admin", "data2", "read"}, { "data2_admin", "data2", "write" }}, {"data2_admin"}); + TestGetFilteredPolicy(e, 1, { {"alice", "data1", "read"}}, {"data1"}); + TestGetFilteredPolicy(e, 1, { {"bob", "data2", "write"}, { "data2_admin", "data2", "read" }, { "data2_admin", "data2", "write" }}, {"data2"}); + TestGetFilteredPolicy(e, 2, { {"alice", "data1", "read"}, { "data2_admin", "data2", "read" }}, {"read"}); + TestGetFilteredPolicy(e, 2, { {"bob", "data2", "write"}, { "data2_admin", "data2", "write" }}, {"write"}); - TestGetFilteredPolicy(e, 0, std::vector>{ {"data2_admin", "data2", "read"}, { "data2_admin", "data2", "write" }}, std::vector{"data2_admin", "data2"}); + TestGetFilteredPolicy(e, 0, { {"data2_admin", "data2", "read"}, { "data2_admin", "data2", "write" }}, {"data2_admin", "data2"}); // Note: "" (empty string) in fieldValues means matching all values. - TestGetFilteredPolicy(e, 0, std::vector>{ {"data2_admin", "data2", "read"}}, std::vector{"data2_admin", "", "read"}); - TestGetFilteredPolicy(e, 1, std::vector>{ {"bob", "data2", "write"}, { "data2_admin", "data2", "write" }}, std::vector{"data2", "write"}); + TestGetFilteredPolicy(e, 0, { {"data2_admin", "data2", "read"}}, {"data2_admin", "", "read"}); + TestGetFilteredPolicy(e, 1, { {"bob", "data2", "write"}, { "data2_admin", "data2", "write" }}, {"data2", "write"}); - TestHasPolicy(e, std::vector{"alice", "data1", "read"}, true); - TestHasPolicy(e, std::vector{"bob", "data2", "write"}, true); - TestHasPolicy(e, std::vector{"alice", "data2", "read"}, false); - TestHasPolicy(e, std::vector{"bob", "data3", "write"}, false); + TestHasPolicy(e, {"alice", "data1", "read"}, true); + TestHasPolicy(e, {"bob", "data2", "write"}, true); + TestHasPolicy(e, {"alice", "data2", "read"}, false); + TestHasPolicy(e, {"bob", "data3", "write"}, false); TestGetGroupingPolicy(e, std::vector>{ {"alice", "data2_admin"}}); - TestGetFilteredGroupingPolicy(e, 0, std::vector>{{"alice", "data2_admin"}}, std::vector{"alice"}); - TestGetFilteredGroupingPolicy(e, 0, std::vector>{}, std::vector{"bob"}); - TestGetFilteredGroupingPolicy(e, 1, std::vector>{}, std::vector{"data1_admin"}); - TestGetFilteredGroupingPolicy(e, 1, std::vector>{ {"alice", "data2_admin"}}, std::vector{"data2_admin"}); + TestGetFilteredGroupingPolicy(e, 0, {{"alice", "data2_admin"}}, {"alice"}); + TestGetFilteredGroupingPolicy(e, 0, {}, {"bob"}); + TestGetFilteredGroupingPolicy(e, 1, {}, {"data1_admin"}); + TestGetFilteredGroupingPolicy(e, 1, { {"alice", "data2_admin"}}, {"data2_admin"}); // Note: "" (empty string) in fieldValues means matching all values. - TestGetFilteredGroupingPolicy(e, 0, std::vector>{ {"alice", "data2_admin"}}, std::vector{"", "data2_admin"}); + TestGetFilteredGroupingPolicy(e, 0, { {"alice", "data2_admin"}}, {"", "data2_admin"}); - TestHasGroupingPolicy(e, std::vector{"alice", "data2_admin"}, true); - TestHasGroupingPolicy(e, std::vector{"bob", "data2_admin"}, false); + TestHasGroupingPolicy(e, {"alice", "data2_admin"}, true); + TestHasGroupingPolicy(e, {"bob", "data2_admin"}, false); } @@ -127,19 +127,20 @@ namespace test_management_api std::shared_ptr adapter = std::shared_ptr(new BatchFileAdapter(policy)); Enforcer e = Enforcer(model, adapter); - TestGetPolicy(e, std::vector>{ + TestGetPolicy(e, { {"alice", "data1", "read"}, - { "bob", "data2", "write" }, - { "data2_admin", "data2", "read" }, - { "data2_admin", "data2", "write" }}); + {"bob", "data2", "write"}, + {"data2_admin", "data2", "read"}, + {"data2_admin", "data2", "write"} + }); - e.RemovePolicy(std::vector{"alice", "data1", "read"}); - e.RemovePolicy(std::vector{"bob", "data2", "write"}); - e.RemovePolicy(std::vector{"alice", "data1", "read"}); - e.AddPolicy(std::vector{"eve", "data3", "read"}); - e.AddPolicy(std::vector{"eve", "data3", "read"}); + e.RemovePolicy({"alice", "data1", "read"}); + e.RemovePolicy({"bob", "data2", "write"}); + e.RemovePolicy({"alice", "data1", "read"}); + e.AddPolicy({"eve", "data3", "read"}); + e.AddPolicy({"eve", "data3", "read"}); - std::vector>rules{ + std::vector> rules { {"jack", "data4", "read"}, {"katy", "data4", "write"}, {"leyo", "data4", "read"}, @@ -149,91 +150,113 @@ namespace test_management_api e.AddPolicies(rules); e.AddPolicies(rules); - TestGetPolicy(e, std::vector>{ + TestGetPolicy(e, { {"data2_admin", "data2", "read"}, { "data2_admin", "data2", "write" }, { "eve", "data3", "read" }, { "jack", "data4", "read" }, { "katy", "data4", "write" }, { "leyo", "data4", "read" }, - { "ham", "data4", "write" }}); + { "ham", "data4", "write" } + }); e.RemovePolicies(rules); e.RemovePolicies(rules); - std::vectornamed_policy{ "eve", "data3", "read" }; + std::vector named_policy{ "eve", "data3", "read" }; e.RemoveNamedPolicy("p", named_policy); e.AddNamedPolicy("p", named_policy); - TestGetPolicy(e, std::vector>{ + TestGetPolicy(e, { {"data2_admin", "data2", "read"}, { "data2_admin", "data2", "write" }, - { "eve", "data3", "read" }}); + { "eve", "data3", "read" } + }); - e.RemoveFilteredPolicy(1, std::vector{"data2"}); + e.RemoveFilteredPolicy(1, {"data2"}); - TestGetPolicy(e, std::vector>{ {"eve", "data3", "read"}}); + TestGetPolicy(e, { {"eve", "data3", "read"}}); + + e.UpdatePolicy({"eve", "data3", "read"}, {"eve", "data3", "write"}); + TestGetPolicy(e, {{"eve", "data3", "write"}}); + + e.AddPolicies(rules); + e.UpdatePolicies({ + {"eve", "data3", "write"}, + {"leyo", "data4", "read"}, + {"katy", "data4", "write"} + }, { + {"eve", "data3", "read"}, + {"leyo", "data4", "write"}, + {"katy", "data1", "write"} + }); + + TestGetPolicy(e, { + {"eve", "data3", "read"}, + {"leyo", "data4", "write"}, + {"katy", "data1", "write"} + }); } TEST_METHOD(TestModifyGroupingPolicyAPI) { std::string model = "../../examples/rbac_model.conf"; std::string policy = "../../examples/rbac_policy.csv"; - std::shared_ptr adapter = std::shared_ptr(new BatchFileAdapter(policy)); + std::shared_ptr adapter = std::make_shared(policy); Enforcer e = Enforcer(model, adapter); - Assert::IsTrue(ArrayEquals(std::vector{"data2_admin"}, e.GetRolesForUser("alice"))); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("bob"))); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("eve"))); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("non_exist"))); + Assert::IsTrue(ArrayEquals({"data2_admin"}, e.GetRolesForUser("alice"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("bob"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("eve"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("non_exist"))); - e.RemoveGroupingPolicy(std::vector{"alice", "data2_admin"}); - e.AddGroupingPolicy(std::vector{"bob", "data1_admin"}); - e.AddGroupingPolicy(std::vector{"eve", "data3_admin"}); + e.RemoveGroupingPolicy({"alice", "data2_admin"}); + e.AddGroupingPolicy({"bob", "data1_admin"}); + e.AddGroupingPolicy({"eve", "data3_admin"}); - std::vector> grouping_rules{ + std::vector> grouping_rules { {"ham", "data4_admin"}, {"jack", "data5_admin"}, }; e.AddGroupingPolicies(grouping_rules); - Assert::IsTrue(ArrayEquals(std::vector{"data4_admin"}, e.GetRolesForUser("ham"))); - Assert::IsTrue(ArrayEquals(std::vector{"data5_admin"}, e.GetRolesForUser("jack"))); + Assert::IsTrue(ArrayEquals({"data4_admin"}, e.GetRolesForUser("ham"))); + Assert::IsTrue(ArrayEquals({"data5_admin"}, e.GetRolesForUser("jack"))); e.RemoveGroupingPolicies(grouping_rules); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("alice"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("alice"))); std::vector named_grouping_policy{ "alice", "data2_admin" }; - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("alice"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("alice"))); e.AddNamedGroupingPolicy("g", named_grouping_policy); - Assert::IsTrue(ArrayEquals(std::vector{"data2_admin"}, e.GetRolesForUser("alice"))); + Assert::IsTrue(ArrayEquals({"data2_admin"}, e.GetRolesForUser("alice"))); e.RemoveNamedGroupingPolicy("g", named_grouping_policy); e.AddNamedGroupingPolicies("g", grouping_rules); e.AddNamedGroupingPolicies("g", grouping_rules); - Assert::IsTrue(ArrayEquals(std::vector{"data4_admin"}, e.GetRolesForUser("ham"))); - Assert::IsTrue(ArrayEquals(std::vector{"data5_admin"}, e.GetRolesForUser("jack"))); + Assert::IsTrue(ArrayEquals({"data4_admin"}, e.GetRolesForUser("ham"))); + Assert::IsTrue(ArrayEquals({"data5_admin"}, e.GetRolesForUser("jack"))); e.RemoveNamedGroupingPolicies("g", grouping_rules); e.RemoveNamedGroupingPolicies("g", grouping_rules); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("alice"))); - Assert::IsTrue(ArrayEquals(std::vector{"data1_admin"}, e.GetRolesForUser("bob"))); - Assert::IsTrue(ArrayEquals(std::vector{"data3_admin"}, e.GetRolesForUser("eve"))); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("non_exist"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("alice"))); + Assert::IsTrue(ArrayEquals({"data1_admin"}, e.GetRolesForUser("bob"))); + Assert::IsTrue(ArrayEquals({"data3_admin"}, e.GetRolesForUser("eve"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("non_exist"))); - Assert::IsTrue(ArrayEquals(std::vector{"bob"}, e.GetUsersForRole("data1_admin"))); + Assert::IsTrue(ArrayEquals({"bob"}, e.GetUsersForRole("data1_admin"))); try { - e.GetUsersForRole("data2_admin", std::vector{}); + e.GetUsersForRole("data2_admin", {}); } catch (CasbinRBACException e) { Assert::IsTrue(true); } - Assert::IsTrue(ArrayEquals(std::vector{"eve"}, e.GetUsersForRole("data3_admin"))); + Assert::IsTrue(ArrayEquals({"eve"}, e.GetUsersForRole("data3_admin"))); - e.RemoveFilteredGroupingPolicy(0, std::vector{"bob"}); + e.RemoveFilteredGroupingPolicy(0, {"bob"}); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("alice"))); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("bob"))); - Assert::IsTrue(ArrayEquals(std::vector{"data3_admin"}, e.GetRolesForUser("eve"))); - Assert::IsTrue(ArrayEquals(std::vector{}, e.GetRolesForUser("non_exist"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("alice"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("bob"))); + Assert::IsTrue(ArrayEquals({"data3_admin"}, e.GetRolesForUser("eve"))); + Assert::IsTrue(ArrayEquals({}, e.GetRolesForUser("non_exist"))); try { e.GetUsersForRole("data1_admin"); @@ -247,7 +270,17 @@ namespace test_management_api catch (CasbinRBACException e) { Assert::IsTrue(true); } - Assert::IsTrue(ArrayEquals(std::vector{"eve"}, e.GetUsersForRole("data3_admin"))); + Assert::IsTrue(ArrayEquals({"eve"}, e.GetUsersForRole("data3_admin"))); + + Assert::IsTrue(e.AddGroupingPolicy({"data3_admin", "data4_admin"})); + e.UpdateGroupingPolicy({"eve", "data3_admin"}, {"eve", "admin"}); + e.UpdateGroupingPolicy({"data3_admin", "data4_admin"}, {"admin", "data4_admin"}); + + // Assert::IsTrue(ArrayEquals({"admin"}, e.GetUsersForRole("data4_admin"))); + Assert::IsTrue(ArrayEquals({"eve"}, e.GetUsersForRole("admin"))); + + Assert::IsTrue(ArrayEquals({"admin"}, e.GetRolesForUser("eve"))); + Assert::IsTrue(ArrayEquals({"data4_admin"}, e.GetRolesForUser("admin"))); } }; } From 5125e2580e51b304b0552ef656843a7e617f40ba Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Thu, 10 Jun 2021 22:05:04 +0530 Subject: [PATCH 4/7] fix: fixing error in UNIX Signed-off-by: Yash Pandey (YP) --- casbin/ip_parser/parser/pch.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/casbin/ip_parser/parser/pch.h b/casbin/ip_parser/parser/pch.h index 37b9b303..16fa8a00 100644 --- a/casbin/ip_parser/parser/pch.h +++ b/casbin/ip_parser/parser/pch.h @@ -1,4 +1,6 @@ #ifndef IPPARSER_PARSER_PCH #define IPPARSER_PARSER_PCH +#include + #endif \ No newline at end of file From 8ae76046a70fbe8e40e61494e4f932c6700650f2 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Thu, 10 Jun 2021 22:35:48 +0530 Subject: [PATCH 5/7] feat: Added CMake GitHub Action Signed-off-by: Yash Pandey (YP) --- .github/workflows/ci.yml | 20 ++++++++++---------- CMakeLists.txt | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06c92ad6..d4fac8d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,18 +25,18 @@ jobs: - name: Checkout id: checkout uses: actions/checkout@v2 - - name: Building files + - name: Configuring CMake files id: building-files run: | - make + mkdir build && cd build && cmake .. - name: Building library id: building-lib run: | - make library + cd build && cmake --build . --config Debug --target all -j 10 -- - name: Cleanup - id: cleanup + id: clean-up run: | - make clean + rm -r build lib macos: name: "macOS Catalina 10.15" @@ -45,15 +45,15 @@ jobs: - name: Checkout id: checkout uses: actions/checkout@v2 - - name: Building files + - name: Configuring CMake files id: building-files run: | - make + mkdir build && cd build && cmake .. - name: Building library id: building-lib run: | - make library + cd build && cmake --build . --config Debug --target all -j 10 -- - name: Cleanup - id: cleanup + id: clean-up run: | - make clean + rm -r build lib diff --git a/CMakeLists.txt b/CMakeLists.txt index f8363a4b..6da0a7b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.19) set(CMAKE_WARN_DEPRECATED ON) From 7f21dfb7fff26998f4309335c963b21b86e58c85 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Fri, 11 Jun 2021 22:27:30 +0530 Subject: [PATCH 6/7] feat: Added CMake CI for Windows Signed-off-by: Yash Pandey (YP) --- .github/workflows/ci.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4fac8d3..0a5b82f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ on: [push, pull_request] jobs: linux: - name: "Linux Ubuntu 20.04" + name: "Linux Ubuntu 20.04 (GNU 9.3.0)" runs-on: ubuntu-20.04 steps: - name: Checkout @@ -38,8 +38,31 @@ jobs: run: | rm -r build lib + windows: + name: "Windows 10 (MSVC 19.29)" + runs-on: windows-latest + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v2 + - name: Configuring CMake files + id: building-files + run: | + mkdir build + cd build + cmake .. + - name: Building library + id: building-lib + run: | + cd build + cmake --build . --config Release --target casbin -j 10 -- + - name: Cleanup + id: clean-up + run: | + rm -r build lib + macos: - name: "macOS Catalina 10.15" + name: "macOS Catalina 10.15 (AppleClang 12.0)" runs-on: macos-latest steps: - name: Checkout @@ -56,4 +79,5 @@ jobs: - name: Cleanup id: clean-up run: | - rm -r build lib + rm -r build + rm -r lib From cf260ae6c81110bcec80f8b73a35856a504206f3 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Fri, 11 Jun 2021 22:29:59 +0530 Subject: [PATCH 7/7] fix: Windows CI Signed-off-by: Yash Pandey (YP) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a5b82f9..aa92a0e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,8 @@ jobs: - name: Cleanup id: clean-up run: | - rm -r build lib + rm -r build + rm -r lib macos: name: "macOS Catalina 10.15 (AppleClang 12.0)" @@ -79,5 +80,4 @@ jobs: - name: Cleanup id: clean-up run: | - rm -r build - rm -r lib + rm -r build lib