Skip to content

Commit f6d8f8f

Browse files
authored
Merge pull request #2 from Xhy-5000/master
Help needed for pymongo_adapter
2 parents 3f651f1 + eb39432 commit f6d8f8f

5 files changed

Lines changed: 236 additions & 13 deletions

File tree

casbin_pymongo_adapter/adapter.py

Lines changed: 104 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,127 @@
1+
import casbin
12
from casbin import persist
23
from pymongo import MongoClient
34

5+
class CasbinRule:
6+
'''
7+
CasbinRule model
8+
'''
9+
ptype = None
10+
v0 = None
11+
v1 = None
12+
v2 = None
13+
v3 = None
14+
v4 = None
15+
v5 = None
16+
17+
def __init__(self, ptype):
18+
self.ptype = ptype
19+
20+
def dict(self):
21+
d = {'ptype': self.ptype}
22+
23+
for i, v in enumerate([self.v0, self.v1, self.v2, self.v3, self.v4, self.v5]):
24+
if v is None:
25+
break
26+
d['v' + str(i)] = v
27+
28+
return d
29+
30+
def __str__(self):
31+
return ', '.join(self.dict().values())
32+
33+
def __repr__(self):
34+
return '<CasbinRule :"{}">'.format(str(self))
435

536
class Adapter(persist.Adapter):
6-
"""the pymongo adapter for Casbin."""
37+
"""the interface for Casbin adapters."""
738

839
def __init__(self, uri, dbname, collection="casbin_rule"):
940
client = MongoClient(uri)
1041
db = client[dbname]
1142
self._collection = db[collection]
12-
pass
1343

1444
def load_policy(self, model):
15-
"""loads all policy rules from the storage."""
16-
for lines in self._collection.find():
17-
pass
45+
'''
46+
implementing add Interface for casbin \n
47+
load all policy rules from mongodb \n
48+
'''
49+
50+
for line in self._collection.find():
51+
if 'ptype' not in line:
52+
continue
53+
54+
rule = CasbinRule(line['ptype'])
55+
if 'v0' in line:
56+
rule.v0 = line['v0']
57+
if 'v1' in line:
58+
rule.v1 = line['v1']
59+
if 'v2' in line:
60+
rule.v2 = line['v2']
61+
if 'v3' in line:
62+
rule.v3 = line['v3']
63+
if 'v4' in line:
64+
rule.v4 = line['v4']
65+
if 'v5' in line:
66+
rule.v5 = line['v5']
67+
68+
persist.load_policy_line(str(rule), model)
69+
70+
def _save_policy_line(self, ptype, rule):
71+
line = CasbinRule(ptype=ptype)
72+
if len(rule) > 0:
73+
line.v0 = rule[0]
74+
if len(rule) > 1:
75+
line.v1 = rule[1]
76+
if len(rule) > 2:
77+
line.v2 = rule[2]
78+
if len(rule) > 3:
79+
line.v3 = rule[3]
80+
if len(rule) > 4:
81+
line.v4 = rule[4]
82+
if len(rule) > 5:
83+
line.v5 = rule[5]
84+
self._collection.insert_one(line.dict)
1885

1986
def save_policy(self, model):
20-
"""saves all policy rules to the storage."""
21-
pass
87+
'''
88+
implementing add Interface for casbin \n
89+
save the policy in mongodb \n
90+
'''
91+
# for sec in ["p", "g"]:
92+
# if sec not in model.model.keys():
93+
# continue
94+
# for ptype, ast in model.model[sec].items():
95+
# for rule in ast.policy:
96+
# self._save_policy_line(ptype, rule)
97+
# return True
98+
self._collection.insert_one(model.dict)
2299

23100
def add_policy(self, sec, ptype, rule):
24-
"""adds a policy rule to the storage."""
25-
pass
101+
"""add policy rules to mongodb"""
102+
# self._save_policy_line(ptype, rule)
103+
line = CasbinRule(ptype = ptype)
104+
if len(rule) > 0:
105+
line.v0 = rule[0]
106+
if len(rule) > 1:
107+
line.v1 = rule[1]
108+
if len(rule) > 2:
109+
line.v2 = rule[2]
110+
if len(rule) > 3:
111+
line.v3 = rule[3]
112+
if len(rule) > 4:
113+
line.v4 = rule[4]
114+
if len(rule) > 5:
115+
line.v5 = rule[5]
116+
self.save_policy(line)
117+
26118

27119
def remove_policy(self, sec, ptype, rule):
28-
"""removes a policy rule from the storage."""
120+
"""delete policy rules from mongodb"""
29121
pass
30122

31123
def remove_filtered_policy(self, sec, ptype, field_index, *field_values):
32-
"""removes policy rules that match the filter from the storage.
33-
This is part of the Auto-Save feature.
124+
"""
125+
delete policy rules for matching filters from mongodb
34126
"""
35127
pass

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
setuptools.setup(
99
name="casbin_pymongo_adapter",
1010
version="0.1.0",
11-
author="TechLee",
11+
author="TechLee,Xhy-5000",
1212
author_email="techlee@qq.com",
1313
description="PyMongo Adapter for PyCasbin",
1414
long_description=long_description,

tests/rbac_model.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act
6+
7+
[role_definition]
8+
g = _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

tests/rbac_policy.csv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
p, alice, data1, read
2+
p, bob, data2, write
3+
p, data2_admin, data2, read
4+
p, data2_admin, data2, write
5+
6+
g, alice, data2_admin

tests/test_adapter.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
from casbin_pymongo_adapter.adapter import Adapter
2+
from casbin_pymongo_adapter.adapter import CasbinRule
3+
from unittest import TestCase
4+
import casbin
5+
import os
6+
import simpleeval
7+
8+
def get_fixture(path):
9+
'''
10+
get model path
11+
'''
12+
dir_path = os.path.split(os.path.realpath(__file__))[0] + "/"
13+
return os.path.abspath(dir_path + path)
14+
15+
16+
def get_enforcer():
17+
adapter = Adapter('mongodb://localhost:27017', 'casbin_test')
18+
c1 = CasbinRule(ptype='p', v0='alice', v1='data1', v2='read')
19+
adapter.save_policy(c1)
20+
c2 = CasbinRule(ptype='p', v0='bob', v1='data2', v2='write')
21+
adapter.save_policy(c2)
22+
c3 = CasbinRule(ptype='p', v0='data2_admin', v1='data2', v2='read')
23+
adapter.save_policy(c3)
24+
c4 = CasbinRule(ptype='p', v0='data2_admin', v1='data2', v2='write')
25+
adapter.save_policy(c4)
26+
c5 = CasbinRule(ptype='g', v0='alice', v1='data2_admin')
27+
adapter.save_policy(c5)
28+
29+
return casbin.Enforcer(get_fixture('rbac_model.conf'), adapter, True)
30+
31+
32+
class TestConfig(TestCase):
33+
'''
34+
unittest
35+
'''
36+
37+
def test_enforcer_basic(self):
38+
'''
39+
test policy
40+
'''
41+
e = get_enforcer()
42+
self.assertFalse(e.enforce('alice', 'data1', 'write'))
43+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
44+
self.assertTrue(e.enforce('bob', 'data2', 'write'))
45+
self.assertTrue(e.enforce('alice', 'data2', 'read'))
46+
self.assertTrue(e.enforce('alice', 'data2', 'write'))
47+
48+
def test_add_policy(self):
49+
'''
50+
test add_policy
51+
'''
52+
adapter = Adapter('mongodb://localhost:27017', 'casbin_test')
53+
e = casbin.Enforcer(get_fixture('rbac_model.conf'), adapter, True)
54+
55+
try:
56+
self.assertFalse(e.enforce('alice', 'data1', 'write'))
57+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
58+
self.assertFalse(e.enforce('bob', 'data2', 'write'))
59+
self.assertFalse(e.enforce('alice', 'data2', 'read'))
60+
self.assertFalse(e.enforce('alice', 'data2', 'write'))
61+
except simpleeval.NameNotDefined:
62+
# This is caused by an upstream bug when there is no policy loaded
63+
# Should be resolved in pycasbin >= 0.3
64+
pass
65+
66+
adapter.add_policy(sec=None, ptype='p', rule=['alice', 'data1', 'read'])
67+
adapter.add_policy(sec=None, ptype='p', rule=['bob', 'data2', 'write'])
68+
adapter.add_policy(sec=None, ptype='p', rule=['data2_admin', 'data2', 'read'])
69+
adapter.add_policy(sec=None, ptype='p', rule=['data2_admin', 'data2', 'write'])
70+
adapter.add_policy(sec=None, ptype='g', rule=['alice', 'data2_admin'])
71+
72+
e.load_policy()
73+
74+
self.assertFalse(e.enforce('alice', 'data1', 'write'))
75+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
76+
self.assertTrue(e.enforce('bob', 'data2', 'write'))
77+
self.assertTrue(e.enforce('alice', 'data2', 'read'))
78+
self.assertTrue(e.enforce('alice', 'data2', 'write'))
79+
self.assertFalse(e.enforce('bogus', 'data2', 'write'))
80+
81+
def test_save_policy(self):
82+
'''
83+
test save_policy
84+
'''
85+
model = casbin.Enforcer(get_fixture('rbac_model.conf'), get_fixture('rbac_policy.csv')).model
86+
adapter = Adapter('mongodb://localhost:27017', 'casbin_test')
87+
adapter.save_policy(model)
88+
e = casbin.Enforcer(get_fixture('rbac_model.conf'), adapter)
89+
90+
self.assertFalse(e.enforce('alice', 'data1', 'read'))
91+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
92+
self.assertTrue(e.enforce('bob', 'data2', 'write'))
93+
self.assertTrue(e.enforce('alice', 'data2', 'read'))
94+
self.assertTrue(e.enforce('alice', 'data2', 'write'))
95+
96+
def test_str(self):
97+
'''
98+
test __str__ function
99+
'''
100+
rule = CasbinRule(ptype='p', v0='alice', v1='data1', v2='read')
101+
self.assertEqual(str(rule), 'p, alice, data1, read')
102+
103+
def test_repr(self):
104+
'''
105+
test __repr__ function
106+
'''
107+
adapter = Adapter('mongodb://localhost:27017', 'casbin_test')
108+
rule = CasbinRule(ptype='p', v0='alice', v1='data1', v2='read')
109+
self.assertEqual(repr(rule), '<CasbinRule :"p, alice, data1, read">')
110+
adapter.save_policy(rule)
111+
self.assertRegex(repr(rule), r'<CasbinRule :"p, alice, data1, read">')

0 commit comments

Comments
 (0)