From 1350a7cdc757dc6e0b470ff136e9120c8e89be80 Mon Sep 17 00:00:00 2001
From: ljyofme <2477354249@qq.com>
Date: Wed, 24 Apr 2024 22:10:47 +0800
Subject: [PATCH] feat: update the Multi-threaded feature parity with go
 version of Casbin

---
 casbin/enforcer_synced.cpp       | 77 +++++++++++++++++++++++++++++++-
 include/casbin/enforcer_synced.h | 36 ++++++++++++++-
 tests/enforcer_synced_test.cpp   | 23 ++++++++++
 3 files changed, 134 insertions(+), 2 deletions(-)

diff --git a/casbin/enforcer_synced.cpp b/casbin/enforcer_synced.cpp
index 44560353..cf8c1c7d 100644
--- a/casbin/enforcer_synced.cpp
+++ b/casbin/enforcer_synced.cpp
@@ -513,6 +513,81 @@ bool SyncedEnforcer ::RemoveFilteredNamedGroupingPolicy(const std::string& ptype
     return Enforcer::RemoveFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues);
 }
 
+// GetAllActions gets the list of actions that show up in the current policy.
+std::vector<std::string> SyncedEnforcer::GetAllActions() {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::GetAllActions();
+}
+
+// GetFilteredPolicy gets all the authorization rules in the policy, field filters can be specified.
+PoliciesValues SyncedEnforcer::GetFilteredPolicy(int fieldIndex, std::vector<std::string> fieldValues) {
+   std::unique_lock<std::shared_mutex> lock(policyMutex);
+   return Enforcer::GetFilteredPolicy(fieldIndex, fieldValues);
+}
+
+// EnforceExWithMatcher use a custom matcher and explain enforcement by informing matched rules.
+bool SyncedEnforcer::SyncedEnforceExWithMatcher(const std::string& matcher, std::shared_ptr<IEvaluator> evalator, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceExWithMatcher(matcher, evalator, explain);
+}
+
+bool SyncedEnforcer::SyncedEnforceExWithMatcher(const std::string& matcher, const DataList& params, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceExWithMatcher(matcher, params, explain);
+}
+
+bool SyncedEnforcer::SyncedEnforceExWithMatcher(const std::string& matcher, const DataVector& params, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceExWithMatcher(matcher, params, explain);
+}
+
+bool SyncedEnforcer::SyncedEnforceExWithMatcher(const std::string& matcher, const DataMap& params, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceExWithMatcher(matcher, params, explain);
+}
+
+// EnforceEx explain enforcement by informing matched rules.
+bool SyncedEnforcer::SyncedEnforceEx(std::shared_ptr<IEvaluator> evalator, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceEx(evalator, explain);
+}
+
+bool SyncedEnforcer::SyncedEnforceEx(const DataList& params, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceEx(params, explain);
+}
+
+bool SyncedEnforcer::SyncedEnforceEx(const DataVector& params, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceEx(params, explain);
+}
+
+bool SyncedEnforcer::SyncedEnforceEx(const DataMap& params, std::vector<std::string>& explain) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceEx(params, explain);
+}
+
+// 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 SyncedEnforcer::SyncedEnforceWithMatcher(const std::string& matcher, std::shared_ptr<IEvaluator> evalator) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceWithMatcher(matcher, evalator);
+}
+
+bool SyncedEnforcer::SyncedEnforceWithMatcher(const std::string& matcher, const DataList& params) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceWithMatcher(matcher, params);
+}
+
+bool SyncedEnforcer::SyncedEnforceWithMatcher(const std::string& matcher, const DataVector& params) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceWithMatcher(matcher, params);
+}
+
+bool SyncedEnforcer::SyncedEnforceWithMatcher(const std::string& matcher, const DataMap& params) {
+    std::unique_lock<std::shared_mutex> lock(policyMutex);
+    return Enforcer::EnforceWithMatcher(matcher, params);
+}
+
 } // namespace casbin
 
-#endif // ENFORCER_SYNCED_CPP
+#endif // ENFORCER_SYNCED_CPP
\ No newline at end of file
diff --git a/include/casbin/enforcer_synced.h b/include/casbin/enforcer_synced.h
index 45103c5f..163c21f0 100644
--- a/include/casbin/enforcer_synced.h
+++ b/include/casbin/enforcer_synced.h
@@ -292,8 +292,42 @@ class SyncedEnforcer : public Enforcer {
 
     // RemoveFilteredNamedGroupingPolicy removes a role inheritance rule from the current named policy, field filters can be specified.
     bool RemoveFilteredNamedGroupingPolicy(const std::string& ptype, int fieldIndex, const std::vector<std::string>& fieldValues) override;
+
+    // GetAllActions gets the list of actions that show up in the current policy.
+
+    std::vector<std::string> GetAllActions();
+
+    // GetFilteredPolicy gets all the authorization rules in the policy, field filters can be specified.
+    PoliciesValues GetFilteredPolicy(int fieldIndex, std::vector<std::string> fieldValues);
+
+    // EnforceExWithMatcher use a custom matcher and explain enforcement by informing matched rules.
+    bool SyncedEnforceExWithMatcher(const std::string& matcher, std::shared_ptr<IEvaluator> evalator, std::vector<std::string>& explain);
+
+    bool SyncedEnforceExWithMatcher(const std::string& matcher, const DataList& params, std::vector<std::string>& explain);
+
+    bool SyncedEnforceExWithMatcher(const std::string& matcher, const DataVector& params, std::vector<std::string>& explain);
+
+    bool SyncedEnforceExWithMatcher(const std::string& matcher, const DataMap& params, std::vector<std::string>& explain);
+
+    // EnforceEx explain enforcement by informing matched rules.
+    bool SyncedEnforceEx(std::shared_ptr<IEvaluator> evalator, std::vector<std::string>& explain);
+
+    bool SyncedEnforceEx(const DataList& params, std::vector<std::string>& explain);
+
+    bool SyncedEnforceEx(const DataVector& params, std::vector<std::string>& explain);
+
+    bool SyncedEnforceEx(const DataMap& params, std::vector<std::string>& explain);
+
+    // 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
+    bool SyncedEnforceWithMatcher(const std::string& matcher, std::shared_ptr<IEvaluator> evalator);
+
+    bool SyncedEnforceWithMatcher(const std::string& matcher, const DataList& params);
+
+    bool SyncedEnforceWithMatcher(const std::string& matcher, const DataVector& params);
+
+    bool SyncedEnforceWithMatcher(const std::string& matcher, const DataMap& params);
 };
 
 } // namespace casbin
 
-#endif
+#endif
\ No newline at end of file
diff --git a/tests/enforcer_synced_test.cpp b/tests/enforcer_synced_test.cpp
index c96db25c..33936a1b 100644
--- a/tests/enforcer_synced_test.cpp
+++ b/tests/enforcer_synced_test.cpp
@@ -334,4 +334,27 @@ TEST(TestEnforcerSynced, TestMultiThreadBatchEnforce) {
     EXPECT_EQ(e.IsAutoLoadingRunning(), false);
 }
 
+void testSyncedEnforcerGetPolicy(casbin::SyncedEnforcer& e, const std::vector<std::vector<std::string>>& res) {
+    auto myRes = e.GetPolicy();
+
+    ASSERT_EQ(res, myRes);
+}
+
+TEST(TestSyncedEnforcer, GetPolicy) {
+    casbin::SyncedEnforcer e("examples/basic_model.conf", "examples/basic_policy.csv");
+
+    std::vector<std::vector<std::string>> expected_policy = {
+        {"alice", "data1", "read"},
+        {"bob", "data2", "write"},
+        {"user1", "data1", "read"},
+        {"user2", "data2", "read"},
+        {"user3", "data3", "read"},
+        {"user4", "data4", "read"},
+        {"user5", "data5", "read"},
+        {"user6", "data6", "read"},
+    };
+
+    testSyncedEnforcerGetPolicy(e, expected_policy);
+}
+
 } // namespace