diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 5348dcc..cfebf7f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 @@ -59,7 +59,7 @@ jobs: - if: matrix.python-version == '3.10' name: Upload coverage to Codecov - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # v4.1.1 + uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # v4.3.0 continue-on-error: true with: token: ${{ secrets.CODECOV_TOKEN }} @@ -74,7 +74,7 @@ jobs: id-token: write # Required for PyPI trusted publishing steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 @@ -105,7 +105,7 @@ jobs: needs: [publish] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 diff --git a/.github/workflows/semgrep.yaml b/.github/workflows/semgrep.yaml index 78ab43f..2b936c0 100644 --- a/.github/workflows/semgrep.yaml +++ b/.github/workflows/semgrep.yaml @@ -11,7 +11,7 @@ jobs: image: returntocorp/semgrep if: (github.actor != 'dependabot[bot]' && github.actor != 'snyk-bot') steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: fetch-depth: 0 - run: semgrep ci --no-suppress-errors diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index f3f15c5..1289c29 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -35,6 +35,7 @@ docs/ErrorCode.md docs/ExpandRequest.md docs/ExpandRequestTupleKey.md docs/ExpandResponse.md +docs/FgaObject.md docs/GetStoreResponse.md docs/InternalErrorCode.md docs/InternalErrorMessageResponse.md @@ -42,11 +43,14 @@ docs/Leaf.md docs/ListObjectsRequest.md docs/ListObjectsResponse.md docs/ListStoresResponse.md +docs/ListUsersRequest.md +docs/ListUsersResponse.md docs/Metadata.md docs/Node.md docs/Nodes.md docs/NotFoundErrorCode.md docs/NullValue.md +docs/ObjectOrUserset.md docs/ObjectRelation.md docs/OpenFgaApi.md docs/PathUnknownErrorMessageResponse.md @@ -71,11 +75,18 @@ docs/TupleOperation.md docs/TupleToUserset.md docs/TypeDefinition.md docs/TypeName.md +docs/TypedWildcard.md +docs/UnauthenticatedResponse.md +docs/UnprocessableContentErrorCode.md +docs/UnprocessableContentMessageResponse.md +docs/User.md +docs/UserTypeFilter.md docs/Users.md docs/Userset.md docs/UsersetTree.md docs/UsersetTreeDifference.md docs/UsersetTreeTupleToUserset.md +docs/UsersetUser.md docs/Usersets.md docs/ValidationErrorMessageResponse.md docs/WriteAssertionsRequest.md @@ -105,6 +116,7 @@ openfga_sdk/client/models/check_request.py openfga_sdk/client/models/expand_request.py openfga_sdk/client/models/list_objects_request.py openfga_sdk/client/models/list_relations_request.py +openfga_sdk/client/models/list_users_request.py openfga_sdk/client/models/read_changes_request.py openfga_sdk/client/models/tuple.py openfga_sdk/client/models/write_request.py @@ -136,6 +148,7 @@ openfga_sdk/models/error_code.py openfga_sdk/models/expand_request.py openfga_sdk/models/expand_request_tuple_key.py openfga_sdk/models/expand_response.py +openfga_sdk/models/fga_object.py openfga_sdk/models/get_store_response.py openfga_sdk/models/internal_error_code.py openfga_sdk/models/internal_error_message_response.py @@ -143,11 +156,14 @@ openfga_sdk/models/leaf.py openfga_sdk/models/list_objects_request.py openfga_sdk/models/list_objects_response.py openfga_sdk/models/list_stores_response.py +openfga_sdk/models/list_users_request.py +openfga_sdk/models/list_users_response.py openfga_sdk/models/metadata.py openfga_sdk/models/node.py openfga_sdk/models/nodes.py openfga_sdk/models/not_found_error_code.py openfga_sdk/models/null_value.py +openfga_sdk/models/object_or_userset.py openfga_sdk/models/object_relation.py openfga_sdk/models/path_unknown_error_message_response.py openfga_sdk/models/read_assertions_response.py @@ -171,11 +187,18 @@ openfga_sdk/models/tuple_operation.py openfga_sdk/models/tuple_to_userset.py openfga_sdk/models/type_definition.py openfga_sdk/models/type_name.py +openfga_sdk/models/typed_wildcard.py +openfga_sdk/models/unauthenticated_response.py +openfga_sdk/models/unprocessable_content_error_code.py +openfga_sdk/models/unprocessable_content_message_response.py +openfga_sdk/models/user.py +openfga_sdk/models/user_type_filter.py openfga_sdk/models/users.py openfga_sdk/models/userset.py openfga_sdk/models/userset_tree.py openfga_sdk/models/userset_tree_difference.py openfga_sdk/models/userset_tree_tuple_to_userset.py +openfga_sdk/models/userset_user.py openfga_sdk/models/usersets.py openfga_sdk/models/validation_error_message_response.py openfga_sdk/models/write_assertions_request.py diff --git a/README.md b/README.md index 3271034..99e73d1 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ This is an autogenerated python SDK for OpenFGA. It provides a wrapper around th - [Expand](#expand) - [List Objects](#list-objects) - [List Relations](#list-relations) + - [List Users](#list-users) - [Assertions](#assertions) - [Read Assertions](#read-assertions) - [Write Assertions](#write-assertions) @@ -132,7 +133,7 @@ async def main(): configuration = ClientConfiguration( api_url=FGA_API_URL, # required store_id=FGA_STORE_ID, # optional, not needed when calling `CreateStore` or `ListStores` - authorization_model_id=FGA_AUTHORIZATION_MODEL_ID, # Optional, can be overridden per request + authorization_model_id=FGA_MODEL_ID, # Optional, can be overridden per request ) # Enter a context with an instance of the OpenFgaClient async with OpenFgaClient(configuration) as fga_client: @@ -152,7 +153,7 @@ async def main(): configuration = ClientConfiguration( api_url=FGA_API_URL, # required store_id=FGA_STORE_ID, # optional, not needed when calling `CreateStore` or `ListStores` - authorization_model_id=FGA_AUTHORIZATION_MODEL_ID, # Optional, can be overridden per request + authorization_model_id=FGA_MODEL_ID, # Optional, can be overridden per request credentials=Credentials( method='api_token', configuration=CredentialConfiguration( @@ -178,7 +179,7 @@ async def main(): configuration = ClientConfiguration( api_url=FGA_API_URL, # required store_id=FGA_STORE_ID, # optional, not needed when calling `CreateStore` or `ListStores` - authorization_model_id=FGA_AUTHORIZATION_MODEL_ID, # Optional, can be overridden per request + authorization_model_id=FGA_MODEL_ID, # Optional, can be overridden per request credentials=Credentials( method='client_credentials', configuration=CredentialConfiguration( @@ -210,7 +211,7 @@ def main(): configuration = ClientConfiguration( api_url=FGA_API_URL, # required store_id=FGA_STORE_ID, # optional, not needed when calling `CreateStore` or `ListStores` - authorization_model_id=FGA_AUTHORIZATION_MODEL_ID, # optional, can be overridden per request + authorization_model_id=FGA_MODEL_ID, # optional, can be overridden per request ) # Enter a context with an instance of the OpenFgaClient with OpenFgaClient(configuration) as fga_client: @@ -444,7 +445,7 @@ Reads the latest authorization model (note: this ignores the model id in configu # Create the cofiguration object # configuration = ClientConfiguration( # ... -# authorization_model_id = FGA_AUTHORIZATION_MODEL_ID, +# authorization_model_id = FGA_MODEL_ID, # ... # ) @@ -832,8 +833,7 @@ response = await fga_client.expand(body. options) # response = ExpandResponse({"tree": UsersetTree({"root": Node({"name": "document:roadmap#viewer", "leaf": Leaf({"users": Users({"users": ["user:81684243-9356-4421-8fbf-a4f8d36aa31b", "user:f52a4f7a-054d-47ff-bb6e-3ac81269988f"]})})})})}) ``` - -##### List Objects +#### List Objects List the objects of a particular type a user has access to. @@ -870,7 +870,7 @@ response = await fga_client.list_objects(body) # response.objects = ["document:roadmap"] ``` -##### List Relations +#### List Relations List the relations a user has on an object. @@ -906,6 +906,54 @@ response = await fga_client.list_relations(body, options) # response.relations = ["can_view", "can_edit"] ``` +#### List Users + +List the users who have a certain relation to a particular type. + +[API Documentation](https://openfga.dev/api/service#/Relationship%20Queries/ListUsers) + +```python +from openfga_sdk import OpenFgaClient +from openfga_sdk.client.models import ClientListUsersRequest, ClientTuple + +configuration = ClientConfiguration( + api_url=FGA_API_URL, + # ... +) + +async with OpenFgaClient(configuration) as api_client: + options = { + "authorization_model_id": "01GXSA8YR785C4FYS3C0RTG7B1" + } + + request = ClientListUsersRequest( + object="document:2021-budget", + relation="can_read", + user_filters=[ + UserTypeFilter(type="user"), + UserTypeFilter(type="team", relation="member"), + ], + context={}, + contextual_tuples=[ + ClientTuple( + user="user:81684243-9356-4421-8fbf-a4f8d36aa31b", + relation="editor", + object="folder:product", + ), + ClientTuple( + user="folder:product", + relation="parent", + object="document:roadmap", + ), + ], + ) + + response = await api_client.list_users(request, options) + + # response.users = [{object: {type: "user", id: "81684243-9356-4421-8fbf-a4f8d36aa31b"}}, {userset: { type: "user" }}, ...] + # response.excluded_users = [ {object: {type: "user", id: "4a455e27-d15a-4434-82e0-136f9c2aa4cf"}}, ... ] +``` + #### Assertions ##### Read Assertions @@ -994,6 +1042,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* | [**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 @@ -1029,6 +1078,7 @@ Class | Method | HTTP request | Description - [ExpandRequest](https://github.com/openfga/python-sdk/blob/main/docs/ExpandRequest.md) - [ExpandRequestTupleKey](https://github.com/openfga/python-sdk/blob/main/docs/ExpandRequestTupleKey.md) - [ExpandResponse](https://github.com/openfga/python-sdk/blob/main/docs/ExpandResponse.md) + - [FgaObject](https://github.com/openfga/python-sdk/blob/main/docs/FgaObject.md) - [GetStoreResponse](https://github.com/openfga/python-sdk/blob/main/docs/GetStoreResponse.md) - [InternalErrorCode](https://github.com/openfga/python-sdk/blob/main/docs/InternalErrorCode.md) - [InternalErrorMessageResponse](https://github.com/openfga/python-sdk/blob/main/docs/InternalErrorMessageResponse.md) @@ -1036,11 +1086,14 @@ Class | Method | HTTP request | Description - [ListObjectsRequest](https://github.com/openfga/python-sdk/blob/main/docs/ListObjectsRequest.md) - [ListObjectsResponse](https://github.com/openfga/python-sdk/blob/main/docs/ListObjectsResponse.md) - [ListStoresResponse](https://github.com/openfga/python-sdk/blob/main/docs/ListStoresResponse.md) + - [ListUsersRequest](https://github.com/openfga/python-sdk/blob/main/docs/ListUsersRequest.md) + - [ListUsersResponse](https://github.com/openfga/python-sdk/blob/main/docs/ListUsersResponse.md) - [Metadata](https://github.com/openfga/python-sdk/blob/main/docs/Metadata.md) - [Node](https://github.com/openfga/python-sdk/blob/main/docs/Node.md) - [Nodes](https://github.com/openfga/python-sdk/blob/main/docs/Nodes.md) - [NotFoundErrorCode](https://github.com/openfga/python-sdk/blob/main/docs/NotFoundErrorCode.md) - [NullValue](https://github.com/openfga/python-sdk/blob/main/docs/NullValue.md) + - [ObjectOrUserset](https://github.com/openfga/python-sdk/blob/main/docs/ObjectOrUserset.md) - [ObjectRelation](https://github.com/openfga/python-sdk/blob/main/docs/ObjectRelation.md) - [PathUnknownErrorMessageResponse](https://github.com/openfga/python-sdk/blob/main/docs/PathUnknownErrorMessageResponse.md) - [ReadAssertionsResponse](https://github.com/openfga/python-sdk/blob/main/docs/ReadAssertionsResponse.md) @@ -1064,11 +1117,18 @@ Class | Method | HTTP request | Description - [TupleToUserset](https://github.com/openfga/python-sdk/blob/main/docs/TupleToUserset.md) - [TypeDefinition](https://github.com/openfga/python-sdk/blob/main/docs/TypeDefinition.md) - [TypeName](https://github.com/openfga/python-sdk/blob/main/docs/TypeName.md) + - [TypedWildcard](https://github.com/openfga/python-sdk/blob/main/docs/TypedWildcard.md) + - [UnauthenticatedResponse](https://github.com/openfga/python-sdk/blob/main/docs/UnauthenticatedResponse.md) + - [UnprocessableContentErrorCode](https://github.com/openfga/python-sdk/blob/main/docs/UnprocessableContentErrorCode.md) + - [UnprocessableContentMessageResponse](https://github.com/openfga/python-sdk/blob/main/docs/UnprocessableContentMessageResponse.md) + - [User](https://github.com/openfga/python-sdk/blob/main/docs/User.md) + - [UserTypeFilter](https://github.com/openfga/python-sdk/blob/main/docs/UserTypeFilter.md) - [Users](https://github.com/openfga/python-sdk/blob/main/docs/Users.md) - [Userset](https://github.com/openfga/python-sdk/blob/main/docs/Userset.md) - [UsersetTree](https://github.com/openfga/python-sdk/blob/main/docs/UsersetTree.md) - [UsersetTreeDifference](https://github.com/openfga/python-sdk/blob/main/docs/UsersetTreeDifference.md) - [UsersetTreeTupleToUserset](https://github.com/openfga/python-sdk/blob/main/docs/UsersetTreeTupleToUserset.md) + - [UsersetUser](https://github.com/openfga/python-sdk/blob/main/docs/UsersetUser.md) - [Usersets](https://github.com/openfga/python-sdk/blob/main/docs/Usersets.md) - [ValidationErrorMessageResponse](https://github.com/openfga/python-sdk/blob/main/docs/ValidationErrorMessageResponse.md) - [WriteAssertionsRequest](https://github.com/openfga/python-sdk/blob/main/docs/WriteAssertionsRequest.md) diff --git a/docs/FgaObject.md b/docs/FgaObject.md new file mode 100644 index 0000000..84754b5 --- /dev/null +++ b/docs/FgaObject.md @@ -0,0 +1,13 @@ +# FgaObject + +Object represents an OpenFGA Object. An Object is composed of a type and identifier (e.g. 'document:1') See https://openfga.dev/docs/concepts#what-is-an-object + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | | +**id** | **str** | | + +[[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 new file mode 100644 index 0000000..381104b --- /dev/null +++ b/docs/ListUsersRequest.md @@ -0,0 +1,16 @@ +# ListUsersRequest + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**authorization_model_id** | **str** | | [optional] +**object** | [**FgaObject**](FgaObject.md) | | +**relation** | **str** | | +**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] + +[[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/ListUsersResponse.md b/docs/ListUsersResponse.md new file mode 100644 index 0000000..6a82454 --- /dev/null +++ b/docs/ListUsersResponse.md @@ -0,0 +1,12 @@ +# ListUsersResponse + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**users** | [**list[User]**](User.md) | | +**excluded_users** | [**list[ObjectOrUserset]**](ObjectOrUserset.md) | | + +[[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/ObjectOrUserset.md b/docs/ObjectOrUserset.md new file mode 100644 index 0000000..8540631 --- /dev/null +++ b/docs/ObjectOrUserset.md @@ -0,0 +1,12 @@ +# ObjectOrUserset + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**object** | [**FgaObject**](FgaObject.md) | | [optional] +**userset** | [**UsersetUser**](UsersetUser.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 7060274..c495d95 100644 --- a/docs/OpenFgaApi.md +++ b/docs/OpenFgaApi.md @@ -11,6 +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. [**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 @@ -26,7 +27,7 @@ Method | HTTP request | Description Check whether a user is authorized to access an object -The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. +The Check API returns whether a given user has a relationship with a given object in a given store. The `user` field of the request can be a specific target, such as `user:anne`, or a userset (set of users) such as `group:marketing#member` or a type-bound public access `user:*`. 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`). A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. Some exceptions apply, but in general, if a Check API responds with `{allowed: true}`, then you can expect the equivalent ListObjects query to return the object, and viceversa. For example, if `Check(user:anne, reader, document:2021-budget)` responds with `{allowed: true}`, then `ListObjects(user:anne, reader, document)` may include `document:2021-budget` in the response. ## Examples ### Querying with contextual tuples In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Querying usersets Some Checks will always return `true`, even without any tuples. For example, for the following authorization model ```python model schema 1.1 type user type document relations define reader: [user] ``` the following query ```json { \"tuple_key\": { \"user\": \"document:2021-budget#reader\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } } ``` will always return `{ \"allowed\": true }`. This is because usersets are self-defining: the userset `document:2021-budget#reader` will always have the `reader` relation with `document:2021-budget`. ### Querying usersets with difference in the model A Check for a userset can yield results that must be treated carefully if the model involves difference. For example, for the following authorization model ```python model schema 1.1 type user type group relations define member: [user] type document relations define blocked: [user] define reader: [group#member] but not blocked ``` the following query ```json { \"tuple_key\": { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"group:finance\" }, { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, { \"user\": \"user:anne\", \"relation\": \"blocked\", \"object\": \"document:2021-budget\" } ] }, } ``` will return `{ \"allowed\": true }`, even though a specific user of the userset `group:finance#member` does not have the `reader` relationship with the given object. ### Example @@ -96,8 +97,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -175,8 +178,10 @@ No authorization required |-------------|-------------|------------------| **201** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -253,8 +258,10 @@ No authorization required |-------------|-------------|------------------| **204** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -334,8 +341,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -413,8 +422,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -424,7 +435,7 @@ No authorization required List all objects of the given type that the user has a relation with -The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. +The ListObjects API returns a list of all the objects of the given type that the user has a relation with. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. ### Example @@ -494,8 +505,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -574,8 +587,93 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | +**500** | Request failed due to internal server error. | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **list_users** +> ListUsersResponse list_users(body) + +[EXPERIMENTAL] 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 certain cases of negation via the `but not` operator, some results are marked as excluded from the main set of results. These exclusions are returned in the `excluded_users` property and should be handled appropriately at the point of implementation.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 + +```python +import time +import openfga_sdk +from openfga_sdk.rest import ApiException +from pprint import pprint +# To configure the configuration +# host is mandatory +# api_scheme is optional and default to https +# store_id is mandatory +# See configuration.py for a list of all supported configuration parameters. +configuration = openfga_sdk.Configuration( + scheme = "https", + api_host = "api.fga.example", + store_id = 'YOUR_STORE_ID', +) + + +# When authenticating via the API TOKEN method +credentials = Credentials(method='api_token', configuration=CredentialConfiguration(api_token='TOKEN1')) +configuration = openfga_sdk.Configuration( + scheme = "https", + api_host = "api.fga.example", + store_id = 'YOUR_STORE_ID', + credentials = credentials +) + +# Enter a context with an instance of the API client +async with openfga_sdk.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = openfga_sdk.OpenFgaApi(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. + api_response = await api_instance.api_instance.list_users(body) + pprint(api_response) + except ApiException as e: + print("Exception when calling OpenFgaApi->list_users: %s\n" % e) + await api_client.close() +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **body** | [**ListUsersRequest**](ListUsersRequest.md)| | + +### Return type + +[**ListUsersResponse**](ListUsersResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | A successful response. | - | +**400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | +**404** | Request failed due to incorrect path. | - | +**409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -655,8 +753,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -736,8 +836,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -817,8 +919,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -900,8 +1004,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -985,8 +1091,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -996,7 +1104,7 @@ No authorization required Add or delete tuples from the store -The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` +The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. The API will not allow you to write tuples such as `document:2021-budget#viewer@document:2021-budget#viewer`, because they are implicit. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` ### Example @@ -1066,8 +1174,10 @@ No authorization required |-------------|-------------|------------------| **200** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -1148,8 +1258,10 @@ No authorization required |-------------|-------------|------------------| **204** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) @@ -1229,8 +1341,10 @@ No authorization required |-------------|-------------|------------------| **201** | A successful response. | - | **400** | Request failed due to invalid input. | - | +**401** | Not authenticated. | - | **404** | Request failed due to incorrect path. | - | **409** | Request was aborted due a transaction conflict. | - | +**422** | Request timed out due to excessive request throttling. | - | **500** | Request failed due to internal server error. | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/docs/TypedWildcard.md b/docs/TypedWildcard.md new file mode 100644 index 0000000..01d46a2 --- /dev/null +++ b/docs/TypedWildcard.md @@ -0,0 +1,12 @@ +# TypedWildcard + +Type bound public access. Normally represented using the `:*` syntax `employee:*` represents every object of type `employee`, including those not currently present in the system See https://openfga.dev/docs/concepts#what-is-type-bound-public-access + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | | + +[[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/UnauthenticatedResponse.md b/docs/UnauthenticatedResponse.md new file mode 100644 index 0000000..2fc69d1 --- /dev/null +++ b/docs/UnauthenticatedResponse.md @@ -0,0 +1,12 @@ +# UnauthenticatedResponse + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**code** | [**ErrorCode**](ErrorCode.md) | | [optional] +**message** | **str** | | [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/UnprocessableContentErrorCode.md b/docs/UnprocessableContentErrorCode.md new file mode 100644 index 0000000..2df708c --- /dev/null +++ b/docs/UnprocessableContentErrorCode.md @@ -0,0 +1,10 @@ +# UnprocessableContentErrorCode + + +## 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/UnprocessableContentMessageResponse.md b/docs/UnprocessableContentMessageResponse.md new file mode 100644 index 0000000..b3fe430 --- /dev/null +++ b/docs/UnprocessableContentMessageResponse.md @@ -0,0 +1,12 @@ +# UnprocessableContentMessageResponse + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**code** | [**UnprocessableContentErrorCode**](UnprocessableContentErrorCode.md) | | [optional] +**message** | **str** | | [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/User.md b/docs/User.md new file mode 100644 index 0000000..73ba82e --- /dev/null +++ b/docs/User.md @@ -0,0 +1,14 @@ +# User + +User. Represents any possible value for a user (subject or principal). Can be a: - Specific user object e.g.: 'user:will', 'folder:marketing', 'org:contoso', ...) - Specific userset (e.g. 'group:engineering#member') - Public-typed wildcard (e.g. 'user:*') See https://openfga.dev/docs/concepts#what-is-a-user + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**object** | [**FgaObject**](FgaObject.md) | | [optional] +**userset** | [**UsersetUser**](UsersetUser.md) | | [optional] +**wildcard** | [**TypedWildcard**](TypedWildcard.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/UserTypeFilter.md b/docs/UserTypeFilter.md new file mode 100644 index 0000000..f66b9e4 --- /dev/null +++ b/docs/UserTypeFilter.md @@ -0,0 +1,12 @@ +# UserTypeFilter + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | | +**relation** | **str** | | [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/UsersetUser.md b/docs/UsersetUser.md new file mode 100644 index 0000000..c788b39 --- /dev/null +++ b/docs/UsersetUser.md @@ -0,0 +1,14 @@ +# UsersetUser + +Userset. A set or group of users, represented in the `:#` format `group:fga#member` represents all members of group FGA, not to be confused by `group:fga` which represents the group itself as a specific object. See: https://openfga.dev/docs/modeling/building-blocks/usersets#what-is-a-userset + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**type** | **str** | | +**id** | **str** | | +**relation** | **str** | | + +[[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 4669444..0b15873 100644 --- a/openfga_sdk/__init__.py +++ b/openfga_sdk/__init__.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -45,6 +45,7 @@ from openfga_sdk.models.expand_request import ExpandRequest from openfga_sdk.models.expand_request_tuple_key import ExpandRequestTupleKey from openfga_sdk.models.expand_response import ExpandResponse +from openfga_sdk.models.fga_object import FgaObject from openfga_sdk.models.get_store_response import GetStoreResponse from openfga_sdk.models.internal_error_code import InternalErrorCode from openfga_sdk.models.internal_error_message_response import ( @@ -54,11 +55,14 @@ from openfga_sdk.models.list_objects_request import ListObjectsRequest from openfga_sdk.models.list_objects_response import ListObjectsResponse from openfga_sdk.models.list_stores_response import ListStoresResponse +from openfga_sdk.models.list_users_request import ListUsersRequest +from openfga_sdk.models.list_users_response import ListUsersResponse from openfga_sdk.models.metadata import Metadata from openfga_sdk.models.node import Node from openfga_sdk.models.nodes import Nodes from openfga_sdk.models.not_found_error_code import NotFoundErrorCode from openfga_sdk.models.null_value import NullValue +from openfga_sdk.models.object_or_userset import ObjectOrUserset from openfga_sdk.models.object_relation import ObjectRelation from openfga_sdk.models.path_unknown_error_message_response import ( PathUnknownErrorMessageResponse, @@ -88,11 +92,22 @@ from openfga_sdk.models.tuple_to_userset import TupleToUserset from openfga_sdk.models.type_definition import TypeDefinition from openfga_sdk.models.type_name import TypeName +from openfga_sdk.models.typed_wildcard import TypedWildcard +from openfga_sdk.models.unauthenticated_response import UnauthenticatedResponse +from openfga_sdk.models.unprocessable_content_error_code import ( + UnprocessableContentErrorCode, +) +from openfga_sdk.models.unprocessable_content_message_response import ( + UnprocessableContentMessageResponse, +) +from openfga_sdk.models.user import User +from openfga_sdk.models.user_type_filter import UserTypeFilter from openfga_sdk.models.users import Users from openfga_sdk.models.userset import Userset from openfga_sdk.models.userset_tree import UsersetTree from openfga_sdk.models.userset_tree_difference import UsersetTreeDifference from openfga_sdk.models.userset_tree_tuple_to_userset import UsersetTreeTupleToUserset +from openfga_sdk.models.userset_user import UsersetUser from openfga_sdk.models.usersets import Usersets from openfga_sdk.models.validation_error_message_response import ( ValidationErrorMessageResponse, diff --git a/openfga_sdk/api/open_fga_api.py b/openfga_sdk/api/open_fga_api.py index 2b88230..354e004 100644 --- a/openfga_sdk/api/open_fga_api.py +++ b/openfga_sdk/api/open_fga_api.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -45,7 +45,7 @@ async def close(self): async def check(self, body, **kwargs): """Check whether a user is authorized to access an object - The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. + The Check API returns whether a given user has a relationship with a given object in a given store. The `user` field of the request can be a specific target, such as `user:anne`, or a userset (set of users) such as `group:marketing#member` or a type-bound public access `user:*`. 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`). A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. Some exceptions apply, but in general, if a Check API responds with `{allowed: true}`, then you can expect the equivalent ListObjects query to return the object, and viceversa. For example, if `Check(user:anne, reader, document:2021-budget)` responds with `{allowed: true}`, then `ListObjects(user:anne, reader, document)` may include `document:2021-budget` in the response. ## Examples ### Querying with contextual tuples In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Querying usersets Some Checks will always return `true`, even without any tuples. For example, for the following authorization model ```python model schema 1.1 type user type document relations define reader: [user] ``` the following query ```json { \"tuple_key\": { \"user\": \"document:2021-budget#reader\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } } ``` will always return `{ \"allowed\": true }`. This is because usersets are self-defining: the userset `document:2021-budget#reader` will always have the `reader` relation with `document:2021-budget`. ### Querying usersets with difference in the model A Check for a userset can yield results that must be treated carefully if the model involves difference. For example, for the following authorization model ```python model schema 1.1 type user type group relations define member: [user] type document relations define blocked: [user] define reader: [group#member] but not blocked ``` the following query ```json { \"tuple_key\": { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"group:finance\" }, { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, { \"user\": \"user:anne\", \"relation\": \"blocked\", \"object\": \"document:2021-budget\" } ] }, } ``` will return `{ \"allowed\": true }`, even though a specific user of the userset `group:finance#member` does not have the `reader` relationship with the given object. >>> thread = await api.check(body) @@ -72,7 +72,7 @@ async def check(self, body, **kwargs): async def check_with_http_info(self, body, **kwargs): """Check whether a user is authorized to access an object - The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. + The Check API returns whether a given user has a relationship with a given object in a given store. The `user` field of the request can be a specific target, such as `user:anne`, or a userset (set of users) such as `group:marketing#member` or a type-bound public access `user:*`. 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`). A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. Some exceptions apply, but in general, if a Check API responds with `{allowed: true}`, then you can expect the equivalent ListObjects query to return the object, and viceversa. For example, if `Check(user:anne, reader, document:2021-budget)` responds with `{allowed: true}`, then `ListObjects(user:anne, reader, document)` may include `document:2021-budget` in the response. ## Examples ### Querying with contextual tuples In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Querying usersets Some Checks will always return `true`, even without any tuples. For example, for the following authorization model ```python model schema 1.1 type user type document relations define reader: [user] ``` the following query ```json { \"tuple_key\": { \"user\": \"document:2021-budget#reader\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } } ``` will always return `{ \"allowed\": true }`. This is because usersets are self-defining: the userset `document:2021-budget#reader` will always have the `reader` relation with `document:2021-budget`. ### Querying usersets with difference in the model A Check for a userset can yield results that must be treated carefully if the model involves difference. For example, for the following authorization model ```python model schema 1.1 type user type group relations define member: [user] type document relations define blocked: [user] define reader: [group#member] but not blocked ``` the following query ```json { \"tuple_key\": { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"group:finance\" }, { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, { \"user\": \"user:anne\", \"relation\": \"blocked\", \"object\": \"document:2021-budget\" } ] }, } ``` will return `{ \"allowed\": true }`, even though a specific user of the userset `group:finance#member` does not have the `reader` relationship with the given object. >>> thread = api.check_with_http_info(body) @@ -176,8 +176,10 @@ async def check_with_http_info(self, body, **kwargs): response_types_map = { 200: "CheckResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -323,8 +325,10 @@ async def create_store_with_http_info(self, body, **kwargs): response_types_map = { 201: "CreateStoreResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -614,8 +618,10 @@ async def expand_with_http_info(self, body, **kwargs): response_types_map = { 200: "ExpandResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -751,8 +757,10 @@ async def get_store_with_http_info(self, **kwargs): response_types_map = { 200: "GetStoreResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -780,7 +788,7 @@ async def get_store_with_http_info(self, **kwargs): async def list_objects(self, body, **kwargs): """List all objects of the given type that the user has a relation with - The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. + The ListObjects API returns a list of all the objects of the given type that the user has a relation with. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. >>> thread = await api.list_objects(body) @@ -807,7 +815,7 @@ async def list_objects(self, body, **kwargs): async def list_objects_with_http_info(self, body, **kwargs): """List all objects of the given type that the user has a relation with - The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. + The ListObjects API returns a list of all the objects of the given type that the user has a relation with. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. >>> thread = api.list_objects_with_http_info(body) @@ -912,8 +920,10 @@ async def list_objects_with_http_info(self, body, **kwargs): response_types_map = { 200: "ListObjectsResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1057,8 +1067,10 @@ async def list_stores_with_http_info(self, **kwargs): response_types_map = { 200: "ListStoresResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1083,6 +1095,169 @@ async def list_stores_with_http_info(self, **kwargs): _oauth2_client=self._oauth2_client, ) + async def list_users(self, body, **kwargs): + """[EXPERIMENTAL] 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 certain cases of negation via the `but not` operator, some results are marked as excluded from the main set of results. These exclusions are returned in the `excluded_users` property and should be handled appropriately at the point of implementation.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) + + :param body: (required) + :type body: ListUsersRequest + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :type _preload_content: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: ListUsersResponse + """ + kwargs["_return_http_data_only"] = True + 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. + + 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 certain cases of negation via the `but not` operator, some results are marked as excluded from the main set of results. These exclusions are returned in the `excluded_users` property and should be handled appropriately at the point of implementation.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) + + :param body: (required) + :type body: ListUsersRequest + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _return_http_data_only: response data without head status code + and headers + :type _return_http_data_only: bool, optional + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :type _preload_content: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :param _retry_param: if specified, override the retry parameters specified in configuration + :type _request_auth: dict, optional + :type _content_type: string, optional: force content-type for the request + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: tuple(ListUsersResponse, status_code(int), headers(HTTPHeaderDict)) + """ + + local_var_params = locals() + + all_params = ["body"] + all_params.extend( + [ + "async_req", + "_return_http_data_only", + "_preload_content", + "_request_timeout", + "_request_auth", + "_content_type", + "_headers", + "_retry_parms", + ] + ) + + for key, val in local_var_params["kwargs"].items(): + if key not in all_params: + raise FgaValidationException( + "Got an unexpected keyword argument '%s'" + " to method list_users" % key + ) + local_var_params[key] = val + del local_var_params["kwargs"] + # verify the required parameter 'body' is set + if ( + self.api_client.client_side_validation + and local_var_params.get("body") is None + ): + raise ApiValueError( + "Missing the required parameter `body` when calling `list_users`" + ) + + collection_formats = {} + + path_params = {} + + if self.api_client._get_store_id() is None: + raise ApiValueError( + "Store ID expected in api_client's configuration when calling `list_users`" + ) + store_id = self.api_client._get_store_id() + + query_params = [] + + header_params = dict(local_var_params.get("_headers", {})) + + form_params = [] + local_var_files = {} + + body_params = None + if "body" in local_var_params: + body_params = local_var_params["body"] + # HTTP header `Accept` + header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) + + # HTTP header `Content-Type` + content_types_list = local_var_params.get( + "_content_type", + self.api_client.select_header_content_type( + ["application/json"], "POST", body_params + ), + ) + if content_types_list: + header_params["Content-Type"] = content_types_list + + # Authentication setting + auth_settings = [] + + response_types_map = { + 200: "ListUsersResponse", + 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", + 404: "PathUnknownErrorMessageResponse", + 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", + 500: "InternalErrorMessageResponse", + } + + return await self.api_client.call_api( + "/stores/{store_id}/list-users".replace("{store_id}", store_id), + "POST", + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_types_map=response_types_map, + auth_settings=auth_settings, + async_req=local_var_params.get("async_req"), + _return_http_data_only=local_var_params.get("_return_http_data_only"), + _preload_content=local_var_params.get("_preload_content", True), + _request_timeout=local_var_params.get("_request_timeout"), + _retry_params=local_var_params.get("_retry_params"), + collection_formats=collection_formats, + _request_auth=local_var_params.get("_request_auth"), + _oauth2_client=self._oauth2_client, + ) + async def read(self, body, **kwargs): """Get tuples from the store that matches a query, without following userset rewrite rules @@ -1217,8 +1392,10 @@ async def read_with_http_info(self, body, **kwargs): response_types_map = { 200: "ReadResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1373,8 +1550,10 @@ async def read_assertions_with_http_info(self, authorization_model_id, **kwargs) response_types_map = { 200: "ReadAssertionsResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1527,8 +1706,10 @@ async def read_authorization_model_with_http_info(self, id, **kwargs): response_types_map = { 200: "ReadAuthorizationModelResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1680,8 +1861,10 @@ async def read_authorization_models_with_http_info(self, **kwargs): response_types_map = { 200: "ReadAuthorizationModelsResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1837,8 +2020,10 @@ async def read_changes_with_http_info(self, **kwargs): response_types_map = { 200: "ReadChangesResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1866,7 +2051,7 @@ async def read_changes_with_http_info(self, **kwargs): async def write(self, body, **kwargs): """Add or delete tuples from the store - The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` + The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. The API will not allow you to write tuples such as `document:2021-budget#viewer@document:2021-budget#viewer`, because they are implicit. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` >>> thread = await api.write(body) @@ -1893,7 +2078,7 @@ async def write(self, body, **kwargs): async def write_with_http_info(self, body, **kwargs): """Add or delete tuples from the store - The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` + The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. The API will not allow you to write tuples such as `document:2021-budget#viewer@document:2021-budget#viewer`, because they are implicit. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` >>> thread = api.write_with_http_info(body) @@ -1997,8 +2182,10 @@ async def write_with_http_info(self, body, **kwargs): response_types_map = { 200: "object", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -2336,8 +2523,10 @@ async def write_authorization_model_with_http_info(self, body, **kwargs): response_types_map = { 201: "WriteAuthorizationModelResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } diff --git a/openfga_sdk/api_client.py b/openfga_sdk/api_client.py index d477815..e486208 100644 --- a/openfga_sdk/api_client.py +++ b/openfga_sdk/api_client.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/__init__.py b/openfga_sdk/client/__init__.py index 863526a..fb3389c 100644 --- a/openfga_sdk/client/__init__.py +++ b/openfga_sdk/client/__init__.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/client.py b/openfga_sdk/client/client.py index 2edee1d..e271037 100644 --- a/openfga_sdk/client/client.py +++ b/openfga_sdk/client/client.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -25,6 +25,7 @@ from openfga_sdk.client.models.expand_request import ClientExpandRequest from openfga_sdk.client.models.list_objects_request import ClientListObjectsRequest from openfga_sdk.client.models.list_relations_request import ClientListRelationsRequest +from openfga_sdk.client.models.list_users_request import ClientListUsersRequest from openfga_sdk.client.models.read_changes_request import ClientReadChangesRequest from openfga_sdk.client.models.tuple import ClientTuple, convert_tuple_keys from openfga_sdk.client.models.write_request import ClientWriteRequest @@ -41,6 +42,7 @@ from openfga_sdk.models.expand_request import ExpandRequest from openfga_sdk.models.expand_request_tuple_key import ExpandRequestTupleKey from openfga_sdk.models.list_objects_request import ListObjectsRequest +from openfga_sdk.models.list_users_request import ListUsersRequest from openfga_sdk.models.read_authorization_model_response import ( ReadAuthorizationModelResponse, ) @@ -718,6 +720,39 @@ async def list_relations( result_list = list(result_iterator) return [i.request.relation for i in result_list] + async def list_users( + self, body: ClientListUsersRequest, options: dict[str, str] = None + ): + """ + Run list users request + :param body - list user parameters + :param authorization_model_id(options) - Overrides the authorization model id in the configuration + :param header(options) - Custom headers to send alongside the request + :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 + """ + options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListUsers") + kwargs = options_to_kwargs(options) + + req_body = ListUsersRequest( + authorization_model_id=self._get_authorization_model_id(options), + object=body.object, + relation=body.relation, + user_filters=body.user_filters, + contextual_tuples=body.contextual_tuples, + context=body.context, + ) + + if body.contextual_tuples: + req_body.contextual_tuples = ContextualTupleKeys( + tuple_keys=convert_tuple_keys(body.contextual_tuples) + ) + + api_response = await self._api.list_users(body=req_body, **kwargs) + + return api_response + ####################### # Assertions ####################### diff --git a/openfga_sdk/client/configuration.py b/openfga_sdk/client/configuration.py index ebc2220..0d8a3a0 100644 --- a/openfga_sdk/client/configuration.py +++ b/openfga_sdk/client/configuration.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/__init__.py b/openfga_sdk/client/models/__init__.py index be27aa4..5fadde2 100644 --- a/openfga_sdk/client/models/__init__.py +++ b/openfga_sdk/client/models/__init__.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/assertion.py b/openfga_sdk/client/models/assertion.py index bbf1900..62b68a2 100644 --- a/openfga_sdk/client/models/assertion.py +++ b/openfga_sdk/client/models/assertion.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/batch_check_response.py b/openfga_sdk/client/models/batch_check_response.py index aa2ee27..3c411c2 100644 --- a/openfga_sdk/client/models/batch_check_response.py +++ b/openfga_sdk/client/models/batch_check_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/check_request.py b/openfga_sdk/client/models/check_request.py index 01e9706..aa2a717 100644 --- a/openfga_sdk/client/models/check_request.py +++ b/openfga_sdk/client/models/check_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/expand_request.py b/openfga_sdk/client/models/expand_request.py index bf03f50..b1553c7 100644 --- a/openfga_sdk/client/models/expand_request.py +++ b/openfga_sdk/client/models/expand_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/list_objects_request.py b/openfga_sdk/client/models/list_objects_request.py index 38e461f..01ad190 100644 --- a/openfga_sdk/client/models/list_objects_request.py +++ b/openfga_sdk/client/models/list_objects_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/list_relations_request.py b/openfga_sdk/client/models/list_relations_request.py index 6169623..cd20acc 100644 --- a/openfga_sdk/client/models/list_relations_request.py +++ b/openfga_sdk/client/models/list_relations_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/list_users_request.py b/openfga_sdk/client/models/list_users_request.py new file mode 100644 index 0000000..ac484a8 --- /dev/null +++ b/openfga_sdk/client/models/list_users_request.py @@ -0,0 +1,141 @@ +""" + 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. +""" + +from openfga_sdk.client.models.tuple import ClientTuple +from openfga_sdk.models.user_type_filter import UserTypeFilter + + +class ClientListUsersRequest: + """ + ClientListUsersRequest encapsulates the parameters required for list users + """ + + def __init__( + self, + object: str = None, + relation: str = None, + user_filters: list[UserTypeFilter] = None, + contextual_tuples: list[ClientTuple] = None, + context: object = None, + ): + self._object = object + self._relation = relation + self._user_filters = user_filters + self._contextual_tuples = contextual_tuples + self._context = context + + @property + def object(self): + """Gets the object of this ClientListUsersRequest. + + + :return: The object of this ClientListUsersRequest. + :rtype: str + """ + return self._object + + @object.setter + def object(self, object): + """Sets the object of this ClientListUsersRequest. + + + :param object: The object of this ClientListUsersRequest. + :type object: str + """ + + self._object = object + + @property + def relation(self): + """Gets the relation of this ClientListUsersRequest. + + + :return: The relation of this ClientListUsersRequest. + :rtype: str + """ + return self._relation + + @relation.setter + def relation(self, relation): + """Sets the relation of this ClientListUsersRequest. + + + :param relation: The relation of this ClientListUsersRequest. + :type relation: str + """ + + self._relation = relation + + @property + def user_filters(self): + """Gets the user_filters of this ClientListUsersRequest. + + + :return: The user_filters of this ClientListUsersRequest. + :rtype: str + """ + return self._user_filters + + @user_filters.setter + def user_filters(self, user_filters): + """Sets the user_filters of this ClientListUsersRequest. + + + :param user_filters: The user_filters of this ClientListUsersRequest. + :type user_filters: str + """ + + self._user_filters = user_filters + + @property + def contextual_tuples(self): + """Gets the contextual_tuples of this ClientListUsersRequest. + + + :return: The contextual_tuples of this ClientListUsersRequest. + :rtype: ContextualTupleKeys + """ + return self._contextual_tuples + + @contextual_tuples.setter + def contextual_tuples(self, contextual_tuples): + """Sets the contextual_tuples of this ClientListUsersRequest. + + + :param contextual_tuples: The contextual_tuples of this ClientListUsersRequest. + :type contextual_tuples: ContextualTupleKeys + """ + + self._contextual_tuples = contextual_tuples + + @property + def context(self): + """Gets the context of this ClientListUsersRequest. + + Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + + :return: The context of this ClientListUsersRequest. + :rtype: object + """ + return self._context + + @context.setter + def context(self, context): + """Sets the context of this ClientListUsersRequest. + + Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + + :param context: The context of this ClientListUsersRequest. + :type context: object + """ + + self._context = context diff --git a/openfga_sdk/client/models/read_changes_request.py b/openfga_sdk/client/models/read_changes_request.py index 0770d77..8eba2a6 100644 --- a/openfga_sdk/client/models/read_changes_request.py +++ b/openfga_sdk/client/models/read_changes_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/tuple.py b/openfga_sdk/client/models/tuple.py index 187ad10..06e18b4 100644 --- a/openfga_sdk/client/models/tuple.py +++ b/openfga_sdk/client/models/tuple.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/write_request.py b/openfga_sdk/client/models/write_request.py index c3a04a8..5bbf79e 100644 --- a/openfga_sdk/client/models/write_request.py +++ b/openfga_sdk/client/models/write_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/write_response.py b/openfga_sdk/client/models/write_response.py index 814accf..7f5b24d 100644 --- a/openfga_sdk/client/models/write_response.py +++ b/openfga_sdk/client/models/write_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/write_single_response.py b/openfga_sdk/client/models/write_single_response.py index 456fe77..1f639fb 100644 --- a/openfga_sdk/client/models/write_single_response.py +++ b/openfga_sdk/client/models/write_single_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/client/models/write_transaction_opts.py b/openfga_sdk/client/models/write_transaction_opts.py index eaa0b32..2b3b9ed 100644 --- a/openfga_sdk/client/models/write_transaction_opts.py +++ b/openfga_sdk/client/models/write_transaction_opts.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/configuration.py b/openfga_sdk/configuration.py index 79d7998..7214335 100644 --- a/openfga_sdk/configuration.py +++ b/openfga_sdk/configuration.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -468,7 +468,7 @@ def to_debug_report(self): "Python SDK Debug Report:\n" "OS: {env}\n" "Python Version: {pyversion}\n" - "Version of the API: 0.1\n" + "Version of the API: 1.x\n" "SDK Package Version: 0.4.2".format(env=sys.platform, pyversion=sys.version) ) diff --git a/openfga_sdk/credentials.py b/openfga_sdk/credentials.py index dae1730..30cc110 100644 --- a/openfga_sdk/credentials.py +++ b/openfga_sdk/credentials.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/exceptions.py b/openfga_sdk/exceptions.py index 1ed9980..bb7c664 100644 --- a/openfga_sdk/exceptions.py +++ b/openfga_sdk/exceptions.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/__init__.py b/openfga_sdk/models/__init__.py index a53f89f..dce87a6 100644 --- a/openfga_sdk/models/__init__.py +++ b/openfga_sdk/models/__init__.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -30,6 +30,7 @@ from openfga_sdk.models.expand_request import ExpandRequest from openfga_sdk.models.expand_request_tuple_key import ExpandRequestTupleKey from openfga_sdk.models.expand_response import ExpandResponse +from openfga_sdk.models.fga_object import FgaObject from openfga_sdk.models.get_store_response import GetStoreResponse from openfga_sdk.models.internal_error_code import InternalErrorCode from openfga_sdk.models.internal_error_message_response import ( @@ -39,11 +40,14 @@ from openfga_sdk.models.list_objects_request import ListObjectsRequest from openfga_sdk.models.list_objects_response import ListObjectsResponse from openfga_sdk.models.list_stores_response import ListStoresResponse +from openfga_sdk.models.list_users_request import ListUsersRequest +from openfga_sdk.models.list_users_response import ListUsersResponse from openfga_sdk.models.metadata import Metadata from openfga_sdk.models.node import Node from openfga_sdk.models.nodes import Nodes from openfga_sdk.models.not_found_error_code import NotFoundErrorCode from openfga_sdk.models.null_value import NullValue +from openfga_sdk.models.object_or_userset import ObjectOrUserset from openfga_sdk.models.object_relation import ObjectRelation from openfga_sdk.models.path_unknown_error_message_response import ( PathUnknownErrorMessageResponse, @@ -73,11 +77,22 @@ from openfga_sdk.models.tuple_to_userset import TupleToUserset from openfga_sdk.models.type_definition import TypeDefinition from openfga_sdk.models.type_name import TypeName +from openfga_sdk.models.typed_wildcard import TypedWildcard +from openfga_sdk.models.unauthenticated_response import UnauthenticatedResponse +from openfga_sdk.models.unprocessable_content_error_code import ( + UnprocessableContentErrorCode, +) +from openfga_sdk.models.unprocessable_content_message_response import ( + UnprocessableContentMessageResponse, +) +from openfga_sdk.models.user import User +from openfga_sdk.models.user_type_filter import UserTypeFilter from openfga_sdk.models.users import Users from openfga_sdk.models.userset import Userset from openfga_sdk.models.userset_tree import UsersetTree from openfga_sdk.models.userset_tree_difference import UsersetTreeDifference from openfga_sdk.models.userset_tree_tuple_to_userset import UsersetTreeTupleToUserset +from openfga_sdk.models.userset_user import UsersetUser from openfga_sdk.models.usersets import Usersets from openfga_sdk.models.validation_error_message_response import ( ValidationErrorMessageResponse, diff --git a/openfga_sdk/models/aborted_message_response.py b/openfga_sdk/models/aborted_message_response.py index f7d03bb..7730ba6 100644 --- a/openfga_sdk/models/aborted_message_response.py +++ b/openfga_sdk/models/aborted_message_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/any.py b/openfga_sdk/models/any.py index a9d9bd8..65be319 100644 --- a/openfga_sdk/models/any.py +++ b/openfga_sdk/models/any.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/assertion.py b/openfga_sdk/models/assertion.py index 8f0f43c..a404928 100644 --- a/openfga_sdk/models/assertion.py +++ b/openfga_sdk/models/assertion.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/assertion_tuple_key.py b/openfga_sdk/models/assertion_tuple_key.py index 3ad9367..63a59ba 100644 --- a/openfga_sdk/models/assertion_tuple_key.py +++ b/openfga_sdk/models/assertion_tuple_key.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/authorization_model.py b/openfga_sdk/models/authorization_model.py index add9d73..6807e55 100644 --- a/openfga_sdk/models/authorization_model.py +++ b/openfga_sdk/models/authorization_model.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/check_request.py b/openfga_sdk/models/check_request.py index dd0c44c..036a2fa 100644 --- a/openfga_sdk/models/check_request.py +++ b/openfga_sdk/models/check_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/check_request_tuple_key.py b/openfga_sdk/models/check_request_tuple_key.py index ab4e6aa..6e91978 100644 --- a/openfga_sdk/models/check_request_tuple_key.py +++ b/openfga_sdk/models/check_request_tuple_key.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/check_response.py b/openfga_sdk/models/check_response.py index 565d3d4..9a81a87 100644 --- a/openfga_sdk/models/check_response.py +++ b/openfga_sdk/models/check_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/computed.py b/openfga_sdk/models/computed.py index e8b83f4..6d31542 100644 --- a/openfga_sdk/models/computed.py +++ b/openfga_sdk/models/computed.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/condition.py b/openfga_sdk/models/condition.py index 6e8b579..d8ee06a 100644 --- a/openfga_sdk/models/condition.py +++ b/openfga_sdk/models/condition.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/condition_metadata.py b/openfga_sdk/models/condition_metadata.py index c5ccfc3..8869a57 100644 --- a/openfga_sdk/models/condition_metadata.py +++ b/openfga_sdk/models/condition_metadata.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/condition_param_type_ref.py b/openfga_sdk/models/condition_param_type_ref.py index ba11cda..c932aae 100644 --- a/openfga_sdk/models/condition_param_type_ref.py +++ b/openfga_sdk/models/condition_param_type_ref.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/contextual_tuple_keys.py b/openfga_sdk/models/contextual_tuple_keys.py index 0a7766e..ac73088 100644 --- a/openfga_sdk/models/contextual_tuple_keys.py +++ b/openfga_sdk/models/contextual_tuple_keys.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/create_store_request.py b/openfga_sdk/models/create_store_request.py index a3688cb..c5afaa2 100644 --- a/openfga_sdk/models/create_store_request.py +++ b/openfga_sdk/models/create_store_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/create_store_response.py b/openfga_sdk/models/create_store_response.py index 3f45cb2..21949bd 100644 --- a/openfga_sdk/models/create_store_response.py +++ b/openfga_sdk/models/create_store_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/difference.py b/openfga_sdk/models/difference.py index bb09789..bc49fa5 100644 --- a/openfga_sdk/models/difference.py +++ b/openfga_sdk/models/difference.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/error_code.py b/openfga_sdk/models/error_code.py index 2dbe666..aadaf74 100644 --- a/openfga_sdk/models/error_code.py +++ b/openfga_sdk/models/error_code.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/expand_request.py b/openfga_sdk/models/expand_request.py index 79f64c0..2229ca6 100644 --- a/openfga_sdk/models/expand_request.py +++ b/openfga_sdk/models/expand_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/expand_request_tuple_key.py b/openfga_sdk/models/expand_request_tuple_key.py index f997cad..73668b1 100644 --- a/openfga_sdk/models/expand_request_tuple_key.py +++ b/openfga_sdk/models/expand_request_tuple_key.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/expand_response.py b/openfga_sdk/models/expand_response.py index 62c1e6a..c5a89ca 100644 --- a/openfga_sdk/models/expand_response.py +++ b/openfga_sdk/models/expand_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/fga_object.py b/openfga_sdk/models/fga_object.py new file mode 100644 index 0000000..effbbd0 --- /dev/null +++ b/openfga_sdk/models/fga_object.py @@ -0,0 +1,147 @@ +""" + 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 FgaObject: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"type": "str", "id": "str"} + + attribute_map = {"type": "type", "id": "id"} + + def __init__(self, type=None, id=None, local_vars_configuration=None): + """FgaObject - 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._type = None + self._id = None + self.discriminator = None + + self.type = type + self.id = id + + @property + def type(self): + """Gets the type of this FgaObject. + + + :return: The type of this FgaObject. + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this FgaObject. + + + :param type: The type of this FgaObject. + :type type: str + """ + if self.local_vars_configuration.client_side_validation and type is None: + raise ValueError("Invalid value for `type`, must not be `None`") + + self._type = type + + @property + def id(self): + """Gets the id of this FgaObject. + + + :return: The id of this FgaObject. + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this FgaObject. + + + :param id: The id of this FgaObject. + :type id: str + """ + if self.local_vars_configuration.client_side_validation and id is None: + raise ValueError("Invalid value for `id`, must not be `None`") + + self._id = id + + 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, FgaObject): + 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, FgaObject): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/get_store_response.py b/openfga_sdk/models/get_store_response.py index 884bf25..5296e5e 100644 --- a/openfga_sdk/models/get_store_response.py +++ b/openfga_sdk/models/get_store_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/internal_error_code.py b/openfga_sdk/models/internal_error_code.py index fb1bcd5..dec0a87 100644 --- a/openfga_sdk/models/internal_error_code.py +++ b/openfga_sdk/models/internal_error_code.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/internal_error_message_response.py b/openfga_sdk/models/internal_error_message_response.py index afc62ba..21ea52f 100644 --- a/openfga_sdk/models/internal_error_message_response.py +++ b/openfga_sdk/models/internal_error_message_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/leaf.py b/openfga_sdk/models/leaf.py index 05e1e72..de1bc3b 100644 --- a/openfga_sdk/models/leaf.py +++ b/openfga_sdk/models/leaf.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/list_objects_request.py b/openfga_sdk/models/list_objects_request.py index 5069e92..e8ec957 100644 --- a/openfga_sdk/models/list_objects_request.py +++ b/openfga_sdk/models/list_objects_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/list_objects_response.py b/openfga_sdk/models/list_objects_response.py index 42784c6..e1d1bfc 100644 --- a/openfga_sdk/models/list_objects_response.py +++ b/openfga_sdk/models/list_objects_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/list_stores_response.py b/openfga_sdk/models/list_stores_response.py index a291294..da386ae 100644 --- a/openfga_sdk/models/list_stores_response.py +++ b/openfga_sdk/models/list_stores_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/list_users_request.py b/openfga_sdk/models/list_users_request.py new file mode 100644 index 0000000..e7647cd --- /dev/null +++ b/openfga_sdk/models/list_users_request.py @@ -0,0 +1,274 @@ +""" + 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 ListUsersRequest: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = { + "authorization_model_id": "str", + "object": "FgaObject", + "relation": "str", + "user_filters": "list[UserTypeFilter]", + "contextual_tuples": "list[TupleKey]", + "context": "object", + } + + attribute_map = { + "authorization_model_id": "authorization_model_id", + "object": "object", + "relation": "relation", + "user_filters": "user_filters", + "contextual_tuples": "contextual_tuples", + "context": "context", + } + + def __init__( + self, + authorization_model_id=None, + object=None, + relation=None, + user_filters=None, + contextual_tuples=None, + context=None, + local_vars_configuration=None, + ): + """ListUsersRequest - 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._authorization_model_id = None + self._object = None + self._relation = None + self._user_filters = None + self._contextual_tuples = None + self._context = None + self.discriminator = None + + if authorization_model_id is not None: + self.authorization_model_id = authorization_model_id + self.object = object + self.relation = relation + self.user_filters = user_filters + if contextual_tuples is not None: + self.contextual_tuples = contextual_tuples + if context is not None: + self.context = context + + @property + def authorization_model_id(self): + """Gets the authorization_model_id of this ListUsersRequest. + + + :return: The authorization_model_id of this ListUsersRequest. + :rtype: str + """ + return self._authorization_model_id + + @authorization_model_id.setter + def authorization_model_id(self, authorization_model_id): + """Sets the authorization_model_id of this ListUsersRequest. + + + :param authorization_model_id: The authorization_model_id of this ListUsersRequest. + :type authorization_model_id: str + """ + + self._authorization_model_id = authorization_model_id + + @property + def object(self): + """Gets the object of this ListUsersRequest. + + + :return: The object of this ListUsersRequest. + :rtype: FgaObject + """ + return self._object + + @object.setter + def object(self, object): + """Sets the object of this ListUsersRequest. + + + :param object: The object of this ListUsersRequest. + :type object: FgaObject + """ + if self.local_vars_configuration.client_side_validation and object is None: + raise ValueError("Invalid value for `object`, must not be `None`") + + self._object = object + + @property + def relation(self): + """Gets the relation of this ListUsersRequest. + + + :return: The relation of this ListUsersRequest. + :rtype: str + """ + return self._relation + + @relation.setter + def relation(self, relation): + """Sets the relation of this ListUsersRequest. + + + :param relation: The relation of this ListUsersRequest. + :type relation: str + """ + if self.local_vars_configuration.client_side_validation and relation is None: + raise ValueError("Invalid value for `relation`, must not be `None`") + + self._relation = relation + + @property + def user_filters(self): + """Gets the user_filters of this ListUsersRequest. + + The type of results returned. Only accepts exactly one value. + + :return: The user_filters of this ListUsersRequest. + :rtype: list[UserTypeFilter] + """ + return self._user_filters + + @user_filters.setter + def user_filters(self, user_filters): + """Sets the user_filters of this ListUsersRequest. + + The type of results returned. Only accepts exactly one value. + + :param user_filters: The user_filters of this ListUsersRequest. + :type user_filters: list[UserTypeFilter] + """ + if ( + self.local_vars_configuration.client_side_validation + and user_filters is None + ): + raise ValueError("Invalid value for `user_filters`, must not be `None`") + + self._user_filters = user_filters + + @property + def contextual_tuples(self): + """Gets the contextual_tuples of this ListUsersRequest. + + + :return: The contextual_tuples of this ListUsersRequest. + :rtype: list[TupleKey] + """ + return self._contextual_tuples + + @contextual_tuples.setter + def contextual_tuples(self, contextual_tuples): + """Sets the contextual_tuples of this ListUsersRequest. + + + :param contextual_tuples: The contextual_tuples of this ListUsersRequest. + :type contextual_tuples: list[TupleKey] + """ + + self._contextual_tuples = contextual_tuples + + @property + def context(self): + """Gets the context of this ListUsersRequest. + + Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + + :return: The context of this ListUsersRequest. + :rtype: object + """ + return self._context + + @context.setter + def context(self, context): + """Sets the context of this ListUsersRequest. + + Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + + :param context: The context of this ListUsersRequest. + :type context: object + """ + + self._context = context + + 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, ListUsersRequest): + 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, ListUsersRequest): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/list_users_response.py b/openfga_sdk/models/list_users_response.py new file mode 100644 index 0000000..a6ce51f --- /dev/null +++ b/openfga_sdk/models/list_users_response.py @@ -0,0 +1,150 @@ +""" + 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 ListUsersResponse: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"users": "list[User]", "excluded_users": "list[ObjectOrUserset]"} + + attribute_map = {"users": "users", "excluded_users": "excluded_users"} + + def __init__(self, users=None, excluded_users=None, local_vars_configuration=None): + """ListUsersResponse - 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._users = None + self._excluded_users = None + self.discriminator = None + + self.users = users + self.excluded_users = excluded_users + + @property + def users(self): + """Gets the users of this ListUsersResponse. + + + :return: The users of this ListUsersResponse. + :rtype: list[User] + """ + return self._users + + @users.setter + def users(self, users): + """Sets the users of this ListUsersResponse. + + + :param users: The users of this ListUsersResponse. + :type users: list[User] + """ + if self.local_vars_configuration.client_side_validation and users is None: + raise ValueError("Invalid value for `users`, must not be `None`") + + self._users = users + + @property + def excluded_users(self): + """Gets the excluded_users of this ListUsersResponse. + + + :return: The excluded_users of this ListUsersResponse. + :rtype: list[ObjectOrUserset] + """ + return self._excluded_users + + @excluded_users.setter + def excluded_users(self, excluded_users): + """Sets the excluded_users of this ListUsersResponse. + + + :param excluded_users: The excluded_users of this ListUsersResponse. + :type excluded_users: list[ObjectOrUserset] + """ + if ( + self.local_vars_configuration.client_side_validation + and excluded_users is None + ): + raise ValueError("Invalid value for `excluded_users`, must not be `None`") + + self._excluded_users = excluded_users + + 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, ListUsersResponse): + 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, ListUsersResponse): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/metadata.py b/openfga_sdk/models/metadata.py index 636ef59..260681e 100644 --- a/openfga_sdk/models/metadata.py +++ b/openfga_sdk/models/metadata.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/node.py b/openfga_sdk/models/node.py index 59cb563..f61546b 100644 --- a/openfga_sdk/models/node.py +++ b/openfga_sdk/models/node.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/nodes.py b/openfga_sdk/models/nodes.py index 0bcf8ed..37473f6 100644 --- a/openfga_sdk/models/nodes.py +++ b/openfga_sdk/models/nodes.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/not_found_error_code.py b/openfga_sdk/models/not_found_error_code.py index 9b92d81..80c89b6 100644 --- a/openfga_sdk/models/not_found_error_code.py +++ b/openfga_sdk/models/not_found_error_code.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/null_value.py b/openfga_sdk/models/null_value.py index 6303d1e..a3eb72c 100644 --- a/openfga_sdk/models/null_value.py +++ b/openfga_sdk/models/null_value.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/object_or_userset.py b/openfga_sdk/models/object_or_userset.py new file mode 100644 index 0000000..2a35551 --- /dev/null +++ b/openfga_sdk/models/object_or_userset.py @@ -0,0 +1,145 @@ +""" + 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 ObjectOrUserset: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"object": "FgaObject", "userset": "UsersetUser"} + + attribute_map = {"object": "object", "userset": "userset"} + + def __init__(self, object=None, userset=None, local_vars_configuration=None): + """ObjectOrUserset - 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._object = None + self._userset = None + self.discriminator = None + + if object is not None: + self.object = object + if userset is not None: + self.userset = userset + + @property + def object(self): + """Gets the object of this ObjectOrUserset. + + + :return: The object of this ObjectOrUserset. + :rtype: FgaObject + """ + return self._object + + @object.setter + def object(self, object): + """Sets the object of this ObjectOrUserset. + + + :param object: The object of this ObjectOrUserset. + :type object: FgaObject + """ + + self._object = object + + @property + def userset(self): + """Gets the userset of this ObjectOrUserset. + + + :return: The userset of this ObjectOrUserset. + :rtype: UsersetUser + """ + return self._userset + + @userset.setter + def userset(self, userset): + """Sets the userset of this ObjectOrUserset. + + + :param userset: The userset of this ObjectOrUserset. + :type userset: UsersetUser + """ + + self._userset = userset + + 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, ObjectOrUserset): + 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, ObjectOrUserset): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/object_relation.py b/openfga_sdk/models/object_relation.py index 3e7a6b7..66444bb 100644 --- a/openfga_sdk/models/object_relation.py +++ b/openfga_sdk/models/object_relation.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/path_unknown_error_message_response.py b/openfga_sdk/models/path_unknown_error_message_response.py index 9582fe6..5a18cf9 100644 --- a/openfga_sdk/models/path_unknown_error_message_response.py +++ b/openfga_sdk/models/path_unknown_error_message_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_assertions_response.py b/openfga_sdk/models/read_assertions_response.py index a9285bc..5dd410d 100644 --- a/openfga_sdk/models/read_assertions_response.py +++ b/openfga_sdk/models/read_assertions_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_authorization_model_response.py b/openfga_sdk/models/read_authorization_model_response.py index 391c9c3..f97bd99 100644 --- a/openfga_sdk/models/read_authorization_model_response.py +++ b/openfga_sdk/models/read_authorization_model_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_authorization_models_response.py b/openfga_sdk/models/read_authorization_models_response.py index 7f13006..f27ad6a 100644 --- a/openfga_sdk/models/read_authorization_models_response.py +++ b/openfga_sdk/models/read_authorization_models_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_changes_response.py b/openfga_sdk/models/read_changes_response.py index 53efee3..70bf67f 100644 --- a/openfga_sdk/models/read_changes_response.py +++ b/openfga_sdk/models/read_changes_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_request.py b/openfga_sdk/models/read_request.py index 9271350..5a7baaa 100644 --- a/openfga_sdk/models/read_request.py +++ b/openfga_sdk/models/read_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_request_tuple_key.py b/openfga_sdk/models/read_request_tuple_key.py index 92031ea..b8dd949 100644 --- a/openfga_sdk/models/read_request_tuple_key.py +++ b/openfga_sdk/models/read_request_tuple_key.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/read_response.py b/openfga_sdk/models/read_response.py index 4df2be9..94a40f2 100644 --- a/openfga_sdk/models/read_response.py +++ b/openfga_sdk/models/read_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/relation_metadata.py b/openfga_sdk/models/relation_metadata.py index 4af57be..99cf0d6 100644 --- a/openfga_sdk/models/relation_metadata.py +++ b/openfga_sdk/models/relation_metadata.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/relation_reference.py b/openfga_sdk/models/relation_reference.py index 680b311..1926adf 100644 --- a/openfga_sdk/models/relation_reference.py +++ b/openfga_sdk/models/relation_reference.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/relationship_condition.py b/openfga_sdk/models/relationship_condition.py index 63362f7..84eebf2 100644 --- a/openfga_sdk/models/relationship_condition.py +++ b/openfga_sdk/models/relationship_condition.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/source_info.py b/openfga_sdk/models/source_info.py index c50e314..1b2e995 100644 --- a/openfga_sdk/models/source_info.py +++ b/openfga_sdk/models/source_info.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/status.py b/openfga_sdk/models/status.py index 23ec8b7..420dd4d 100644 --- a/openfga_sdk/models/status.py +++ b/openfga_sdk/models/status.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/store.py b/openfga_sdk/models/store.py index 2dbcb11..d7c276b 100644 --- a/openfga_sdk/models/store.py +++ b/openfga_sdk/models/store.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/tuple.py b/openfga_sdk/models/tuple.py index 3a55d08..a54c556 100644 --- a/openfga_sdk/models/tuple.py +++ b/openfga_sdk/models/tuple.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/tuple_change.py b/openfga_sdk/models/tuple_change.py index bccf339..d56ee16 100644 --- a/openfga_sdk/models/tuple_change.py +++ b/openfga_sdk/models/tuple_change.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/tuple_key.py b/openfga_sdk/models/tuple_key.py index 7bd853a..5f6c5fa 100644 --- a/openfga_sdk/models/tuple_key.py +++ b/openfga_sdk/models/tuple_key.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/tuple_key_without_condition.py b/openfga_sdk/models/tuple_key_without_condition.py index 473ec1d..fa58b3c 100644 --- a/openfga_sdk/models/tuple_key_without_condition.py +++ b/openfga_sdk/models/tuple_key_without_condition.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/tuple_operation.py b/openfga_sdk/models/tuple_operation.py index 05e4214..59c6225 100644 --- a/openfga_sdk/models/tuple_operation.py +++ b/openfga_sdk/models/tuple_operation.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/tuple_to_userset.py b/openfga_sdk/models/tuple_to_userset.py index e2c9458..2e33a05 100644 --- a/openfga_sdk/models/tuple_to_userset.py +++ b/openfga_sdk/models/tuple_to_userset.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/type_definition.py b/openfga_sdk/models/type_definition.py index b0ae496..c3b5002 100644 --- a/openfga_sdk/models/type_definition.py +++ b/openfga_sdk/models/type_definition.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/type_name.py b/openfga_sdk/models/type_name.py index 1e74321..65e7e53 100644 --- a/openfga_sdk/models/type_name.py +++ b/openfga_sdk/models/type_name.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/typed_wildcard.py b/openfga_sdk/models/typed_wildcard.py new file mode 100644 index 0000000..5e8939e --- /dev/null +++ b/openfga_sdk/models/typed_wildcard.py @@ -0,0 +1,122 @@ +""" + 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 TypedWildcard: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"type": "str"} + + attribute_map = {"type": "type"} + + def __init__(self, type=None, local_vars_configuration=None): + """TypedWildcard - 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._type = None + self.discriminator = None + + self.type = type + + @property + def type(self): + """Gets the type of this TypedWildcard. + + + :return: The type of this TypedWildcard. + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this TypedWildcard. + + + :param type: The type of this TypedWildcard. + :type type: str + """ + if self.local_vars_configuration.client_side_validation and type is None: + raise ValueError("Invalid value for `type`, must not be `None`") + + self._type = type + + 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, TypedWildcard): + 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, TypedWildcard): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/unauthenticated_response.py b/openfga_sdk/models/unauthenticated_response.py new file mode 100644 index 0000000..d85c036 --- /dev/null +++ b/openfga_sdk/models/unauthenticated_response.py @@ -0,0 +1,145 @@ +""" + 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 UnauthenticatedResponse: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"code": "ErrorCode", "message": "str"} + + attribute_map = {"code": "code", "message": "message"} + + def __init__(self, code=None, message=None, local_vars_configuration=None): + """UnauthenticatedResponse - 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._code = None + self._message = None + self.discriminator = None + + if code is not None: + self.code = code + if message is not None: + self.message = message + + @property + def code(self): + """Gets the code of this UnauthenticatedResponse. + + + :return: The code of this UnauthenticatedResponse. + :rtype: ErrorCode + """ + return self._code + + @code.setter + def code(self, code): + """Sets the code of this UnauthenticatedResponse. + + + :param code: The code of this UnauthenticatedResponse. + :type code: ErrorCode + """ + + self._code = code + + @property + def message(self): + """Gets the message of this UnauthenticatedResponse. + + + :return: The message of this UnauthenticatedResponse. + :rtype: str + """ + return self._message + + @message.setter + def message(self, message): + """Sets the message of this UnauthenticatedResponse. + + + :param message: The message of this UnauthenticatedResponse. + :type message: str + """ + + self._message = message + + 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, UnauthenticatedResponse): + 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, UnauthenticatedResponse): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/unprocessable_content_error_code.py b/openfga_sdk/models/unprocessable_content_error_code.py new file mode 100644 index 0000000..490aeb7 --- /dev/null +++ b/openfga_sdk/models/unprocessable_content_error_code.py @@ -0,0 +1,103 @@ +""" + 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 UnprocessableContentErrorCode: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + NO_THROTTLED_ERROR_CODE = "no_throttled_error_code" + THROTTLED_TIMEOUT_ERROR = "throttled_timeout_error" + + allowable_values = [NO_THROTTLED_ERROR_CODE, THROTTLED_TIMEOUT_ERROR] + + """ + 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): + """UnprocessableContentErrorCode - 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, UnprocessableContentErrorCode): + 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, UnprocessableContentErrorCode): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/unprocessable_content_message_response.py b/openfga_sdk/models/unprocessable_content_message_response.py new file mode 100644 index 0000000..1c2dd2b --- /dev/null +++ b/openfga_sdk/models/unprocessable_content_message_response.py @@ -0,0 +1,145 @@ +""" + 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 UnprocessableContentMessageResponse: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"code": "UnprocessableContentErrorCode", "message": "str"} + + attribute_map = {"code": "code", "message": "message"} + + def __init__(self, code=None, message=None, local_vars_configuration=None): + """UnprocessableContentMessageResponse - 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._code = None + self._message = None + self.discriminator = None + + if code is not None: + self.code = code + if message is not None: + self.message = message + + @property + def code(self): + """Gets the code of this UnprocessableContentMessageResponse. + + + :return: The code of this UnprocessableContentMessageResponse. + :rtype: UnprocessableContentErrorCode + """ + return self._code + + @code.setter + def code(self, code): + """Sets the code of this UnprocessableContentMessageResponse. + + + :param code: The code of this UnprocessableContentMessageResponse. + :type code: UnprocessableContentErrorCode + """ + + self._code = code + + @property + def message(self): + """Gets the message of this UnprocessableContentMessageResponse. + + + :return: The message of this UnprocessableContentMessageResponse. + :rtype: str + """ + return self._message + + @message.setter + def message(self, message): + """Sets the message of this UnprocessableContentMessageResponse. + + + :param message: The message of this UnprocessableContentMessageResponse. + :type message: str + """ + + self._message = message + + 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, UnprocessableContentMessageResponse): + 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, UnprocessableContentMessageResponse): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/user.py b/openfga_sdk/models/user.py new file mode 100644 index 0000000..2c53d8e --- /dev/null +++ b/openfga_sdk/models/user.py @@ -0,0 +1,175 @@ +""" + 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 User: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = { + "object": "FgaObject", + "userset": "UsersetUser", + "wildcard": "TypedWildcard", + } + + attribute_map = {"object": "object", "userset": "userset", "wildcard": "wildcard"} + + def __init__( + self, object=None, userset=None, wildcard=None, local_vars_configuration=None + ): + """User - 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._object = None + self._userset = None + self._wildcard = None + self.discriminator = None + + if object is not None: + self.object = object + if userset is not None: + self.userset = userset + if wildcard is not None: + self.wildcard = wildcard + + @property + def object(self): + """Gets the object of this User. + + + :return: The object of this User. + :rtype: FgaObject + """ + return self._object + + @object.setter + def object(self, object): + """Sets the object of this User. + + + :param object: The object of this User. + :type object: FgaObject + """ + + self._object = object + + @property + def userset(self): + """Gets the userset of this User. + + + :return: The userset of this User. + :rtype: UsersetUser + """ + return self._userset + + @userset.setter + def userset(self, userset): + """Sets the userset of this User. + + + :param userset: The userset of this User. + :type userset: UsersetUser + """ + + self._userset = userset + + @property + def wildcard(self): + """Gets the wildcard of this User. + + + :return: The wildcard of this User. + :rtype: TypedWildcard + """ + return self._wildcard + + @wildcard.setter + def wildcard(self, wildcard): + """Sets the wildcard of this User. + + + :param wildcard: The wildcard of this User. + :type wildcard: TypedWildcard + """ + + self._wildcard = wildcard + + 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, User): + 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, User): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/user_type_filter.py b/openfga_sdk/models/user_type_filter.py new file mode 100644 index 0000000..31d13d6 --- /dev/null +++ b/openfga_sdk/models/user_type_filter.py @@ -0,0 +1,146 @@ +""" + 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 UserTypeFilter: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"type": "str", "relation": "str"} + + attribute_map = {"type": "type", "relation": "relation"} + + def __init__(self, type=None, relation=None, local_vars_configuration=None): + """UserTypeFilter - 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._type = None + self._relation = None + self.discriminator = None + + self.type = type + if relation is not None: + self.relation = relation + + @property + def type(self): + """Gets the type of this UserTypeFilter. + + + :return: The type of this UserTypeFilter. + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this UserTypeFilter. + + + :param type: The type of this UserTypeFilter. + :type type: str + """ + if self.local_vars_configuration.client_side_validation and type is None: + raise ValueError("Invalid value for `type`, must not be `None`") + + self._type = type + + @property + def relation(self): + """Gets the relation of this UserTypeFilter. + + + :return: The relation of this UserTypeFilter. + :rtype: str + """ + return self._relation + + @relation.setter + def relation(self, relation): + """Sets the relation of this UserTypeFilter. + + + :param relation: The relation of this UserTypeFilter. + :type relation: str + """ + + self._relation = relation + + 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, UserTypeFilter): + 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, UserTypeFilter): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/users.py b/openfga_sdk/models/users.py index 1ae7d5b..1b96299 100644 --- a/openfga_sdk/models/users.py +++ b/openfga_sdk/models/users.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/userset.py b/openfga_sdk/models/userset.py index 074014a..7d2fa50 100644 --- a/openfga_sdk/models/userset.py +++ b/openfga_sdk/models/userset.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/userset_tree.py b/openfga_sdk/models/userset_tree.py index 505b2b8..ed06353 100644 --- a/openfga_sdk/models/userset_tree.py +++ b/openfga_sdk/models/userset_tree.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/userset_tree_difference.py b/openfga_sdk/models/userset_tree_difference.py index 8df495d..1488e21 100644 --- a/openfga_sdk/models/userset_tree_difference.py +++ b/openfga_sdk/models/userset_tree_difference.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/userset_tree_tuple_to_userset.py b/openfga_sdk/models/userset_tree_tuple_to_userset.py index 5b75b34..3a44735 100644 --- a/openfga_sdk/models/userset_tree_tuple_to_userset.py +++ b/openfga_sdk/models/userset_tree_tuple_to_userset.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/userset_user.py b/openfga_sdk/models/userset_user.py new file mode 100644 index 0000000..aff964d --- /dev/null +++ b/openfga_sdk/models/userset_user.py @@ -0,0 +1,174 @@ +""" + 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 UsersetUser: + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + """ + 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 = {"type": "str", "id": "str", "relation": "str"} + + attribute_map = {"type": "type", "id": "id", "relation": "relation"} + + def __init__( + self, type=None, id=None, relation=None, local_vars_configuration=None + ): + """UsersetUser - 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._type = None + self._id = None + self._relation = None + self.discriminator = None + + self.type = type + self.id = id + self.relation = relation + + @property + def type(self): + """Gets the type of this UsersetUser. + + + :return: The type of this UsersetUser. + :rtype: str + """ + return self._type + + @type.setter + def type(self, type): + """Sets the type of this UsersetUser. + + + :param type: The type of this UsersetUser. + :type type: str + """ + if self.local_vars_configuration.client_side_validation and type is None: + raise ValueError("Invalid value for `type`, must not be `None`") + + self._type = type + + @property + def id(self): + """Gets the id of this UsersetUser. + + + :return: The id of this UsersetUser. + :rtype: str + """ + return self._id + + @id.setter + def id(self, id): + """Sets the id of this UsersetUser. + + + :param id: The id of this UsersetUser. + :type id: str + """ + if self.local_vars_configuration.client_side_validation and id is None: + raise ValueError("Invalid value for `id`, must not be `None`") + + self._id = id + + @property + def relation(self): + """Gets the relation of this UsersetUser. + + + :return: The relation of this UsersetUser. + :rtype: str + """ + return self._relation + + @relation.setter + def relation(self, relation): + """Sets the relation of this UsersetUser. + + + :param relation: The relation of this UsersetUser. + :type relation: str + """ + if self.local_vars_configuration.client_side_validation and relation is None: + raise ValueError("Invalid value for `relation`, must not be `None`") + + self._relation = relation + + 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, UsersetUser): + 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, UsersetUser): + return True + + return self.to_dict() != other.to_dict() diff --git a/openfga_sdk/models/usersets.py b/openfga_sdk/models/usersets.py index 9726249..685ccee 100644 --- a/openfga_sdk/models/usersets.py +++ b/openfga_sdk/models/usersets.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/validation_error_message_response.py b/openfga_sdk/models/validation_error_message_response.py index 5d2a965..e71beee 100644 --- a/openfga_sdk/models/validation_error_message_response.py +++ b/openfga_sdk/models/validation_error_message_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/write_assertions_request.py b/openfga_sdk/models/write_assertions_request.py index 0f71d9c..4fad43c 100644 --- a/openfga_sdk/models/write_assertions_request.py +++ b/openfga_sdk/models/write_assertions_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/write_authorization_model_request.py b/openfga_sdk/models/write_authorization_model_request.py index 91fc6ba..68c3b0c 100644 --- a/openfga_sdk/models/write_authorization_model_request.py +++ b/openfga_sdk/models/write_authorization_model_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/write_authorization_model_response.py b/openfga_sdk/models/write_authorization_model_response.py index c843f9d..a40c1b9 100644 --- a/openfga_sdk/models/write_authorization_model_response.py +++ b/openfga_sdk/models/write_authorization_model_response.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/write_request.py b/openfga_sdk/models/write_request.py index 47d8d8c..a783d3a 100644 --- a/openfga_sdk/models/write_request.py +++ b/openfga_sdk/models/write_request.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/write_request_deletes.py b/openfga_sdk/models/write_request_deletes.py index 4b021bc..915d5f7 100644 --- a/openfga_sdk/models/write_request_deletes.py +++ b/openfga_sdk/models/write_request_deletes.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/models/write_request_writes.py b/openfga_sdk/models/write_request_writes.py index bd3182b..bb044ae 100644 --- a/openfga_sdk/models/write_request_writes.py +++ b/openfga_sdk/models/write_request_writes.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/oauth2.py b/openfga_sdk/oauth2.py index b3ae50c..adbeedc 100644 --- a/openfga_sdk/oauth2.py +++ b/openfga_sdk/oauth2.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/rest.py b/openfga_sdk/rest.py index b905a54..dc7c701 100644 --- a/openfga_sdk/rest.py +++ b/openfga_sdk/rest.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/sync/__init__.py b/openfga_sdk/sync/__init__.py index 5c5c908..da94389 100644 --- a/openfga_sdk/sync/__init__.py +++ b/openfga_sdk/sync/__init__.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/sync/api_client.py b/openfga_sdk/sync/api_client.py index 8ad7412..c21fc5e 100644 --- a/openfga_sdk/sync/api_client.py +++ b/openfga_sdk/sync/api_client.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/sync/client/__init__.py b/openfga_sdk/sync/client/__init__.py index 2d05ee3..8c82238 100644 --- a/openfga_sdk/sync/client/__init__.py +++ b/openfga_sdk/sync/client/__init__.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/sync/client/client.py b/openfga_sdk/sync/client/client.py index 079cb52..17605b7 100644 --- a/openfga_sdk/sync/client/client.py +++ b/openfga_sdk/sync/client/client.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -23,6 +23,7 @@ from openfga_sdk.client.models.expand_request import ClientExpandRequest from openfga_sdk.client.models.list_objects_request import ClientListObjectsRequest from openfga_sdk.client.models.list_relations_request import ClientListRelationsRequest +from openfga_sdk.client.models.list_users_request import ClientListUsersRequest from openfga_sdk.client.models.read_changes_request import ClientReadChangesRequest from openfga_sdk.client.models.tuple import ClientTuple, convert_tuple_keys from openfga_sdk.client.models.write_request import ClientWriteRequest @@ -39,6 +40,7 @@ from openfga_sdk.models.expand_request import ExpandRequest from openfga_sdk.models.expand_request_tuple_key import ExpandRequestTupleKey from openfga_sdk.models.list_objects_request import ListObjectsRequest +from openfga_sdk.models.list_users_request import ListUsersRequest from openfga_sdk.models.read_authorization_model_response import ( ReadAuthorizationModelResponse, ) @@ -708,6 +710,37 @@ def list_relations( result_list = list(result_iterator) return [i.request.relation for i in result_list] + def list_users(self, body: ClientListUsersRequest, options: dict[str, str] = None): + """ + Run list users request + :param body - list user parameters + :param authorization_model_id(options) - Overrides the authorization model id in the configuration + :param header(options) - Custom headers to send alongside the request + :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 + """ + options = set_heading_if_not_set(options, CLIENT_METHOD_HEADER, "ListUsers") + kwargs = options_to_kwargs(options) + + req_body = ListUsersRequest( + authorization_model_id=self._get_authorization_model_id(options), + object=body.object, + relation=body.relation, + user_filters=body.user_filters, + contextual_tuples=body.contextual_tuples, + context=body.context, + ) + + if body.contextual_tuples: + req_body.contextual_tuples = ContextualTupleKeys( + tuple_keys=convert_tuple_keys(body.contextual_tuples) + ) + + api_response = self._api.list_users(body=req_body, **kwargs) + + return api_response + ####################### # Assertions ####################### diff --git a/openfga_sdk/sync/oauth2.py b/openfga_sdk/sync/oauth2.py index aa0bf10..b012008 100644 --- a/openfga_sdk/sync/oauth2.py +++ b/openfga_sdk/sync/oauth2.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/sync/open_fga_api.py b/openfga_sdk/sync/open_fga_api.py index 09a8c7d..e771541 100644 --- a/openfga_sdk/sync/open_fga_api.py +++ b/openfga_sdk/sync/open_fga_api.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -45,7 +45,7 @@ def close(self): def check(self, body, **kwargs): """Check whether a user is authorized to access an object - The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. + The Check API returns whether a given user has a relationship with a given object in a given store. The `user` field of the request can be a specific target, such as `user:anne`, or a userset (set of users) such as `group:marketing#member` or a type-bound public access `user:*`. 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`). A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. Some exceptions apply, but in general, if a Check API responds with `{allowed: true}`, then you can expect the equivalent ListObjects query to return the object, and viceversa. For example, if `Check(user:anne, reader, document:2021-budget)` responds with `{allowed: true}`, then `ListObjects(user:anne, reader, document)` may include `document:2021-budget` in the response. ## Examples ### Querying with contextual tuples In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Querying usersets Some Checks will always return `true`, even without any tuples. For example, for the following authorization model ```python model schema 1.1 type user type document relations define reader: [user] ``` the following query ```json { \"tuple_key\": { \"user\": \"document:2021-budget#reader\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } } ``` will always return `{ \"allowed\": true }`. This is because usersets are self-defining: the userset `document:2021-budget#reader` will always have the `reader` relation with `document:2021-budget`. ### Querying usersets with difference in the model A Check for a userset can yield results that must be treated carefully if the model involves difference. For example, for the following authorization model ```python model schema 1.1 type user type group relations define member: [user] type document relations define blocked: [user] define reader: [group#member] but not blocked ``` the following query ```json { \"tuple_key\": { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"group:finance\" }, { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, { \"user\": \"user:anne\", \"relation\": \"blocked\", \"object\": \"document:2021-budget\" } ] }, } ``` will return `{ \"allowed\": true }`, even though a specific user of the userset `group:finance#member` does not have the `reader` relationship with the given object. >>> thread = api.check(body) @@ -72,7 +72,7 @@ def check(self, body, **kwargs): def check_with_http_info(self, body, **kwargs): """Check whether a user is authorized to access an object - The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. + The Check API returns whether a given user has a relationship with a given object in a given store. The `user` field of the request can be a specific target, such as `user:anne`, or a userset (set of users) such as `group:marketing#member` or a type-bound public access `user:*`. 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`). A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. 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 return whether the relationship exists in the field `allowed`. Some exceptions apply, but in general, if a Check API responds with `{allowed: true}`, then you can expect the equivalent ListObjects query to return the object, and viceversa. For example, if `Check(user:anne, reader, document:2021-budget)` responds with `{allowed: true}`, then `ListObjects(user:anne, reader, document)` may include `document:2021-budget` in the response. ## Examples ### Querying with contextual tuples In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Querying usersets Some Checks will always return `true`, even without any tuples. For example, for the following authorization model ```python model schema 1.1 type user type document relations define reader: [user] ``` the following query ```json { \"tuple_key\": { \"user\": \"document:2021-budget#reader\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } } ``` will always return `{ \"allowed\": true }`. This is because usersets are self-defining: the userset `document:2021-budget#reader` will always have the `reader` relation with `document:2021-budget`. ### Querying usersets with difference in the model A Check for a userset can yield results that must be treated carefully if the model involves difference. For example, for the following authorization model ```python model schema 1.1 type user type group relations define member: [user] type document relations define blocked: [user] define reader: [group#member] but not blocked ``` the following query ```json { \"tuple_key\": { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"group:finance\" }, { \"user\": \"group:finance#member\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, { \"user\": \"user:anne\", \"relation\": \"blocked\", \"object\": \"document:2021-budget\" } ] }, } ``` will return `{ \"allowed\": true }`, even though a specific user of the userset `group:finance#member` does not have the `reader` relationship with the given object. >>> thread = api.check_with_http_info(body) @@ -176,8 +176,10 @@ def check_with_http_info(self, body, **kwargs): response_types_map = { 200: "CheckResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -323,8 +325,10 @@ def create_store_with_http_info(self, body, **kwargs): response_types_map = { 201: "CreateStoreResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -614,8 +618,10 @@ def expand_with_http_info(self, body, **kwargs): response_types_map = { 200: "ExpandResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -751,8 +757,10 @@ def get_store_with_http_info(self, **kwargs): response_types_map = { 200: "GetStoreResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -780,7 +788,7 @@ def get_store_with_http_info(self, **kwargs): def list_objects(self, body, **kwargs): """List all objects of the given type that the user has a relation with - The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. + The ListObjects API returns a list of all the objects of the given type that the user has a relation with. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. >>> thread = api.list_objects(body) @@ -807,7 +815,7 @@ def list_objects(self, body, **kwargs): def list_objects_with_http_info(self, body, **kwargs): """List all objects of the given type that the user has a relation with - The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. + The ListObjects API returns a list of all the objects of the given type that the user has a relation with. 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 objects in an array in the \"objects\" field of the response and they will be strings in the object format `:` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. >>> thread = api.list_objects_with_http_info(body) @@ -912,8 +920,10 @@ def list_objects_with_http_info(self, body, **kwargs): response_types_map = { 200: "ListObjectsResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1057,8 +1067,10 @@ def list_stores_with_http_info(self, **kwargs): response_types_map = { 200: "ListStoresResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1083,6 +1095,169 @@ def list_stores_with_http_info(self, **kwargs): _oauth2_client=self._oauth2_client, ) + def list_users(self, body, **kwargs): + """[EXPERIMENTAL] 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 certain cases of negation via the `but not` operator, some results are marked as excluded from the main set of results. These exclusions are returned in the `excluded_users` property and should be handled appropriately at the point of implementation.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) + + :param body: (required) + :type body: ListUsersRequest + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :type _preload_content: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: ListUsersResponse + """ + kwargs["_return_http_data_only"] = True + 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. + + 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 certain cases of negation via the `but not` operator, some results are marked as excluded from the main set of results. These exclusions are returned in the `excluded_users` property and should be handled appropriately at the point of implementation.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) + + :param body: (required) + :type body: ListUsersRequest + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _return_http_data_only: response data without head status code + and headers + :type _return_http_data_only: bool, optional + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :type _preload_content: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :param _retry_param: if specified, override the retry parameters specified in configuration + :type _request_auth: dict, optional + :type _content_type: string, optional: force content-type for the request + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: tuple(ListUsersResponse, status_code(int), headers(HTTPHeaderDict)) + """ + + local_var_params = locals() + + all_params = ["body"] + all_params.extend( + [ + "async_req", + "_return_http_data_only", + "_preload_content", + "_request_timeout", + "_request_auth", + "_content_type", + "_headers", + "_retry_parms", + ] + ) + + for key, val in local_var_params["kwargs"].items(): + if key not in all_params: + raise FgaValidationException( + "Got an unexpected keyword argument '%s'" + " to method list_users" % key + ) + local_var_params[key] = val + del local_var_params["kwargs"] + # verify the required parameter 'body' is set + if ( + self.api_client.client_side_validation + and local_var_params.get("body") is None + ): + raise ApiValueError( + "Missing the required parameter `body` when calling `list_users`" + ) + + collection_formats = {} + + path_params = {} + + if self.api_client._get_store_id() is None: + raise ApiValueError( + "Store ID expected in api_client's configuration when calling `list_users`" + ) + store_id = self.api_client._get_store_id() + + query_params = [] + + header_params = dict(local_var_params.get("_headers", {})) + + form_params = [] + local_var_files = {} + + body_params = None + if "body" in local_var_params: + body_params = local_var_params["body"] + # HTTP header `Accept` + header_params["Accept"] = self.api_client.select_header_accept( + ["application/json"] + ) + + # HTTP header `Content-Type` + content_types_list = local_var_params.get( + "_content_type", + self.api_client.select_header_content_type( + ["application/json"], "POST", body_params + ), + ) + if content_types_list: + header_params["Content-Type"] = content_types_list + + # Authentication setting + auth_settings = [] + + response_types_map = { + 200: "ListUsersResponse", + 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", + 404: "PathUnknownErrorMessageResponse", + 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", + 500: "InternalErrorMessageResponse", + } + + return self.api_client.call_api( + "/stores/{store_id}/list-users".replace("{store_id}", store_id), + "POST", + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_types_map=response_types_map, + auth_settings=auth_settings, + async_req=local_var_params.get("async_req"), + _return_http_data_only=local_var_params.get("_return_http_data_only"), + _preload_content=local_var_params.get("_preload_content", True), + _request_timeout=local_var_params.get("_request_timeout"), + _retry_params=local_var_params.get("_retry_params"), + collection_formats=collection_formats, + _request_auth=local_var_params.get("_request_auth"), + _oauth2_client=self._oauth2_client, + ) + def read(self, body, **kwargs): """Get tuples from the store that matches a query, without following userset rewrite rules @@ -1217,8 +1392,10 @@ def read_with_http_info(self, body, **kwargs): response_types_map = { 200: "ReadResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1371,8 +1548,10 @@ def read_assertions_with_http_info(self, authorization_model_id, **kwargs): response_types_map = { 200: "ReadAssertionsResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1525,8 +1704,10 @@ def read_authorization_model_with_http_info(self, id, **kwargs): response_types_map = { 200: "ReadAuthorizationModelResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1678,8 +1859,10 @@ def read_authorization_models_with_http_info(self, **kwargs): response_types_map = { 200: "ReadAuthorizationModelsResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1835,8 +2018,10 @@ def read_changes_with_http_info(self, **kwargs): response_types_map = { 200: "ReadChangesResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -1864,7 +2049,7 @@ def read_changes_with_http_info(self, **kwargs): def write(self, body, **kwargs): """Add or delete tuples from the store - The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` + The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. The API will not allow you to write tuples such as `document:2021-budget#viewer@document:2021-budget#viewer`, because they are implicit. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` >>> thread = api.write(body) @@ -1891,7 +2076,7 @@ def write(self, body, **kwargs): def write_with_http_info(self, body, **kwargs): """Add or delete tuples from the store - The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` + The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. The API will not allow you to write tuples such as `document:2021-budget#viewer@document:2021-budget#viewer`, because they are implicit. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` >>> thread = api.write_with_http_info(body) @@ -1995,8 +2180,10 @@ def write_with_http_info(self, body, **kwargs): response_types_map = { 200: "object", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } @@ -2332,8 +2519,10 @@ def write_authorization_model_with_http_info(self, body, **kwargs): response_types_map = { 201: "WriteAuthorizationModelResponse", 400: "ValidationErrorMessageResponse", + 401: "UnauthenticatedResponse", 404: "PathUnknownErrorMessageResponse", 409: "AbortedMessageResponse", + 422: "UnprocessableContentMessageResponse", 500: "InternalErrorMessageResponse", } diff --git a/openfga_sdk/sync/rest.py b/openfga_sdk/sync/rest.py index d5f19b4..0f07412 100644 --- a/openfga_sdk/sync/rest.py +++ b/openfga_sdk/sync/rest.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/openfga_sdk/validation.py b/openfga_sdk/validation.py index 115397c..00278d9 100644 --- a/openfga_sdk/validation.py +++ b/openfga_sdk/validation.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/setup.cfg b/setup.cfg index 60b6c63..719e295 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,3 +14,7 @@ use_parentheses = True ensure_newline_before_comments = True line_length = 88 split_on_trailing_comma = True + +[tool:pytest] +testpaths=test +addopts=--cov=openfga_sdk --cov-report term-missing --cov-report xml --cov-report html diff --git a/setup.py b/setup.py index 64fdbd7..49f5fbd 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/test/test_client.py b/test/test_client.py index 0bd72ee..9834954 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -24,6 +24,7 @@ from openfga_sdk.client.models.expand_request import ClientExpandRequest from openfga_sdk.client.models.list_objects_request import ClientListObjectsRequest from openfga_sdk.client.models.list_relations_request import ClientListRelationsRequest +from openfga_sdk.client.models.list_users_request import ClientListUsersRequest from openfga_sdk.client.models.read_changes_request import ClientReadChangesRequest from openfga_sdk.client.models.tuple import ClientTuple from openfga_sdk.client.models.write_request import ClientWriteRequest @@ -44,6 +45,7 @@ from openfga_sdk.models.leaf import Leaf from openfga_sdk.models.list_objects_response import ListObjectsResponse from openfga_sdk.models.list_stores_response import ListStoresResponse +from openfga_sdk.models.list_users_response import ListUsersResponse from openfga_sdk.models.node import Node from openfga_sdk.models.object_relation import ObjectRelation from openfga_sdk.models.read_assertions_response import ReadAssertionsResponse @@ -63,6 +65,7 @@ from openfga_sdk.models.tuple_key_without_condition import TupleKeyWithoutCondition from openfga_sdk.models.tuple_operation import TupleOperation from openfga_sdk.models.type_definition import TypeDefinition +from openfga_sdk.models.user_type_filter import UserTypeFilter from openfga_sdk.models.users import Users from openfga_sdk.models.userset import Userset from openfga_sdk.models.userset_tree import UsersetTree @@ -2468,6 +2471,128 @@ async def test_list_relations_unauthorized(self, mock_request): ) await api_client.close() + @patch.object(rest.RESTClientObject, "request") + async def test_list_users(self, mock_request): + """ + Test case for list_users + """ + + response_body = """{ + "excluded_users": [], + "users": [ + { + "object": { + "id": "81684243-9356-4421-8fbf-a4f8d36aa31b", + "type": "user" + } + }, + { + "userset": { + "id": "fga", + "relation": "member", + "type": "team" + } + }, + { + "wildcard": { + "type": "user" + } + } + ] +}""" + + mock_request.return_value = mock_response(response_body, 200) + + configuration = self.configuration + configuration.store_id = store_id + + async with OpenFgaClient(configuration) as api_client: + body = ClientListUsersRequest( + object="document:2021-budget", + relation="can_read", + user_filters=[ + UserTypeFilter(type="user"), + UserTypeFilter(type="team", relation="member"), + ], + context={}, + contextual_tuples=[ + ClientTuple( + user="user:81684243-9356-4421-8fbf-a4f8d36aa31b", + relation="editor", + object="folder:product", + ), + ClientTuple( + user="folder:product", + relation="parent", + object="document:roadmap", + ), + ], + ) + + response = await api_client.list_users( + body, options={"authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J"} + ) + + self.assertIsInstance(response, ListUsersResponse) + + self.assertEqual(response.users.__len__(), 3) + + self.assertIsNotNone(response.users[0].object) + self.assertEqual( + response.users[0].object.id, "81684243-9356-4421-8fbf-a4f8d36aa31b" + ) + self.assertEqual(response.users[0].object.type, "user") + self.assertIsNone(response.users[0].userset) + self.assertIsNone(response.users[0].wildcard) + + self.assertIsNone(response.users[1].object) + self.assertIsNotNone(response.users[1].userset) + self.assertEqual(response.users[1].userset.id, "fga") + self.assertEqual(response.users[1].userset.relation, "member") + self.assertEqual(response.users[1].userset.type, "team") + self.assertIsNone(response.users[1].wildcard) + + self.assertIsNone(response.users[2].object) + self.assertIsNone(response.users[2].userset) + self.assertIsNotNone(response.users[2].wildcard) + self.assertEqual(response.users[2].wildcard.type, "user") + + mock_request.assert_called_once_with( + "POST", + "http://api.fga.example/stores/01YCP46JKYM8FJCQ37NMBYHE5X/list-users", + headers=ANY, + query_params=[], + post_params=[], + body={ + "authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J", + "object": "document:2021-budget", + "relation": "can_read", + "user_filters": [ + {"type": "user"}, + {"type": "team", "relation": "member"}, + ], + "contextual_tuples": { + "tuple_keys": [ + { + "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "relation": "editor", + "object": "folder:product", + }, + { + "user": "folder:product", + "relation": "parent", + "object": "document:roadmap", + }, + ] + }, + "context": {}, + }, + _preload_content=ANY, + _request_timeout=None, + ) + + await api_client.close() + @patch.object(rest.RESTClientObject, "request") async def test_read_assertions(self, mock_request): """Test case for read assertions""" diff --git a/test/test_client_sync.py b/test/test_client_sync.py index 67605d7..5fbeb3e 100644 --- a/test/test_client_sync.py +++ b/test/test_client_sync.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -22,6 +22,7 @@ from openfga_sdk.client.models.expand_request import ClientExpandRequest from openfga_sdk.client.models.list_objects_request import ClientListObjectsRequest from openfga_sdk.client.models.list_relations_request import ClientListRelationsRequest +from openfga_sdk.client.models.list_users_request import ClientListUsersRequest from openfga_sdk.client.models.read_changes_request import ClientReadChangesRequest from openfga_sdk.client.models.tuple import ClientTuple from openfga_sdk.client.models.write_request import ClientWriteRequest @@ -42,6 +43,7 @@ from openfga_sdk.models.leaf import Leaf from openfga_sdk.models.list_objects_response import ListObjectsResponse from openfga_sdk.models.list_stores_response import ListStoresResponse +from openfga_sdk.models.list_users_response import ListUsersResponse from openfga_sdk.models.node import Node from openfga_sdk.models.object_relation import ObjectRelation from openfga_sdk.models.read_assertions_response import ReadAssertionsResponse @@ -61,6 +63,7 @@ from openfga_sdk.models.tuple_key_without_condition import TupleKeyWithoutCondition from openfga_sdk.models.tuple_operation import TupleOperation from openfga_sdk.models.type_definition import TypeDefinition +from openfga_sdk.models.user_type_filter import UserTypeFilter from openfga_sdk.models.users import Users from openfga_sdk.models.userset import Userset from openfga_sdk.models.userset_tree import UsersetTree @@ -2468,6 +2471,127 @@ def test_list_relations_unauthorized(self, mock_request): ) api_client.close() + @patch.object(rest.RESTClientObject, "request") + def test_list_users(self, mock_request): + """ + Test case for list_users + """ + + response_body = """{ + "excluded_users": [], + "users": [ + { + "object": { + "id": "81684243-9356-4421-8fbf-a4f8d36aa31b", + "type": "user" + } + }, + { + "userset": { + "id": "fga", + "relation": "member", + "type": "team" + } + }, + { + "wildcard": { + "type": "user" + } + } + ] +}""" + + mock_request.return_value = mock_response(response_body, 200) + + configuration = self.configuration + configuration.store_id = store_id + + with OpenFgaClient(configuration) as api_client: + body = ClientListUsersRequest() + body.object = "document:2021-budget" + body.relation = "can_read" + body.user_filters = [ + UserTypeFilter(type="user"), + UserTypeFilter(type="team", relation="member"), + ] + body.context = {} + body.contextual_tuples = [ + ClientTuple( + user="user:81684243-9356-4421-8fbf-a4f8d36aa31b", + relation="editor", + object="folder:product", + ), + ClientTuple( + user="folder:product", + relation="parent", + object="document:roadmap", + ), + ] + + response = api_client.list_users( + body, options={"authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J"} + ) + + self.assertIsInstance(response, ListUsersResponse) + + self.assertEqual(response.users.__len__(), 3) + + self.assertIsNotNone(response.users[0].object) + self.assertEqual( + response.users[0].object.id, "81684243-9356-4421-8fbf-a4f8d36aa31b" + ) + self.assertEqual(response.users[0].object.type, "user") + self.assertIsNone(response.users[0].userset) + self.assertIsNone(response.users[0].wildcard) + + self.assertIsNone(response.users[1].object) + self.assertIsNotNone(response.users[1].userset) + self.assertEqual(response.users[1].userset.id, "fga") + self.assertEqual(response.users[1].userset.relation, "member") + self.assertEqual(response.users[1].userset.type, "team") + self.assertIsNone(response.users[1].wildcard) + + self.assertIsNone(response.users[2].object) + self.assertIsNone(response.users[2].userset) + self.assertIsNotNone(response.users[2].wildcard) + self.assertEqual(response.users[2].wildcard.type, "user") + + mock_request.assert_called_once_with( + "POST", + "http://api.fga.example/stores/01YCP46JKYM8FJCQ37NMBYHE5X/list-users", + headers=ANY, + query_params=[], + post_params=[], + body={ + "authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J", + "object": "document:2021-budget", + "relation": "can_read", + "user_filters": [ + {"type": "user"}, + {"type": "team", "relation": "member"}, + ], + "contextual_tuples": { + "tuple_keys": [ + { + "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "relation": "editor", + "object": "folder:product", + }, + { + "user": "folder:product", + "relation": "parent", + "object": "document:roadmap", + }, + ] + }, + "context": {}, + }, + _preload_content=ANY, + _request_timeout=None, + ) + + api_client.close() + @patch.object(rest.RESTClientObject, "request") def test_read_assertions(self, mock_request): """Test case for read assertions""" diff --git a/test/test_configuration.py b/test/test_configuration.py index a204676..7be3338 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/test/test_credentials.py b/test/test_credentials.py index 57467fd..d6733cd 100644 --- a/test/test_credentials.py +++ b/test/test_credentials.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/test/test_oauth2.py b/test/test_oauth2.py index 8b0e511..2f20542 100644 --- a/test/test_oauth2.py +++ b/test/test_oauth2.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/test/test_oauth2_sync.py b/test/test_oauth2_sync.py index 43534df..fc0bd85 100644 --- a/test/test_oauth2_sync.py +++ b/test/test_oauth2_sync.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community diff --git a/test/test_open_fga_api.py b/test/test_open_fga_api.py index 83c397b..ab9b37c 100644 --- a/test/test_open_fga_api.py +++ b/test/test_open_fga_api.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -49,6 +49,8 @@ from openfga_sdk.models.list_objects_request import ListObjectsRequest from openfga_sdk.models.list_objects_response import ListObjectsResponse from openfga_sdk.models.list_stores_response import ListStoresResponse +from openfga_sdk.models.list_users_request import ListUsersRequest +from openfga_sdk.models.list_users_response import ListUsersResponse from openfga_sdk.models.node import Node from openfga_sdk.models.not_found_error_code import NotFoundErrorCode from openfga_sdk.models.object_relation import ObjectRelation @@ -422,6 +424,127 @@ async def test_list_stores(self, mock_request): ) await api_client.close() + @patch.object(rest.RESTClientObject, "request") + async def test_list_users(self, mock_request): + """ + Test case for list_users + """ + + response_body = """{ + "excluded_users": [], + "users": [ + { + "object": { + "id": "81684243-9356-4421-8fbf-a4f8d36aa31b", + "type": "user" + } + }, + { + "userset": { + "id": "fga", + "relation": "member", + "type": "team" + } + }, + { + "wildcard": { + "type": "user" + } + } + ] +}""" + + mock_request.return_value = mock_response(response_body, 200) + + configuration = self.configuration + configuration.store_id = store_id + + async with openfga_sdk.ApiClient(configuration) as api_client: + api_instance = open_fga_api.OpenFgaApi(api_client) + + request = ListUsersRequest( + authorization_model_id="01G5JAVJ41T49E9TT3SKVS7X1J", + object="document:2021-budget", + relation="can_read", + user_filters=[ + {"type": "user"}, + {"type": "team", "relation": "member"}, + ], + context={}, + contextual_tuples=[ + { + "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "relation": "editor", + "object": "folder:product", + }, + { + "user": "folder:product", + "relation": "parent", + "object": "document:roadmap", + }, + ], + ) + + response = await api_instance.list_users(request) + + self.assertIsInstance(response, ListUsersResponse) + + self.assertEqual(response.users.__len__(), 3) + + self.assertIsNotNone(response.users[0].object) + self.assertEqual( + response.users[0].object.id, "81684243-9356-4421-8fbf-a4f8d36aa31b" + ) + self.assertEqual(response.users[0].object.type, "user") + self.assertIsNone(response.users[0].userset) + self.assertIsNone(response.users[0].wildcard) + + self.assertIsNone(response.users[1].object) + self.assertIsNotNone(response.users[1].userset) + self.assertEqual(response.users[1].userset.id, "fga") + self.assertEqual(response.users[1].userset.relation, "member") + self.assertEqual(response.users[1].userset.type, "team") + self.assertIsNone(response.users[1].wildcard) + + self.assertIsNone(response.users[2].object) + self.assertIsNone(response.users[2].userset) + self.assertIsNotNone(response.users[2].wildcard) + self.assertEqual(response.users[2].wildcard.type, "user") + + mock_request.assert_called_once_with( + "POST", + "http://api.fga.example/stores/01H0H015178Y2V4CX10C2KGHF4/list-users", + headers=ANY, + query_params=[], + post_params=[], + body={ + "authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J", + "object": "document:2021-budget", + "relation": "can_read", + "user_filters": [ + {"type": "user"}, + {"type": "team", "relation": "member"}, + ], + "context": {}, + "contextual_tuples": [ + { + "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "relation": "editor", + "object": "folder:product", + }, + { + "user": "folder:product", + "relation": "parent", + "object": "document:roadmap", + }, + ], + }, + _preload_content=ANY, + _request_timeout=None, + ) + + await api_client.close() + @patch.object(rest.RESTClientObject, "request") async def test_read(self, mock_request): """Test case for read diff --git a/test/test_open_fga_api_sync.py b/test/test_open_fga_api_sync.py index afffefd..6b9098b 100644 --- a/test/test_open_fga_api_sync.py +++ b/test/test_open_fga_api_sync.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community @@ -48,6 +48,8 @@ from openfga_sdk.models.list_objects_request import ListObjectsRequest from openfga_sdk.models.list_objects_response import ListObjectsResponse from openfga_sdk.models.list_stores_response import ListStoresResponse +from openfga_sdk.models.list_users_request import ListUsersRequest +from openfga_sdk.models.list_users_response import ListUsersResponse from openfga_sdk.models.node import Node from openfga_sdk.models.not_found_error_code import NotFoundErrorCode from openfga_sdk.models.object_relation import ObjectRelation @@ -423,6 +425,130 @@ async def test_list_stores(self, mock_request): ) api_client.close() + @patch.object(rest.RESTClientObject, "request") + async def test_list_users(self, mock_request): + """ + Test case for list_users + """ + + response_body = """{ + "excluded_users": [], + "users": [ + { + "object": { + "id": "81684243-9356-4421-8fbf-a4f8d36aa31b", + "type": "user" + } + }, + { + "userset": { + "id": "fga", + "relation": "member", + "type": "team" + } + }, + { + "wildcard": { + "type": "user" + } + } + ] +}""" + + mock_request.return_value = mock_response(response_body, 200) + + configuration = self.configuration + configuration.store_id = store_id + + with ApiClient(configuration) as api_client: + api_instance = open_fga_api.OpenFgaApi(api_client) + + request = ListUsersRequest( + object="test:123", + relation="can_test", + user_filters=[{"type": "test", "relation": "test"}], + ) + request.authorization_model_id = "01G5JAVJ41T49E9TT3SKVS7X1J" + request.object = "document:2021-budget" + request.relation = "can_read" + request.user_filters = [ + {"type": "user"}, + {"type": "team", "relation": "member"}, + ] + request.context = {} + request.contextual_tuples = [ + { + "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "relation": "editor", + "object": "folder:product", + }, + { + "user": "folder:product", + "relation": "parent", + "object": "document:roadmap", + }, + ] + + response = api_instance.list_users(request) + + self.assertIsInstance(response, ListUsersResponse) + + self.assertEqual(response.users.__len__(), 3) + + self.assertIsNotNone(response.users[0].object) + self.assertEqual( + response.users[0].object.id, "81684243-9356-4421-8fbf-a4f8d36aa31b" + ) + self.assertEqual(response.users[0].object.type, "user") + self.assertIsNone(response.users[0].userset) + self.assertIsNone(response.users[0].wildcard) + + self.assertIsNone(response.users[1].object) + self.assertIsNotNone(response.users[1].userset) + self.assertEqual(response.users[1].userset.id, "fga") + self.assertEqual(response.users[1].userset.relation, "member") + self.assertEqual(response.users[1].userset.type, "team") + self.assertIsNone(response.users[1].wildcard) + + self.assertIsNone(response.users[2].object) + self.assertIsNone(response.users[2].userset) + self.assertIsNotNone(response.users[2].wildcard) + self.assertEqual(response.users[2].wildcard.type, "user") + + mock_request.assert_called_once_with( + "POST", + "http://api.fga.example/stores/01H0H015178Y2V4CX10C2KGHF4/list-users", + headers=ANY, + query_params=[], + post_params=[], + body={ + "authorization_model_id": "01G5JAVJ41T49E9TT3SKVS7X1J", + "object": "document:2021-budget", + "relation": "can_read", + "user_filters": [ + {"type": "user"}, + {"type": "team", "relation": "member"}, + ], + "context": {}, + "contextual_tuples": [ + { + "user": "user:81684243-9356-4421-8fbf-a4f8d36aa31b", + "relation": "editor", + "object": "folder:product", + }, + { + "user": "folder:product", + "relation": "parent", + "object": "document:roadmap", + }, + ], + }, + _preload_content=ANY, + _request_timeout=None, + ) + + api_client.close() + @patch.object(rest.RESTClientObject, "request") async def test_read(self, mock_request): """Test case for read diff --git a/test/test_validation.py b/test/test_validation.py index 0a77242..7837dc9 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -1,7 +1,7 @@ """ Python SDK for OpenFGA - API version: 0.1 + API version: 1.x Website: https://openfga.dev Documentation: https://openfga.dev/docs Support: https://openfga.dev/community