1- import casbin
21from casbin import persist
32from pymongo import MongoClient
43
@@ -19,10 +18,9 @@ def __init__(self, ptype = None, v0 = None, v1 = None, v2 = None, v3 = None, v4
1918 def dict (self ):
2019 d = {'ptype' : self .ptype }
2120
22- for i , v in enumerate ([self .v0 , self .v1 , self .v2 , self .v3 , self .v4 , self .v5 ]):
23- if v is None :
24- break
25- d ['v' + str (i )] = v
21+ for value in dir (self ):
22+ if getattr (self , value ) is not None and value .startswith ('v' ) and value [1 :].isnumeric ():
23+ d [value ] = getattr (self , value )
2624
2725 return d
2826
@@ -36,57 +34,73 @@ class Adapter(persist.Adapter):
3634 """the interface for Casbin adapters."""
3735
3836 def __init__ (self , uri , dbname , collection = "casbin_rule" ):
37+ """Create an adapter for Mongodb
38+
39+ Args:
40+ uri (str): This should be the same requiement as pymongo Client's 'uri' parameter.
41+ See https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient.
42+ dbname (str): Database to store policy.
43+ collection (str, optional): Collection of the choosen database. Defaults to "casbin_rule".
44+ """
3945 client = MongoClient (uri )
4046 db = client [dbname ]
4147 self ._collection = db [collection ]
4248
4349 def load_policy (self , model ):
44- '''
45- implementing add Interface for casbin \n
46- load all policy rules from mongodb \n
47- '''
50+ """Implementing add Interface for casbin. Load all policy rules from mongodb
51+
52+ Args:
53+ model (CasbinRule): CasbinRule object
54+ """
4855
4956 for line in self ._collection .find ():
5057 if 'ptype' not in line :
5158 continue
52-
5359 rule = CasbinRule (line ['ptype' ])
54- if 'v0' in line :
55- rule .v0 = line ['v0' ]
56- if 'v1' in line :
57- rule .v1 = line ['v1' ]
58- if 'v2' in line :
59- rule .v2 = line ['v2' ]
60- if 'v3' in line :
61- rule .v3 = line ['v3' ]
62- if 'v4' in line :
63- rule .v4 = line ['v4' ]
64- if 'v5' in line :
65- rule .v5 = line ['v5' ]
60+ for key , value in line .items ():
61+ setattr (rule , key , value )
6662
6763 persist .load_policy_line (str (rule ), model )
6864
6965 def _save_policy_line (self , ptype , rule ):
7066 line = CasbinRule (ptype = ptype )
71- if len (rule ) > 0 :
72- line .v0 = rule [0 ]
73- if len (rule ) > 1 :
74- line .v1 = rule [1 ]
75- if len (rule ) > 2 :
76- line .v2 = rule [2 ]
77- if len (rule ) > 3 :
78- line .v3 = rule [3 ]
79- if len (rule ) > 4 :
80- line .v4 = rule [4 ]
81- if len (rule ) > 5 :
82- line .v5 = rule [5 ]
67+ for index , value in enumerate (rule ):
68+ setattr (line , f'v{ index } ' , value )
8369 self ._collection .insert_one (line .dict ())
84-
85- def save_policy (self , model ):
86- '''
87- implementing add Interface for casbin \n
88- save the policy in mongodb \n
89- '''
70+
71+ def _find_policy_lines (self , ptype , rule ):
72+ line = CasbinRule (ptype = ptype )
73+ for index , value in enumerate (rule ):
74+ setattr (line , f'v{ index } ' , value )
75+ return self ._collection .find (line .dict ())
76+
77+ def _delete_policy_lines (self , ptype , rule ):
78+ line = CasbinRule (ptype = ptype )
79+ for index , value in enumerate (rule ):
80+ setattr (line , f'v{ index } ' , value )
81+
82+ # if rule is empty, do nothing
83+ # else find all given rules and delete them
84+ if len (line .dict ()) == 0 :
85+ return 0
86+ else :
87+ line_dict = line .dict ()
88+ line_dict_keys_len = len (line_dict )
89+ results = self ._collection .find (line_dict )
90+ to_delete = [result ['_id' ] for result in results
91+ if line_dict_keys_len == len (result .keys ()) - 1 ]
92+ results = self ._collection .delete_many ({'_id' : {'$in' : to_delete }})
93+ return results .deleted_count
94+
95+ def save_policy (self , model ) -> bool :
96+ """Implement add Interface for casbin. Save the policy in mongodb
97+
98+ Args:
99+ model (Class Model): Casbin Model which loads from .conf file usually.
100+
101+ Returns:
102+ bool: True if succeed
103+ """
90104 for sec in ["p" , "g" ]:
91105 if sec not in model .model .keys ():
92106 continue
@@ -96,15 +110,51 @@ def save_policy(self, model):
96110 return True
97111
98112 def add_policy (self , sec , ptype , rule ):
99- """add policy rules to mongodb"""
113+ """Add policy rules to mongodb
114+
115+ Args:
116+ sec (str): Section name, 'g' or 'p'
117+ ptype (str): Policy type, 'g', 'g2', 'p', etc.
118+ rule (CasbinRule): Casbin rule will be added
119+
120+ Returns:
121+ bool: True if succeed else False
122+ """
100123 self ._save_policy_line (ptype , rule )
124+ return True
101125
102126 def remove_policy (self , sec , ptype , rule ):
103- """delete policy rules from mongodb"""
104- pass
127+ """Remove policy rules in mongodb(rules duplicate are also removed)
128+
129+ Args:
130+ ptype (str): Policy type, 'g', 'g2', 'p', etc.
131+ rule (CasbinRule): Casbin rule if it is exactly same as will be removed.
132+
133+ Returns:
134+ Number: Number of policies be removed
135+ """
136+ deleted_count = self ._delete_policy_lines (ptype , rule )
137+ return deleted_count > 0
105138
106139 def remove_filtered_policy (self , sec , ptype , field_index , * field_values ):
140+ """Remove policy rules taht match the filter from the storage.
141+ This is part of the Auto-Save feature.
142+
143+ Args:
144+ ptype (str): Policy type, 'g', 'g2', 'p', etc.
145+ rule (CasbinRule): Casbin rule will be removed
146+ field_index (int): The policy index at which the filed_values begins filtering. Its range is [0, 5]
147+ field_values(List[str]): A list of rules to filter policy which starts from
148+
149+ Returns:
150+ bool: True if succeed else False
107151 """
108- delete policy rules for matching filters from mongodb
109- """
110- pass
152+ if not (0 <= field_index <= 5 ):
153+ return False
154+ if not (1 <= field_index + len (field_values ) <= 6 ):
155+ return False
156+ query = {f'v{ index + field_index } ' : value
157+ for index , value in enumerate (field_values )}
158+ query ['ptype' ] = ptype
159+ results = self ._collection .delete_many (query )
160+ return results .deleted_count > 0
0 commit comments