Skip to content

Commit 74d351a

Browse files
committed
fix(conditions): update example and fix list relations
1 parent 02f29ce commit 74d351a

6 files changed

Lines changed: 211 additions & 132 deletions

File tree

example/example1/auth-model.json

Lines changed: 0 additions & 73 deletions
This file was deleted.

example/example1/example1.py

Lines changed: 160 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import 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
88
from openfga_sdk.credentials import CredentialConfiguration, Credentials
99
import 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
),

openfga_sdk/client/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ async def list_relations(self, body: ClientListRelationsRequest, options: dict[s
632632
options = set_heading_if_not_set(options, CLIENT_BULK_REQUEST_ID_HEADER, str(uuid.uuid4()))
633633

634634
request_body = [construct_check_request(
635-
user=body.user, relation=i, object=body.object, contextual_tuples=body.contextual_tuples) for i in body.relations]
635+
user=body.user, relation=i, object=body.object, contextual_tuples=body.contextual_tuples, context=body.context) for i in body.relations]
636636
result = await self.batch_check(request_body, options)
637637
# need to filter with the allowed response
638638
result_iterator = filter(_check_allowed, result)

0 commit comments

Comments
 (0)