From 346af0769cdaad12a478f901ab784982b1ee1ba9 Mon Sep 17 00:00:00 2001 From: ZipoChan <1517708105@qq.com> Date: Sat, 4 Jul 2020 21:12:28 +0800 Subject: [PATCH] feat: add enforce functions with convenient interface. --- casbin/enforcer.cpp | 34 +++++++++++ casbin/enforcer.h | 10 +++- test/test.vcxproj | 1 + test/test.vcxproj.filters | 3 + test/test_enforcer.cpp | 116 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 test/test_enforcer.cpp diff --git a/casbin/enforcer.cpp b/casbin/enforcer.cpp index 105934c3..ebceddf9 100644 --- a/casbin/enforcer.cpp +++ b/casbin/enforcer.cpp @@ -444,6 +444,40 @@ bool Enforcer :: Enforce(Scope scope) { return this->enforce("", scope); } +// Enforce with two params, decides whether a "subject" can do the operation "action", input parameters are usually: (sub, act). +bool Enforcer::Enforce(string sub, string act) { + return Enforce({ sub,act }); +} + +// Enforce with three params, decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). +bool Enforcer::Enforce(string sub, string obj, string act) { + return Enforce({sub,obj,act}); +} + +// Enforce with four params, decides whether a "subject" can access a "object" with the operation "action" in the domain "dom", input parameters are usually: (sub, dom, obj,act). +bool Enforcer::Enforce(string sub, string dom, string obj, string act) { + return Enforce({ sub,dom,obj,act }); +} + +// Enforce with a vector param,decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). +bool Enforcer::Enforce(vector params) { + vector r_tokens = this->model->m["r"].assertion_map["r"]->tokens; + + int r_cnt = r_tokens.size(); + int cnt = params.size(); + + if (cnt != r_cnt) + return false; + + Scope scope = InitializeScope(); + PushObject(scope, "r"); + for (int i = 0; i < cnt; i++) { + PushStringPropToObject(scope, "r", params[i] , r_tokens[i].substr(2,r_tokens[i].size()-2)); + } + + return this->enforce("", scope); +} + // EnforceWithMatcher use a custom matcher to decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (matcher, sub, obj, act), use model matcher by default when matcher is "". bool Enforcer :: EnforceWithMatcher(string matcher, Scope scope) { return this->enforce(matcher, scope); diff --git a/casbin/enforcer.h b/casbin/enforcer.h index 9f3ef161..95ee8a1d 100644 --- a/casbin/enforcer.h +++ b/casbin/enforcer.h @@ -147,9 +147,17 @@ class Enforcer : public IEnforcer{ void BuildIncrementalRoleLinks(policy_op op, string p_type, vector> rules); // Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). bool Enforce(Scope scope); + // Enforce with two params, decides whether a "subject" can do the operation "action", input parameters are usually: (sub, act). + bool Enforce(string sub, string act); + // Enforce with three params, decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). + bool Enforce(string sub, string obj, string act); + // Enforce with four params, decides whether a "subject" can access a "object" with the operation "action" in the domain "dom", input parameters are usually: (sub, dom, obj,act). + bool Enforce(string sub, string dom, string obj, string act); + // Enforce with a vector param,decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). + bool Enforce(vector params); // EnforceWithMatcher use a custom matcher to decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (matcher, sub, obj, act), use model matcher by default when matcher is "". bool EnforceWithMatcher(string matcher, Scope scope); - + /*Management API member functions.*/ vector GetAllSubjects(); vector GetAllNamedSubjects(string ptype); diff --git a/test/test.vcxproj b/test/test.vcxproj index e4b0b3f8..277f9779 100644 --- a/test/test.vcxproj +++ b/test/test.vcxproj @@ -167,6 +167,7 @@ + diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters index fc1fde8c..39d8390e 100644 --- a/test/test.vcxproj.filters +++ b/test/test.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + diff --git a/test/test_enforcer.cpp b/test/test_enforcer.cpp new file mode 100644 index 00000000..59f60aee --- /dev/null +++ b/test/test_enforcer.cpp @@ -0,0 +1,116 @@ +#pragma once + +#include "pch.h" + +#include +#include + +#include +#include +#include +#include + +using namespace std; + +namespace test_enforcer +{ + TEST_CLASS(TestEnforcer) + { + public: + + string filePath(string filepath) { + char* root = _getcwd(NULL, 0); + string rootStr = string(root); + + vector directories = Split(rootStr, "\\", -1); + vector::iterator it = find(directories.begin(), directories.end(), "x64"); + vector left{ *(it - 1) }; + it = find_end(directories.begin(), directories.end(), left.begin(), left.end()); + int index = int(directories.size() + (it - directories.end())); + + vector finalDirectories(directories.begin(), directories.begin() + index + 1); + + vector userD = Split(filepath, "/", -1); + for (int i = 1; i < userD.size(); i++) + finalDirectories.push_back(userD[i]); + + string filepath1 = finalDirectories[0]; + for (int i = 1; i < finalDirectories.size(); i++) + filepath1 = filepath1 + "/" + finalDirectories[i]; + return filepath1; + } + + void TestEnforce(Enforcer* e, string sub, string dom, string obj, string act, bool res) { + Assert::AreEqual(res, e->Enforce(sub, dom, obj, act)); + } + + void TestEnforce(Enforcer* e, string sub, string obj, string act, bool res) { + Assert::AreEqual(res, e->Enforce(sub, obj, act)); + } + + void TestEnforce(Enforcer* e, string sub, string act, bool res) { + Assert::AreEqual(res, e->Enforce(sub, act)); + } + + void TestEnforce(Enforcer* e, vector params, bool res) { + Assert::AreEqual(res, e->Enforce(params)); + } + + + TEST_METHOD(TestFourParams) { + string model = filePath("../examples/rbac_with_domains_model.conf"); + string policy = filePath("../examples/rbac_with_domains_policy.csv"); + Enforcer* e = Enforcer::NewEnforcer(model, policy); + + TestEnforce(e, "alice", "domain1", "data1", "read", true); + TestEnforce(e, "alice", "domain1", "data1", "write", true); + TestEnforce(e, "alice", "domain1", "data2", "read", false); + TestEnforce(e, "alice", "domain1", "data2", "write", false); + TestEnforce(e, "bob", "domain2", "data1", "read", false); + TestEnforce(e, "bob", "domain2", "data1", "write", false); + TestEnforce(e, "bob", "domain2", "data2", "read", true); + TestEnforce(e, "bob", "domain2", "data2", "write", true); + } + + TEST_METHOD(TestThreeParams) { + string model = filePath("../examples/basic_model_without_spaces.conf"); + string policy = filePath("../examples/basic_policy.csv"); + Enforcer* e = Enforcer::NewEnforcer(model, policy); + + TestEnforce(e, "alice", "data1", "read", true); + TestEnforce(e, "alice", "data1", "write", false); + TestEnforce(e, "alice", "data2", "read", false); + TestEnforce(e, "alice", "data2", "write", false); + TestEnforce(e, "bob", "data1", "read", false); + TestEnforce(e, "bob", "data1", "write", false); + TestEnforce(e, "bob", "data2", "read", false); + TestEnforce(e, "bob", "data2", "write", true); + } + + TEST_METHOD(TestTwoParams) { + string model = filePath("../examples/basic_without_users_model.conf"); + string policy = filePath("../examples/basic_without_users_policy.csv"); + Enforcer* e = Enforcer::NewEnforcer(model, policy); + + TestEnforce(e, "data1", "read", true); + TestEnforce(e, "data1", "write", false); + TestEnforce(e, "data2", "read", false); + TestEnforce(e, "data2", "write", true); + } + + TEST_METHOD(TestVectorParams) { + string model = filePath("../examples/basic_model_without_spaces.conf"); + string policy = filePath("../examples/basic_policy.csv"); + Enforcer* e = Enforcer::NewEnforcer(model, policy); + + TestEnforce(e, { "alice", "data1", "read" }, true); + TestEnforce(e, { "alice", "data1", "write" }, false); + TestEnforce(e, {"alice", "data2", "read" }, false); + TestEnforce(e, {"alice", "data2", "write" }, false); + TestEnforce(e, {"bob", "data1", "read" }, false); + TestEnforce(e, {"bob", "data1", "write" }, false); + TestEnforce(e, {"bob", "data2", "read" }, false); + TestEnforce(e, {"bob", "data2", "write" }, true); + } + }; +} \ No newline at end of file