11import asyncio
2- import json
32
4- import openfga_sdk
5- from openfga_sdk .client .models import ClientAssertion , ClientCheckRequest , ClientReadChangesRequest , ClientTuple , ClientWriteRequest
6- from openfga_sdk .models import CreateStoreRequest , Metadata , ObjectRelation , RelationMetadata , TupleKey , TypeDefinition , Userset , Usersets , WriteAuthorizationModelRequest
7- from openfga_sdk import ClientConfiguration , OpenFgaClient
3+ from openfga_sdk .client .models import ClientAssertion , ClientCheckRequest , ClientReadChangesRequest , ClientTuple , \
4+ ClientWriteRequest , ClientListRelationsRequest , ClientListObjectsRequest , WriteTransactionOpts
5+ from openfga_sdk import ClientConfiguration , OpenFgaClient , RelationReference , RelationshipCondition , \
6+ ConditionParamTypeRef , Condition , ReadRequestTupleKey , CreateStoreRequest , Metadata , ObjectRelation , \
7+ RelationMetadata , TypeDefinition , Userset , Usersets , WriteAuthorizationModelRequest
88from openfga_sdk .credentials import CredentialConfiguration , Credentials
99import os
1010
@@ -76,9 +76,65 @@ async def main():
7676
7777 # WriteAuthorizationModel
7878 print ('Writing an Authorization Model' )
79- with open (os .path .join (os .path .dirname (__file__ ), 'auth-model.json' )) as f :
80- auth_model_request = json .load (f )
81- response = await fga_client .write_authorization_model (auth_model_request )
79+ response = await fga_client .write_authorization_model (WriteAuthorizationModelRequest (
80+ schema_version = "1.1" ,
81+ type_definitions = [
82+ TypeDefinition (
83+ type = "user"
84+ ),
85+ TypeDefinition (
86+ type = "document" ,
87+ relations = dict (
88+ writer = Userset (
89+ this = dict (),
90+ ),
91+ viewer = Userset (
92+ union = Usersets (
93+ child = [
94+ Userset (this = dict ()),
95+ Userset (computed_userset = ObjectRelation (
96+ object = "" ,
97+ relation = "writer" ,
98+ )),
99+ ],
100+ ),
101+ ),
102+ ),
103+ metadata = Metadata (
104+ relations = dict (
105+ writer = RelationMetadata (
106+ directly_related_user_types = [
107+ RelationReference (type = "user" ),
108+ RelationReference (type = "user" , condition = "ViewCountLessThan200" ),
109+ ]
110+ ),
111+ viewer = RelationMetadata (
112+ directly_related_user_types = [
113+ RelationReference (type = "user" ),
114+ ]
115+ )
116+ )
117+ )
118+ )
119+ ],
120+ conditions = dict (
121+ ViewCountLessThan200 = Condition (
122+ name = "ViewCountLessThan200" ,
123+ expression = "ViewCount < 200" ,
124+ parameters = dict (
125+ ViewCount = ConditionParamTypeRef (
126+ type_name = "TYPE_NAME_INT"
127+ ),
128+ Type = ConditionParamTypeRef (
129+ type_name = "TYPE_NAME_STRING"
130+ ),
131+ Name = ConditionParamTypeRef (
132+ type_name = "TYPE_NAME_STRING"
133+ ),
134+ )
135+ )
136+ )
137+ ))
82138 print (f"Authorization Model ID: { response .authorization_model_id } " )
83139
84140 # ReadAuthorizationModels (after write)
@@ -101,13 +157,13 @@ async def main():
101157 user = 'user:anne' ,
102158 relation = 'writer' ,
103159 object = 'document:roadmap' ,
104- # condition=RelationshipCondition(
105- # name='ViewCountLessThan200',
106- # context=dict(
107- # Name='Roadmap',
108- # Type='Document',
109- # ),
110- # ),
160+ condition = RelationshipCondition (
161+ name = 'ViewCountLessThan200' ,
162+ context = dict (
163+ Name = 'Roadmap' ,
164+ Type = 'Document' ,
165+ ),
166+ ),
111167 ),
112168 ],
113169 )
@@ -118,31 +174,113 @@ async def main():
118174 await fga_client .write (body , options )
119175 print ('Done Writing Tuples' )
120176
177+ # Write
178+ print ('Writing Tuples - non txn' )
179+ body = ClientWriteRequest (
180+ writes = [
181+ ClientTuple (
182+ user = 'user:beth' ,
183+ relation = 'writer' ,
184+ object = 'document:1' ,
185+ condition = RelationshipCondition (
186+ name = 'ViewCountLessThan200' ,
187+ context = dict (
188+ Name = 'Roadmap' ,
189+ Type = 'Document' ,
190+ ),
191+ ),
192+ ),
193+ ClientTuple (
194+ user = 'user:beth' ,
195+ relation = 'viewer' ,
196+ object = 'document:2'
197+ ),
198+ ],
199+ )
200+ options = {
201+ # You can rely on the model id set in the configuration or override it for this specific request
202+ "authorization_model_id" : auth_model_id ,
203+ "transaction" : WriteTransactionOpts (
204+ max_per_chunk = 1
205+ )
206+ }
207+ await fga_client .write (body , options )
208+ print ('Done Writing Tuples' )
209+
121210 # Set the model ID
122211 fga_client .set_authorization_model_id (auth_model_id )
123212
124213 # Read
125214 print ('Reading Tuples' )
126- response = await fga_client .read (TupleKey (user = 'user:anne' , object = 'document:' ))
215+ response = await fga_client .read (ReadRequestTupleKey (user = 'user:anne' , object = 'document:' ))
127216 print (f"Read Tuples: { response .tuples } " )
128217
129218 # ReadChanges
130219 print ('Reading Tuple Changes' )
131- body = ClientReadChangesRequest ('document' )
220+ body = ClientReadChangesRequest (type = 'document' )
132221 response = await fga_client .read_changes (body )
133222 print (f"Read Changes Tuples: { response .changes } " )
134223
135224 # Check
136- print ('Checking for access' )
225+ print ('Checking for access w/o context' )
226+ try :
227+ response = await fga_client .check (ClientCheckRequest (
228+ user = 'user:anne' ,
229+ relation = 'viewer' ,
230+ object = 'document:roadmap'
231+ ))
232+ print (f"Allowed: { response .allowed } " )
233+ except Exception as err :
234+ print (f"Failed due to: { err } " )
235+
236+ # Checking for access with context
237+ print ('Checking for access with context' )
238+
137239 response = await fga_client .check (ClientCheckRequest (
138240 user = 'user:anne' ,
139- relation = 'reader ' ,
241+ relation = 'viewer ' ,
140242 object = 'document:roadmap' ,
243+ context = dict (
244+ ViewCount = 100
245+ )
141246 ))
142247 print (f"Allowed: { response .allowed } " )
143248
144- # Checking for access with context
145- # TODO
249+ # List objects with context
250+ print ('Listing objects for access with context' )
251+
252+ response = await fga_client .list_objects (ClientListObjectsRequest (
253+ user = 'user:anne' ,
254+ relation = 'viewer' ,
255+ type = 'document' ,
256+ context = dict (
257+ ViewCount = 100
258+ )
259+ ))
260+ print (f"Objects: { response .objects } " )
261+
262+ # List relations w/o context
263+ print ('Listing relations for access w/o context' )
264+
265+ response = await fga_client .list_relations (ClientListRelationsRequest (
266+ user = 'user:anne' ,
267+ relations = ['viewer' , 'writer' ],
268+ object = 'document:roadmap'
269+ ))
270+ print (f"Relations: { response } " )
271+
272+ # List relations with context
273+ print ('Listing relations for access with context' )
274+
275+ response = await fga_client .list_relations (ClientListRelationsRequest (
276+ user = 'user:anne' ,
277+ relations = ['viewer' , 'writer' ],
278+ object = 'document:roadmap' ,
279+ context = dict (
280+ ViewCount = 100
281+ )
282+ ))
283+ print (f"Relations: { response } " )
146284
147285 # WriteAssertions
148286 await fga_client .write_assertions ([
@@ -154,7 +292,7 @@ async def main():
154292 ),
155293 ClientAssertion (
156294 user = 'user:anne' ,
157- relation = 'reader ' ,
295+ relation = 'viewer ' ,
158296 object = 'document:roadmap' ,
159297 expectation = False ,
160298 ),
0 commit comments