diff --git a/.github/workflows/semgrep.yaml b/.github/workflows/semgrep.yaml index 66e24d3..44718e2 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@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.2 - run: semgrep ci env: SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} diff --git a/README.md b/README.md index 120883a..5bd1a0d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Release](https://img.shields.io/github/v/release/openfga/go-sdk?sort=semver&color=green)](https://github.com/openfga/go-sdk/releases) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fopenfga%2Fgo-sdk.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fopenfga%2Fgo-sdk?ref=badge_shield) -[![Discord Server](https://img.shields.io/discord/759188666072825867?color=7289da&logo=discord "Discord Server")](https://discord.com/channels/759188666072825867/930524706854031421) +[![Discord Server](https://img.shields.io/discord/759188666072825867?color=7289da&logo=discord "Discord Server")](https://discord.gg/8naAwJfWN6) [![Twitter](https://img.shields.io/twitter/follow/openfga?color=%23179CF0&logo=twitter&style=flat-square "@openfga on Twitter")](https://twitter.com/openfga) This is an autogenerated Go SDK for OpenFGA. It provides a wrapper around the [OpenFGA API definition](https://openfga.dev/api). diff --git a/api_open_fga.go b/api_open_fga.go index e6390cc..40c60e2 100644 --- a/api_open_fga.go +++ b/api_open_fga.go @@ -185,12 +185,10 @@ type OpenFgaApi interface { /* * ListObjects 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, it will be used to decide the underlying implementation used. 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. + 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. 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. - Note: If you have `and` or `but not` in your model while using ListObjects, checkout the [caveats](https://openfga.dev/docs/interacting/relationship-queries#caveats-and-when-not-to-use-it-3). - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @return ApiListObjectsRequest */ @@ -203,11 +201,13 @@ type OpenFgaApi interface { ListObjectsExecute(r ApiListObjectsRequest) (ListObjectsResponse, *_nethttp.Response, error) /* - * ListStores List all stores - * Returns a paginated list of OpenFGA stores. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return ApiListStoresRequest - */ + * ListStores List all stores + * Returns a paginated list of OpenFGA stores and a continuation token to get additional stores. + The continuation token will be empty if there are no more stores. + + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiListStoresRequest + */ ListStores(ctx _context.Context) ApiListStoresRequest /* @@ -220,11 +220,12 @@ type OpenFgaApi interface { * Read Get tuples from the store that matches a query, without following userset rewrite rules * The Read API will return the tuples for a certain store that match a query filter specified in the body of the request. It is different from the `/stores/{store_id}/expand` API in that it only returns relationship tuples that are stored in the system and satisfy the query. In the body: - 1. tuple_key is optional. If tuple_key is not specified, it will return all tuples in the store.2. `tuple_key.object` is mandatory if tuple_key is specified. It can be a full object (e.g., `type:object_id`) or type only (e.g., `type:`). + 1. `tuple_key` is optional. If not specified, it will return all tuples in the store. + 2. `tuple_key.object` is mandatory if `tuple_key` is specified. It can be a full object (e.g., `type:object_id`) or type only (e.g., `type:`). 3. `tuple_key.user` is mandatory if tuple_key is specified in the case the `tuple_key.object` is a type only. ## Examples ### Query for all objects in a type definition - To query for all objects that `user:bob` has `reader` relationship in the document type definition, call read API with body of + To query for all objects that `user:bob` has `reader` relationship in the `document` type definition, call read API with body of ```json { "tuple_key": { @@ -234,7 +235,7 @@ type OpenFgaApi interface { } } ``` - The API will return tuples and an optional continuation token, something like + The API will return tuples and a continuation token, something like ```json { "tuples": [ @@ -246,10 +247,12 @@ type OpenFgaApi interface { }, "timestamp": "2021-10-06T15:32:11.128Z" } - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` - This means that `user:bob` has a `reader` relationship with 1 document `document:2021-budget`. + This means that `user:bob` has a `reader` relationship with 1 document `document:2021-budget`. Note that this API, unlike the List Objects API, does not evaluate the tuples in the store. + The continuation token will be empty if there are no more tuples to query. ### Query for all stored relationship tuples that have a particular relation and object To query for all users that have `reader` relationship with `document:2021-budget`, call read API with body of ```json @@ -272,10 +275,11 @@ type OpenFgaApi interface { }, "timestamp": "2021-10-06T15:32:11.128Z" } - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` - This means that `document:2021-budget` has 1 `reader` (`user:bob`). Note that the API will not return writers such as `user:anne` even when all writers are readers. This is because only direct relationship are returned for the READ API. + This means that `document:2021-budget` has 1 `reader` (`user:bob`). Note that, even if the model said that all `writers` are also `readers`, the API will not return writers such as `user:anne` because it only returns tuples and does not evaluate them. ### Query for all users with all relationships for a particular document To query for all users that have any relationship with `document:2021-budget`, call read API with body of ```json @@ -305,7 +309,8 @@ type OpenFgaApi interface { }, "timestamp": "2021-10-06T15:32:11.128Z" } - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` This means that `document:2021-budget` has 1 `reader` (`user:bob`) and 1 `writer` (`user:anne`). @@ -409,10 +414,11 @@ type OpenFgaApi interface { "id": "01G4ZW8F4A07AKQ8RHSVG9RW04", "type_definitions": [...] }, - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` - If there are more authorization models available, the response will contain an extra field `continuation_token`: + If there are no more authorization models available, the `continuation_token` field will be empty ```json { "authorization_models": [ @@ -425,7 +431,7 @@ type OpenFgaApi interface { "type_definitions": [...] }, ], - "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + "continuation_token": "" } ``` @@ -1988,12 +1994,10 @@ func (r ApiListObjectsRequest) Execute() (ListObjectsResponse, *_nethttp.Respons - ListObjects 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, it will be used to decide the underlying implementation used. 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. +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. 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. -Note: If you have `and` or `but not` in your model while using ListObjects, checkout the [caveats](https://openfga.dev/docs/interacting/relationship-queries#caveats-and-when-not-to-use-it-3). - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListObjectsRequest */ @@ -2265,11 +2269,14 @@ func (r ApiListStoresRequest) Execute() (ListStoresResponse, *_nethttp.Response, } /* - * ListStores List all stores - * Returns a paginated list of OpenFGA stores. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return ApiListStoresRequest - */ + - ListStores List all stores + - Returns a paginated list of OpenFGA stores and a continuation token to get additional stores. + +The continuation token will be empty if there are no more stores. + + - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @return ApiListStoresRequest +*/ func (a *OpenFgaApiService) ListStores(ctx _context.Context) ApiListStoresRequest { return ApiListStoresRequest{ ApiService: a, @@ -2531,11 +2538,12 @@ func (r ApiReadRequest) Execute() (ReadResponse, *_nethttp.Response, error) { - The Read API will return the tuples for a certain store that match a query filter specified in the body of the request. It is different from the `/stores/{store_id}/expand` API in that it only returns relationship tuples that are stored in the system and satisfy the query. In the body: -1. tuple_key is optional. If tuple_key is not specified, it will return all tuples in the store.2. `tuple_key.object` is mandatory if tuple_key is specified. It can be a full object (e.g., `type:object_id`) or type only (e.g., `type:`). +1. `tuple_key` is optional. If not specified, it will return all tuples in the store. +2. `tuple_key.object` is mandatory if `tuple_key` is specified. It can be a full object (e.g., `type:object_id`) or type only (e.g., `type:`). 3. `tuple_key.user` is mandatory if tuple_key is specified in the case the `tuple_key.object` is a type only. ## Examples ### Query for all objects in a type definition -To query for all objects that `user:bob` has `reader` relationship in the document type definition, call read API with body of +To query for all objects that `user:bob` has `reader` relationship in the `document` type definition, call read API with body of ```json { @@ -2547,7 +2555,7 @@ To query for all objects that `user:bob` has `reader` relationship in the docume } ``` -The API will return tuples and an optional continuation token, something like +The API will return tuples and a continuation token, something like ```json { @@ -2560,11 +2568,13 @@ The API will return tuples and an optional continuation token, something like }, "timestamp": "2021-10-06T15:32:11.128Z" } - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` -This means that `user:bob` has a `reader` relationship with 1 document `document:2021-budget`. +This means that `user:bob` has a `reader` relationship with 1 document `document:2021-budget`. Note that this API, unlike the List Objects API, does not evaluate the tuples in the store. +The continuation token will be empty if there are no more tuples to query. ### Query for all stored relationship tuples that have a particular relation and object To query for all users that have `reader` relationship with `document:2021-budget`, call read API with body of ```json @@ -2590,11 +2600,12 @@ The API will return something like }, "timestamp": "2021-10-06T15:32:11.128Z" } - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` -This means that `document:2021-budget` has 1 `reader` (`user:bob`). Note that the API will not return writers such as `user:anne` even when all writers are readers. This is because only direct relationship are returned for the READ API. +This means that `document:2021-budget` has 1 `reader` (`user:bob`). Note that, even if the model said that all `writers` are also `readers`, the API will not return writers such as `user:anne` because it only returns tuples and does not evaluate them. ### Query for all users with all relationships for a particular document To query for all users that have any relationship with `document:2021-budget`, call read API with body of ```json @@ -2627,7 +2638,8 @@ The API will return something like }, "timestamp": "2021-10-06T15:32:11.128Z" } - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` @@ -3488,11 +3500,12 @@ Assume that a store's authorization model has been configured twice. To get all "id": "01G4ZW8F4A07AKQ8RHSVG9RW04", "type_definitions": [...] }, - ] + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" } ``` -If there are more authorization models available, the response will contain an extra field `continuation_token`: +If there are no more authorization models available, the `continuation_token` field will be empty ```json { @@ -3506,7 +3519,7 @@ If there are more authorization models available, the response will contain an e "type_definitions": [...] }, ], - "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + "continuation_token": "" } ``` diff --git a/client/client.go b/client/client.go index 990e0b5..1a9c0c9 100644 --- a/client/client.go +++ b/client/client.go @@ -419,7 +419,7 @@ type SdkClient interface { func (client *OpenFgaClient) getAuthorizationModelId(authorizationModelId *string) (*string, error) { modelId := client.config.AuthorizationModelId - if authorizationModelId != nil { + if authorizationModelId != nil && *authorizationModelId != "" { modelId = authorizationModelId } @@ -431,7 +431,7 @@ func (client *OpenFgaClient) getAuthorizationModelId(authorizationModelId *strin // helper function to validate the connection (i.e., get token) func (client *OpenFgaClient) checkValidApiConnection(ctx _context.Context, authorizationModelId *string) error { - if authorizationModelId != nil { + if authorizationModelId != nil && *authorizationModelId != "" { _, _, err := client.OpenFgaApi.ReadAuthorizationModel(ctx, *authorizationModelId).Execute() return err } else { diff --git a/configuration.go b/configuration.go index 1bcf182..71d54f2 100644 --- a/configuration.go +++ b/configuration.go @@ -65,7 +65,7 @@ func NewConfiguration(config Configuration) (*Configuration, error) { Credentials: config.Credentials, DefaultHeaders: config.DefaultHeaders, UserAgent: config.UserAgent, - Debug: false, + Debug: config.Debug, RetryParams: config.RetryParams, } diff --git a/docs/ListStoresResponse.md b/docs/ListStoresResponse.md index 43c4d1e..e3f2bbb 100644 --- a/docs/ListStoresResponse.md +++ b/docs/ListStoresResponse.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Stores** | Pointer to [**[]Store**](Store.md) | | [optional] -**ContinuationToken** | Pointer to **string** | | [optional] +**ContinuationToken** | Pointer to **string** | The continuation token will be empty if there are no more stores. | [optional] ## Methods diff --git a/docs/ReadAuthorizationModelsResponse.md b/docs/ReadAuthorizationModelsResponse.md index 5f3d22e..f176ebc 100644 --- a/docs/ReadAuthorizationModelsResponse.md +++ b/docs/ReadAuthorizationModelsResponse.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **AuthorizationModels** | Pointer to [**[]AuthorizationModel**](AuthorizationModel.md) | | [optional] -**ContinuationToken** | Pointer to **string** | | [optional] +**ContinuationToken** | Pointer to **string** | The continuation token will be empty if there are no more models. | [optional] ## Methods diff --git a/docs/ReadChangesResponse.md b/docs/ReadChangesResponse.md index f4ff2de..552d697 100644 --- a/docs/ReadChangesResponse.md +++ b/docs/ReadChangesResponse.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Changes** | Pointer to [**[]TupleChange**](TupleChange.md) | | [optional] -**ContinuationToken** | Pointer to **string** | | [optional] +**ContinuationToken** | Pointer to **string** | The continuation token will be identical if there are no new changes. | [optional] ## Methods diff --git a/docs/ReadResponse.md b/docs/ReadResponse.md index c5a9f72..a698890 100644 --- a/docs/ReadResponse.md +++ b/docs/ReadResponse.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Tuples** | Pointer to [**[]Tuple**](Tuple.md) | | [optional] -**ContinuationToken** | Pointer to **string** | | [optional] +**ContinuationToken** | Pointer to **string** | The continuation token will be empty if there are no more tuples. | [optional] ## Methods diff --git a/model_list_stores_response.go b/model_list_stores_response.go index af29843..e8cbf58 100644 --- a/model_list_stores_response.go +++ b/model_list_stores_response.go @@ -18,8 +18,9 @@ import ( // ListStoresResponse struct for ListStoresResponse type ListStoresResponse struct { - Stores *[]Store `json:"stores,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` + Stores *[]Store `json:"stores,omitempty"` + // The continuation token will be empty if there are no more stores. + ContinuationToken *string `json:"continuation_token,omitempty"` } // NewListStoresResponse instantiates a new ListStoresResponse object diff --git a/model_read_authorization_models_response.go b/model_read_authorization_models_response.go index 9fdaca1..be5ceab 100644 --- a/model_read_authorization_models_response.go +++ b/model_read_authorization_models_response.go @@ -19,7 +19,8 @@ import ( // ReadAuthorizationModelsResponse struct for ReadAuthorizationModelsResponse type ReadAuthorizationModelsResponse struct { AuthorizationModels *[]AuthorizationModel `json:"authorization_models,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` + // The continuation token will be empty if there are no more models. + ContinuationToken *string `json:"continuation_token,omitempty"` } // NewReadAuthorizationModelsResponse instantiates a new ReadAuthorizationModelsResponse object diff --git a/model_read_changes_response.go b/model_read_changes_response.go index 10c2f4d..d519c2c 100644 --- a/model_read_changes_response.go +++ b/model_read_changes_response.go @@ -18,8 +18,9 @@ import ( // ReadChangesResponse struct for ReadChangesResponse type ReadChangesResponse struct { - Changes *[]TupleChange `json:"changes,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` + Changes *[]TupleChange `json:"changes,omitempty"` + // The continuation token will be identical if there are no new changes. + ContinuationToken *string `json:"continuation_token,omitempty"` } // NewReadChangesResponse instantiates a new ReadChangesResponse object diff --git a/model_read_response.go b/model_read_response.go index c1b069e..b3036b2 100644 --- a/model_read_response.go +++ b/model_read_response.go @@ -18,8 +18,9 @@ import ( // ReadResponse struct for ReadResponse type ReadResponse struct { - Tuples *[]Tuple `json:"tuples,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` + Tuples *[]Tuple `json:"tuples,omitempty"` + // The continuation token will be empty if there are no more tuples. + ContinuationToken *string `json:"continuation_token,omitempty"` } // NewReadResponse instantiates a new ReadResponse object