Skip to content

Commit 0fdacfa

Browse files
authored
Merge pull request #122 from EmperorYP7/abac
feat: Streamlined types
2 parents dbb4d24 + 27ac2bd commit 0fdacfa

16 files changed

+271
-137
lines changed

casbin/abac_data.cpp

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,35 +24,22 @@
2424

2525
namespace casbin {
2626

27-
/**
28-
* @brief Get casbin::ABACData object
29-
*
30-
* @param attribs Should be of the format: {
31-
* { "attrib_name1", value1 },
32-
* { "attrib_name2", value2 },
33-
* ...
34-
* }
35-
*
36-
* Key's type is std::string and value's type can be one of std::string, int32_t, and float only
37-
* @return Pointer to casbin::ABACData entity
38-
*/
39-
const std::shared_ptr<ABACData> GetData(const ABACData::VariantMap& attribs) {
27+
const std::shared_ptr<ABACData> GetDataObject(const AttributeMap& attribs) {
4028
return std::make_shared<ABACData>(attribs);
4129
}
4230

43-
ABACData::ABACData(const VariantMap& attrib)
44-
: m_attributes(attrib)
31+
ABACData::ABACData(const AttributeMap& attribs)
32+
: m_attributes(std::move(attribs))
4533
{}
4634

47-
bool ABACData::AddAttribute(const std::string& key, const VariantType& value) {
35+
bool ABACData::AddAttribute(const std::string& key, const AttributeValue& value) {
4836
m_attributes[key] = value;
4937
return true;
5038
}
5139

52-
bool ABACData::AddAttributes(const VariantMap& attribs) {
53-
for(auto attrib : attribs) {
54-
m_attributes[attrib.first] = attrib.second;
55-
}
40+
bool ABACData::AddAttributes(const AttributeList& attribs) {
41+
for(auto [name, value] : attribs)
42+
m_attributes[name] = value;
5643
return true;
5744
}
5845

@@ -68,12 +55,12 @@ bool ABACData::DeleteAttribute(const std::string& key) {
6855
return true;
6956
}
7057

71-
bool ABACData::UpdateAttribute(const std::string& key, const VariantType& value) {
58+
bool ABACData::UpdateAttribute(const std::string& key, const AttributeValue& value) {
7259
m_attributes[key] = value;
7360
return true;
7461
}
7562

76-
const ABACData::VariantMap& ABACData::GetAttributes() {
63+
const AttributeMap& ABACData::GetAttributes() {
7764
return m_attributes;
7865
}
7966

casbin/abac_data.h

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@
1717
#ifndef ABAC_H
1818
#define ABAC_H
1919

20-
#include <unordered_map>
21-
#include <string>
22-
#include <vector>
23-
#include <variant>
24-
#include <memory>
20+
#include "attribute_types.h"
2521

2622
namespace casbin {
2723

@@ -31,16 +27,10 @@ namespace casbin {
3127
*/
3228
class ABACData {
3329

34-
public:
35-
36-
// Intrinsic definitions
37-
typedef std::variant<std::string, int32_t, float> VariantType;
38-
typedef std::unordered_map<std::string, VariantType> VariantMap;
39-
4030
private:
4131

4232
// HashMap containing attributes as key-value pairs
43-
VariantMap m_attributes;
33+
AttributeMap m_attributes;
4434

4535
public:
4636
/**
@@ -54,15 +44,15 @@ class ABACData {
5444
*
5545
* Key's type is std::string and value's type can be one of std::string, int32_t, and float only
5646
*/
57-
ABACData(const VariantMap& attribs);
47+
ABACData(const AttributeMap& attribs);
5848
/**
5949
* @brief Add attribute to the corresponding ABAC entity
6050
*
6151
* @param key Name of the attribute
6252
* @param value Value of the attribute
6353
* @return true when attribute is added successfully, false otherwise
6454
*/
65-
bool AddAttribute(const std::string& key, const VariantType& value);
55+
bool AddAttribute(const std::string& key, const AttributeValue& value);
6656
/**
6757
* @brief Add attributes to the corresponding ABAC entity
6858
*
@@ -75,7 +65,7 @@ class ABACData {
7565
* Key's type is std::string and value's type can be one of std::string, int32_t, and float only
7666
* @return true if attributes are added successfully, false otherwise
7767
*/
78-
bool AddAttributes(const VariantMap& attribs);
68+
bool AddAttributes(const AttributeList& attribs);
7969
/**
8070
* @brief Delete attribute of the corresponding ABAC entity
8171
*
@@ -92,19 +82,31 @@ class ABACData {
9282
* @return true
9383
* @return false
9484
*/
95-
bool UpdateAttribute(const std::string& key, const VariantType& value);
85+
bool UpdateAttribute(const std::string& key, const AttributeValue& value);
9686
/**
9787
* @brief Get the Attributes of the corresponding ABAC entity
9888
*
9989
* @return const reference to the hashmap containing attributes in key-value pairs
10090
*/
101-
const VariantMap& GetAttributes();
91+
const AttributeMap& GetAttributes();
10292
};
10393

10494
// Casbin ABAC entity type
10595
typedef ABACData ABACData;
10696

107-
const std::shared_ptr<ABACData> GetData(const ABACData::VariantMap& attribs);
97+
/**
98+
* @brief Get casbin::ABACData object
99+
*
100+
* @param attribs Should be of the format: {
101+
* { "attrib_name1", value1 },
102+
* { "attrib_name2", value2 },
103+
* ...
104+
* }
105+
*
106+
* Key's type is std::string and value's type can be one of std::string, int32_t, double, and float only
107+
* @return Pointer to casbin::ABACData entity
108+
*/
109+
const std::shared_ptr<ABACData> GetDataObject(const AttributeMap& attribs);
108110
}
109111

110112
#endif

casbin/attribute_types.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2021 The casbin Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <variant>
18+
#include <vector>
19+
#include <initializer_list>
20+
#include <unordered_map>
21+
#include <memory>
22+
23+
namespace casbin {
24+
25+
typedef std::variant<std::string, int32_t, float, double> AttributeValue;
26+
typedef std::pair<std::string, AttributeValue> Attribute;
27+
typedef std::vector<Attribute> AttributeVector;
28+
typedef std::initializer_list<Attribute> AttributeList;
29+
typedef std::unordered_map<std::string, AttributeValue> AttributeMap;
30+
31+
} // namespace casbin

casbin/data_types.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2021 The casbin Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <variant>
18+
#include <vector>
19+
#include <initializer_list>
20+
#include <unordered_map>
21+
#include "abac_data.h"
22+
23+
namespace casbin {
24+
25+
typedef std::variant<std::string, std::shared_ptr<ABACData>> Data;
26+
typedef std::vector<Data> DataVector;
27+
typedef std::initializer_list<Data> DataList;
28+
typedef std::unordered_map<std::string, Data> DataMap;
29+
30+
} // namespace casbin

casbin/enforcer.cpp

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -435,12 +435,12 @@ bool Enforcer :: Enforce(Scope scope) {
435435
}
436436

437437
// Enforce with a vector param,decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
438-
bool Enforcer::Enforce(const std::vector<std::string>& params) {
438+
bool Enforcer::Enforce(const DataList& params) {
439439
return this->EnforceWithMatcher("", params);
440440
}
441441

442442
// Enforce with a map param,decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
443-
bool Enforcer::Enforce(const std::unordered_map<std::string, std::string>& params) {
443+
bool Enforcer::Enforce(const DataMap& params) {
444444
return this->EnforceWithMatcher("", params);
445445
}
446446

@@ -450,22 +450,55 @@ bool Enforcer :: EnforceWithMatcher(const std::string& matcher, Scope scope) {
450450
}
451451

452452
// 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 "".
453-
bool Enforcer::EnforceWithMatcher(const std::string& matcher, const std::vector<std::string>& params) {
454-
std::vector<std::string> r_tokens = m_model->m["r"].assertion_map["r"]->tokens;
453+
bool Enforcer::EnforceWithMatcher(const std::string& matcher, const DataList& params) {
454+
const std::vector<std::string>& r_tokens = m_model->m["r"].assertion_map["r"]->tokens;
455455

456-
int r_cnt = int(r_tokens.size());
457-
int cnt = int(params.size());
456+
size_t r_cnt = r_tokens.size();
457+
size_t cnt = params.size();
458458

459459
if (cnt != r_cnt)
460460
return false;
461461

462462
Scope scope = InitializeScope();
463463
PushObject(scope, "r");
464464

465-
for (int i = 0; i < cnt; i++) {
466-
PushStringPropToObject(scope, "r", params[i], r_tokens[i].substr(2, r_tokens[i].size() - 2));
465+
size_t i = 0;
466+
467+
for(const auto& param : params) {
468+
if(const auto string_param = std::get_if<std::string>(&param)) {
469+
PushStringPropToObject(scope, "r", *string_param, r_tokens[i].substr(2, r_tokens[i].size() - 2));
470+
}
471+
else if(const auto abac_param = std::get_if<std::shared_ptr<ABACData>>(&param)) {
472+
auto data_ptr = *abac_param;
473+
std::string token_name = r_tokens[i].substr(2, r_tokens[i].size() - 2);
474+
475+
PushObjectPropToObject(scope, "r", token_name);
476+
477+
for(auto [attrib_name, attrib_value] : data_ptr->GetAttributes()) {
478+
479+
if(const auto string_value = std::get_if<std::string>(&attrib_value))
480+
PushStringPropToObject(scope, token_name, *string_value, attrib_name);
481+
482+
else if(const auto int_value = std::get_if<int32_t>(&attrib_value))
483+
PushIntPropToObject(scope, token_name, *int_value, attrib_name);
484+
485+
else if(const auto float_value = std::get_if<float>(&attrib_value))
486+
PushFloatPropToObject(scope, token_name, *float_value, attrib_name);
487+
488+
else if(const auto double_value = std::get_if<double>(&attrib_value))
489+
PushDoublePropToObject(scope, token_name, *double_value, attrib_name);
490+
491+
else
492+
throw CasbinEnforcerException("Not a valid type");
493+
}
494+
}
495+
++i;
467496
}
468497

498+
// for (size_t i = 0; i < cnt; i++) {
499+
// PushStringPropToObject(scope, "r", params[i], r_tokens[i].substr(2, r_tokens[i].size() - 2));
500+
// }
501+
469502
bool result = m_enforce(matcher, scope);
470503
DeinitializeScope(scope);
471504
return result;
@@ -474,12 +507,36 @@ bool Enforcer::EnforceWithMatcher(const std::string& matcher, const std::vector<
474507
// EnforceWithMatcher use a custom matcher to decides whether a "subject" can access a "object"
475508
// with the operation "action", input parameters are usually: (matcher, sub, obj, act),
476509
// use model matcher by default when matcher is "".
477-
bool Enforcer::EnforceWithMatcher(const std::string& matcher, const std::unordered_map<std::string, std::string>& params) {
510+
bool Enforcer::EnforceWithMatcher(const std::string& matcher, const DataMap& params) {
478511
Scope scope = InitializeScope();
479512
PushObject(scope, "r");
480513

481-
for (auto r : params) {
482-
PushStringPropToObject(scope, "r", r.second, r.first);
514+
for (auto [param_name, param_data] : params) {
515+
if(const auto string_param = std::get_if<std::string>(&param_data))
516+
PushStringPropToObject(scope, "r", *string_param, param_name);
517+
else if(const auto abac_param = std::get_if<std::shared_ptr<ABACData>>(&param_data)) {
518+
auto data_ptr = *abac_param;
519+
520+
PushObjectPropToObject(scope, "r", param_name);
521+
522+
for(auto [attrib_name, attrib_value] : data_ptr->GetAttributes()) {
523+
524+
if(const auto string_value = std::get_if<std::string>(&attrib_value))
525+
PushStringPropToObject(scope, param_name, *string_value, attrib_name);
526+
527+
else if(const auto int_value = std::get_if<int32_t>(&attrib_value))
528+
PushIntPropToObject(scope, param_name, *int_value, attrib_name);
529+
530+
else if(const auto float_value = std::get_if<float>(&attrib_value))
531+
PushFloatPropToObject(scope, param_name, *float_value, attrib_name);
532+
533+
else if(const auto double_value = std::get_if<double>(&attrib_value))
534+
PushDoublePropToObject(scope, param_name, *double_value, attrib_name);
535+
536+
else
537+
throw CasbinEnforcerException("Not a valid type");
538+
}
539+
}
483540
}
484541

485542
bool result = m_enforce(matcher, scope);
@@ -488,21 +545,21 @@ bool Enforcer::EnforceWithMatcher(const std::string& matcher, const std::unorder
488545
}
489546

490547
// BatchEnforce enforce in batches
491-
std::vector<bool> Enforcer :: BatchEnforce(const std::vector<std::vector<std::string>>& requests) {
548+
std::vector<bool> Enforcer :: BatchEnforce(const std::initializer_list<DataList>& requests) {
492549
// Initializing an array for storing results with false
493550
std::vector<bool> results;
494551
results.reserve(requests.size());
495-
for (auto request : requests) {
552+
for (const auto& request : requests) {
496553
results.push_back(this->Enforce(request));
497554
}
498555
return results;
499556
}
500557

501558
// BatchEnforceWithMatcher enforce with matcher in batches
502-
std::vector<bool> Enforcer :: BatchEnforceWithMatcher(const std::string& matcher, const std::vector<std::vector<std::string>>& requests) {
559+
std::vector<bool> Enforcer :: BatchEnforceWithMatcher(const std::string& matcher, const std::initializer_list<DataList>& requests) {
503560
std::vector<bool> results;
504561
results.reserve(requests.size());
505-
for (auto request : requests) {
562+
for (const auto& request : requests) {
506563
results.push_back(this->EnforceWithMatcher(matcher, request));
507564
}
508565
return results;

casbin/enforcer.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,19 +156,19 @@ class Enforcer : public IEnforcer {
156156
// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
157157
bool Enforce(Scope scope);
158158
// Enforce with a vector param,decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
159-
bool Enforce(const std::vector<std::string>& params);
159+
bool Enforce(const DataList& params);
160160
// Enforce with a map param,decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
161-
bool Enforce(const std::unordered_map<std::string,std::string>& params);
161+
bool Enforce(const DataMap& params);
162162
// 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 "".
163163
bool EnforceWithMatcher(const std::string& matcher, Scope scope);
164164
// 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 "".
165-
bool EnforceWithMatcher(const std::string& matcher, const std::vector<std::string>& params);
165+
bool EnforceWithMatcher(const std::string& matcher, const DataList& params);
166166
// 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 "".
167-
bool EnforceWithMatcher(const std::string& matcher, const std::unordered_map<std::string, std::string>& params);
167+
bool EnforceWithMatcher(const std::string& matcher, const DataMap& params);
168168
// BatchEnforce enforce in batches
169-
std::vector<bool> BatchEnforce(const std::vector<std::vector<std::string>>& requests);
169+
std::vector<bool> BatchEnforce(const std::initializer_list<DataList>& requests);
170170
// BatchEnforceWithMatcher enforce with matcher in batches
171-
std::vector<bool> BatchEnforceWithMatcher(const std::string& matcher, const std::vector<std::vector<std::string>>& requests);
171+
std::vector<bool> BatchEnforceWithMatcher(const std::string& matcher, const std::initializer_list<DataList>& requests);
172172

173173
/*Management API member functions.*/
174174
std::vector<std::string> GetAllSubjects();

0 commit comments

Comments
 (0)