Skip to content

Commit 7c25596

Browse files
authored
Merge pull request #1 from TripleDogDare/master
Fix bug in save policy line
2 parents aa7b1f5 + 7d01b68 commit 7c25596

File tree

5 files changed

+114
-34
lines changed

5 files changed

+114
-34
lines changed

casbin_sqlalchemy_adapter/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .adapter import CasbinRule, Adapter
1+
from .adapter import CasbinRule, Adapter, Base

casbin_sqlalchemy_adapter/adapter.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from casbin import persist
2-
from sqlalchemy.ext.declarative import declarative_base
32
from sqlalchemy import Column, Integer, String
43
from sqlalchemy import create_engine
4+
from sqlalchemy.ext.declarative import declarative_base
55
from sqlalchemy.orm import sessionmaker
66

77
Base = declarative_base()
@@ -19,12 +19,36 @@ class CasbinRule(Base):
1919
v4 = Column(String(255))
2020
v5 = Column(String(255))
2121

22+
def __str__(self):
23+
text = self.ptype
24+
25+
if self.v0:
26+
text = text + ', ' + self.v0
27+
if self.v1:
28+
text = text + ', ' + self.v1
29+
if self.v2:
30+
text = text + ', ' + self.v2
31+
if self.v3:
32+
text = text + ', ' + self.v3
33+
if self.v4:
34+
text = text + ', ' + self.v4
35+
if self.v5:
36+
text = text + ', ' + self.v5
37+
return text
38+
39+
def __repr__(self):
40+
return '<CasbinRule {}: "{}">'.format(self.id, str(self))
41+
2242

2343
class Adapter(persist.Adapter):
2444
"""the interface for Casbin adapters."""
2545

26-
def __init__(self, dsn):
27-
self._engine = create_engine(dsn)
46+
def __init__(self, engine):
47+
if isinstance(engine, str):
48+
self._engine = create_engine(engine)
49+
else:
50+
self._engine = engine
51+
2852
session = sessionmaker(bind=self._engine)
2953
self._session = session()
3054

@@ -34,37 +58,22 @@ def load_policy(self, model):
3458
"""loads all policy rules from the storage."""
3559
lines = self._session.query(CasbinRule).all()
3660
for line in lines:
37-
text = line.ptype
38-
39-
if line.v0:
40-
text = text + ', ' + line.v0
41-
if line.v1:
42-
text = text + ', ' + line.v1
43-
if line.v2:
44-
text = text + ', ' + line.v2
45-
if line.v3:
46-
text = text + ', ' + line.v3
47-
if line.v4:
48-
text = text + ', ' + line.v4
49-
if line.v5:
50-
text = text + ', ' + line.v5
51-
52-
persist.load_policy_line(text, model)
61+
persist.load_policy_line(str(line), model)
5362

5463
def _save_policy_line(self, ptype, rule):
5564
line = CasbinRule(ptype=ptype)
5665
if len(rule) > 0:
5766
line.v0 = rule[0]
5867
if len(rule) > 1:
59-
line.v0 = rule[1]
68+
line.v1 = rule[1]
6069
if len(rule) > 2:
61-
line.v0 = rule[2]
70+
line.v2 = rule[2]
6271
if len(rule) > 3:
63-
line.v0 = rule[3]
72+
line.v3 = rule[3]
6473
if len(rule) > 4:
65-
line.v0 = rule[4]
74+
line.v4 = rule[4]
6675
if len(rule) > 5:
67-
line.v0 = rule[5]
76+
line.v5 = rule[5]
6877
self._session.add(line)
6978
self._session.commit()
7079

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.db

-8 KB
Binary file not shown.

tests/test_adapter.py

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
from unittest import TestCase
2-
from casbin_sqlalchemy_adapter import Adapter, CasbinRule
3-
import casbin
1+
from casbin_sqlalchemy_adapter import Adapter
2+
from casbin_sqlalchemy_adapter import Base
3+
from casbin_sqlalchemy_adapter import CasbinRule
44
from sqlalchemy import create_engine
55
from sqlalchemy.orm import sessionmaker
6+
from unittest import TestCase
7+
import casbin
68
import os
9+
import simpleeval
710

8-
dir = os.path.split(os.path.realpath(__file__))[0]
11+
12+
def get_fixture(path):
13+
dir_path = os.path.split(os.path.realpath(__file__))[0] + "/"
14+
return os.path.abspath(dir_path + path)
915

1016

1117
def get_enforcer():
12-
dsn = "sqlite:///" + dir + "/test.db"
13-
adapter = Adapter(dsn)
18+
engine = create_engine("sqlite://")
19+
adapter = Adapter(engine)
1420

15-
engine = create_engine(dsn)
1621
session = sessionmaker(bind=engine)
22+
Base.metadata.create_all(engine)
1723
s = session()
18-
s.query(CasbinRule).delete(synchronize_session=False)
1924

2025
s.add(CasbinRule(ptype='p', v0='alice', v1='data1', v2='read'))
2126
s.add(CasbinRule(ptype='p', v0='bob', v1='data2', v2='write'))
@@ -25,7 +30,7 @@ def get_enforcer():
2530
s.commit()
2631
s.close()
2732

28-
return casbin.Enforcer(dir + '/rbac_model.conf', adapter, True)
33+
return casbin.Enforcer(get_fixture('rbac_model.conf'), adapter, True)
2934

3035

3136
class TestConfig(TestCase):
@@ -37,3 +42,63 @@ def test_enforcer_basic(self):
3742
self.assertTrue(e.enforce('bob', 'data2', 'write'))
3843
self.assertTrue(e.enforce('alice', 'data2', 'read'))
3944
self.assertTrue(e.enforce('alice', 'data2', 'write'))
45+
46+
def test_add_policy(self):
47+
adapter = Adapter('sqlite://')
48+
e = casbin.Enforcer(get_fixture('rbac_model.conf'), adapter, True)
49+
50+
try:
51+
self.assertFalse(e.enforce('alice', 'data1', 'read'))
52+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
53+
self.assertFalse(e.enforce('bob', 'data2', 'write'))
54+
self.assertFalse(e.enforce('alice', 'data2', 'read'))
55+
self.assertFalse(e.enforce('alice', 'data2', 'write'))
56+
except simpleeval.NameNotDefined:
57+
# This is caused by an upstream bug when there is no policy loaded
58+
# Should be resolved in pycasbin >= 0.3
59+
pass
60+
61+
adapter.add_policy(sec=None, ptype='p', rule=['alice', 'data1', 'read'])
62+
adapter.add_policy(sec=None, ptype='p', rule=['bob', 'data2', 'write'])
63+
adapter.add_policy(sec=None, ptype='p', rule=['data2_admin', 'data2', 'read'])
64+
adapter.add_policy(sec=None, ptype='p', rule=['data2_admin', 'data2', 'write'])
65+
adapter.add_policy(sec=None, ptype='g', rule=['alice', 'data2_admin'])
66+
67+
e.load_policy()
68+
69+
self.assertTrue(e.enforce('alice', 'data1', 'read'))
70+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
71+
self.assertTrue(e.enforce('bob', 'data2', 'write'))
72+
self.assertTrue(e.enforce('alice', 'data2', 'read'))
73+
self.assertTrue(e.enforce('alice', 'data2', 'write'))
74+
self.assertFalse(e.enforce('bogus', 'data2', 'write'))
75+
76+
def test_save_policy(self):
77+
model = casbin.Enforcer(get_fixture('rbac_model.conf'), get_fixture('rbac_policy.csv')).model
78+
adapter = Adapter('sqlite://')
79+
adapter.save_policy(model)
80+
e = casbin.Enforcer(get_fixture('rbac_model.conf'), adapter)
81+
82+
self.assertTrue(e.enforce('alice', 'data1', 'read'))
83+
self.assertFalse(e.enforce('bob', 'data1', 'read'))
84+
self.assertTrue(e.enforce('bob', 'data2', 'write'))
85+
self.assertTrue(e.enforce('alice', 'data2', 'read'))
86+
self.assertTrue(e.enforce('alice', 'data2', 'write'))
87+
88+
def test_str(self):
89+
rule = CasbinRule(ptype='p', v0='alice', v1='data1', v2='read')
90+
self.assertEqual(str(rule), 'p, alice, data1, read')
91+
92+
def test_repr(self):
93+
rule = CasbinRule(ptype='p', v0='alice', v1='data1', v2='read')
94+
self.assertEqual(repr(rule), '<CasbinRule None: "p, alice, data1, read">')
95+
engine = create_engine("sqlite://")
96+
97+
session = sessionmaker(bind=engine)
98+
Base.metadata.create_all(engine)
99+
s = session()
100+
101+
s.add(rule)
102+
s.commit()
103+
self.assertRegex(repr(rule), r'<CasbinRule \d+: "p, alice, data1, read">')
104+
s.close()

0 commit comments

Comments
 (0)