diff --git a/casbin/casbin.vcxproj b/casbin/casbin.vcxproj index e9ee4d5f..ac39d519 100644 --- a/casbin/casbin.vcxproj +++ b/casbin/casbin.vcxproj @@ -198,7 +198,6 @@ - @@ -281,7 +280,6 @@ - diff --git a/casbin/casbin.vcxproj.filters b/casbin/casbin.vcxproj.filters index c28bc8c8..65149081 100644 --- a/casbin/casbin.vcxproj.filters +++ b/casbin/casbin.vcxproj.filters @@ -216,9 +216,6 @@ Source Files\rbac - - Source Files\rbac - Source Files\persist\file_adapter @@ -287,9 +284,6 @@ Header Files\rbac - - Header Files\rbac - Header Files\rbac diff --git a/casbin/ip_parser/parser/IP.cpp b/casbin/ip_parser/parser/IP.cpp index 76766485..800425fe 100644 --- a/casbin/ip_parser/parser/IP.cpp +++ b/casbin/ip_parser/parser/IP.cpp @@ -13,15 +13,19 @@ IP :: IP() { } IP IP :: Mask(IPMask mask) { - IPMask mask_2(mask.begin(), mask.begin()+12); - if(mask.size() == IPv6len && ip.size() == IPv4len && allFF(mask_2)) { - IPMask mask_3(mask.begin() + 12, mask.end()); - mask = mask_3; + if (mask.size() == IPv6len && ip.size() == IPv4len) { + IPMask mask_2(mask.begin(), mask.begin() + 12); + if (allFF(mask_2)) { + IPMask mask_3(mask.begin() + 12, mask.end()); + mask = mask_3; + } } - IPMask ip_2(ip.begin(), ip.begin() + 12); - if(mask.size() == IPv4len && ip.size() == IPv6len && equal(ip_2, v4InV6Prefix)) { - IPMask ip_3(ip.begin() + 12, ip.end()); - ip = ip_3; + if (mask.size() == IPv4len && ip.size() == IPv6len) { + IPMask ip_2(ip.begin(), ip.begin() + 12); + if (equal(ip_2, v4InV6Prefix)) { + IPMask ip_3(ip.begin() + 12, ip.end()); + ip = ip_3; + } } unsigned int n = int(ip.size()); if(n != mask.size()) { diff --git a/casbin/rbac.h b/casbin/rbac.h index bf6c43b9..b8cbab3f 100644 --- a/casbin/rbac.h +++ b/casbin/rbac.h @@ -2,7 +2,6 @@ #define CASBIN_CPP_RBAC #include "./rbac/default_role_manager.h" -#include "./rbac/group_role_manager.h" #include "./rbac/role_manager.h" #endif \ No newline at end of file diff --git a/casbin/rbac/default_role_manager.cpp b/casbin/rbac/default_role_manager.cpp index 5e48a809..e6c227e6 100644 --- a/casbin/rbac/default_role_manager.cpp +++ b/casbin/rbac/default_role_manager.cpp @@ -21,9 +21,9 @@ void Role :: AddRole(Role* role) { } void Role :: DeleteRole(Role* role) { - for (vector :: iterator it = roles.begin() ; it != roles.end() ; it++) { - if (!(*it)->name.compare(role->name)) { - roles.erase(it); + for (int i = 0; i < roles.size();i++) { + if (!roles[i]->name.compare(role->name)) { + roles.erase(roles.begin()+i); } } } diff --git a/casbin/rbac/default_role_manager.h b/casbin/rbac/default_role_manager.h index 82e74571..136335dd 100644 --- a/casbin/rbac/default_role_manager.h +++ b/casbin/rbac/default_role_manager.h @@ -69,28 +69,28 @@ class DefaultRoleManager : public RoleManager { // AddLink adds the inheritance link between role: name1 and role: name2. // aka role: name1 inherits role: name2. // domain is a prefix to the roles. - void AddLink(string name1, string name2, vector domain); + void AddLink(string name1, string name2, vector domain = vector{}); /** * deleteLink deletes the inheritance link between role: name1 and role: name2. * aka role: name1 does not inherit role: name2 any more. * domain is a prefix to the roles. */ - void DeleteLink(string name1, string name2, vector domain); + void DeleteLink(string name1, string name2, vector domain = vector{}); /** * hasLink determines whether role: name1 inherits role: name2. * domain is a prefix to the roles. */ - bool HasLink(string name1, string name2, vector domain); + bool HasLink(string name1, string name2, vector domain = vector{}); /** * getRoles gets the roles that a subject inherits. * domain is a prefix to the roles. */ - vector GetRoles(string name, vector domain); + vector GetRoles(string name, vector domain = vector{}); - vector GetUsers(string name, vector domain); + vector GetUsers(string name, vector domain = vector{}); /** * printRoles prints all the roles to log. diff --git a/casbin/rbac/group_role_manager.cpp b/casbin/rbac/group_role_manager.cpp deleted file mode 100644 index 74c44912..00000000 --- a/casbin/rbac/group_role_manager.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "pch.h" - -#include "./group_role_manager.h" -#include "../exception/casbin_rbac_exception.h" - -/** - * GroupRoleManager is the constructor for creating an instance of the - * GroupRoleManager implementation. - * - * @param max_hierarchy_level the maximized allowed RBAC hierarchy level. - */ -GroupRoleManager* GroupRoleManager :: NewGroupRoleManager(int max_hierarchy_level){ - return (GroupRoleManager*)NewRoleManager(max_hierarchy_level); -} - -/** - * hasLink determines whether role: name1 inherits role: name2. - * domain is a prefix to the roles. - */ -bool GroupRoleManager :: HasLink(string name1, string name2, vector domain) { - if (DefaultRoleManager :: HasLink(name1, name2, domain)) { - return true; - } - unsigned int domain_length = sizeof(domain) / sizeof(domain[0]); - // check name1's groups - if (domain_length == 1) { - try { - vector domain1; - vector groups = DefaultRoleManager :: GetRoles(name1, domain1); - for (vector :: iterator group = groups.begin() ; group < groups.end() ; group++) { - if (DefaultRoleManager :: HasLink(*group, name2, domain)) { - return true; - } - } - } catch (CasbinRBACException ignore) { - return false; - } - } - return false; -} \ No newline at end of file diff --git a/casbin/rbac/group_role_manager.h b/casbin/rbac/group_role_manager.h deleted file mode 100644 index c3e935d0..00000000 --- a/casbin/rbac/group_role_manager.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CASBIN_CPP_RBAC_GROUP_ROLE_MANAGER -#define CASBIN_CPP_RBAC_GROUP_ROLE_MANAGER - -#include "./default_role_manager.h" - -/** - * GroupRoleManager is used for authorization if the user's group is the role who has permission, - * but the group information is in the default format (policy start with "g") and the role information - * is in named format (policy start with "g2", "g3", ...). - * e.g. - * p, admin, domain1, data1, read - * g, alice, group1 - * g2, group1, admin, domain1 - * - * As for the previous example, alice should have the permission to read data1, but if we use the - * DefaultRoleManager, it will return false. - * GroupRoleManager is to handle this situation. - */ -class GroupRoleManager : public DefaultRoleManager { - public: - /** - * GroupRoleManager is the constructor for creating an instance of the - * GroupRoleManager implementation. - * - * @param max_hierarchy_level the maximized allowed RBAC hierarchy level. - */ - static GroupRoleManager* NewGroupRoleManager(int max_hierarchy_level); - - /** - * hasLink determines whether role: name1 inherits role: name2. - * domain is a prefix to the roles. - */ - bool HasLink(string name1, string name2, vector domain); -}; - -#endif \ No newline at end of file diff --git a/casbin/rbac/role_manager.h b/casbin/rbac/role_manager.h index 0c90ccd7..2aa71d0e 100644 --- a/casbin/rbac/role_manager.h +++ b/casbin/rbac/role_manager.h @@ -6,65 +6,28 @@ using namespace std; +// RoleManager provides interface to define the operations for managing roles. class RoleManager { public: - /** - * Clear clears all stored data and resets the role manager to the initial state. - */ - virtual void Clear() = 0; - - /** - * AddLink adds the inheritance link between two roles. role: name1 and role: name2. - * domain is a prefix to the roles. - * - * @param name1 the first role (or user). - * @param name2 the second role. - * @param domain the domain the roles belong to. - */ - virtual void AddLink(string name1, string name2, vector domain) = 0; - - /** - * DeleteLink deletes the inheritance link between two roles. role: name1 and role: name2. - * domain is a prefix to the roles. - * - * @param name1 the first role (or user). - * @param name2 the second role. - * @param domain the domain the roles belong to. - */ - virtual void DeleteLink(string name1, string name2, vector domain) = 0; - - /** - * hasLink determines whether a link exists between two roles. role: name1 inherits role: name2. - * domain is a prefix to the roles. - * - * @param name1 the first role (or a user). - * @param name2 the second role. - * @param domain the domain the roles belong to. - * @return whether name1 inherits name2 (name1 has role name2). - */ - virtual bool HasLink(string name1, string name2, vector domain) = 0; - - /** - * GetRoles gets the roles that a user inherits. - * domain is a prefix to the roles. - * - * @param name the user (or a role). - * @param domain the domain the roles belong to. - * @return the roles. - */ - virtual vector GetRoles(string name, vector domain) = 0; - - /** - * GetUsers gets the users that inherits a role. - * @param name the role. - * @return the users. - */ - virtual vector GetUsers(string name, vector domain) = 0; - - /** - * PrintRoles prints all the roles to log. - */ - virtual void PrintRoles() = 0; + // Clear clears all stored data and resets the role manager to the initial state. + virtual void Clear() = 0; + // AddLink adds the inheritance link between two roles. role: name1 and role: name2. + // domain is a prefix to the roles (can be used for other purposes). + virtual void AddLink(string name1, string name2, vector domain = vector{}) = 0; + // DeleteLink deletes the inheritance link between two roles. role: name1 and role: name2. + // domain is a prefix to the roles (can be used for other purposes). + virtual void DeleteLink(string name1, string name2, vector domain = vector{}) = 0; + // HasLink determines whether a link exists between two roles. role: name1 inherits role: name2. + // domain is a prefix to the roles (can be used for other purposes). + virtual bool HasLink(string name1, string name2, vector domain = vector{}) = 0; + // GetRoles gets the roles that a user inherits. + // domain is a prefix to the roles (can be used for other purposes). + virtual vector GetRoles(string name, vector domain = vector{}) = 0; + // GetUsers gets the users that inherits a role. + // domain is a prefix to the users (can be used for other purposes). + virtual vector GetUsers(string name, vector domain = vector{}) = 0; + // PrintRoles prints all the roles to log. + virtual void PrintRoles() = 0; }; #endif \ No newline at end of file diff --git a/casbin/util/built_in_functions.cpp b/casbin/util/built_in_functions.cpp index fe9edd2c..ffce2f5d 100644 --- a/casbin/util/built_in_functions.cpp +++ b/casbin/util/built_in_functions.cpp @@ -43,28 +43,47 @@ ReturnType KeyMatch2(Scope scope) { string key1 = GetString(scope, 0); string key2 = GetString(scope, 1); - vector indexes = FindAllOccurences(key2, "/*"); - for (int i = 0 ; i < indexes.size() ; i++) { - key1.replace(indexes[i], 2, "/.*"); - } - - regex regex_s("(.*):[^/]+(.*)"); - smatch match; - - while (true) { + vector key1_arr = Split(key1, "/"); + vector key2_arr = Split(key2, "/"); - if (key2.find("/:") == string::npos) + bool res = true; + for(int i=0;i= key1_arr.size()){ + res = false; break; - - if (regex_search(key2, match, regex_s)) { - for (int i=1; i indexes = FindAllOccurences(key2, "/*"); - for (int i = 0 ; i < indexes.size() ; i++) - key1.replace(indexes[i], 2, "/.*"); - - regex regex_s("(.*)\\{[^/]+\\}(.*)"); - smatch match; + vector key1_arr = Split(key1, "/"); + vector key2_arr = Split(key2, "/"); - while (true) { - if (key2.find("/{") == string::npos) + bool res = true; + for(int i=0;i= key1_arr.size()){ + res = false; break; - - if (regex_search(key2, match, regex_s)) { - for (int i=1; i 0 && index3 != string::npos){ + if(key1_arr[i]=="" || !key2_arr[i].substr(1, key2_arr[i].length()-2).compare("")){ + res = false; + break; + } + else + continue; + } + res = false; + break; + }else + continue; } - regex regex_s1("^"+key2+"$"); - PushBooleanValue(scope, regex_match(key1, regex_s1)); + if(key2_arr.size() < key1_arr.size()) + if(key2_arr[key2_arr.size()-1] != "*") + res = false; + + PushBooleanValue(scope, res); return RETURN_RESULT; } @@ -114,13 +156,13 @@ ReturnType IPMatch(Scope scope) { IP objIP1 = parseIP(ip1); if (objIP1.isLegal == false) - IllegalArgumentException("invalid argument: ip1 in IPMatch() function is not an IP address."); + throw IllegalArgumentException("invalid argument: ip1 in IPMatch() function is not an IP address."); CIDR objCIDR = parseCIDR(ip2); if (objCIDR.ip.isLegal == false) { IP objIP2 = parseIP(ip2); if (objIP2.isLegal == false) - IllegalArgumentException("invalid argument: ip1 in IPMatch() function is not an IP address."); + throw IllegalArgumentException("invalid argument: ip1 in IPMatch() function is not an IP address."); PushBooleanValue(scope, objIP1.Equal(objIP2)); return RETURN_RESULT; diff --git a/test/test.vcxproj b/test/test.vcxproj index d08f6b82..cd613c9b 100644 --- a/test/test.vcxproj +++ b/test/test.vcxproj @@ -165,8 +165,10 @@ Create Create + + diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters index 40e42832..01e9d08f 100644 --- a/test/test.vcxproj.filters +++ b/test/test.vcxproj.filters @@ -27,6 +27,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/test/test_built_in_functions.cpp b/test/test_built_in_functions.cpp new file mode 100644 index 00000000..32ead58e --- /dev/null +++ b/test/test_built_in_functions.cpp @@ -0,0 +1,160 @@ +#pragma once + +#include "pch.h" + +#include + +using namespace std; + +namespace test_built_in_functions +{ + TEST_CLASS(TestBuiltInFunctions) + { + public: + void TestKeyMatch(string key1, string key2, bool res) { + Scope scope = InitializeScope(); + PushStringValue(scope, key1); + PushStringValue(scope, key2); + + KeyMatch(scope); + bool my_res = GetBoolean(scope); + + Assert::AreEqual(res, my_res); + } + + TEST_METHOD(TestKeyMatch) { + TestKeyMatch("/foo", "/foo", true); + TestKeyMatch("/foo", "/foo*", true); + TestKeyMatch("/foo", "/foo/*", false); + TestKeyMatch("/foo/bar", "/foo", false); + TestKeyMatch("/foo/bar", "/foo*", true); + TestKeyMatch("/foo/bar", "/foo/*", true); + TestKeyMatch("/foobar", "/foo", false); + TestKeyMatch("/foobar", "/foo*", true); + TestKeyMatch("/foobar", "/foo/*", false); + } + + void TestKeyMatch2(string key1, string key2, bool res) { + Scope scope = InitializeScope(); + PushStringValue(scope, key1); + PushStringValue(scope, key2); + + KeyMatch2(scope); + bool my_res = GetBoolean(scope); + + Assert::AreEqual(res, my_res); + } + + TEST_METHOD(TestKeyMatch2){ + TestKeyMatch2("/foo", "/foo", true); + TestKeyMatch2("/foo", "/foo*", true); + TestKeyMatch2("/foo", "/foo/*", false); + TestKeyMatch2("/foo/bar", "/foo", false); + TestKeyMatch2("/foo/bar", "/foo*", false); // different with KeyMatch. + TestKeyMatch2("/foo/bar", "/foo/*", true); + TestKeyMatch2("/foobar", "/foo", false); + TestKeyMatch2("/foobar", "/foo*", false); // different with KeyMatch. + TestKeyMatch2("/foobar", "/foo/*", false); + + TestKeyMatch2("/", "/:resource", false); + TestKeyMatch2("/resource1", "/:resource", true); + TestKeyMatch2("/myid", "/:id/using/:resId", false); + TestKeyMatch2("/myid/using/myresid", "/:id/using/:resId", true); + + TestKeyMatch2("/proxy/myid", "/proxy/:id/*", false); + TestKeyMatch2("/proxy/myid/", "/proxy/:id/*", true); + TestKeyMatch2("/proxy/myid/res", "/proxy/:id/*", true); + TestKeyMatch2("/proxy/myid/res/res2", "/proxy/:id/*", true); + TestKeyMatch2("/proxy/myid/res/res2/res3", "/proxy/:id/*", true); + TestKeyMatch2("/proxy/", "/proxy/:id/*", false); + + TestKeyMatch2("/alice", "/:id", true); + TestKeyMatch2("/alice/all", "/:id/all", true); + TestKeyMatch2("/alice", "/:id/all", false); + TestKeyMatch2("/alice/all", "/:id", false); + + TestKeyMatch2("/alice/all", "/:/all", false); + } + + void TestKeyMatch3(string key1, string key2, bool res) { + Scope scope = InitializeScope(); + PushStringValue(scope, key1); + PushStringValue(scope, key2); + + KeyMatch3(scope); + bool my_res = GetBoolean(scope); + + Assert::AreEqual(res, my_res); + } + + TEST_METHOD(TestKeyMatch3){ + // keyMatch3() is similar with KeyMatch2(), except using "/proxy/{id}" instead of "/proxy/:id". + TestKeyMatch3("/foo", "/foo", true); + TestKeyMatch3("/foo", "/foo*", true); + TestKeyMatch3("/foo", "/foo/*", false); + TestKeyMatch3("/foo/bar", "/foo", false); + TestKeyMatch3("/foo/bar", "/foo*", false); + TestKeyMatch3("/foo/bar", "/foo/*", true); + TestKeyMatch3("/foobar", "/foo", false); + TestKeyMatch3("/foobar", "/foo*", false); + TestKeyMatch3("/foobar", "/foo/*", false); + + TestKeyMatch3("/", "/{resource}", false); + TestKeyMatch3("/resource1", "/{resource}", true); + TestKeyMatch3("/myid", "/{id}/using/{resId}", false); + TestKeyMatch3("/myid/using/myresid", "/{id}/using/{resId}", true); + + TestKeyMatch3("/proxy/myid", "/proxy/{id}/*", false); + TestKeyMatch3("/proxy/myid/", "/proxy/{id}/*", true); + TestKeyMatch3("/proxy/myid/res", "/proxy/{id}/*", true); + TestKeyMatch3("/proxy/myid/res/res2", "/proxy/{id}/*", true); + TestKeyMatch3("/proxy/myid/res/res2/res3", "/proxy/{id}/*", true); + TestKeyMatch3("/proxy/", "/proxy/{id}/*", false); + + TestKeyMatch3("/myid/using/myresid", "/{id/using/{resId}", false); + } + + void TestRegexMatch(string key1, string key2, bool res) { + Scope scope = InitializeScope(); + PushStringValue(scope, key1); + PushStringValue(scope, key2); + + RegexMatch(scope); + bool my_res = GetBoolean(scope); + + Assert::AreEqual(res, my_res); + } + + TEST_METHOD(TestRegexMatch) { + TestRegexMatch("/topic/create", "/topic/create", true); + TestRegexMatch("/topic/create/123", "/topic/create", false); + TestRegexMatch("/topic/delete", "/topic/create", false); + TestRegexMatch("/topic/edit", "/topic/edit/[0-9]+", false); + TestRegexMatch("/topic/edit/123", "/topic/edit/[0-9]+", true); + TestRegexMatch("/topic/edit/abc", "/topic/edit/[0-9]+", false); + TestRegexMatch("/foo/delete/123", "/topic/delete/[0-9]+", false); + TestRegexMatch("/topic/delete/0", "/topic/delete/[0-9]+", true); + TestRegexMatch("/topic/edit/123s", "/topic/delete/[0-9]+", false); + } + + void TestIPMatch(string ip1, string ip2, bool res) { + Scope scope = InitializeScope(); + PushStringValue(scope, ip1); + PushStringValue(scope, ip2); + + IPMatch(scope); + bool my_res = GetBoolean(scope); + + Assert::AreEqual(res, my_res); + } + + TEST_METHOD(TestIPMatch) { + TestIPMatch("192.168.2.123", "192.168.2.0/24", true); + TestIPMatch("192.168.2.123", "192.168.3.0/24", false); + TestIPMatch("192.168.2.123", "192.168.2.0/16", true); + TestIPMatch("192.168.2.123", "192.168.2.123/32", true); + TestIPMatch("10.0.0.11", "10.0.0.0/8", true); + TestIPMatch("11.0.0.123", "10.0.0.0/8", false); + } + }; +} \ No newline at end of file diff --git a/test/test_config.cpp b/test/test_config.cpp index 31b8dd49..3535dc52 100644 --- a/test/test_config.cpp +++ b/test/test_config.cpp @@ -25,7 +25,6 @@ namespace test_config string filePath(string filepath) { char* root = _getcwd(NULL, 0); - Logger::WriteMessage(root); string rootStr = string(root); vector directories = Split(rootStr, "\\", -1); diff --git a/test/test_role_manager.cpp b/test/test_role_manager.cpp new file mode 100644 index 00000000..5dfafa5e --- /dev/null +++ b/test/test_role_manager.cpp @@ -0,0 +1,183 @@ +#pragma once + +#include "pch.h" + +#include + +using namespace std; + +namespace test_role_manager +{ + TEST_CLASS(TestRoleManager) + { + public: + void TestRole(RoleManager* rm, string name1, string name2, bool res) { + bool my_res = rm->HasLink(name1, name2); + + Assert::AreEqual(res, my_res); + } + + void TestDomainRole(RoleManager* rm, string name1, string name2, vector domain, bool res) { + bool my_res = rm->HasLink(name1, name2, domain); + + Assert::AreEqual(res, my_res); + } + + TEST_METHOD(TestRole) { + RoleManager* rm = DefaultRoleManager :: NewRoleManager(3); + rm->AddLink("u1", "g1"); + rm->AddLink("u2", "g1"); + rm->AddLink("u3", "g2"); + rm->AddLink("u4", "g2"); + rm->AddLink("u4", "g3"); + rm->AddLink("g1", "g3"); + + // Current role inheritance tree: + // g3 g2 + // / \ / \ + // g1 u4 u3 + // / \ + // u1 u2 + + TestRole(rm, "u1", "g1", true); + TestRole(rm, "u1", "g2", false); + TestRole(rm, "u1", "g3", true); + TestRole(rm, "u2", "g1", true); + TestRole(rm, "u2", "g2", false); + TestRole(rm, "u2", "g3", true); + TestRole(rm, "u3", "g1", false); + TestRole(rm, "u3", "g2", true); + TestRole(rm, "u3", "g3", false); + TestRole(rm, "u4", "g1", false); + TestRole(rm, "u4", "g2", true); + TestRole(rm, "u4", "g3", true); + + rm->DeleteLink("g1", "g3"); + rm->DeleteLink("u4", "g2"); + + // Current role inheritance tree after deleting the links: + // g3 g2 + // \ \ + // g1 u4 u3 + // / \ + // u1 u2 + + TestRole(rm, "u1", "g1", true); + TestRole(rm, "u1", "g2", false); + TestRole(rm, "u1", "g3", false); + TestRole(rm, "u2", "g1", true); + TestRole(rm, "u2", "g2", false); + TestRole(rm, "u2", "g3", false); + TestRole(rm, "u3", "g1", false); + TestRole(rm, "u3", "g2", true); + TestRole(rm, "u3", "g3", false); + TestRole(rm, "u4", "g1", false); + TestRole(rm, "u4", "g2", false); + TestRole(rm, "u4", "g3", true); + } + + TEST_METHOD(TestDomainRole) { + RoleManager* rm = DefaultRoleManager :: NewRoleManager(3); + vector domain1{ "domain1" }; + vector domain2{ "domain2" }; + rm->AddLink("u1", "g1", domain1); + rm->AddLink("u2", "g1", domain1); + rm->AddLink("u3", "admin", domain2); + rm->AddLink("u4", "admin", domain2); + rm->AddLink("u4", "admin", domain1); + rm->AddLink("g1", "admin", domain1); + + // Current role inheritance tree: + // domain1:admin domain2:admin + // / \ / \ + // domain1:g1 u4 u3 + // / \ + // u1 u2 + + TestDomainRole(rm, "u1", "g1", domain1, true); + TestDomainRole(rm, "u1", "g1", domain2, false); + TestDomainRole(rm, "u1", "admin", domain1, true); + TestDomainRole(rm, "u1", "admin", domain2, false); + + TestDomainRole(rm, "u2", "g1", domain1, true); + TestDomainRole(rm, "u2", "g1", domain2, false); + TestDomainRole(rm, "u2", "admin", domain1, true); + TestDomainRole(rm, "u2", "admin", domain2, false); + + TestDomainRole(rm, "u3", "g1", domain1, false); + TestDomainRole(rm, "u3", "g1", domain2, false); + TestDomainRole(rm, "u3", "admin", domain1, false); + TestDomainRole(rm, "u3", "admin", domain2, true); + + TestDomainRole(rm, "u4", "g1", domain1, false); + TestDomainRole(rm, "u4", "g1", domain2, false); + TestDomainRole(rm, "u4", "admin", domain1, true); + TestDomainRole(rm, "u4", "admin", domain2, true); + + rm->DeleteLink("g1", "admin", domain1); + rm->DeleteLink("u4", "admin", domain2); + + // Current role inheritance tree after deleting the links: + // domain1:admin domain2:admin + // \ \ + // domain1:g1 u4 u3 + // / \ + // u1 u2 + + TestDomainRole(rm, "u1", "g1", domain1, true); + TestDomainRole(rm, "u1", "g1", domain2, false); + TestDomainRole(rm, "u1", "admin", domain1, false); + TestDomainRole(rm, "u1", "admin", domain2, false); + + TestDomainRole(rm, "u2", "g1", domain1, true); + TestDomainRole(rm, "u2", "g1", domain2, false); + TestDomainRole(rm, "u2", "admin", domain1, false); + TestDomainRole(rm, "u2", "admin", domain2, false); + + TestDomainRole(rm, "u3", "g1", domain1, false); + TestDomainRole(rm, "u3", "g1", domain2, false); + TestDomainRole(rm, "u3", "admin", domain1, false); + TestDomainRole(rm, "u3", "admin", domain2, true); + + TestDomainRole(rm, "u4", "g1", domain1, false); + TestDomainRole(rm, "u4", "g1", domain2, false); + TestDomainRole(rm, "u4", "admin", domain1, true); + TestDomainRole(rm, "u4", "admin", domain2, false); + } + + TEST_METHOD(TestClear) { + RoleManager* rm = DefaultRoleManager::NewRoleManager(3); + rm->AddLink("u1", "g1"); + rm->AddLink("u2", "g1"); + rm->AddLink("u3", "g2"); + rm->AddLink("u4", "g2"); + rm->AddLink("u4", "g3"); + rm->AddLink("g1", "g3"); + + // Current role inheritance tree: + // g3 g2 + // / \ / \ + // g1 u4 u3 + // / \ + // u1 u2 + + rm->Clear(); + + // All data is cleared. + // No role inheritance now. + + TestRole(rm, "u1", "g1", false); + TestRole(rm, "u1", "g2", false); + TestRole(rm, "u1", "g3", false); + TestRole(rm, "u2", "g1", false); + TestRole(rm, "u2", "g2", false); + TestRole(rm, "u2", "g3", false); + TestRole(rm, "u3", "g1", false); + TestRole(rm, "u3", "g2", false); + TestRole(rm, "u3", "g3", false); + TestRole(rm, "u4", "g1", false); + TestRole(rm, "u4", "g2", false); + TestRole(rm, "u4", "g3", false); + } + }; +} \ No newline at end of file