From 4af82eaed255f161ed948c9742dde7c3e6655659 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 24 Jul 2024 16:11:22 +0100 Subject: [PATCH] feat: support passing consistency parameter --- .openapi-generator/FILES | 2 + README.md | 3 +- docs/CheckRequest.md | 1 + docs/ConsistencyPreference.md | 11 ++ docs/ExpandRequest.md | 1 + docs/ListObjectsRequest.md | 1 + docs/ListUsersRequest.md | 1 + docs/OpenFgaApi.md | 8 +- docs/ReadRequest.md | 1 + openfga_sdk/__init__.py | 1 + openfga_sdk/api/open_fga_api.py | 8 +- openfga_sdk/client/client.py | 20 ++++ openfga_sdk/models/__init__.py | 1 + openfga_sdk/models/check_request.py | 27 +++++ openfga_sdk/models/consistency_preference.py | 104 +++++++++++++++++++ openfga_sdk/models/expand_request.py | 32 +++++- openfga_sdk/models/list_objects_request.py | 27 +++++ openfga_sdk/models/list_users_request.py | 27 +++++ openfga_sdk/models/read_request.py | 27 +++++ openfga_sdk/sync/client/client.py | 21 ++++ openfga_sdk/sync/open_fga_api.py | 8 +- test/client/client_test.py | 37 ++++++- test/sync/client/client_test.py | 43 ++++++-- 23 files changed, 387 insertions(+), 25 deletions(-) create mode 100644 docs/ConsistencyPreference.md create mode 100644 openfga_sdk/models/consistency_preference.py diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 73f5024..d0a5c64 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -27,6 +27,7 @@ docs/Computed.md docs/Condition.md docs/ConditionMetadata.md docs/ConditionParamTypeRef.md +docs/ConsistencyPreference.md docs/ContextualTupleKeys.md docs/CreateStoreRequest.md docs/CreateStoreResponse.md @@ -147,6 +148,7 @@ openfga_sdk/models/computed.py openfga_sdk/models/condition.py openfga_sdk/models/condition_metadata.py openfga_sdk/models/condition_param_type_ref.py +openfga_sdk/models/consistency_preference.py openfga_sdk/models/contextual_tuple_keys.py openfga_sdk/models/create_store_request.py openfga_sdk/models/create_store_response.py diff --git a/README.md b/README.md index d695edc..3555395 100644 --- a/README.md +++ b/README.md @@ -1044,7 +1044,7 @@ Class | Method | HTTP request | Description *OpenFgaApi* | [**get_store**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#get_store) | **GET** /stores/{store_id} | Get a store *OpenFgaApi* | [**list_objects**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#list_objects) | **POST** /stores/{store_id}/list-objects | List all objects of the given type that the user has a relation with *OpenFgaApi* | [**list_stores**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#list_stores) | **GET** /stores | List all stores -*OpenFgaApi* | [**list_users**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#list_users) | **POST** /stores/{store_id}/list-users | [EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. +*OpenFgaApi* | [**list_users**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#list_users) | **POST** /stores/{store_id}/list-users | List the users matching the provided filter who have a certain relation to a particular type. *OpenFgaApi* | [**read**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#read) | **POST** /stores/{store_id}/read | Get tuples from the store that matches a query, without following userset rewrite rules *OpenFgaApi* | [**read_assertions**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#read_assertions) | **GET** /stores/{store_id}/assertions/{authorization_model_id} | Read assertions for an authorization model ID *OpenFgaApi* | [**read_authorization_model**](https://github.com/openfga/python-sdk/blob/main/docs/OpenFgaApi.md#read_authorization_model) | **GET** /stores/{store_id}/authorization-models/{id} | Return a particular version of an authorization model @@ -1072,6 +1072,7 @@ Class | Method | HTTP request | Description - [Condition](https://github.com/openfga/python-sdk/blob/main/docs/Condition.md) - [ConditionMetadata](https://github.com/openfga/python-sdk/blob/main/docs/ConditionMetadata.md) - [ConditionParamTypeRef](https://github.com/openfga/python-sdk/blob/main/docs/ConditionParamTypeRef.md) + - [ConsistencyPreference](https://github.com/openfga/python-sdk/blob/main/docs/ConsistencyPreference.md) - [ContextualTupleKeys](https://github.com/openfga/python-sdk/blob/main/docs/ContextualTupleKeys.md) - [CreateStoreRequest](https://github.com/openfga/python-sdk/blob/main/docs/CreateStoreRequest.md) - [CreateStoreResponse](https://github.com/openfga/python-sdk/blob/main/docs/CreateStoreResponse.md) diff --git a/docs/CheckRequest.md b/docs/CheckRequest.md index cba772d..6a7c58c 100644 --- a/docs/CheckRequest.md +++ b/docs/CheckRequest.md @@ -9,6 +9,7 @@ Name | Type | Description | Notes **authorization_model_id** | **str** | | [optional] **trace** | **bool** | Defaults to false. Making it true has performance implications. | [optional] [readonly] **context** | **object** | Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. | [optional] +**consistency** | [**ConsistencyPreference**](ConsistencyPreference.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ConsistencyPreference.md b/docs/ConsistencyPreference.md new file mode 100644 index 0000000..410472a --- /dev/null +++ b/docs/ConsistencyPreference.md @@ -0,0 +1,11 @@ +# ConsistencyPreference + +- UNSPECIFIED: Default if not set. Behavior will be the same as MINIMIZE_LATENCY - MINIMIZE_LATENCY: Minimize latency at the potential expense of lower consistency. - HIGHER_CONSISTENCY: Prefer higher consistency, at the potential expense of increased latency. + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/docs/ExpandRequest.md b/docs/ExpandRequest.md index 662d3b3..c24434b 100644 --- a/docs/ExpandRequest.md +++ b/docs/ExpandRequest.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **tuple_key** | [**ExpandRequestTupleKey**](ExpandRequestTupleKey.md) | | **authorization_model_id** | **str** | | [optional] +**consistency** | [**ConsistencyPreference**](ConsistencyPreference.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ListObjectsRequest.md b/docs/ListObjectsRequest.md index b55c1e9..151b6b9 100644 --- a/docs/ListObjectsRequest.md +++ b/docs/ListObjectsRequest.md @@ -10,6 +10,7 @@ Name | Type | Description | Notes **user** | **str** | | **contextual_tuples** | [**ContextualTupleKeys**](ContextualTupleKeys.md) | | [optional] **context** | **object** | Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. | [optional] +**consistency** | [**ConsistencyPreference**](ConsistencyPreference.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/ListUsersRequest.md b/docs/ListUsersRequest.md index 381104b..43907a6 100644 --- a/docs/ListUsersRequest.md +++ b/docs/ListUsersRequest.md @@ -10,6 +10,7 @@ Name | Type | Description | Notes **user_filters** | [**list[UserTypeFilter]**](UserTypeFilter.md) | The type of results returned. Only accepts exactly one value. | **contextual_tuples** | [**list[TupleKey]**](TupleKey.md) | | [optional] **context** | **object** | Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. | [optional] +**consistency** | [**ConsistencyPreference**](ConsistencyPreference.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/docs/OpenFgaApi.md b/docs/OpenFgaApi.md index 985e537..550687d 100644 --- a/docs/OpenFgaApi.md +++ b/docs/OpenFgaApi.md @@ -11,7 +11,7 @@ Method | HTTP request | Description [**get_store**](OpenFgaApi.md#get_store) | **GET** /stores/{store_id} | Get a store [**list_objects**](OpenFgaApi.md#list_objects) | **POST** /stores/{store_id}/list-objects | List all objects of the given type that the user has a relation with [**list_stores**](OpenFgaApi.md#list_stores) | **GET** /stores | List all stores -[**list_users**](OpenFgaApi.md#list_users) | **POST** /stores/{store_id}/list-users | [EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. +[**list_users**](OpenFgaApi.md#list_users) | **POST** /stores/{store_id}/list-users | List the users matching the provided filter who have a certain relation to a particular type. [**read**](OpenFgaApi.md#read) | **POST** /stores/{store_id}/read | Get tuples from the store that matches a query, without following userset rewrite rules [**read_assertions**](OpenFgaApi.md#read_assertions) | **GET** /stores/{store_id}/assertions/{authorization_model_id} | Read assertions for an authorization model ID [**read_authorization_model**](OpenFgaApi.md#read_authorization_model) | **GET** /stores/{store_id}/authorization-models/{id} | Return a particular version of an authorization model @@ -598,9 +598,9 @@ No authorization required # **list_users** > ListUsersResponse list_users(body) -[EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. +List the users matching the provided filter who have a certain relation to a particular type. -The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. This API is available in an experimental capacity and can be enabled with the `--experimentals enable-list-users` flag. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. +The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. ### Example @@ -637,7 +637,7 @@ async with openfga_sdk.ApiClient(configuration) as api_client: body = openfga_sdk.ListUsersRequest() # ListUsersRequest | try: - # [EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. + # List the users matching the provided filter who have a certain relation to a particular type. api_response = await api_instance.api_instance.list_users(body) pprint(api_response) except ApiException as e: diff --git a/docs/ReadRequest.md b/docs/ReadRequest.md index 31ceeaa..25a50ac 100644 --- a/docs/ReadRequest.md +++ b/docs/ReadRequest.md @@ -7,6 +7,7 @@ Name | Type | Description | Notes **tuple_key** | [**ReadRequestTupleKey**](ReadRequestTupleKey.md) | | [optional] **page_size** | **int** | | [optional] **continuation_token** | **str** | | [optional] +**consistency** | [**ConsistencyPreference**](ConsistencyPreference.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/openfga_sdk/__init__.py b/openfga_sdk/__init__.py index 0665bd2..2854907 100644 --- a/openfga_sdk/__init__.py +++ b/openfga_sdk/__init__.py @@ -37,6 +37,7 @@ from openfga_sdk.models.condition import Condition from openfga_sdk.models.condition_metadata import ConditionMetadata from openfga_sdk.models.condition_param_type_ref import ConditionParamTypeRef +from openfga_sdk.models.consistency_preference import ConsistencyPreference from openfga_sdk.models.contextual_tuple_keys import ContextualTupleKeys from openfga_sdk.models.create_store_request import CreateStoreRequest from openfga_sdk.models.create_store_response import CreateStoreResponse diff --git a/openfga_sdk/api/open_fga_api.py b/openfga_sdk/api/open_fga_api.py index 7db6c40..18afdb6 100644 --- a/openfga_sdk/api/open_fga_api.py +++ b/openfga_sdk/api/open_fga_api.py @@ -1331,9 +1331,9 @@ async def list_stores_with_http_info(self, **kwargs): ) async def list_users(self, body, **kwargs): - """[EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. + """List the users matching the provided filter who have a certain relation to a particular type. - The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. This API is available in an experimental capacity and can be enabled with the `--experimentals enable-list-users` flag. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. + The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. >>> thread = await api.list_users(body) @@ -1358,9 +1358,9 @@ async def list_users(self, body, **kwargs): return await self.list_users_with_http_info(body, **kwargs) async def list_users_with_http_info(self, body, **kwargs): - """[EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. + """List the users matching the provided filter who have a certain relation to a particular type. - The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. This API is available in an experimental capacity and can be enabled with the `--experimentals enable-list-users` flag. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. + The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. >>> thread = api.list_users_with_http_info(body) diff --git a/openfga_sdk/client/client.py b/openfga_sdk/client/client.py index 861940d..466656b 100644 --- a/openfga_sdk/client/client.py +++ b/openfga_sdk/client/client.py @@ -158,6 +158,15 @@ def _get_authorization_model_id(self, options: object) -> str | None: ) return authorization_model_id + def _get_consistency(self, options: object) -> str | None: + """ + Returns the consistency requested if specified in the options. + Otherwise, returns None. + """ + if options is not None and "consistency" in options: + return options["consistency"] + return None + def set_store_id(self, value): """ Update the store ID in the configuration @@ -362,6 +371,7 @@ async def read(self, body: ReadRequestTupleKey, options: dict[str, str] = None): :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "Read") page_size = None @@ -387,6 +397,7 @@ async def read(self, body: ReadRequestTupleKey, options: dict[str, str] = None): tuple_key=tuple_key, page_size=page_size, continuation_token=continuation_token, + consistency=self._get_consistency(options), ), **kwargs, ) @@ -548,6 +559,7 @@ async def check(self, body: ClientCheckRequest, options: dict[str, str] = None): :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "Check") @@ -561,6 +573,7 @@ async def check(self, body: ClientCheckRequest, options: dict[str, str] = None): ), context=body.context, authorization_model_id=self._get_authorization_model_id(options), + consistency=self._get_consistency(options), ) if body.contextual_tuples: req_body.contextual_tuples = ContextualTupleKeys( @@ -637,6 +650,7 @@ async def expand(self, body: ClientExpandRequest, options: dict[str, str] = None :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "Expand") kwargs = options_to_kwargs(options) @@ -647,6 +661,7 @@ async def expand(self, body: ClientExpandRequest, options: dict[str, str] = None object=body.object, ), authorization_model_id=self._get_authorization_model_id(options), + consistency=self._get_consistency(options), ) api_response = await self._api.expand(body=req_body, **kwargs) return api_response @@ -662,6 +677,7 @@ async def list_objects( :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListObjects") kwargs = options_to_kwargs(options) @@ -672,6 +688,7 @@ async def list_objects( relation=body.relation, type=body.type, context=body.context, + consistency=self._get_consistency(options), ) if body.contextual_tuples: req_body.contextual_tuples = ContextualTupleKeys( @@ -691,6 +708,7 @@ async def list_relations( :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListRelations") options = set_heading_if_not_set( @@ -724,6 +742,7 @@ async def list_users( :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListUsers") kwargs = options_to_kwargs(options) @@ -735,6 +754,7 @@ async def list_users( user_filters=body.user_filters, contextual_tuples=body.contextual_tuples, context=body.context, + consistency=self._get_consistency(options), ) if body.contextual_tuples: diff --git a/openfga_sdk/models/__init__.py b/openfga_sdk/models/__init__.py index 630591b..d7c8c92 100644 --- a/openfga_sdk/models/__init__.py +++ b/openfga_sdk/models/__init__.py @@ -22,6 +22,7 @@ from openfga_sdk.models.condition import Condition from openfga_sdk.models.condition_metadata import ConditionMetadata from openfga_sdk.models.condition_param_type_ref import ConditionParamTypeRef +from openfga_sdk.models.consistency_preference import ConsistencyPreference from openfga_sdk.models.contextual_tuple_keys import ContextualTupleKeys from openfga_sdk.models.create_store_request import CreateStoreRequest from openfga_sdk.models.create_store_response import CreateStoreResponse diff --git a/openfga_sdk/models/check_request.py b/openfga_sdk/models/check_request.py index 036a2fa..0bbc9d4 100644 --- a/openfga_sdk/models/check_request.py +++ b/openfga_sdk/models/check_request.py @@ -39,6 +39,7 @@ class CheckRequest: "authorization_model_id": "str", "trace": "bool", "context": "object", + "consistency": "ConsistencyPreference", } attribute_map = { @@ -47,6 +48,7 @@ class CheckRequest: "authorization_model_id": "authorization_model_id", "trace": "trace", "context": "context", + "consistency": "consistency", } def __init__( @@ -56,6 +58,7 @@ def __init__( authorization_model_id=None, trace=None, context=None, + consistency=None, local_vars_configuration=None, ): """CheckRequest - a model defined in OpenAPI""" @@ -68,6 +71,7 @@ def __init__( self._authorization_model_id = None self._trace = None self._context = None + self._consistency = None self.discriminator = None self.tuple_key = tuple_key @@ -79,6 +83,8 @@ def __init__( self.trace = trace if context is not None: self.context = context + if consistency is not None: + self.consistency = consistency @property def tuple_key(self): @@ -191,6 +197,27 @@ def context(self, context): self._context = context + @property + def consistency(self): + """Gets the consistency of this CheckRequest. + + + :return: The consistency of this CheckRequest. + :rtype: ConsistencyPreference + """ + return self._consistency + + @consistency.setter + def consistency(self, consistency): + """Sets the consistency of this CheckRequest. + + + :param consistency: The consistency of this CheckRequest. + :type consistency: ConsistencyPreference + """ + + self._consistency = consistency + def to_dict(self, serialize=False): """Returns the model properties as a dict""" result = {} diff --git a/openfga_sdk/models/consistency_preference.py b/openfga_sdk/models/consistency_preference.py new file mode 100644 index 0000000..7340dc5 --- /dev/null +++ b/openfga_sdk/models/consistency_preference.py @@ -0,0 +1,104 @@ +""" + Python SDK for OpenFGA + + API version: 1.x + Website: https://openfga.dev + Documentation: https://openfga.dev/docs + Support: https://openfga.dev/community + License: [Apache-2.0](https://github.com/openfga/python-sdk/blob/main/LICENSE) + + NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. +""" + +try: + from inspect import getfullargspec +except ImportError: + from inspect import getargspec as getfullargspec +import pprint + +from openfga_sdk.configuration import Configuration + + +class ConsistencyPreference: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + UNSPECIFIED = "UNSPECIFIED" + MINIMIZE_LATENCY = "MINIMIZE_LATENCY" + HIGHER_CONSISTENCY = "HIGHER_CONSISTENCY" + + allowable_values = [UNSPECIFIED, MINIMIZE_LATENCY, HIGHER_CONSISTENCY] + + """ + Attributes: + openapi_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + openapi_types = {} + + attribute_map = {} + + def __init__(self, local_vars_configuration=None): + """ConsistencyPreference - a model defined in OpenAPI""" + if local_vars_configuration is None: + local_vars_configuration = Configuration.get_default_copy() + self.local_vars_configuration = local_vars_configuration + self.discriminator = None + + def to_dict(self, serialize=False): + """Returns the model properties as a dict""" + result = {} + + def convert(x): + if hasattr(x, "to_dict"): + args = getfullargspec(x.to_dict).args + if len(args) == 1: + return x.to_dict() + else: + return x.to_dict(serialize) + else: + return x + + for attr, _ in self.openapi_types.items(): + value = getattr(self, attr) + attr = self.attribute_map.get(attr, attr) if serialize else attr + if isinstance(value, list): + result[attr] = list(map(lambda x: convert(x), value)) + elif isinstance(value, dict): + result[attr] = dict( + map(lambda item: (item[0], convert(item[1])), value.items()) + ) + else: + result[attr] = convert(value) + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, ConsistencyPreference): + return False + + return self.to_dict() == other.to_dict() + + def __ne__(self, other): + """Returns true if both objects are not equal""" + if not isinstance(other, ConsistencyPreference): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/expand_request.py b/openfga_sdk/models/expand_request.py index 2229ca6..08c7e27 100644 --- a/openfga_sdk/models/expand_request.py +++ b/openfga_sdk/models/expand_request.py @@ -36,15 +36,21 @@ class ExpandRequest: openapi_types = { "tuple_key": "ExpandRequestTupleKey", "authorization_model_id": "str", + "consistency": "ConsistencyPreference", } attribute_map = { "tuple_key": "tuple_key", "authorization_model_id": "authorization_model_id", + "consistency": "consistency", } def __init__( - self, tuple_key=None, authorization_model_id=None, local_vars_configuration=None + self, + tuple_key=None, + authorization_model_id=None, + consistency=None, + local_vars_configuration=None, ): """ExpandRequest - a model defined in OpenAPI""" if local_vars_configuration is None: @@ -53,11 +59,14 @@ def __init__( self._tuple_key = None self._authorization_model_id = None + self._consistency = None self.discriminator = None self.tuple_key = tuple_key if authorization_model_id is not None: self.authorization_model_id = authorization_model_id + if consistency is not None: + self.consistency = consistency @property def tuple_key(self): @@ -103,6 +112,27 @@ def authorization_model_id(self, authorization_model_id): self._authorization_model_id = authorization_model_id + @property + def consistency(self): + """Gets the consistency of this ExpandRequest. + + + :return: The consistency of this ExpandRequest. + :rtype: ConsistencyPreference + """ + return self._consistency + + @consistency.setter + def consistency(self, consistency): + """Sets the consistency of this ExpandRequest. + + + :param consistency: The consistency of this ExpandRequest. + :type consistency: ConsistencyPreference + """ + + self._consistency = consistency + def to_dict(self, serialize=False): """Returns the model properties as a dict""" result = {} diff --git a/openfga_sdk/models/list_objects_request.py b/openfga_sdk/models/list_objects_request.py index e8ec957..500db21 100644 --- a/openfga_sdk/models/list_objects_request.py +++ b/openfga_sdk/models/list_objects_request.py @@ -40,6 +40,7 @@ class ListObjectsRequest: "user": "str", "contextual_tuples": "ContextualTupleKeys", "context": "object", + "consistency": "ConsistencyPreference", } attribute_map = { @@ -49,6 +50,7 @@ class ListObjectsRequest: "user": "user", "contextual_tuples": "contextual_tuples", "context": "context", + "consistency": "consistency", } def __init__( @@ -59,6 +61,7 @@ def __init__( user=None, contextual_tuples=None, context=None, + consistency=None, local_vars_configuration=None, ): """ListObjectsRequest - a model defined in OpenAPI""" @@ -72,6 +75,7 @@ def __init__( self._user = None self._contextual_tuples = None self._context = None + self._consistency = None self.discriminator = None if authorization_model_id is not None: @@ -83,6 +87,8 @@ def __init__( self.contextual_tuples = contextual_tuples if context is not None: self.context = context + if consistency is not None: + self.consistency = consistency @property def authorization_model_id(self): @@ -234,6 +240,27 @@ def context(self, context): self._context = context + @property + def consistency(self): + """Gets the consistency of this ListObjectsRequest. + + + :return: The consistency of this ListObjectsRequest. + :rtype: ConsistencyPreference + """ + return self._consistency + + @consistency.setter + def consistency(self, consistency): + """Sets the consistency of this ListObjectsRequest. + + + :param consistency: The consistency of this ListObjectsRequest. + :type consistency: ConsistencyPreference + """ + + self._consistency = consistency + def to_dict(self, serialize=False): """Returns the model properties as a dict""" result = {} diff --git a/openfga_sdk/models/list_users_request.py b/openfga_sdk/models/list_users_request.py index e7647cd..27422e2 100644 --- a/openfga_sdk/models/list_users_request.py +++ b/openfga_sdk/models/list_users_request.py @@ -40,6 +40,7 @@ class ListUsersRequest: "user_filters": "list[UserTypeFilter]", "contextual_tuples": "list[TupleKey]", "context": "object", + "consistency": "ConsistencyPreference", } attribute_map = { @@ -49,6 +50,7 @@ class ListUsersRequest: "user_filters": "user_filters", "contextual_tuples": "contextual_tuples", "context": "context", + "consistency": "consistency", } def __init__( @@ -59,6 +61,7 @@ def __init__( user_filters=None, contextual_tuples=None, context=None, + consistency=None, local_vars_configuration=None, ): """ListUsersRequest - a model defined in OpenAPI""" @@ -72,6 +75,7 @@ def __init__( self._user_filters = None self._contextual_tuples = None self._context = None + self._consistency = None self.discriminator = None if authorization_model_id is not None: @@ -83,6 +87,8 @@ def __init__( self.contextual_tuples = contextual_tuples if context is not None: self.context = context + if consistency is not None: + self.consistency = consistency @property def authorization_model_id(self): @@ -223,6 +229,27 @@ def context(self, context): self._context = context + @property + def consistency(self): + """Gets the consistency of this ListUsersRequest. + + + :return: The consistency of this ListUsersRequest. + :rtype: ConsistencyPreference + """ + return self._consistency + + @consistency.setter + def consistency(self, consistency): + """Sets the consistency of this ListUsersRequest. + + + :param consistency: The consistency of this ListUsersRequest. + :type consistency: ConsistencyPreference + """ + + self._consistency = consistency + def to_dict(self, serialize=False): """Returns the model properties as a dict""" result = {} diff --git a/openfga_sdk/models/read_request.py b/openfga_sdk/models/read_request.py index 5a7baaa..451677d 100644 --- a/openfga_sdk/models/read_request.py +++ b/openfga_sdk/models/read_request.py @@ -37,12 +37,14 @@ class ReadRequest: "tuple_key": "ReadRequestTupleKey", "page_size": "int", "continuation_token": "str", + "consistency": "ConsistencyPreference", } attribute_map = { "tuple_key": "tuple_key", "page_size": "page_size", "continuation_token": "continuation_token", + "consistency": "consistency", } def __init__( @@ -50,6 +52,7 @@ def __init__( tuple_key=None, page_size=None, continuation_token=None, + consistency=None, local_vars_configuration=None, ): """ReadRequest - a model defined in OpenAPI""" @@ -60,6 +63,7 @@ def __init__( self._tuple_key = None self._page_size = None self._continuation_token = None + self._consistency = None self.discriminator = None if tuple_key is not None: @@ -68,6 +72,8 @@ def __init__( self.page_size = page_size if continuation_token is not None: self.continuation_token = continuation_token + if consistency is not None: + self.consistency = consistency @property def tuple_key(self): @@ -132,6 +138,27 @@ def continuation_token(self, continuation_token): self._continuation_token = continuation_token + @property + def consistency(self): + """Gets the consistency of this ReadRequest. + + + :return: The consistency of this ReadRequest. + :rtype: ConsistencyPreference + """ + return self._consistency + + @consistency.setter + def consistency(self, consistency): + """Sets the consistency of this ReadRequest. + + + :param consistency: The consistency of this ReadRequest. + :type consistency: ConsistencyPreference + """ + + self._consistency = consistency + def to_dict(self, serialize=False): """Returns the model properties as a dict""" result = {} diff --git a/openfga_sdk/sync/client/client.py b/openfga_sdk/sync/client/client.py index e4de694..27bb4a7 100644 --- a/openfga_sdk/sync/client/client.py +++ b/openfga_sdk/sync/client/client.py @@ -158,6 +158,15 @@ def _get_authorization_model_id(self, options: object) -> str | None: ) return authorization_model_id + def _get_consistency(self, options: object) -> str | None: + """ + Returns the consistency requested if specified in the options. + Otherwise, returns None. + """ + if options is not None and "consistency" in options: + return options["consistency"] + return None + def set_store_id(self, value): """ Update the store ID in the configuration @@ -360,6 +369,7 @@ def read(self, body: ReadRequestTupleKey, options: dict[str, str] = None): :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "Read") page_size = None @@ -385,6 +395,7 @@ def read(self, body: ReadRequestTupleKey, options: dict[str, str] = None): tuple_key=tuple_key, page_size=page_size, continuation_token=continuation_token, + consistency=self._get_consistency(options), ), **kwargs, ) @@ -541,6 +552,7 @@ def check(self, body: ClientCheckRequest, options: dict[str, str] = None): :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "Check") @@ -554,6 +566,7 @@ def check(self, body: ClientCheckRequest, options: dict[str, str] = None): ), context=body.context, authorization_model_id=self._get_authorization_model_id(options), + consistency=self._get_consistency(options), ) if body.contextual_tuples: req_body.contextual_tuples = ContextualTupleKeys( @@ -597,6 +610,7 @@ def batch_check( :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "BatchCheck") options = set_heading_if_not_set( @@ -627,6 +641,7 @@ def expand(self, body: ClientExpandRequest, options: dict[str, str] = None): :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "Expand") kwargs = options_to_kwargs(options) @@ -637,6 +652,7 @@ def expand(self, body: ClientExpandRequest, options: dict[str, str] = None): object=body.object, ), authorization_model_id=self._get_authorization_model_id(options), + consistency=self._get_consistency(options), ) api_response = self._api.expand(body=req_body, **kwargs) return api_response @@ -652,6 +668,7 @@ def list_objects( :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListObjects") kwargs = options_to_kwargs(options) @@ -662,6 +679,7 @@ def list_objects( relation=body.relation, type=body.type, context=body.context, + consistency=self._get_consistency(options), ) if body.contextual_tuples: req_body.contextual_tuples = ContextualTupleKeys( @@ -681,6 +699,7 @@ def list_relations( :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListRelations") options = set_heading_if_not_set( @@ -712,6 +731,7 @@ def list_users(self, body: ClientListUsersRequest, options: dict[str, str] = Non :param retryParams(options) - Override the retry parameters for this request :param retryParams.maxRetry(options) - Override the max number of retries on each API request :param retryParams.minWaitInMs(options) - Override the minimum wait before a retry is initiated + :param consistency(options) - The type of consistency preferred for the request """ options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListUsers") kwargs = options_to_kwargs(options) @@ -723,6 +743,7 @@ def list_users(self, body: ClientListUsersRequest, options: dict[str, str] = Non user_filters=body.user_filters, contextual_tuples=body.contextual_tuples, context=body.context, + consistency=self._get_consistency(options), ) if body.contextual_tuples: diff --git a/openfga_sdk/sync/open_fga_api.py b/openfga_sdk/sync/open_fga_api.py index 2512f0b..4405952 100644 --- a/openfga_sdk/sync/open_fga_api.py +++ b/openfga_sdk/sync/open_fga_api.py @@ -1331,9 +1331,9 @@ def list_stores_with_http_info(self, **kwargs): ) def list_users(self, body, **kwargs): - """[EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. + """List the users matching the provided filter who have a certain relation to a particular type. - The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. This API is available in an experimental capacity and can be enabled with the `--experimentals enable-list-users` flag. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. + The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. >>> thread = api.list_users(body) @@ -1358,9 +1358,9 @@ def list_users(self, body, **kwargs): return self.list_users_with_http_info(body, **kwargs) def list_users_with_http_info(self, body, **kwargs): - """[EXPERIMENTAL] List the users matching the provided filter who have a certain relation to a particular type. + """List the users matching the provided filter who have a certain relation to a particular type. - The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. This API is available in an experimental capacity and can be enabled with the `--experimentals enable-list-users` flag. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. + The ListUsers API returns a list of all the users of a specific type that have a relation to a given object. To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related users in an array in the \"users\" field of the response. These results may include specific objects, usersets or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public acces result is returned (e.g. `user:*`), it cannot be inferred that all subjects of that type have a relation to the object; it is possible that negations exist and checks should still be queried on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. The returned users will not be sorted, and therefore two identical calls may yield different sets of users. >>> thread = api.list_users_with_http_info(body) diff --git a/test/client/client_test.py b/test/client/client_test.py index 196e3d4..eba82b8 100644 --- a/test/client/client_test.py +++ b/test/client/client_test.py @@ -38,6 +38,7 @@ from openfga_sdk.models.assertion import Assertion from openfga_sdk.models.authorization_model import AuthorizationModel from openfga_sdk.models.check_response import CheckResponse +from openfga_sdk.models.consistency_preference import ConsistencyPreference from openfga_sdk.models.create_store_request import CreateStoreRequest from openfga_sdk.models.create_store_response import CreateStoreResponse from openfga_sdk.models.expand_response import ExpandResponse @@ -711,6 +712,7 @@ async def test_read(self, mock_request): options={ "page_size": 50, "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, }, ) self.assertIsInstance(api_response, ReadResponse) @@ -738,6 +740,7 @@ async def test_read(self, mock_request): }, "page_size": 50, "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -1801,7 +1804,10 @@ async def test_check(self, mock_request): async with OpenFgaClient(configuration) as api_client: api_response = await api_client.check( body=body, - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, CheckResponse) self.assertTrue(api_response.allowed) @@ -1828,6 +1834,7 @@ async def test_check(self, mock_request): ] }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2159,7 +2166,10 @@ async def test_expand(self, mock_request): ) api_response = await api_client.expand( body=body, - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, ExpandResponse) cur_users = Users(users=["user:81684243-9356-4421-8fbf-a4f8d36aa31b"]) @@ -2177,6 +2187,7 @@ async def test_expand(self, mock_request): body={ "tuple_key": {"object": "document:budget", "relation": "reader"}, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2207,7 +2218,11 @@ async def test_list_objects(self, mock_request): ) # Get all stores api_response = await api_client.list_objects( - body, options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"} + body, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, ListObjectsResponse) self.assertEqual(api_response.objects, ["document:abcd1234"]) @@ -2222,6 +2237,7 @@ async def test_list_objects(self, mock_request): "type": "document", "relation": "reader", "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2311,7 +2327,10 @@ async def test_list_relations(self, mock_request): relations=["reader", "owner", "viewer"], object="document:2021-budget", ), - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertEqual(api_response, ["reader", "viewer"]) @@ -2329,6 +2348,7 @@ async def test_list_relations(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2346,6 +2366,7 @@ async def test_list_relations(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2363,6 +2384,7 @@ async def test_list_relations(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2452,7 +2474,11 @@ async def test_list_users(self, mock_request): ) response = await api_client.list_users( - body, options={"authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J"} + body, + options={ + "authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(response, ListUsersResponse) @@ -2508,6 +2534,7 @@ async def test_list_users(self, mock_request): ] }, "context": {}, + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, diff --git a/test/sync/client/client_test.py b/test/sync/client/client_test.py index da90879..c358dea 100644 --- a/test/sync/client/client_test.py +++ b/test/sync/client/client_test.py @@ -36,6 +36,7 @@ from openfga_sdk.models.assertion import Assertion from openfga_sdk.models.authorization_model import AuthorizationModel from openfga_sdk.models.check_response import CheckResponse +from openfga_sdk.models.consistency_preference import ConsistencyPreference from openfga_sdk.models.create_store_request import CreateStoreRequest from openfga_sdk.models.create_store_response import CreateStoreResponse from openfga_sdk.models.expand_response import ExpandResponse @@ -711,6 +712,7 @@ def test_read(self, mock_request): options={ "page_size": 50, "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, }, ) self.assertIsInstance(api_response, ReadResponse) @@ -738,6 +740,7 @@ def test_read(self, mock_request): }, "page_size": 50, "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -1802,7 +1805,10 @@ def test_check(self, mock_request): with OpenFgaClient(configuration) as api_client: api_response = api_client.check( body=body, - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, CheckResponse) self.assertTrue(api_response.allowed) @@ -1829,6 +1835,7 @@ def test_check(self, mock_request): ] }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -1899,7 +1906,10 @@ def test_batch_check_single_request(self, mock_request): with OpenFgaClient(configuration) as api_client: api_response = api_client.batch_check( body=[body], - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, list) self.assertEqual(len(api_response), 1) @@ -1920,6 +1930,7 @@ def test_batch_check_single_request(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2160,7 +2171,10 @@ def test_expand(self, mock_request): ) api_response = api_client.expand( body=body, - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, ExpandResponse) cur_users = Users(users=["user:81684243-9356-4421-8fbf-a4f8d36aa31b"]) @@ -2178,6 +2192,7 @@ def test_expand(self, mock_request): body={ "tuple_key": {"object": "document:budget", "relation": "reader"}, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2208,7 +2223,11 @@ def test_list_objects(self, mock_request): ) # Get all stores api_response = api_client.list_objects( - body, options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"} + body, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(api_response, ListObjectsResponse) self.assertEqual(api_response.objects, ["document:abcd1234"]) @@ -2223,6 +2242,7 @@ def test_list_objects(self, mock_request): "type": "document", "relation": "reader", "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2312,7 +2332,10 @@ def test_list_relations(self, mock_request): relations=["reader", "owner", "viewer"], object="document:2021-budget", ), - options={"authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1"}, + options={ + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertEqual(api_response, ["reader", "viewer"]) @@ -2330,6 +2353,7 @@ def test_list_relations(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2347,6 +2371,7 @@ def test_list_relations(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2364,6 +2389,7 @@ def test_list_relations(self, mock_request): "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", }, "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1", + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None, @@ -2452,7 +2478,11 @@ def test_list_users(self, mock_request): ] response = api_client.list_users( - body, options={"authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J"} + body, + options={ + "authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J", + "consistency": ConsistencyPreference.MINIMIZE_LATENCY, + }, ) self.assertIsInstance(response, ListUsersResponse) @@ -2508,6 +2538,7 @@ def test_list_users(self, mock_request): ] }, "context": {}, + "consistency": "MINIMIZE_LATENCY", }, _preload_content=ANY, _request_timeout=None,