From 1b89e05329936ec8138f2a7f1c98421810a4129b Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Fri, 24 Oct 2025 17:34:09 +0530 Subject: [PATCH 1/9] feat: generate API layer for streaming endpoints feat: streaming list objects support --- .openapi-generator/FILES | 4 + CHANGELOG.md | 4 +- CONTRIBUTING.md | 2 +- README.md | 3 + api_open_fga.go | 214 + client/client.go | 4419 +++++++++-------- client/streaming_test.go | 329 ++ docs/OpenFgaApi.md | 94 + ...reamResultOfStreamedListObjectsResponse.md | 82 + docs/StreamedListObjectsResponse.md | 51 + example/README.md | 3 + example/streamed_list_objects/README.md | 143 + example/streamed_list_objects/go.mod | 20 + example/streamed_list_objects/main.go | 255 + ...esult_of_streamed_list_objects_response.go | 160 + model_streamed_list_objects_response.go | 115 + streaming.go | 153 + streaming_test.go | 493 ++ 18 files changed, 4417 insertions(+), 2127 deletions(-) create mode 100644 client/streaming_test.go create mode 100644 docs/StreamResultOfStreamedListObjectsResponse.md create mode 100644 docs/StreamedListObjectsResponse.md create mode 100644 example/streamed_list_objects/README.md create mode 100644 example/streamed_list_objects/go.mod create mode 100644 example/streamed_list_objects/main.go create mode 100644 model_stream_result_of_streamed_list_objects_response.go create mode 100644 model_streamed_list_objects_response.go create mode 100644 streaming.go create mode 100644 streaming_test.go diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 26f3192..a3c05a2 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -68,6 +68,8 @@ docs/RelationshipCondition.md docs/SourceInfo.md docs/Status.md docs/Store.md +docs/StreamResultOfStreamedListObjectsResponse.md +docs/StreamedListObjectsResponse.md docs/Tuple.md docs/TupleChange.md docs/TupleKey.md @@ -157,6 +159,8 @@ model_relationship_condition.go model_source_info.go model_status.go model_store.go +model_stream_result_of_streamed_list_objects_response.go +model_streamed_list_objects_response.go model_tuple.go model_tuple_change.go model_tuple_key.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 882715e..289d9ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,12 @@ ## [Unreleased](https://github.com/openfga/go-sdk/compare/v0.7.3...HEAD) - feat: add generic `ToPtr[T any](v T) *T` function for creating pointers to any type - deprecation: `PtrBool`, `PtrInt`, `PtrInt32`, `PtrInt64`, `PtrFloat32`, `PtrFloat64`, `PtrString`, and `PtrTime` are now deprecated in favor of the generic `ToPtr` function +- feat: add support for StreamedListObjects endpoint +- feat: add configurable buffer size for streaming responses via `ClientStreamedListObjectsOptions.StreamBufferSize` ## v0.7.3 -### [0.7.3](https://github.com/openfga/go-sdk/compare/v0.7.2...v0.7.3) +### [0.7.3](https://github.com/openfga/go-sdk/compare/v0.7.2...v0.7.3) (2025-10-08) - feat: add support for custom headers per request. See [documentation](https://github.com/openfga/go-sdk#custom-headers). - feat: add support for conflict options for Write operations**: (#229) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb0c695..e2e23f3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ Reading and following these guidelines will help us make the contribution proces * [Getting Started](#getting-started) * [Making Changes](#making-changes) * [Opening Issues](#opening-issues) - * [Submitting Pull Requests](#submitting-pull-requests) [Note: We are not accepting Pull Requests at this time!] + * [Submitting Pull Requests](#submitting-pull-requests) * [Getting in Touch](#getting-in-touch) * [Have a question or problem?](#have-a-question-or-problem) * [Vulnerability Reporting](#vulnerability-reporting) diff --git a/README.md b/README.md index c81e159..d5d6c6c 100644 --- a/README.md +++ b/README.md @@ -1101,6 +1101,7 @@ Class | Method | HTTP request | Description *OpenFgaApi* | [**ReadAuthorizationModel**](docs/OpenFgaApi.md#readauthorizationmodel) | **Get** /stores/{store_id}/authorization-models/{id} | Return a particular version of an authorization model *OpenFgaApi* | [**ReadAuthorizationModels**](docs/OpenFgaApi.md#readauthorizationmodels) | **Get** /stores/{store_id}/authorization-models | Return all the authorization models for a particular store *OpenFgaApi* | [**ReadChanges**](docs/OpenFgaApi.md#readchanges) | **Get** /stores/{store_id}/changes | Return a list of all the tuple changes +*OpenFgaApi* | [**StreamedListObjects**](docs/OpenFgaApi.md#streamedlistobjects) | **Post** /stores/{store_id}/streamed-list-objects | Stream all objects of the given type that the user has a relation with *OpenFgaApi* | [**Write**](docs/OpenFgaApi.md#write) | **Post** /stores/{store_id}/write | Add or delete tuples from the store *OpenFgaApi* | [**WriteAssertions**](docs/OpenFgaApi.md#writeassertions) | **Put** /stores/{store_id}/assertions/{authorization_model_id} | Upsert assertions for an authorization model ID *OpenFgaApi* | [**WriteAuthorizationModel**](docs/OpenFgaApi.md#writeauthorizationmodel) | **Post** /stores/{store_id}/authorization-models | Create a new authorization model @@ -1166,6 +1167,8 @@ Class | Method | HTTP request | Description - [SourceInfo](docs/SourceInfo.md) - [Status](docs/Status.md) - [Store](docs/Store.md) + - [StreamResultOfStreamedListObjectsResponse](docs/StreamResultOfStreamedListObjectsResponse.md) + - [StreamedListObjectsResponse](docs/StreamedListObjectsResponse.md) - [Tuple](docs/Tuple.md) - [TupleChange](docs/TupleChange.md) - [TupleKey](docs/TupleKey.md) diff --git a/api_open_fga.go b/api_open_fga.go index 309b182..045765f 100644 --- a/api_open_fga.go +++ b/api_open_fga.go @@ -771,6 +771,24 @@ type OpenFgaApi interface { */ ReadChangesExecute(r ApiReadChangesRequest) (ReadChangesResponse, *http.Response, error) + /* + * StreamedListObjects Stream all objects of the given type that the user has a relation with + * The Streamed ListObjects API is very similar to the the ListObjects API, with two differences: + 1. Instead of collecting all objects before returning a response, it streams them to the client as they are collected. + 2. The number of results returned is only limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE. + + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiStreamedListObjectsRequest + */ + StreamedListObjects(ctx context.Context, storeId string) ApiStreamedListObjectsRequest + + /* + * StreamedListObjectsExecute executes the request + * @return StreamResultOfStreamedListObjectsResponse + */ + StreamedListObjectsExecute(r ApiStreamedListObjectsRequest) (StreamResultOfStreamedListObjectsResponse, *http.Response, error) + /* * Write Add or delete tuples from the store * 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. @@ -4170,6 +4188,202 @@ func (a *OpenFgaApiService) ReadChangesExecute(r ApiReadChangesRequest) (ReadCha return returnValue, nil, reportError("Error not handled properly") } +type ApiStreamedListObjectsRequest struct { + ctx context.Context + ApiService OpenFgaApi + storeId string + body *ListObjectsRequest + options RequestOptions +} + +func (r ApiStreamedListObjectsRequest) Body(body ListObjectsRequest) ApiStreamedListObjectsRequest { + r.body = &body + return r +} + +func (r ApiStreamedListObjectsRequest) Options(options RequestOptions) ApiStreamedListObjectsRequest { + r.options = options + return r +} + +func (r ApiStreamedListObjectsRequest) Execute() (StreamResultOfStreamedListObjectsResponse, *http.Response, error) { + return r.ApiService.StreamedListObjectsExecute(r) +} + +/* + - StreamedListObjects Stream all objects of the given type that the user has a relation with + - The Streamed ListObjects API is very similar to the the ListObjects API, with two differences: + +1. Instead of collecting all objects before returning a response, it streams them to the client as they are collected. +2. The number of results returned is only limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE. + + - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + - @param storeId + - @return ApiStreamedListObjectsRequest +*/ +func (a *OpenFgaApiService) StreamedListObjects(ctx context.Context, storeId string) ApiStreamedListObjectsRequest { + return ApiStreamedListObjectsRequest{ + ApiService: a, + ctx: ctx, + storeId: storeId, + } +} + +/* + * Execute executes the request + * @return StreamResultOfStreamedListObjectsResponse + */ +func (a *OpenFgaApiService) StreamedListObjectsExecute(r ApiStreamedListObjectsRequest) (StreamResultOfStreamedListObjectsResponse, *http.Response, error) { + const ( + operationName = "StreamedListObjects" + httpMethod = http.MethodPost + ) + var ( + requestStarted = time.Now() + requestBody interface{} + returnValue StreamResultOfStreamedListObjectsResponse + ) + + path := "/stores/{store_id}/streamed-list-objects" + if r.storeId == "" { + return returnValue, nil, reportError("storeId is required and must be specified") + } + + path = strings.ReplaceAll(path, "{"+"store_id"+"}", url.PathEscape(parameterToString(r.storeId, ""))) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + if r.body == nil { + return returnValue, nil, reportError("body is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + requestBody = r.body + + // if any override headers were in the options, set them now + for header, val := range r.options.Headers { + localVarHeaderParams[header] = val + } + + retryParams := a.client.cfg.RetryParams + for i := 0; i < retryParams.MaxRetry+1; i++ { + req, err := a.client.prepareRequest(r.ctx, path, httpMethod, requestBody, localVarHeaderParams, localVarQueryParams) + if err != nil { + return returnValue, nil, err + } + + httpResponse, err := a.client.callAPI(req) + if err != nil || httpResponse == nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, http.Header{}, operationName) + if timeToWait > 0 { + if a.client.cfg.Debug { + log.Printf("\nWaiting %v to retry %v (%v %v) due to network error (error=%v) on attempt %v. Request body: %v\n", timeToWait, operationName, req.Method, req.URL, err, i, requestBody) + } + time.Sleep(timeToWait) + continue + } + } + return returnValue, httpResponse, err + } + + responseBody, err := io.ReadAll(httpResponse.Body) + _ = httpResponse.Body.Close() + httpResponse.Body = io.NopCloser(bytes.NewBuffer(responseBody)) + if err != nil { + if i < retryParams.MaxRetry { + timeToWait := retryutils.GetTimeToWait(i, retryParams.MaxRetry, retryParams.MinWaitInMs, httpResponse.Header, operationName) + if timeToWait > 0 { + if a.client.cfg.Debug { + log.Printf("\nWaiting %v to retry %v (%v %v) due to error parsing response body (err=%v) on attempt %v. Request body: %v\n", timeToWait, operationName, req.Method, req.URL, err, i, requestBody) + } + time.Sleep(timeToWait) + continue + } + } + return returnValue, httpResponse, err + } + + if httpResponse.StatusCode >= http.StatusMultipleChoices { + err := a.client.handleAPIError(httpResponse, responseBody, requestBody, operationName, r.storeId) + if err != nil && i < retryParams.MaxRetry { + timeToWait := time.Duration(0) + var fgaApiRateLimitExceededError FgaApiRateLimitExceededError + var fgaApiInternalError FgaApiInternalError + switch { + case errors.As(err, &fgaApiRateLimitExceededError): + timeToWait = err.(FgaApiRateLimitExceededError).GetTimeToWait(i, *retryParams) + case errors.As(err, &fgaApiInternalError): + timeToWait = err.(FgaApiInternalError).GetTimeToWait(i, *retryParams) + } + + if timeToWait > 0 { + if a.client.cfg.Debug { + log.Printf("\nWaiting %v to retry %v (%v %v) due to api retryable error (status code %v, error=%v) on attempt %v. Request body: %v\n", timeToWait, operationName, req.Method, req.URL, httpResponse.StatusCode, err, i, requestBody) + } + time.Sleep(timeToWait) + continue + } + } + + return returnValue, httpResponse, err + } + + err = a.client.decode(&returnValue, responseBody, httpResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: responseBody, + error: err.Error(), + } + return returnValue, httpResponse, newErr + } + + metrics := telemetry.GetMetrics(telemetry.TelemetryFactoryParameters{Configuration: a.client.cfg.Telemetry}) + + var attrs, queryDuration, requestDuration, _ = metrics.BuildTelemetryAttributes( + operationName, + map[string]interface{}{ + "storeId": r.storeId, + "body": requestBody, + }, + req, + httpResponse, + requestStarted, + i, + ) + + if requestDuration > 0 { + _, _ = metrics.RequestDuration(requestDuration, attrs) + } + + if queryDuration > 0 { + _, _ = metrics.QueryDuration(queryDuration, attrs) + } + + return returnValue, httpResponse, nil + } + + // should never have reached this + return returnValue, nil, reportError("Error not handled properly") +} + type ApiWriteRequest struct { ctx context.Context ApiService OpenFgaApi diff --git a/client/client.go b/client/client.go index 0a9ccff..f4d045d 100644 --- a/client/client.go +++ b/client/client.go @@ -1,121 +1,121 @@ package client import ( - _context "context" - "encoding/json" - "fmt" - "math" - _nethttp "net/http" - "time" - - "github.com/sourcegraph/conc/pool" - "golang.org/x/sync/errgroup" - - fgaSdk "github.com/openfga/go-sdk" - "github.com/openfga/go-sdk/credentials" - "github.com/openfga/go-sdk/internal/constants" - internalutils "github.com/openfga/go-sdk/internal/utils" - "github.com/openfga/go-sdk/telemetry" + _context "context" + "encoding/json" + "fmt" + "math" + _nethttp "net/http" + "time" + + "github.com/sourcegraph/conc/pool" + "golang.org/x/sync/errgroup" + + fgaSdk "github.com/openfga/go-sdk" + "github.com/openfga/go-sdk/credentials" + "github.com/openfga/go-sdk/internal/constants" + internalutils "github.com/openfga/go-sdk/internal/utils" + "github.com/openfga/go-sdk/telemetry" ) var ( - _ _context.Context - // Ensure the SdkClient fits OpenFgaClient interface - _ SdkClient = (*OpenFgaClient)(nil) + _ _context.Context + // Ensure the SdkClient fits OpenFgaClient interface + _ SdkClient = (*OpenFgaClient)(nil) ) var DEFAULT_MAX_METHOD_PARALLEL_REQS = int32(constants.ClientMaxMethodParallelRequests) type ClientConfiguration struct { - fgaSdk.Configuration - // ApiScheme - defines the scheme for the API: http or https - // Deprecated: use ApiUrl instead of ApiScheme and ApiHost - ApiScheme string `json:"api_scheme"` - // ApiHost - defines the host for the API without the scheme e.g. (api.fga.example) - // Deprecated: use ApiUrl instead of ApiScheme and ApiHost - ApiHost string `json:"api_host"` - ApiUrl string `json:"api_url"` - StoreId string `json:"store_id"` - AuthorizationModelId string `json:"authorization_model_id"` - Credentials *credentials.Credentials `json:"credentials"` - DefaultHeaders map[string]string `json:"default_headers"` - UserAgent string `json:"user_agent"` - Debug bool `json:"debug"` - HTTPClient *_nethttp.Client - RetryParams *fgaSdk.RetryParams - Telemetry *telemetry.Configuration `json:"telemetry,omitempty"` + fgaSdk.Configuration + // ApiScheme - defines the scheme for the API: http or https + // Deprecated: use ApiUrl instead of ApiScheme and ApiHost + ApiScheme string `json:"api_scheme"` + // ApiHost - defines the host for the API without the scheme e.g. (api.fga.example) + // Deprecated: use ApiUrl instead of ApiScheme and ApiHost + ApiHost string `json:"api_host"` + ApiUrl string `json:"api_url"` + StoreId string `json:"store_id"` + AuthorizationModelId string `json:"authorization_model_id"` + Credentials *credentials.Credentials `json:"credentials"` + DefaultHeaders map[string]string `json:"default_headers"` + UserAgent string `json:"user_agent"` + Debug bool `json:"debug"` + HTTPClient *_nethttp.Client + RetryParams *fgaSdk.RetryParams + Telemetry *telemetry.Configuration `json:"telemetry,omitempty"` } func newClientConfiguration(cfg *fgaSdk.Configuration) ClientConfiguration { - return ClientConfiguration{ - ApiScheme: cfg.ApiScheme, - ApiHost: cfg.ApiHost, - ApiUrl: cfg.ApiUrl, - Credentials: cfg.Credentials, - DefaultHeaders: cfg.DefaultHeaders, - UserAgent: cfg.UserAgent, - Debug: cfg.Debug, - HTTPClient: cfg.HTTPClient, - RetryParams: cfg.RetryParams, - Telemetry: cfg.Telemetry, - } + return ClientConfiguration{ + ApiScheme: cfg.ApiScheme, + ApiHost: cfg.ApiHost, + ApiUrl: cfg.ApiUrl, + Credentials: cfg.Credentials, + DefaultHeaders: cfg.DefaultHeaders, + UserAgent: cfg.UserAgent, + Debug: cfg.Debug, + HTTPClient: cfg.HTTPClient, + RetryParams: cfg.RetryParams, + Telemetry: cfg.Telemetry, + } } type OpenFgaClient struct { - config ClientConfiguration - SdkClient - fgaSdk.APIClient + config ClientConfiguration + SdkClient + fgaSdk.APIClient } func NewSdkClient(cfg *ClientConfiguration) (*OpenFgaClient, error) { - apiConfiguration, err := fgaSdk.NewConfiguration(fgaSdk.Configuration{ - ApiScheme: cfg.ApiScheme, - ApiHost: cfg.ApiHost, - ApiUrl: cfg.ApiUrl, - Credentials: cfg.Credentials, - DefaultHeaders: cfg.DefaultHeaders, - UserAgent: cfg.UserAgent, - Debug: cfg.Debug, - HTTPClient: cfg.HTTPClient, - RetryParams: cfg.RetryParams, - Telemetry: cfg.Telemetry, - }) + apiConfiguration, err := fgaSdk.NewConfiguration(fgaSdk.Configuration{ + ApiScheme: cfg.ApiScheme, + ApiHost: cfg.ApiHost, + ApiUrl: cfg.ApiUrl, + Credentials: cfg.Credentials, + DefaultHeaders: cfg.DefaultHeaders, + UserAgent: cfg.UserAgent, + Debug: cfg.Debug, + HTTPClient: cfg.HTTPClient, + RetryParams: cfg.RetryParams, + Telemetry: cfg.Telemetry, + }) - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - clientConfig := newClientConfiguration(apiConfiguration) - clientConfig.AuthorizationModelId = cfg.AuthorizationModelId - clientConfig.StoreId = cfg.StoreId + clientConfig := newClientConfiguration(apiConfiguration) + clientConfig.AuthorizationModelId = cfg.AuthorizationModelId + clientConfig.StoreId = cfg.StoreId - // store id is already validate as part of configuration validation + // store id is already validate as part of configuration validation - if cfg.AuthorizationModelId != "" && !internalutils.IsWellFormedUlidString(cfg.AuthorizationModelId) { - return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } + if cfg.AuthorizationModelId != "" && !internalutils.IsWellFormedUlidString(cfg.AuthorizationModelId) { + return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } - if cfg.StoreId != "" && !internalutils.IsWellFormedUlidString(cfg.StoreId) { - return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } + if cfg.StoreId != "" && !internalutils.IsWellFormedUlidString(cfg.StoreId) { + return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } - apiClient := fgaSdk.NewAPIClient(apiConfiguration) + apiClient := fgaSdk.NewAPIClient(apiConfiguration) - return &OpenFgaClient{ - config: clientConfig, - APIClient: *apiClient, - }, nil + return &OpenFgaClient{ + config: clientConfig, + APIClient: *apiClient, + }, nil } type RequestOptions = fgaSdk.RequestOptions type AuthorizationModelIdOptions struct { - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` } type ClientRequestOptionsWithAuthZModelId struct { - RequestOptions - AuthorizationModelIdOptions + RequestOptions + AuthorizationModelIdOptions } type ClientTupleKey = fgaSdk.TupleKey @@ -127,1877 +127,1890 @@ type ClientContextualTupleKey = ClientTupleKey // ClientBatchCheckItem represents a flattened check item for batch check operations type ClientBatchCheckItem struct { - User string `json:"user"` - Relation string `json:"relation"` - Object string `json:"object"` - CorrelationId string `json:"correlation_id"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` + User string `json:"user"` + Relation string `json:"relation"` + Object string `json:"object"` + CorrelationId string `json:"correlation_id"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` } // ClientBatchCheckRequest represents a request for batch check operations type ClientBatchCheckRequest struct { - Checks []ClientBatchCheckItem `json:"checks"` + Checks []ClientBatchCheckItem `json:"checks"` } // BatchCheckOptions represents options for server-side batch check operations type BatchCheckOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` - MaxBatchSize *int32 `json:"max_batch_size,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` + MaxBatchSize *int32 `json:"max_batch_size,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientPaginationOptions struct { - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` } func getPageSizeFromRequest(options *ClientPaginationOptions) *int32 { - if options == nil { - return nil - } - return options.PageSize + if options == nil { + return nil + } + return options.PageSize } func getContinuationTokenFromRequest(options *ClientPaginationOptions) *string { - if options == nil { - return nil - } - return options.ContinuationToken + if options == nil { + return nil + } + return options.ContinuationToken } type SdkClient interface { - /* Stores */ - - /* - * ListStores Get a paginated list of stores. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientListStoresRequestInterface - */ - ListStores(ctx _context.Context) SdkClientListStoresRequestInterface - - /* - * ListStoresExecute executes the ListStores request - * @return *ClientListStoresResponse - */ - ListStoresExecute(request SdkClientListStoresRequestInterface) (*ClientListStoresResponse, error) - - /* - * CreateStore Create and initialize a store - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientCreateStoreRequestInterface - */ - CreateStore(ctx _context.Context) SdkClientCreateStoreRequestInterface - - /* - * CreateStoreExecute executes the CreateStore request - * @return *ClientCreateStoreResponse - */ - CreateStoreExecute(request SdkClientCreateStoreRequestInterface) (*ClientCreateStoreResponse, error) - - /* - * GetStore Get information about the current store. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientGetStoreRequestInterface - */ - GetStore(ctx _context.Context) SdkClientGetStoreRequestInterface - - /* - * GetStoreExecute executes the GetStore request - * @return *ClientGetStoreResponse - */ - GetStoreExecute(request SdkClientGetStoreRequestInterface) (*ClientGetStoreResponse, error) - - /* - * DeleteStore Delete a store. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientDeleteStoreRequestInterface - */ - DeleteStore(ctx _context.Context) SdkClientDeleteStoreRequestInterface - - /* - * DeleteStoreExecute executes the DeleteStore request - * @return *ClientDeleteStoreResponse - */ - DeleteStoreExecute(request SdkClientDeleteStoreRequestInterface) (*ClientDeleteStoreResponse, error) - - /* Authorization Models */ - - /* - * ReadAuthorizationModels Read all authorization models in the store. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadAuthorizationModelsRequest - */ - ReadAuthorizationModels(ctx _context.Context) SdkClientReadAuthorizationModelsRequestInterface - - /* - * ReadAuthorizationModelsExecute executes the ReadAuthorizationModels request - * @return *ClientReadAuthorizationModelsResponse - */ - ReadAuthorizationModelsExecute(request SdkClientReadAuthorizationModelsRequestInterface) (*ClientReadAuthorizationModelsResponse, error) - - /* - * WriteAuthorizationModel Create a new authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteAuthorizationModelRequest - */ - WriteAuthorizationModel(ctx _context.Context) SdkClientWriteAuthorizationModelRequestInterface - - /* - * WriteAuthorizationModelExecute executes the WriteAuthorizationModel request - * @return *ClientWriteAuthorizationModelResponse - */ - WriteAuthorizationModelExecute(request SdkClientWriteAuthorizationModelRequestInterface) (*ClientWriteAuthorizationModelResponse, error) - - /* - * ReadAuthorizationModel Read a particular authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadAuthorizationModelRequestInterface - */ - ReadAuthorizationModel(ctx _context.Context) SdkClientReadAuthorizationModelRequestInterface - - /* - * ReadAuthorizationModelExecute executes the ReadAuthorizationModel request - * @return *ClientReadAuthorizationModelResponse - */ - ReadAuthorizationModelExecute(request SdkClientReadAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) - - /* - * ReadLatestAuthorizationModel Reads the latest authorization model (note: this ignores the model id in configuration). - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadLatestAuthorizationModelRequestInterface - */ - ReadLatestAuthorizationModel(ctx _context.Context) SdkClientReadLatestAuthorizationModelRequestInterface - - /* - * ReadLatestAuthorizationModelExecute executes the ReadLatestAuthorizationModel request - * @return *ClientReadAuthorizationModelResponse - */ - ReadLatestAuthorizationModelExecute(request SdkClientReadLatestAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) - - /* Relationship Tuples */ - - /* - * ReadChanges Reads the list of historical relationship tuple writes and deletes. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadChangesRequestInterface - */ - ReadChanges(ctx _context.Context) SdkClientReadChangesRequestInterface - - /* - * ReadChangesExecute executes the ReadChanges request - * @return *ClientReadChangesResponse - */ - ReadChangesExecute(request SdkClientReadChangesRequestInterface) (*ClientReadChangesResponse, error) - - /* - * Read Reads the relationship tuples stored in the database. It does not evaluate nor exclude invalid tuples according to the authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadRequestInterface - */ - Read(ctx _context.Context) SdkClientReadRequestInterface - - /* - * ReadExecute executes the Read request - * @return *ClientReadResponse - */ - ReadExecute(request SdkClientReadRequestInterface) (*ClientReadResponse, error) - - /* - * Write Create and/or delete relationship tuples to update the system state. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteRequestInterface - */ - Write(ctx _context.Context) SdkClientWriteRequestInterface - - /* - * WriteExecute executes the Write request - * @return *ClientWriteResponse - */ - WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) - - /* - * WriteTuples Utility method around Write - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteTuplesRequestInterface - */ - WriteTuples(ctx _context.Context) SdkClientWriteTuplesRequestInterface - - /* - * WriteTuplesExecute executes the WriteTuples request - * @return *ClientWriteResponse - */ - WriteTuplesExecute(request SdkClientWriteTuplesRequestInterface) (*ClientWriteResponse, error) - - /* - * DeleteTuples Utility method around Write - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientDeleteTuplesRequestInterface - */ - DeleteTuples(ctx _context.Context) SdkClientDeleteTuplesRequestInterface - - /* - * DeleteTuplesExecute executes the DeleteTuples request - * @return *ClientWriteResponse - */ - DeleteTuplesExecute(request SdkClientDeleteTuplesRequestInterface) (*ClientWriteResponse, error) - - /* Relationship Queries */ - - /* - * Check Check if a user has a particular relation with an object. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientCheckRequestInterface - */ - Check(ctx _context.Context) SdkClientCheckRequestInterface - - /* - * CheckExecute executes the Check request - * @return *ClientCheckResponse - */ - CheckExecute(request SdkClientCheckRequestInterface) (*ClientCheckResponse, error) - - /* - * ClientBatchCheck Run a set of [checks](#check). Batch Check will return `allowed: false` if it encounters an error, and will return the error in the body. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientBatchCheckRequestInterface - */ - ClientBatchCheck(ctx _context.Context) SdkClientBatchCheckClientRequestInterface - - /* - * ClientBatchCheckExecute executes the BatchCheck request - * @return *ClientBatchCheckResponse - */ - ClientBatchCheckExecute(request SdkClientBatchCheckClientRequestInterface) (*ClientBatchCheckClientResponse, error) - - /* - * BatchCheck Run a set of checks on the server. Server-side batch check allows for more efficient checking of multiple tuples. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientBatchCheckRequestInterface - */ - BatchCheck(ctx _context.Context) SdkClientBatchCheckRequestInterface - - /* - * BatchCheckExecute executes the server-side BatchCheck request - * @return *BatchCheckResponse - */ - BatchCheckExecute(request SdkClientBatchCheckRequestInterface) (*fgaSdk.BatchCheckResponse, error) - - /* - * Expand Expands the relationships in userset tree format. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientExpandRequestInterface - */ - Expand(ctx _context.Context) SdkClientExpandRequestInterface - - /* - * ExpandExecute executes the Expand request - * @return *ClientExpandResponse - */ - ExpandExecute(request SdkClientExpandRequestInterface) (*ClientExpandResponse, error) - - /* - * ListObjects List the objects of a particular type a user has access to. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientListObjectsRequestInterface - */ - ListObjects(ctx _context.Context) SdkClientListObjectsRequestInterface - - /* - * ListObjectsExecute executes the ListObjects request - * @return *ClientListObjectsResponse - */ - ListObjectsExecute(request SdkClientListObjectsRequestInterface) (*ClientListObjectsResponse, error) - - /* - * ListRelations List the relations a user has on an object. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientListRelationsRequestInterface - */ - ListRelations(ctx _context.Context) SdkClientListRelationsRequestInterface - - /* - * ListRelationsExecute executes the ListRelations request - * @return *ClientListRelationsResponse - */ - ListRelationsExecute(request SdkClientListRelationsRequestInterface) (*ClientListRelationsResponse, error) - - /* - * ListUsers List all users of the given type that the object has a relation with - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return ApiListUsersRequest - */ - ListUsers(ctx _context.Context) SdkClientListUsersRequestInterface - - /* - * ListUsersExecute executes the request - * @return ListUsersResponse - */ - ListUsersExecute(r SdkClientListUsersRequestInterface) (*ClientListUsersResponse, error) - - /* Assertions */ - - /* - * ReadAssertions Read assertions for a particular authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadAssertionsRequestInterface - */ - ReadAssertions(ctx _context.Context) SdkClientReadAssertionsRequestInterface - - /* - * ReadAssertionsExecute executes the ReadAssertions request - * @return *ClientReadAssertionsResponse - */ - ReadAssertionsExecute(request SdkClientReadAssertionsRequestInterface) (*ClientReadAssertionsResponse, error) - - /* - * WriteAssertions Update the assertions for a particular authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteAssertionsRequestInterface - */ - WriteAssertions(ctx _context.Context) SdkClientWriteAssertionsRequestInterface - - /* - * WriteAssertionsExecute executes the WriteAssertions request - * @return *ClientWriteAssertionsResponse - */ - WriteAssertionsExecute(request SdkClientWriteAssertionsRequestInterface) (*ClientWriteAssertionsResponse, error) - - /* - * SetAuthorizationModelId allows setting the Authorization Model ID for an OpenFgaClient. - * @param string authorizationModelId - The Authorization Model ID to set. - */ - SetAuthorizationModelId(authorizationModelId string) error - /* - * GetAuthorizationModelId retrieves the Authorization Model ID for an OpenFgaClient. - * @return string - */ - GetAuthorizationModelId() (string, error) - /* - * SetStoreId allows setting the Store ID for an OpenFgaClient. - * @param string storeId - The Store ID to set. - */ - SetStoreId(storeId string) error - /* - * GetStoreId retrieves the Store ID set in the OpenFgaClient. - * @return string - */ - GetStoreId() (string, error) + /* Stores */ + + /* + * ListStores Get a paginated list of stores. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientListStoresRequestInterface + */ + ListStores(ctx _context.Context) SdkClientListStoresRequestInterface + + /* + * ListStoresExecute executes the ListStores request + * @return *ClientListStoresResponse + */ + ListStoresExecute(request SdkClientListStoresRequestInterface) (*ClientListStoresResponse, error) + + /* + * CreateStore Create and initialize a store + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientCreateStoreRequestInterface + */ + CreateStore(ctx _context.Context) SdkClientCreateStoreRequestInterface + + /* + * CreateStoreExecute executes the CreateStore request + * @return *ClientCreateStoreResponse + */ + CreateStoreExecute(request SdkClientCreateStoreRequestInterface) (*ClientCreateStoreResponse, error) + + /* + * GetStore Get information about the current store. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientGetStoreRequestInterface + */ + GetStore(ctx _context.Context) SdkClientGetStoreRequestInterface + + /* + * GetStoreExecute executes the GetStore request + * @return *ClientGetStoreResponse + */ + GetStoreExecute(request SdkClientGetStoreRequestInterface) (*ClientGetStoreResponse, error) + + /* + * DeleteStore Delete a store. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientDeleteStoreRequestInterface + */ + DeleteStore(ctx _context.Context) SdkClientDeleteStoreRequestInterface + + /* + * DeleteStoreExecute executes the DeleteStore request + * @return *ClientDeleteStoreResponse + */ + DeleteStoreExecute(request SdkClientDeleteStoreRequestInterface) (*ClientDeleteStoreResponse, error) + + /* Authorization Models */ + + /* + * ReadAuthorizationModels Read all authorization models in the store. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadAuthorizationModelsRequest + */ + ReadAuthorizationModels(ctx _context.Context) SdkClientReadAuthorizationModelsRequestInterface + + /* + * ReadAuthorizationModelsExecute executes the ReadAuthorizationModels request + * @return *ClientReadAuthorizationModelsResponse + */ + ReadAuthorizationModelsExecute(request SdkClientReadAuthorizationModelsRequestInterface) (*ClientReadAuthorizationModelsResponse, error) + + /* + * WriteAuthorizationModel Create a new authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteAuthorizationModelRequest + */ + WriteAuthorizationModel(ctx _context.Context) SdkClientWriteAuthorizationModelRequestInterface + + /* + * WriteAuthorizationModelExecute executes the WriteAuthorizationModel request + * @return *ClientWriteAuthorizationModelResponse + */ + WriteAuthorizationModelExecute(request SdkClientWriteAuthorizationModelRequestInterface) (*ClientWriteAuthorizationModelResponse, error) + + /* + * ReadAuthorizationModel Read a particular authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadAuthorizationModelRequestInterface + */ + ReadAuthorizationModel(ctx _context.Context) SdkClientReadAuthorizationModelRequestInterface + + /* + * ReadAuthorizationModelExecute executes the ReadAuthorizationModel request + * @return *ClientReadAuthorizationModelResponse + */ + ReadAuthorizationModelExecute(request SdkClientReadAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) + + /* + * ReadLatestAuthorizationModel Reads the latest authorization model (note: this ignores the model id in configuration). + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadLatestAuthorizationModelRequestInterface + */ + ReadLatestAuthorizationModel(ctx _context.Context) SdkClientReadLatestAuthorizationModelRequestInterface + + /* + * ReadLatestAuthorizationModelExecute executes the ReadLatestAuthorizationModel request + * @return *ClientReadAuthorizationModelResponse + */ + ReadLatestAuthorizationModelExecute(request SdkClientReadLatestAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) + + /* Relationship Tuples */ + + /* + * ReadChanges Reads the list of historical relationship tuple writes and deletes. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadChangesRequestInterface + */ + ReadChanges(ctx _context.Context) SdkClientReadChangesRequestInterface + + /* + * ReadChangesExecute executes the ReadChanges request + * @return *ClientReadChangesResponse + */ + ReadChangesExecute(request SdkClientReadChangesRequestInterface) (*ClientReadChangesResponse, error) + + /* + * Read Reads the relationship tuples stored in the database. It does not evaluate nor exclude invalid tuples according to the authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadRequestInterface + */ + Read(ctx _context.Context) SdkClientReadRequestInterface + + /* + * ReadExecute executes the Read request + * @return *ClientReadResponse + */ + ReadExecute(request SdkClientReadRequestInterface) (*ClientReadResponse, error) + + /* + * Write Create and/or delete relationship tuples to update the system state. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteRequestInterface + */ + Write(ctx _context.Context) SdkClientWriteRequestInterface + + /* + * WriteExecute executes the Write request + * @return *ClientWriteResponse + */ + WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) + + /* + * WriteTuples Utility method around Write + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteTuplesRequestInterface + */ + WriteTuples(ctx _context.Context) SdkClientWriteTuplesRequestInterface + + /* + * WriteTuplesExecute executes the WriteTuples request + * @return *ClientWriteResponse + */ + WriteTuplesExecute(request SdkClientWriteTuplesRequestInterface) (*ClientWriteResponse, error) + + /* + * DeleteTuples Utility method around Write + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientDeleteTuplesRequestInterface + */ + DeleteTuples(ctx _context.Context) SdkClientDeleteTuplesRequestInterface + + /* + * DeleteTuplesExecute executes the DeleteTuples request + * @return *ClientWriteResponse + */ + DeleteTuplesExecute(request SdkClientDeleteTuplesRequestInterface) (*ClientWriteResponse, error) + + /* Relationship Queries */ + + /* + * Check Check if a user has a particular relation with an object. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientCheckRequestInterface + */ + Check(ctx _context.Context) SdkClientCheckRequestInterface + + /* + * CheckExecute executes the Check request + * @return *ClientCheckResponse + */ + CheckExecute(request SdkClientCheckRequestInterface) (*ClientCheckResponse, error) + + /* + * ClientBatchCheck Run a set of [checks](#check). Batch Check will return `allowed: false` if it encounters an error, and will return the error in the body. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientBatchCheckRequestInterface + */ + ClientBatchCheck(ctx _context.Context) SdkClientBatchCheckClientRequestInterface + + /* + * ClientBatchCheckExecute executes the BatchCheck request + * @return *ClientBatchCheckResponse + */ + ClientBatchCheckExecute(request SdkClientBatchCheckClientRequestInterface) (*ClientBatchCheckClientResponse, error) + + /* + * BatchCheck Run a set of checks on the server. Server-side batch check allows for more efficient checking of multiple tuples. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientBatchCheckRequestInterface + */ + BatchCheck(ctx _context.Context) SdkClientBatchCheckRequestInterface + + /* + * BatchCheckExecute executes the server-side BatchCheck request + * @return *BatchCheckResponse + */ + BatchCheckExecute(request SdkClientBatchCheckRequestInterface) (*fgaSdk.BatchCheckResponse, error) + + /* + * Expand Expands the relationships in userset tree format. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientExpandRequestInterface + */ + Expand(ctx _context.Context) SdkClientExpandRequestInterface + + /* + * ExpandExecute executes the Expand request + * @return *ClientExpandResponse + */ + ExpandExecute(request SdkClientExpandRequestInterface) (*ClientExpandResponse, error) + + /* + * ListObjects List the objects of a particular type a user has access to. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientListObjectsRequestInterface + */ + ListObjects(ctx _context.Context) SdkClientListObjectsRequestInterface + + /* + * ListObjectsExecute executes the ListObjects request + * @return *ClientListObjectsResponse + */ + ListObjectsExecute(request SdkClientListObjectsRequestInterface) (*ClientListObjectsResponse, error) + + /* + * ListRelations List the relations a user has on an object. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientListRelationsRequestInterface + */ + ListRelations(ctx _context.Context) SdkClientListRelationsRequestInterface + + /* + * ListRelationsExecute executes the ListRelations request + * @return *ClientListRelationsResponse + */ + ListRelationsExecute(request SdkClientListRelationsRequestInterface) (*ClientListRelationsResponse, error) + + /* + * ListUsers List all users of the given type that the object has a relation with + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiListUsersRequest + */ + ListUsers(ctx _context.Context) SdkClientListUsersRequestInterface + + /* + * ListUsersExecute executes the request + * @return ListUsersResponse + */ + ListUsersExecute(r SdkClientListUsersRequestInterface) (*ClientListUsersResponse, error) + + /* + * StreamedListObjects Stream all objects of the given type that the user has a relation with + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientStreamedListObjectsRequestInterface + */ + StreamedListObjects(ctx _context.Context) SdkClientStreamedListObjectsRequestInterface + + /* + * StreamedListObjectsExecute executes the StreamedListObjects request and returns a channel + * @return *ClientStreamedListObjectsResponse + */ + StreamedListObjectsExecute(request SdkClientStreamedListObjectsRequestInterface) (*ClientStreamedListObjectsResponse, error) + + /* Assertions */ + + /* + * ReadAssertions Read assertions for a particular authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadAssertionsRequestInterface + */ + ReadAssertions(ctx _context.Context) SdkClientReadAssertionsRequestInterface + + /* + * ReadAssertionsExecute executes the ReadAssertions request + * @return *ClientReadAssertionsResponse + */ + ReadAssertionsExecute(request SdkClientReadAssertionsRequestInterface) (*ClientReadAssertionsResponse, error) + + /* + * WriteAssertions Update the assertions for a particular authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteAssertionsRequestInterface + */ + WriteAssertions(ctx _context.Context) SdkClientWriteAssertionsRequestInterface + + /* + * WriteAssertionsExecute executes the WriteAssertions request + * @return *ClientWriteAssertionsResponse + */ + WriteAssertionsExecute(request SdkClientWriteAssertionsRequestInterface) (*ClientWriteAssertionsResponse, error) + + /* + * SetAuthorizationModelId allows setting the Authorization Model ID for an OpenFgaClient. + * @param string authorizationModelId - The Authorization Model ID to set. + */ + SetAuthorizationModelId(authorizationModelId string) error + /* + * GetAuthorizationModelId retrieves the Authorization Model ID for an OpenFgaClient. + * @return string + */ + GetAuthorizationModelId() (string, error) + /* + * SetStoreId allows setting the Store ID for an OpenFgaClient. + * @param string storeId - The Store ID to set. + */ + SetStoreId(storeId string) error + /* + * GetStoreId retrieves the Store ID set in the OpenFgaClient. + * @return string + */ + GetStoreId() (string, error) } func (client *OpenFgaClient) SetAuthorizationModelId(authorizationModelId string) error { - if authorizationModelId != "" && !internalutils.IsWellFormedUlidString(authorizationModelId) { - return FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } + if authorizationModelId != "" && !internalutils.IsWellFormedUlidString(authorizationModelId) { + return FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } - client.config.AuthorizationModelId = authorizationModelId + client.config.AuthorizationModelId = authorizationModelId - return nil + return nil } func (client *OpenFgaClient) GetAuthorizationModelId() (string, error) { - modelId := client.config.AuthorizationModelId - if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { - return "", FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } + modelId := client.config.AuthorizationModelId + if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { + return "", FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } - return modelId, nil + return modelId, nil } func (client *OpenFgaClient) getAuthorizationModelId(authorizationModelId *string) (*string, error) { - modelId := client.config.AuthorizationModelId - if authorizationModelId != nil && *authorizationModelId != "" { - modelId = *authorizationModelId - } + modelId := client.config.AuthorizationModelId + if authorizationModelId != nil && *authorizationModelId != "" { + modelId = *authorizationModelId + } - if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { - return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } - return &modelId, nil + if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { + return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } + return &modelId, nil } func (client *OpenFgaClient) SetStoreId(storeId string) error { - if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { - return FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } - client.config.StoreId = storeId - return nil + if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { + return FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } + client.config.StoreId = storeId + return nil } func (client *OpenFgaClient) GetStoreId() (string, error) { - storeId := client.config.StoreId - if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { - return "", FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } - return storeId, nil + storeId := client.config.StoreId + if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { + return "", FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } + return storeId, nil } func (client *OpenFgaClient) getStoreId(storeId *string) (*string, error) { - store := client.config.StoreId - if storeId != nil && *storeId != "" { - store = *storeId - } - if store != "" && !internalutils.IsWellFormedUlidString(store) { - return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } + store := client.config.StoreId + if storeId != nil && *storeId != "" { + store = *storeId + } + if store != "" && !internalutils.IsWellFormedUlidString(store) { + return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } - return &store, nil + return &store, nil } /* Stores */ // / ListStores type SdkClientListStoresRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientListStoresOptions + options *ClientListStoresOptions } type SdkClientListStoresRequestInterface interface { - Options(options ClientListStoresOptions) SdkClientListStoresRequestInterface - Execute() (*ClientListStoresResponse, error) - GetContext() _context.Context - GetOptions() *ClientListStoresOptions + Options(options ClientListStoresOptions) SdkClientListStoresRequestInterface + Execute() (*ClientListStoresResponse, error) + GetContext() _context.Context + GetOptions() *ClientListStoresOptions } type ClientListStoresOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - Name *string `json:"name,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + Name *string `json:"name,omitempty"` } type ClientListStoresResponse = fgaSdk.ListStoresResponse func (request *SdkClientListStoresRequest) Options(options ClientListStoresOptions) SdkClientListStoresRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListStoresRequest) Execute() (*ClientListStoresResponse, error) { - return request.Client.ListStoresExecute(request) + return request.Client.ListStoresExecute(request) } func (request *SdkClientListStoresRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListStoresRequest) GetOptions() *ClientListStoresOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListStoresExecute(request SdkClientListStoresRequestInterface) (*ClientListStoresResponse, error) { - req := client.OpenFgaApi.ListStores(request.GetContext()) - options := request.GetOptions() - if options != nil { - req = req.Options(options.RequestOptions) - if options.PageSize != nil { - req = req.PageSize(*options.PageSize) - } - if options.ContinuationToken != nil { - req = req.ContinuationToken(*options.ContinuationToken) - } - if options.Name != nil { - req = req.Name(*options.Name) - } - } - - data, _, err := req.Execute() - if err != nil { - return nil, err - } - return &data, nil + req := client.OpenFgaApi.ListStores(request.GetContext()) + options := request.GetOptions() + if options != nil { + req = req.Options(options.RequestOptions) + if options.PageSize != nil { + req = req.PageSize(*options.PageSize) + } + if options.ContinuationToken != nil { + req = req.ContinuationToken(*options.ContinuationToken) + } + if options.Name != nil { + req = req.Name(*options.Name) + } + } + + data, _, err := req.Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) ListStores(ctx _context.Context) SdkClientListStoresRequestInterface { - return &SdkClientListStoresRequest{ - ctx: ctx, - Client: client, - } + return &SdkClientListStoresRequest{ + ctx: ctx, + Client: client, + } } // / CreateStore type SdkClientCreateStoreRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientCreateStoreRequest - options *ClientCreateStoreOptions + body *ClientCreateStoreRequest + options *ClientCreateStoreOptions } type SdkClientCreateStoreRequestInterface interface { - Options(options ClientCreateStoreOptions) SdkClientCreateStoreRequestInterface - Body(body ClientCreateStoreRequest) SdkClientCreateStoreRequestInterface - Execute() (*ClientCreateStoreResponse, error) + Options(options ClientCreateStoreOptions) SdkClientCreateStoreRequestInterface + Body(body ClientCreateStoreRequest) SdkClientCreateStoreRequestInterface + Execute() (*ClientCreateStoreResponse, error) - GetContext() _context.Context - GetOptions() *ClientCreateStoreOptions - GetBody() *ClientCreateStoreRequest + GetContext() _context.Context + GetOptions() *ClientCreateStoreOptions + GetBody() *ClientCreateStoreRequest } type ClientCreateStoreRequest struct { - Name string `json:"name"` + Name string `json:"name"` } type ClientCreateStoreOptions struct { - RequestOptions + RequestOptions } type ClientCreateStoreResponse = fgaSdk.CreateStoreResponse func (request *SdkClientCreateStoreRequest) Options(options ClientCreateStoreOptions) SdkClientCreateStoreRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientCreateStoreRequest) Body(body ClientCreateStoreRequest) SdkClientCreateStoreRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientCreateStoreRequest) Execute() (*ClientCreateStoreResponse, error) { - return request.Client.CreateStoreExecute(request) + return request.Client.CreateStoreExecute(request) } func (request *SdkClientCreateStoreRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientCreateStoreRequest) GetOptions() *ClientCreateStoreOptions { - return request.options + return request.options } func (request *SdkClientCreateStoreRequest) GetBody() *ClientCreateStoreRequest { - return request.body + return request.body } func (client *OpenFgaClient) CreateStoreExecute(request SdkClientCreateStoreRequestInterface) (*ClientCreateStoreResponse, error) { - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - requestBody := fgaSdk.CreateStoreRequest{ - Name: request.GetBody().Name, - } - - data, _, err := client.OpenFgaApi. - CreateStore(request.GetContext()). - Body(requestBody). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + requestBody := fgaSdk.CreateStoreRequest{ + Name: request.GetBody().Name, + } + + data, _, err := client.OpenFgaApi. + CreateStore(request.GetContext()). + Body(requestBody). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) CreateStore(ctx _context.Context) SdkClientCreateStoreRequestInterface { - return &SdkClientCreateStoreRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientCreateStoreRequest{ + Client: client, + ctx: ctx, + } } // / GetStore type SdkClientGetStoreRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientGetStoreOptions + options *ClientGetStoreOptions } type SdkClientGetStoreRequestInterface interface { - Options(options ClientGetStoreOptions) SdkClientGetStoreRequestInterface - Execute() (*ClientGetStoreResponse, error) - GetStoreIdOverride() *string + Options(options ClientGetStoreOptions) SdkClientGetStoreRequestInterface + Execute() (*ClientGetStoreResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientGetStoreOptions + GetContext() _context.Context + GetOptions() *ClientGetStoreOptions } type ClientGetStoreOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientGetStoreResponse = fgaSdk.GetStoreResponse func (request *SdkClientGetStoreRequest) Options(options ClientGetStoreOptions) SdkClientGetStoreRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientGetStoreRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientGetStoreRequest) Execute() (*ClientGetStoreResponse, error) { - return request.Client.GetStoreExecute(request) + return request.Client.GetStoreExecute(request) } func (request *SdkClientGetStoreRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientGetStoreRequest) GetOptions() *ClientGetStoreOptions { - return request.options + return request.options } func (client *OpenFgaClient) GetStoreExecute(request SdkClientGetStoreRequestInterface) (*ClientGetStoreResponse, error) { - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - GetStore(request.GetContext(), *storeId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + GetStore(request.GetContext(), *storeId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) GetStore(ctx _context.Context) SdkClientGetStoreRequestInterface { - return &SdkClientGetStoreRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientGetStoreRequest{ + Client: client, + ctx: ctx, + } } // / DeleteStore type SdkClientDeleteStoreRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientDeleteStoreOptions + options *ClientDeleteStoreOptions } type SdkClientDeleteStoreRequestInterface interface { - Options(options ClientDeleteStoreOptions) SdkClientDeleteStoreRequestInterface - Execute() (*ClientDeleteStoreResponse, error) - GetStoreIdOverride() *string + Options(options ClientDeleteStoreOptions) SdkClientDeleteStoreRequestInterface + Execute() (*ClientDeleteStoreResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientDeleteStoreOptions + GetContext() _context.Context + GetOptions() *ClientDeleteStoreOptions } type ClientDeleteStoreOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientDeleteStoreResponse struct{} func (request *SdkClientDeleteStoreRequest) Options(options ClientDeleteStoreOptions) SdkClientDeleteStoreRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientDeleteStoreRequest) Execute() (*ClientDeleteStoreResponse, error) { - return request.Client.DeleteStoreExecute(request) + return request.Client.DeleteStoreExecute(request) } func (request *SdkClientDeleteStoreRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientDeleteStoreRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientDeleteStoreRequest) GetOptions() *ClientDeleteStoreOptions { - return request.options + return request.options } func (client *OpenFgaClient) DeleteStoreExecute(request SdkClientDeleteStoreRequestInterface) (*ClientDeleteStoreResponse, error) { - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - _, err = client.OpenFgaApi. - DeleteStore(request.GetContext(), *storeId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &ClientDeleteStoreResponse{}, nil + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + _, err = client.OpenFgaApi. + DeleteStore(request.GetContext(), *storeId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &ClientDeleteStoreResponse{}, nil } func (client *OpenFgaClient) DeleteStore(ctx _context.Context) SdkClientDeleteStoreRequestInterface { - return &SdkClientDeleteStoreRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientDeleteStoreRequest{ + Client: client, + ctx: ctx, + } } /* Authorization Models */ // / ReadAuthorizationModels type SdkClientReadAuthorizationModelsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientReadAuthorizationModelsOptions + options *ClientReadAuthorizationModelsOptions } type SdkClientReadAuthorizationModelsRequestInterface interface { - Options(options ClientReadAuthorizationModelsOptions) SdkClientReadAuthorizationModelsRequestInterface - Execute() (*ClientReadAuthorizationModelsResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadAuthorizationModelsOptions) SdkClientReadAuthorizationModelsRequestInterface + Execute() (*ClientReadAuthorizationModelsResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientReadAuthorizationModelsOptions + GetContext() _context.Context + GetOptions() *ClientReadAuthorizationModelsOptions } type ClientReadAuthorizationModelsOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - StoreId *string `json:"store_id,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientReadAuthorizationModelsResponse = fgaSdk.ReadAuthorizationModelsResponse func (request *SdkClientReadAuthorizationModelsRequest) Options(options ClientReadAuthorizationModelsOptions) SdkClientReadAuthorizationModelsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadAuthorizationModelsRequest) Execute() (*ClientReadAuthorizationModelsResponse, error) { - return request.Client.ReadAuthorizationModelsExecute(request) + return request.Client.ReadAuthorizationModelsExecute(request) } func (request *SdkClientReadAuthorizationModelsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadAuthorizationModelsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadAuthorizationModelsRequest) GetOptions() *ClientReadAuthorizationModelsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadAuthorizationModelsExecute(request SdkClientReadAuthorizationModelsRequestInterface) (*ClientReadAuthorizationModelsResponse, error) { - pagingOpts := ClientPaginationOptions{} - if request.GetOptions() != nil { - pagingOpts.PageSize = request.GetOptions().PageSize - pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - req := client.OpenFgaApi. - ReadAuthorizationModels(request.GetContext(), *storeId). - Options(requestOptions) - - pageSize := getPageSizeFromRequest(&pagingOpts) - if pageSize != nil { - req = req.PageSize(*pageSize) - } - continuationToken := getContinuationTokenFromRequest(&pagingOpts) - if continuationToken != nil { - req = req.ContinuationToken(*continuationToken) - } - data, _, err := req.Execute() - if err != nil { - return nil, err - } - return &data, nil + pagingOpts := ClientPaginationOptions{} + if request.GetOptions() != nil { + pagingOpts.PageSize = request.GetOptions().PageSize + pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + req := client.OpenFgaApi. + ReadAuthorizationModels(request.GetContext(), *storeId). + Options(requestOptions) + + pageSize := getPageSizeFromRequest(&pagingOpts) + if pageSize != nil { + req = req.PageSize(*pageSize) + } + continuationToken := getContinuationTokenFromRequest(&pagingOpts) + if continuationToken != nil { + req = req.ContinuationToken(*continuationToken) + } + data, _, err := req.Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) ReadAuthorizationModels(ctx _context.Context) SdkClientReadAuthorizationModelsRequestInterface { - return &SdkClientReadAuthorizationModelsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadAuthorizationModelsRequest{ + Client: client, + ctx: ctx, + } } // / WriteAuthorizationModel type SdkClientWriteAuthorizationModelRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteAuthorizationModelRequest - options *ClientWriteAuthorizationModelOptions + body *ClientWriteAuthorizationModelRequest + options *ClientWriteAuthorizationModelOptions } type SdkClientWriteAuthorizationModelRequestInterface interface { - Options(options ClientWriteAuthorizationModelOptions) SdkClientWriteAuthorizationModelRequestInterface - Body(body ClientWriteAuthorizationModelRequest) SdkClientWriteAuthorizationModelRequestInterface - Execute() (*ClientWriteAuthorizationModelResponse, error) - GetStoreIdOverride() *string + Options(options ClientWriteAuthorizationModelOptions) SdkClientWriteAuthorizationModelRequestInterface + Body(body ClientWriteAuthorizationModelRequest) SdkClientWriteAuthorizationModelRequestInterface + Execute() (*ClientWriteAuthorizationModelResponse, error) + GetStoreIdOverride() *string - GetBody() *ClientWriteAuthorizationModelRequest - GetOptions() *ClientWriteAuthorizationModelOptions - GetContext() _context.Context + GetBody() *ClientWriteAuthorizationModelRequest + GetOptions() *ClientWriteAuthorizationModelOptions + GetContext() _context.Context } type ClientWriteAuthorizationModelRequest = fgaSdk.WriteAuthorizationModelRequest type ClientWriteAuthorizationModelOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientWriteAuthorizationModelResponse = fgaSdk.WriteAuthorizationModelResponse func (request *SdkClientWriteAuthorizationModelRequest) Options(options ClientWriteAuthorizationModelOptions) SdkClientWriteAuthorizationModelRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteAuthorizationModelRequest) Body(body ClientWriteAuthorizationModelRequest) SdkClientWriteAuthorizationModelRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteAuthorizationModelRequest) Execute() (*ClientWriteAuthorizationModelResponse, error) { - return request.Client.WriteAuthorizationModelExecute(request) + return request.Client.WriteAuthorizationModelExecute(request) } func (request *SdkClientWriteAuthorizationModelRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientWriteAuthorizationModelRequest) GetBody() *ClientWriteAuthorizationModelRequest { - return request.body + return request.body } func (request *SdkClientWriteAuthorizationModelRequest) GetOptions() *ClientWriteAuthorizationModelOptions { - return request.options + return request.options } func (request *SdkClientWriteAuthorizationModelRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (client *OpenFgaClient) WriteAuthorizationModelExecute(request SdkClientWriteAuthorizationModelRequestInterface) (*ClientWriteAuthorizationModelResponse, error) { - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - WriteAuthorizationModel(request.GetContext(), *storeId). - Body(*request.GetBody()). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + WriteAuthorizationModel(request.GetContext(), *storeId). + Body(*request.GetBody()). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) WriteAuthorizationModel(ctx _context.Context) SdkClientWriteAuthorizationModelRequestInterface { - return &SdkClientWriteAuthorizationModelRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteAuthorizationModelRequest{ + Client: client, + ctx: ctx, + } } // / ReadAuthorizationModel type SdkClientReadAuthorizationModelRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientReadAuthorizationModelRequest - options *ClientReadAuthorizationModelOptions + body *ClientReadAuthorizationModelRequest + options *ClientReadAuthorizationModelOptions } type SdkClientReadAuthorizationModelRequestInterface interface { - Options(options ClientReadAuthorizationModelOptions) SdkClientReadAuthorizationModelRequestInterface - Body(body ClientReadAuthorizationModelRequest) SdkClientReadAuthorizationModelRequestInterface - Execute() (*ClientReadAuthorizationModelResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientReadAuthorizationModelOptions) SdkClientReadAuthorizationModelRequestInterface + Body(body ClientReadAuthorizationModelRequest) SdkClientReadAuthorizationModelRequestInterface + Execute() (*ClientReadAuthorizationModelResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientReadAuthorizationModelRequest - GetOptions() *ClientReadAuthorizationModelOptions + GetContext() _context.Context + GetBody() *ClientReadAuthorizationModelRequest + GetOptions() *ClientReadAuthorizationModelOptions } type ClientReadAuthorizationModelRequest struct { } type ClientReadAuthorizationModelOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientReadAuthorizationModelResponse = fgaSdk.ReadAuthorizationModelResponse func (request *SdkClientReadAuthorizationModelRequest) Options(options ClientReadAuthorizationModelOptions) SdkClientReadAuthorizationModelRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadAuthorizationModelRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientReadAuthorizationModelRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadAuthorizationModelRequest) Body(body ClientReadAuthorizationModelRequest) SdkClientReadAuthorizationModelRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientReadAuthorizationModelRequest) Execute() (*ClientReadAuthorizationModelResponse, error) { - return request.Client.ReadAuthorizationModelExecute(request) + return request.Client.ReadAuthorizationModelExecute(request) } func (request *SdkClientReadAuthorizationModelRequest) GetBody() *ClientReadAuthorizationModelRequest { - return request.body + return request.body } func (request *SdkClientReadAuthorizationModelRequest) GetOptions() *ClientReadAuthorizationModelOptions { - return request.options + return request.options } func (request *SdkClientReadAuthorizationModelRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (client *OpenFgaClient) ReadAuthorizationModelExecute(request SdkClientReadAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) { - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - if authorizationModelId == nil || *authorizationModelId == "" { - return nil, FgaRequiredParamError{param: "AuthorizationModelId"} - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - ReadAuthorizationModel(request.GetContext(), *storeId, *authorizationModelId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + if authorizationModelId == nil || *authorizationModelId == "" { + return nil, FgaRequiredParamError{param: "AuthorizationModelId"} + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + ReadAuthorizationModel(request.GetContext(), *storeId, *authorizationModelId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) ReadAuthorizationModel(ctx _context.Context) SdkClientReadAuthorizationModelRequestInterface { - return &SdkClientReadAuthorizationModelRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadAuthorizationModelRequest{ + Client: client, + ctx: ctx, + } } // / ReadLatestAuthorizationModel type SdkClientReadLatestAuthorizationModelRequest struct { - ctx _context.Context - Client OpenFgaClient + ctx _context.Context + Client OpenFgaClient - options *ClientReadLatestAuthorizationModelOptions + options *ClientReadLatestAuthorizationModelOptions } type SdkClientReadLatestAuthorizationModelRequestInterface interface { - Options(options ClientReadLatestAuthorizationModelOptions) SdkClientReadLatestAuthorizationModelRequestInterface - Execute() (*ClientReadAuthorizationModelResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadLatestAuthorizationModelOptions) SdkClientReadLatestAuthorizationModelRequestInterface + Execute() (*ClientReadAuthorizationModelResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientReadLatestAuthorizationModelOptions + GetContext() _context.Context + GetOptions() *ClientReadLatestAuthorizationModelOptions } type ClientReadLatestAuthorizationModelOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } func (client *OpenFgaClient) ReadLatestAuthorizationModel(ctx _context.Context) SdkClientReadLatestAuthorizationModelRequestInterface { - return &SdkClientReadLatestAuthorizationModelRequest{ - Client: *client, - ctx: ctx, - } + return &SdkClientReadLatestAuthorizationModelRequest{ + Client: *client, + ctx: ctx, + } } func (request *SdkClientReadLatestAuthorizationModelRequest) Options(options ClientReadLatestAuthorizationModelOptions) SdkClientReadLatestAuthorizationModelRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadLatestAuthorizationModelRequest) Execute() (*ClientReadAuthorizationModelResponse, error) { - return request.Client.ReadLatestAuthorizationModelExecute(request) + return request.Client.ReadLatestAuthorizationModelExecute(request) } func (request *SdkClientReadLatestAuthorizationModelRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadLatestAuthorizationModelRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadLatestAuthorizationModelRequest) GetOptions() *ClientReadLatestAuthorizationModelOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadLatestAuthorizationModelExecute(request SdkClientReadLatestAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) { - opts := ClientReadAuthorizationModelsOptions{ - PageSize: fgaSdk.PtrInt32(1), - } - if request.GetOptions() != nil { - opts.StoreId = request.GetOptions().StoreId - opts.RequestOptions = request.GetOptions().RequestOptions - } - req := client.ReadAuthorizationModels(request.GetContext()).Options(opts) + opts := ClientReadAuthorizationModelsOptions{ + PageSize: fgaSdk.PtrInt32(1), + } + if request.GetOptions() != nil { + opts.StoreId = request.GetOptions().StoreId + opts.RequestOptions = request.GetOptions().RequestOptions + } + req := client.ReadAuthorizationModels(request.GetContext()).Options(opts) - response, err := req.Execute() - if err != nil { - return nil, err - } + response, err := req.Execute() + if err != nil { + return nil, err + } - var authorizationModel *fgaSdk.AuthorizationModel + var authorizationModel *fgaSdk.AuthorizationModel - if len(response.AuthorizationModels) > 0 { - authorizationModels := response.AuthorizationModels - authorizationModel = &(authorizationModels)[0] - } + if len(response.AuthorizationModels) > 0 { + authorizationModels := response.AuthorizationModels + authorizationModel = &(authorizationModels)[0] + } - return &fgaSdk.ReadAuthorizationModelResponse{ - AuthorizationModel: authorizationModel, - }, nil + return &fgaSdk.ReadAuthorizationModelResponse{ + AuthorizationModel: authorizationModel, + }, nil } /* Relationship Tuples */ // / ReadChanges type SdkClientReadChangesRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientReadChangesRequest - options *ClientReadChangesOptions + body *ClientReadChangesRequest + options *ClientReadChangesOptions } type SdkClientReadChangesRequestInterface interface { - Options(options ClientReadChangesOptions) SdkClientReadChangesRequestInterface - Body(body ClientReadChangesRequest) SdkClientReadChangesRequestInterface - Execute() (*ClientReadChangesResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadChangesOptions) SdkClientReadChangesRequestInterface + Body(body ClientReadChangesRequest) SdkClientReadChangesRequestInterface + Execute() (*ClientReadChangesResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientReadChangesRequest - GetOptions() *ClientReadChangesOptions + GetContext() _context.Context + GetBody() *ClientReadChangesRequest + GetOptions() *ClientReadChangesOptions } type ClientReadChangesRequest struct { - Type string `json:"type,omitempty"` - StartTime time.Time `json:"start_time,omitempty"` + Type string `json:"type,omitempty"` + StartTime time.Time `json:"start_time,omitempty"` } type ClientReadChangesOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - StoreId *string `json:"store_id"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + StoreId *string `json:"store_id"` } type ClientReadChangesResponse = fgaSdk.ReadChangesResponse func (client *OpenFgaClient) ReadChanges(ctx _context.Context) SdkClientReadChangesRequestInterface { - return &SdkClientReadChangesRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadChangesRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientReadChangesRequest) Options(options ClientReadChangesOptions) SdkClientReadChangesRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadChangesRequest) Body(body ClientReadChangesRequest) SdkClientReadChangesRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientReadChangesRequest) Execute() (*ClientReadChangesResponse, error) { - return request.Client.ReadChangesExecute(request) + return request.Client.ReadChangesExecute(request) } func (request *SdkClientReadChangesRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadChangesRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadChangesRequest) GetBody() *ClientReadChangesRequest { - return request.body + return request.body } func (request *SdkClientReadChangesRequest) GetOptions() *ClientReadChangesOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadChangesExecute(request SdkClientReadChangesRequestInterface) (*ClientReadChangesResponse, error) { - pagingOpts := ClientPaginationOptions{} - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - pagingOpts.PageSize = request.GetOptions().PageSize - pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - req := client.OpenFgaApi. - ReadChanges(request.GetContext(), *storeId). - Options(requestOptions) - pageSize := getPageSizeFromRequest(&pagingOpts) - if pageSize != nil { - req = req.PageSize(*pageSize) - } - continuationToken := getContinuationTokenFromRequest(&pagingOpts) - if continuationToken != nil { - req = req.ContinuationToken(*continuationToken) - } - requestBody := request.GetBody() - if requestBody != nil && requestBody.Type != "" { - req = req.Type_(requestBody.Type) - } - if requestBody != nil && !requestBody.StartTime.IsZero() { - req = req.StartTime(requestBody.StartTime) - } - - data, _, err := req.Execute() - if err != nil { - return nil, err - } - return &data, nil + pagingOpts := ClientPaginationOptions{} + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + pagingOpts.PageSize = request.GetOptions().PageSize + pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + req := client.OpenFgaApi. + ReadChanges(request.GetContext(), *storeId). + Options(requestOptions) + pageSize := getPageSizeFromRequest(&pagingOpts) + if pageSize != nil { + req = req.PageSize(*pageSize) + } + continuationToken := getContinuationTokenFromRequest(&pagingOpts) + if continuationToken != nil { + req = req.ContinuationToken(*continuationToken) + } + requestBody := request.GetBody() + if requestBody != nil && requestBody.Type != "" { + req = req.Type_(requestBody.Type) + } + if requestBody != nil && !requestBody.StartTime.IsZero() { + req = req.StartTime(requestBody.StartTime) + } + + data, _, err := req.Execute() + if err != nil { + return nil, err + } + return &data, nil } // / Read type SdkClientReadRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientReadRequest - options *ClientReadOptions + body *ClientReadRequest + options *ClientReadOptions } type SdkClientReadRequestInterface interface { - Options(options ClientReadOptions) SdkClientReadRequestInterface - Body(body ClientReadRequest) SdkClientReadRequestInterface - Execute() (*ClientReadResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadOptions) SdkClientReadRequestInterface + Body(body ClientReadRequest) SdkClientReadRequestInterface + Execute() (*ClientReadResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientReadRequest - GetOptions() *ClientReadOptions + GetContext() _context.Context + GetBody() *ClientReadRequest + GetOptions() *ClientReadOptions } type ClientReadRequest struct { - User *string `json:"user,omitempty"` - Relation *string `json:"relation,omitempty"` - Object *string `json:"object,omitempty"` + User *string `json:"user,omitempty"` + Relation *string `json:"relation,omitempty"` + Object *string `json:"object,omitempty"` } type ClientReadOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientReadResponse = fgaSdk.ReadResponse func (client *OpenFgaClient) Read(ctx _context.Context) SdkClientReadRequestInterface { - return &SdkClientReadRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientReadRequest) Options(options ClientReadOptions) SdkClientReadRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadRequest) Body(body ClientReadRequest) SdkClientReadRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientReadRequest) Execute() (*ClientReadResponse, error) { - return request.Client.ReadExecute(request) + return request.Client.ReadExecute(request) } func (request *SdkClientReadRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadRequest) GetBody() *ClientReadRequest { - return request.body + return request.body } func (request *SdkClientReadRequest) GetOptions() *ClientReadOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadExecute(request SdkClientReadRequestInterface) (*ClientReadResponse, error) { - pagingOpts := ClientPaginationOptions{} - requestOptions := RequestOptions{} - var consistency *fgaSdk.ConsistencyPreference - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - pagingOpts.PageSize = request.GetOptions().PageSize - pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken - consistency = request.GetOptions().Consistency - } - - body := fgaSdk.ReadRequest{ - PageSize: getPageSizeFromRequest(&pagingOpts), - ContinuationToken: getContinuationTokenFromRequest(&pagingOpts), - Consistency: consistency, - } - if request.GetBody() != nil && (request.GetBody().User != nil || request.GetBody().Relation != nil || request.GetBody().Object != nil) { - body.TupleKey = &fgaSdk.ReadRequestTupleKey{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Object: request.GetBody().Object, - } - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - data, _, err := client.OpenFgaApi. - Read(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + pagingOpts := ClientPaginationOptions{} + requestOptions := RequestOptions{} + var consistency *fgaSdk.ConsistencyPreference + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + pagingOpts.PageSize = request.GetOptions().PageSize + pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken + consistency = request.GetOptions().Consistency + } + + body := fgaSdk.ReadRequest{ + PageSize: getPageSizeFromRequest(&pagingOpts), + ContinuationToken: getContinuationTokenFromRequest(&pagingOpts), + Consistency: consistency, + } + if request.GetBody() != nil && (request.GetBody().User != nil || request.GetBody().Relation != nil || request.GetBody().Object != nil) { + body.TupleKey = &fgaSdk.ReadRequestTupleKey{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Object: request.GetBody().Object, + } + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + data, _, err := client.OpenFgaApi. + Read(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / Write type SdkClientWriteRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteRequest - options *ClientWriteOptions + body *ClientWriteRequest + options *ClientWriteOptions } type SdkClientWriteRequestInterface interface { - Options(options ClientWriteOptions) SdkClientWriteRequestInterface - Body(body ClientWriteRequest) SdkClientWriteRequestInterface - Execute() (*ClientWriteResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientWriteOptions) SdkClientWriteRequestInterface + Body(body ClientWriteRequest) SdkClientWriteRequestInterface + Execute() (*ClientWriteResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientWriteOptions - GetBody() *ClientWriteRequest + GetContext() _context.Context + GetOptions() *ClientWriteOptions + GetBody() *ClientWriteRequest } type ClientWriteRequest struct { - Writes []ClientTupleKey - Deletes []ClientTupleKeyWithoutCondition + Writes []ClientTupleKey + Deletes []ClientTupleKeyWithoutCondition } type TransactionOptions struct { - // If set to true will disable running in transaction mode (transaction mode means everything is sent in a single transaction to the server) - Disable bool `json:"disable,omitempty"` - // When transaction mode is disabled, the requests are chunked and sent separately and each chunk is a transaction (default = 1) - MaxPerChunk int32 `json:"max_per_chunk,omitempty"` - // Number of requests to issue in parallel - MaxParallelRequests int32 `json:"max_parallel_requests,omitempty"` + // If set to true will disable running in transaction mode (transaction mode means everything is sent in a single transaction to the server) + Disable bool `json:"disable,omitempty"` + // When transaction mode is disabled, the requests are chunked and sent separately and each chunk is a transaction (default = 1) + MaxPerChunk int32 `json:"max_per_chunk,omitempty"` + // Number of requests to issue in parallel + MaxParallelRequests int32 `json:"max_parallel_requests,omitempty"` } // ClientWriteRequestOnDuplicateWrites indicates what to do when a write conflicts with an existing tuple type ClientWriteRequestOnDuplicateWrites string func (w *ClientWriteRequestOnDuplicateWrites) ToString() *string { - if w == nil { - return nil - } + if w == nil { + return nil + } - str := string(*w) + str := string(*w) - return &str + return &str } const ( - // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR returns an error if a write conflicts with an existing tuple (default) - CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR ClientWriteRequestOnDuplicateWrites = "error" - // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ignores writes that conflict with existing tuples (they must match exactly, including conditions) - CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ClientWriteRequestOnDuplicateWrites = "ignore" + // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR returns an error if a write conflicts with an existing tuple (default) + CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR ClientWriteRequestOnDuplicateWrites = "error" + // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ignores writes that conflict with existing tuples (they must match exactly, including conditions) + CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ClientWriteRequestOnDuplicateWrites = "ignore" ) // ClientWriteRequestOnMissingDeletes indicates what to do when a delete is issued for a tuple that does not exist type ClientWriteRequestOnMissingDeletes string func (d *ClientWriteRequestOnMissingDeletes) ToString() *string { - if d == nil { - return nil - } + if d == nil { + return nil + } - str := string(*d) + str := string(*d) - return &str + return &str } const ( - // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR returns an error if a delete is issued for a tuple that does not exist (default) - CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR ClientWriteRequestOnMissingDeletes = "error" - // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ignores deletes for tuples that do not exist - CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ClientWriteRequestOnMissingDeletes = "ignore" + // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR returns an error if a delete is issued for a tuple that does not exist (default) + CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR ClientWriteRequestOnMissingDeletes = "error" + // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ignores deletes for tuples that do not exist + CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ClientWriteRequestOnMissingDeletes = "ignore" ) type ClientWriteConflictOptions struct { - // OnDuplicateWrites defines what to do when a write conflicts with an existing tuple - // Options are: "error" (default) or "ignore" - OnDuplicateWrites ClientWriteRequestOnDuplicateWrites `json:"on_duplicate_writes,omitempty"` - // OnMissingDeletes defines what to do when a delete is issued for a tuple that does not exist - // Options are: "error" (default) or "ignore" - OnMissingDeletes ClientWriteRequestOnMissingDeletes `json:"on_missing_deletes,omitempty"` + // OnDuplicateWrites defines what to do when a write conflicts with an existing tuple + // Options are: "error" (default) or "ignore" + OnDuplicateWrites ClientWriteRequestOnDuplicateWrites `json:"on_duplicate_writes,omitempty"` + // OnMissingDeletes defines what to do when a delete is issued for a tuple that does not exist + // Options are: "error" (default) or "ignore" + OnMissingDeletes ClientWriteRequestOnMissingDeletes `json:"on_missing_deletes,omitempty"` } type ClientWriteOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Transaction *TransactionOptions `json:"transaction_options,omitempty"` - Conflict ClientWriteConflictOptions + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Transaction *TransactionOptions `json:"transaction_options,omitempty"` + Conflict ClientWriteConflictOptions } type ClientWriteStatus string // List of ClientWriteStatus const ( - SUCCESS ClientWriteStatus = "CLIENT_WRITE_STATUS_SUCCESS" - FAILURE ClientWriteStatus = "CLIENT_WRITE_STATUS_FAILURE" + SUCCESS ClientWriteStatus = "CLIENT_WRITE_STATUS_SUCCESS" + FAILURE ClientWriteStatus = "CLIENT_WRITE_STATUS_FAILURE" ) type ClientWriteRequestWriteResponse struct { - TupleKey ClientTupleKey `json:"tuple_key,omitempty"` - Status ClientWriteStatus `json:"status,omitempty"` - HttpResponse *_nethttp.Response `json:"http_response,omitempty"` - Error error `json:"error,omitempty"` + TupleKey ClientTupleKey `json:"tuple_key,omitempty"` + Status ClientWriteStatus `json:"status,omitempty"` + HttpResponse *_nethttp.Response `json:"http_response,omitempty"` + Error error `json:"error,omitempty"` } func (o ClientWriteRequestWriteResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - toSerialize["tuple_key"] = o.TupleKey - toSerialize["status"] = o.Status - if o.Error != nil { - toSerialize["error"] = o.Error - } - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + toSerialize["tuple_key"] = o.TupleKey + toSerialize["status"] = o.Status + if o.Error != nil { + toSerialize["error"] = o.Error + } + return json.Marshal(toSerialize) } type ClientWriteRequestDeleteResponse struct { - TupleKey ClientTupleKeyWithoutCondition `json:"tuple_key,omitempty"` - Status ClientWriteStatus `json:"status,omitempty"` - HttpResponse *_nethttp.Response `json:"http_response,omitempty"` - Error error `json:"error,omitempty"` + TupleKey ClientTupleKeyWithoutCondition `json:"tuple_key,omitempty"` + Status ClientWriteStatus `json:"status,omitempty"` + HttpResponse *_nethttp.Response `json:"http_response,omitempty"` + Error error `json:"error,omitempty"` } func (o ClientWriteRequestDeleteResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - toSerialize["tuple_key"] = o.TupleKey - toSerialize["status"] = o.Status - if o.Error != nil { - toSerialize["error"] = o.Error - } - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + toSerialize["tuple_key"] = o.TupleKey + toSerialize["status"] = o.Status + if o.Error != nil { + toSerialize["error"] = o.Error + } + return json.Marshal(toSerialize) } type ClientWriteResponse struct { - Writes []ClientWriteRequestWriteResponse `json:"writes,omitempty"` - Deletes []ClientWriteRequestDeleteResponse `json:"deletes,omitempty"` + Writes []ClientWriteRequestWriteResponse `json:"writes,omitempty"` + Deletes []ClientWriteRequestDeleteResponse `json:"deletes,omitempty"` } func (o ClientWriteResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - if o.Writes != nil { - toSerialize["writes"] = o.Writes - } - if o.Deletes != nil { - toSerialize["deletes"] = o.Deletes - } - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + if o.Writes != nil { + toSerialize["writes"] = o.Writes + } + if o.Deletes != nil { + toSerialize["deletes"] = o.Deletes + } + return json.Marshal(toSerialize) } func (client *OpenFgaClient) Write(ctx _context.Context) SdkClientWriteRequestInterface { - return &SdkClientWriteRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientWriteRequest) Options(options ClientWriteOptions) SdkClientWriteRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientWriteRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientWriteRequest) Body(body ClientWriteRequest) SdkClientWriteRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteRequest) Execute() (*ClientWriteResponse, error) { - return request.Client.WriteExecute(request) + return request.Client.WriteExecute(request) } func (request *SdkClientWriteRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientWriteRequest) GetOptions() *ClientWriteOptions { - return request.options + return request.options } func (request *SdkClientWriteRequest) GetBody() *ClientWriteRequest { - return request.body + return request.body } func (client *OpenFgaClient) WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) { - options := request.GetOptions() - transactionOptionsSet := options != nil && options.Transaction != nil - response := ClientWriteResponse{ - Writes: []ClientWriteRequestWriteResponse{}, - Deletes: []ClientWriteRequestDeleteResponse{}, - } - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - // Unless explicitly disabled, transaction mode is enabled - // In transaction mode, the client will send the request to the server as is - if !transactionOptionsSet || !options.Transaction.Disable { - writeRequest := fgaSdk.WriteRequest{ - AuthorizationModelId: authorizationModelId, - } - if len(request.GetBody().Writes) > 0 { - writes := fgaSdk.WriteRequestWrites{} - if options != nil { - writes.OnDuplicate = options.Conflict.OnDuplicateWrites.ToString() - } - for index := 0; index < len(request.GetBody().Writes); index++ { - writes.TupleKeys = append(writes.TupleKeys, (request.GetBody().Writes)[index]) - } - writeRequest.Writes = &writes - } - if len(request.GetBody().Deletes) > 0 { - deletes := fgaSdk.WriteRequestDeletes{} - if options != nil { - deletes.OnMissing = options.Conflict.OnMissingDeletes.ToString() - } - for index := 0; index < len(request.GetBody().Deletes); index++ { - deletes.TupleKeys = append(deletes.TupleKeys, (request.GetBody().Deletes)[index]) - } - writeRequest.Deletes = &deletes - } - - _, httpResponse, err := client.OpenFgaApi. - Write(request.GetContext(), *storeId). - Body(writeRequest). - Options(requestOptions). - Execute() - - clientWriteStatus := SUCCESS - if err != nil { - clientWriteStatus = FAILURE - } - - if request.GetBody() != nil && request.GetBody().Writes != nil { - writeRequestTupleKeys := request.GetBody().Writes - for index := 0; index < len(writeRequestTupleKeys); index++ { - response.Writes = append(response.Writes, ClientWriteRequestWriteResponse{ - TupleKey: writeRequestTupleKeys[index], - HttpResponse: httpResponse, - Status: clientWriteStatus, - Error: err, - }) - } - } - - if request.GetBody() != nil && request.GetBody().Deletes != nil { - deleteRequestTupleKeys := request.GetBody().Deletes - for index := 0; index < len(deleteRequestTupleKeys); index++ { - response.Deletes = append(response.Deletes, ClientWriteRequestDeleteResponse{ - TupleKey: deleteRequestTupleKeys[index], - HttpResponse: httpResponse, - Status: clientWriteStatus, - Error: err, - }) - } - } - - return &response, err - } - - maxPerChunk := int32(1) // 1 has to be the default otherwise the chunks will be sent in transactions - if options.Transaction.MaxPerChunk > 0 { - maxPerChunk = options.Transaction.MaxPerChunk - } - - maxParallelReqs := DEFAULT_MAX_METHOD_PARALLEL_REQS - if options.Transaction.MaxParallelRequests > 0 { - maxParallelReqs = options.Transaction.MaxParallelRequests - } - - // If the transaction mode is disabled: - // - the client will attempt to chunk the writes and deletes into multiple requests - // - each request is a transaction - // - the max items in each request are based on maxPerChunk (default=1) - var writeChunkSize = int(maxPerChunk) - var writeChunks [][]ClientTupleKey - if request.GetBody() != nil { - for i := 0; i < len(request.GetBody().Writes); i += writeChunkSize { - end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Writes)))) - - writeChunks = append(writeChunks, (request.GetBody().Writes)[i:end]) - } - } - - writeGroup, ctx := errgroup.WithContext(request.GetContext()) - - writeGroup.SetLimit(int(maxParallelReqs)) - writeResponses := make([]ClientWriteResponse, len(writeChunks)) - for index, writeBody := range writeChunks { - index, writeBody := index, writeBody - writeGroup.Go(func() error { - singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ - ctx: ctx, - Client: client, - body: &ClientWriteRequest{ - Writes: writeBody, - }, - options: &ClientWriteOptions{ - RequestOptions: options.RequestOptions, - AuthorizationModelId: authorizationModelId, - StoreId: request.GetStoreIdOverride(), - Conflict: options.Conflict, - }, - }) - - if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { - return err - } - - writeResponses[index] = *singleResponse - - return nil - }) - } - - err = writeGroup.Wait() - // If an error was returned then it will be an authentication error so we want to return - if err != nil { - return &response, err - } - - var deleteChunkSize = int(maxPerChunk) - var deleteChunks [][]ClientTupleKeyWithoutCondition - if request.GetBody() != nil { - for i := 0; i < len(request.GetBody().Deletes); i += deleteChunkSize { - end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Deletes)))) - - deleteChunks = append(deleteChunks, (request.GetBody().Deletes)[i:end]) - } - } - - deleteGroup, ctx := errgroup.WithContext(request.GetContext()) - deleteGroup.SetLimit(int(maxParallelReqs)) - deleteResponses := make([]ClientWriteResponse, len(deleteChunks)) - for index, deleteBody := range deleteChunks { - index, deleteBody := index, deleteBody - deleteGroup.Go(func() error { - singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ - ctx: ctx, - Client: client, - body: &ClientWriteRequest{ - Deletes: deleteBody, - }, - options: &ClientWriteOptions{ - RequestOptions: options.RequestOptions, - AuthorizationModelId: authorizationModelId, - StoreId: request.GetStoreIdOverride(), - Conflict: options.Conflict, - }, - }) - - if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { - return err - } - - deleteResponses[index] = *singleResponse - - return nil - }) - } - - err = deleteGroup.Wait() - if err != nil { - // If an error was returned then it will be an authentication error so we want to return - return &response, err - } - - for _, writeResponse := range writeResponses { - response.Writes = append(response.Writes, writeResponse.Writes...) - } - - for _, deleteResponse := range deleteResponses { - response.Deletes = append(response.Deletes, deleteResponse.Deletes...) - } - - return &response, nil + options := request.GetOptions() + transactionOptionsSet := options != nil && options.Transaction != nil + response := ClientWriteResponse{ + Writes: []ClientWriteRequestWriteResponse{}, + Deletes: []ClientWriteRequestDeleteResponse{}, + } + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + // Unless explicitly disabled, transaction mode is enabled + // In transaction mode, the client will send the request to the server as is + if !transactionOptionsSet || !options.Transaction.Disable { + writeRequest := fgaSdk.WriteRequest{ + AuthorizationModelId: authorizationModelId, + } + if len(request.GetBody().Writes) > 0 { + writes := fgaSdk.WriteRequestWrites{} + if options != nil { + writes.OnDuplicate = options.Conflict.OnDuplicateWrites.ToString() + } + for index := 0; index < len(request.GetBody().Writes); index++ { + writes.TupleKeys = append(writes.TupleKeys, (request.GetBody().Writes)[index]) + } + writeRequest.Writes = &writes + } + if len(request.GetBody().Deletes) > 0 { + deletes := fgaSdk.WriteRequestDeletes{} + if options != nil { + deletes.OnMissing = options.Conflict.OnMissingDeletes.ToString() + } + for index := 0; index < len(request.GetBody().Deletes); index++ { + deletes.TupleKeys = append(deletes.TupleKeys, (request.GetBody().Deletes)[index]) + } + writeRequest.Deletes = &deletes + } + + _, httpResponse, err := client.OpenFgaApi. + Write(request.GetContext(), *storeId). + Body(writeRequest). + Options(requestOptions). + Execute() + + clientWriteStatus := SUCCESS + if err != nil { + clientWriteStatus = FAILURE + } + + if request.GetBody() != nil && request.GetBody().Writes != nil { + writeRequestTupleKeys := request.GetBody().Writes + for index := 0; index < len(writeRequestTupleKeys); index++ { + response.Writes = append(response.Writes, ClientWriteRequestWriteResponse{ + TupleKey: writeRequestTupleKeys[index], + HttpResponse: httpResponse, + Status: clientWriteStatus, + Error: err, + }) + } + } + + if request.GetBody() != nil && request.GetBody().Deletes != nil { + deleteRequestTupleKeys := request.GetBody().Deletes + for index := 0; index < len(deleteRequestTupleKeys); index++ { + response.Deletes = append(response.Deletes, ClientWriteRequestDeleteResponse{ + TupleKey: deleteRequestTupleKeys[index], + HttpResponse: httpResponse, + Status: clientWriteStatus, + Error: err, + }) + } + } + + return &response, err + } + + maxPerChunk := int32(1) // 1 has to be the default otherwise the chunks will be sent in transactions + if options.Transaction.MaxPerChunk > 0 { + maxPerChunk = options.Transaction.MaxPerChunk + } + + maxParallelReqs := DEFAULT_MAX_METHOD_PARALLEL_REQS + if options.Transaction.MaxParallelRequests > 0 { + maxParallelReqs = options.Transaction.MaxParallelRequests + } + + // If the transaction mode is disabled: + // - the client will attempt to chunk the writes and deletes into multiple requests + // - each request is a transaction + // - the max items in each request are based on maxPerChunk (default=1) + var writeChunkSize = int(maxPerChunk) + var writeChunks [][]ClientTupleKey + if request.GetBody() != nil { + for i := 0; i < len(request.GetBody().Writes); i += writeChunkSize { + end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Writes)))) + + writeChunks = append(writeChunks, (request.GetBody().Writes)[i:end]) + } + } + + writeGroup, ctx := errgroup.WithContext(request.GetContext()) + + writeGroup.SetLimit(int(maxParallelReqs)) + writeResponses := make([]ClientWriteResponse, len(writeChunks)) + for index, writeBody := range writeChunks { + index, writeBody := index, writeBody + writeGroup.Go(func() error { + singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ + ctx: ctx, + Client: client, + body: &ClientWriteRequest{ + Writes: writeBody, + }, + options: &ClientWriteOptions{ + RequestOptions: options.RequestOptions, + AuthorizationModelId: authorizationModelId, + StoreId: request.GetStoreIdOverride(), + Conflict: options.Conflict, + }, + }) + + if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { + return err + } + + writeResponses[index] = *singleResponse + + return nil + }) + } + + err = writeGroup.Wait() + // If an error was returned then it will be an authentication error so we want to return + if err != nil { + return &response, err + } + + var deleteChunkSize = int(maxPerChunk) + var deleteChunks [][]ClientTupleKeyWithoutCondition + if request.GetBody() != nil { + for i := 0; i < len(request.GetBody().Deletes); i += deleteChunkSize { + end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Deletes)))) + + deleteChunks = append(deleteChunks, (request.GetBody().Deletes)[i:end]) + } + } + + deleteGroup, ctx := errgroup.WithContext(request.GetContext()) + deleteGroup.SetLimit(int(maxParallelReqs)) + deleteResponses := make([]ClientWriteResponse, len(deleteChunks)) + for index, deleteBody := range deleteChunks { + index, deleteBody := index, deleteBody + deleteGroup.Go(func() error { + singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ + ctx: ctx, + Client: client, + body: &ClientWriteRequest{ + Deletes: deleteBody, + }, + options: &ClientWriteOptions{ + RequestOptions: options.RequestOptions, + AuthorizationModelId: authorizationModelId, + StoreId: request.GetStoreIdOverride(), + Conflict: options.Conflict, + }, + }) + + if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { + return err + } + + deleteResponses[index] = *singleResponse + + return nil + }) + } + + err = deleteGroup.Wait() + if err != nil { + // If an error was returned then it will be an authentication error so we want to return + return &response, err + } + + for _, writeResponse := range writeResponses { + response.Writes = append(response.Writes, writeResponse.Writes...) + } + + for _, deleteResponse := range deleteResponses { + response.Deletes = append(response.Deletes, deleteResponse.Deletes...) + } + + return &response, nil } // / WriteTuples type SdkClientWriteTuplesRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteTuplesBody - options *ClientWriteOptions + body *ClientWriteTuplesBody + options *ClientWriteOptions } type SdkClientWriteTuplesRequestInterface interface { - Options(options ClientWriteOptions) SdkClientWriteTuplesRequestInterface - Body(body ClientWriteTuplesBody) SdkClientWriteTuplesRequestInterface - Execute() (*ClientWriteResponse, error) + Options(options ClientWriteOptions) SdkClientWriteTuplesRequestInterface + Body(body ClientWriteTuplesBody) SdkClientWriteTuplesRequestInterface + Execute() (*ClientWriteResponse, error) - GetContext() _context.Context - GetBody() *ClientWriteTuplesBody - GetOptions() *ClientWriteOptions + GetContext() _context.Context + GetBody() *ClientWriteTuplesBody + GetOptions() *ClientWriteOptions } type ClientWriteTuplesBody = []ClientTupleKey func (client *OpenFgaClient) WriteTuples(ctx _context.Context) SdkClientWriteTuplesRequestInterface { - return &SdkClientWriteTuplesRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteTuplesRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientWriteTuplesRequest) Options(options ClientWriteOptions) SdkClientWriteTuplesRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteTuplesRequest) Body(body ClientWriteTuplesBody) SdkClientWriteTuplesRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteTuplesRequest) Execute() (*ClientWriteResponse, error) { - return request.Client.WriteTuplesExecute(request) + return request.Client.WriteTuplesExecute(request) } func (request *SdkClientWriteTuplesRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientWriteTuplesRequest) GetBody() *ClientWriteTuplesBody { - return request.body + return request.body } func (request *SdkClientWriteTuplesRequest) GetOptions() *ClientWriteOptions { - return request.options + return request.options } func (client *OpenFgaClient) WriteTuplesExecute(request SdkClientWriteTuplesRequestInterface) (*ClientWriteResponse, error) { - baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ - Writes: *request.GetBody(), - }) - if request.GetOptions() != nil { - baseReq = baseReq.Options(*request.GetOptions()) - } - return baseReq.Execute() + baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ + Writes: *request.GetBody(), + }) + if request.GetOptions() != nil { + baseReq = baseReq.Options(*request.GetOptions()) + } + return baseReq.Execute() } // / DeleteTuples type SdkClientDeleteTuplesRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientDeleteTuplesBody - options *ClientWriteOptions + body *ClientDeleteTuplesBody + options *ClientWriteOptions } type SdkClientDeleteTuplesRequestInterface interface { - Options(options ClientWriteOptions) SdkClientDeleteTuplesRequestInterface - Body(body ClientDeleteTuplesBody) SdkClientDeleteTuplesRequestInterface - Execute() (*ClientWriteResponse, error) + Options(options ClientWriteOptions) SdkClientDeleteTuplesRequestInterface + Body(body ClientDeleteTuplesBody) SdkClientDeleteTuplesRequestInterface + Execute() (*ClientWriteResponse, error) - GetContext() _context.Context - GetBody() *ClientDeleteTuplesBody - GetOptions() *ClientWriteOptions + GetContext() _context.Context + GetBody() *ClientDeleteTuplesBody + GetOptions() *ClientWriteOptions } type ClientDeleteTuplesBody = []ClientTupleKeyWithoutCondition func (client *OpenFgaClient) DeleteTuples(ctx _context.Context) SdkClientDeleteTuplesRequestInterface { - return &SdkClientDeleteTuplesRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientDeleteTuplesRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientDeleteTuplesRequest) Options(options ClientWriteOptions) SdkClientDeleteTuplesRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientDeleteTuplesRequest) Body(body ClientDeleteTuplesBody) SdkClientDeleteTuplesRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientDeleteTuplesRequest) Execute() (*ClientWriteResponse, error) { - return request.Client.DeleteTuplesExecute(request) + return request.Client.DeleteTuplesExecute(request) } func (request *SdkClientDeleteTuplesRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientDeleteTuplesRequest) GetBody() *ClientDeleteTuplesBody { - return request.body + return request.body } func (request *SdkClientDeleteTuplesRequest) GetOptions() *ClientWriteOptions { - return request.options + return request.options } func (client *OpenFgaClient) DeleteTuplesExecute(request SdkClientDeleteTuplesRequestInterface) (*ClientWriteResponse, error) { - baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ - Deletes: *request.GetBody(), - }) - if request.GetOptions() != nil { - baseReq = baseReq.Options(*request.GetOptions()) - } - return baseReq.Execute() + baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ + Deletes: *request.GetBody(), + }) + if request.GetOptions() != nil { + baseReq = baseReq.Options(*request.GetOptions()) + } + return baseReq.Execute() } /* Relationship Queries */ @@ -2005,343 +2018,343 @@ func (client *OpenFgaClient) DeleteTuplesExecute(request SdkClientDeleteTuplesRe /// Check type SdkClientCheckRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientCheckRequest - options *ClientCheckOptions + body *ClientCheckRequest + options *ClientCheckOptions } type SdkClientCheckRequestInterface interface { - Options(options ClientCheckOptions) SdkClientCheckRequestInterface - Body(body ClientCheckRequest) SdkClientCheckRequestInterface - Execute() (*ClientCheckResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientCheckOptions) SdkClientCheckRequestInterface + Body(body ClientCheckRequest) SdkClientCheckRequestInterface + Execute() (*ClientCheckResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientCheckRequest - GetOptions() *ClientCheckOptions + GetContext() _context.Context + GetBody() *ClientCheckRequest + GetOptions() *ClientCheckOptions } type ClientCheckRequest struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Object string `json:"object,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Object string `json:"object,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientCheckOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientCheckResponse struct { - fgaSdk.CheckResponse - HttpResponse *_nethttp.Response + fgaSdk.CheckResponse + HttpResponse *_nethttp.Response } func (client *OpenFgaClient) Check(ctx _context.Context) SdkClientCheckRequestInterface { - return &SdkClientCheckRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientCheckRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientCheckRequest) Options(options ClientCheckOptions) SdkClientCheckRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientCheckRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientCheckRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientCheckRequest) Body(body ClientCheckRequest) SdkClientCheckRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientCheckRequest) Execute() (*ClientCheckResponse, error) { - return request.Client.CheckExecute(request) + return request.Client.CheckExecute(request) } func (request *SdkClientCheckRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientCheckRequest) GetBody() *ClientCheckRequest { - return request.body + return request.body } func (request *SdkClientCheckRequest) GetOptions() *ClientCheckOptions { - return request.options + return request.options } func (client *OpenFgaClient) CheckExecute(request SdkClientCheckRequestInterface) (*ClientCheckResponse, error) { - if request.GetBody() == nil { - return nil, FgaRequiredParamError{param: "body"} - } - - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - requestBody := fgaSdk.CheckRequest{ - TupleKey: fgaSdk.CheckRequestTupleKey{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Object: request.GetBody().Object, - }, - Context: request.GetBody().Context, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - AuthorizationModelId: authorizationModelId, - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - requestBody.Consistency = request.GetOptions().Consistency - } - - data, httpResponse, err := client.OpenFgaApi. - Check(request.GetContext(), *storeId). - Body(requestBody). - Options(requestOptions). - Execute() - return &ClientCheckResponse{CheckResponse: data, HttpResponse: httpResponse}, err + if request.GetBody() == nil { + return nil, FgaRequiredParamError{param: "body"} + } + + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + requestBody := fgaSdk.CheckRequest{ + TupleKey: fgaSdk.CheckRequestTupleKey{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Object: request.GetBody().Object, + }, + Context: request.GetBody().Context, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + AuthorizationModelId: authorizationModelId, + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + requestBody.Consistency = request.GetOptions().Consistency + } + + data, httpResponse, err := client.OpenFgaApi. + Check(request.GetContext(), *storeId). + Body(requestBody). + Options(requestOptions). + Execute() + return &ClientCheckResponse{CheckResponse: data, HttpResponse: httpResponse}, err } /// ClientBatchCheck type SdkClientBatchCheckClientRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientBatchCheckClientBody - options *ClientBatchCheckClientOptions + body *ClientBatchCheckClientBody + options *ClientBatchCheckClientOptions } type SdkClientBatchCheckClientRequestInterface interface { - Options(options ClientBatchCheckClientOptions) SdkClientBatchCheckClientRequestInterface - Body(body ClientBatchCheckClientBody) SdkClientBatchCheckClientRequestInterface - Execute() (*ClientBatchCheckClientResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientBatchCheckClientOptions) SdkClientBatchCheckClientRequestInterface + Body(body ClientBatchCheckClientBody) SdkClientBatchCheckClientRequestInterface + Execute() (*ClientBatchCheckClientResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientBatchCheckClientBody - GetOptions() *ClientBatchCheckClientOptions + GetContext() _context.Context + GetBody() *ClientBatchCheckClientBody + GetOptions() *ClientBatchCheckClientOptions } type ClientBatchCheckClientBody = []ClientCheckRequest type ClientBatchCheckClientOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientBatchCheckClientSingleResponse struct { - ClientCheckResponse - Request ClientCheckRequest - Error error + ClientCheckResponse + Request ClientCheckRequest + Error error } type ClientBatchCheckClientResponse = []ClientBatchCheckClientSingleResponse func (client *OpenFgaClient) ClientBatchCheck(ctx _context.Context) SdkClientBatchCheckClientRequestInterface { - return &SdkClientBatchCheckClientRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientBatchCheckClientRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientBatchCheckClientRequest) Options(options ClientBatchCheckClientOptions) SdkClientBatchCheckClientRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientBatchCheckClientRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientBatchCheckClientRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientBatchCheckClientRequest) Body(body ClientBatchCheckClientBody) SdkClientBatchCheckClientRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientBatchCheckClientRequest) Execute() (*ClientBatchCheckClientResponse, error) { - return request.Client.ClientBatchCheckExecute(request) + return request.Client.ClientBatchCheckExecute(request) } func (request *SdkClientBatchCheckClientRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientBatchCheckClientRequest) GetBody() *ClientBatchCheckClientBody { - return request.body + return request.body } func (request *SdkClientBatchCheckClientRequest) GetOptions() *ClientBatchCheckClientOptions { - return request.options + return request.options } func (client *OpenFgaClient) ClientBatchCheckExecute(request SdkClientBatchCheckClientRequestInterface) (*ClientBatchCheckClientResponse, error) { - group, ctx := errgroup.WithContext(request.GetContext()) - requestOptions := RequestOptions{} - maxParallelReqs := int(DEFAULT_MAX_METHOD_PARALLEL_REQS) - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - if request.GetOptions().MaxParallelRequests != nil { - maxParallelReqs = int(*request.GetOptions().MaxParallelRequests) - } - } - - group.SetLimit(maxParallelReqs) - var numOfChecks = len(*request.GetBody()) - response := make(ClientBatchCheckClientResponse, numOfChecks) - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - checkOptions := &ClientCheckOptions{ - RequestOptions: requestOptions, - - AuthorizationModelId: authorizationModelId, - StoreId: storeId, - } - - if request.GetOptions() != nil && request.GetOptions().Consistency != nil { - checkOptions.Consistency = request.GetOptions().Consistency - } - - for index, checkBody := range *request.GetBody() { - index, checkBody := index, checkBody - group.Go(func() error { - singleResponse, err := client.CheckExecute(&SdkClientCheckRequest{ - ctx: ctx, - Client: client, - body: &checkBody, - options: checkOptions, - }) - - if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { - return err - } - - response[index] = ClientBatchCheckClientSingleResponse{ - Request: checkBody, - ClientCheckResponse: *singleResponse, - Error: err, - } - - return nil - }) - } - - if err := group.Wait(); err != nil { - return nil, err - } - - return &response, nil + group, ctx := errgroup.WithContext(request.GetContext()) + requestOptions := RequestOptions{} + maxParallelReqs := int(DEFAULT_MAX_METHOD_PARALLEL_REQS) + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + if request.GetOptions().MaxParallelRequests != nil { + maxParallelReqs = int(*request.GetOptions().MaxParallelRequests) + } + } + + group.SetLimit(maxParallelReqs) + var numOfChecks = len(*request.GetBody()) + response := make(ClientBatchCheckClientResponse, numOfChecks) + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + checkOptions := &ClientCheckOptions{ + RequestOptions: requestOptions, + + AuthorizationModelId: authorizationModelId, + StoreId: storeId, + } + + if request.GetOptions() != nil && request.GetOptions().Consistency != nil { + checkOptions.Consistency = request.GetOptions().Consistency + } + + for index, checkBody := range *request.GetBody() { + index, checkBody := index, checkBody + group.Go(func() error { + singleResponse, err := client.CheckExecute(&SdkClientCheckRequest{ + ctx: ctx, + Client: client, + body: &checkBody, + options: checkOptions, + }) + + if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { + return err + } + + response[index] = ClientBatchCheckClientSingleResponse{ + Request: checkBody, + ClientCheckResponse: *singleResponse, + Error: err, + } + + return nil + }) + } + + if err := group.Wait(); err != nil { + return nil, err + } + + return &response, nil } // Server-side BatchCheck implementation // SdkClientBatchCheckRequest represents a server-side batch check request type SdkClientBatchCheckRequest struct { - ctx _context.Context - client *OpenFgaClient - body *ClientBatchCheckRequest - options *BatchCheckOptions + ctx _context.Context + client *OpenFgaClient + body *ClientBatchCheckRequest + options *BatchCheckOptions } // SdkClientBatchCheckRequestInterface defines the interface for server-side batch check requests type SdkClientBatchCheckRequestInterface interface { - Body(body ClientBatchCheckRequest) SdkClientBatchCheckRequestInterface - Options(options BatchCheckOptions) SdkClientBatchCheckRequestInterface - Execute() (*fgaSdk.BatchCheckResponse, error) - GetContext() _context.Context - GetBody() *ClientBatchCheckRequest - GetOptions() *BatchCheckOptions + Body(body ClientBatchCheckRequest) SdkClientBatchCheckRequestInterface + Options(options BatchCheckOptions) SdkClientBatchCheckRequestInterface + Execute() (*fgaSdk.BatchCheckResponse, error) + GetContext() _context.Context + GetBody() *ClientBatchCheckRequest + GetOptions() *BatchCheckOptions } func (r *SdkClientBatchCheckRequest) Body(body ClientBatchCheckRequest) SdkClientBatchCheckRequestInterface { - r.body = &body - return r + r.body = &body + return r } func (r *SdkClientBatchCheckRequest) Options(options BatchCheckOptions) SdkClientBatchCheckRequestInterface { - r.options = &options - return r + r.options = &options + return r } func (r *SdkClientBatchCheckRequest) Execute() (*fgaSdk.BatchCheckResponse, error) { - return r.client.BatchCheckExecute(r) + return r.client.BatchCheckExecute(r) } func (r *SdkClientBatchCheckRequest) GetContext() _context.Context { - return r.ctx + return r.ctx } func (r *SdkClientBatchCheckRequest) GetBody() *ClientBatchCheckRequest { - return r.body + return r.body } func (r *SdkClientBatchCheckRequest) GetOptions() *BatchCheckOptions { - return r.options + return r.options } // BatchCheck initializes a new batch check request func (client *OpenFgaClient) BatchCheck(ctx _context.Context) SdkClientBatchCheckRequestInterface { - return &SdkClientBatchCheckRequest{ - ctx: ctx, - client: client, - } + return &SdkClientBatchCheckRequest{ + ctx: ctx, + client: client, + } } /* @@ -2350,68 +2363,68 @@ func (client *OpenFgaClient) BatchCheck(ctx _context.Context) SdkClientBatchChec * @return *fgaSdk.BatchCheckResponse */ func (client *OpenFgaClient) BatchCheckExecute(request SdkClientBatchCheckRequestInterface) (*fgaSdk.BatchCheckResponse, error) { - ctx := request.GetContext() - body := request.GetBody() - options := request.GetOptions() + ctx := request.GetContext() + body := request.GetBody() + options := request.GetOptions() - if body == nil || len(body.Checks) == 0 { - return nil, FgaRequiredParamError{param: "checks"} - } + if body == nil || len(body.Checks) == 0 { + return nil, FgaRequiredParamError{param: "checks"} + } - if options == nil { - options = &BatchCheckOptions{} - } + if options == nil { + options = &BatchCheckOptions{} + } - maxParallelRequests := DEFAULT_MAX_METHOD_PARALLEL_REQS - if options.MaxParallelRequests != nil { - maxParallelRequests = *options.MaxParallelRequests - } + maxParallelRequests := DEFAULT_MAX_METHOD_PARALLEL_REQS + if options.MaxParallelRequests != nil { + maxParallelRequests = *options.MaxParallelRequests + } - maxBatchSize := int32(constants.ClientMaxBatchSize) - if options.MaxBatchSize != nil { - maxBatchSize = *options.MaxBatchSize - } + maxBatchSize := int32(constants.ClientMaxBatchSize) + if options.MaxBatchSize != nil { + maxBatchSize = *options.MaxBatchSize + } - _, err := client.getStoreId(options.StoreId) - if err != nil { - return nil, err - } + _, err := client.getStoreId(options.StoreId) + if err != nil { + return nil, err + } - authorizationModelId, err := client.getAuthorizationModelId(options.AuthorizationModelId) - if err != nil { - return nil, err - } + authorizationModelId, err := client.getAuthorizationModelId(options.AuthorizationModelId) + if err != nil { + return nil, err + } - chunks := chunkClientBatchCheckItems(body.Checks, int(maxBatchSize)) + chunks := chunkClientBatchCheckItems(body.Checks, int(maxBatchSize)) - p := pool.NewWithResults[*fgaSdk.BatchCheckResponse]().WithContext(ctx).WithMaxGoroutines(int(maxParallelRequests)) + p := pool.NewWithResults[*fgaSdk.BatchCheckResponse]().WithContext(ctx).WithMaxGoroutines(int(maxParallelRequests)) - for _, chunk := range chunks { - chunkCopy := chunk + for _, chunk := range chunks { + chunkCopy := chunk - p.Go(func(ctx _context.Context) (*fgaSdk.BatchCheckResponse, error) { - batchCheckRequest := createBatchCheckRequest(chunkCopy, authorizationModelId, options.Consistency) - return client.singleBatchCheck(ctx, batchCheckRequest, options) - }) - } + p.Go(func(ctx _context.Context) (*fgaSdk.BatchCheckResponse, error) { + batchCheckRequest := createBatchCheckRequest(chunkCopy, authorizationModelId, options.Consistency) + return client.singleBatchCheck(ctx, batchCheckRequest, options) + }) + } - responses, err := p.Wait() - if err != nil { - return nil, err - } + responses, err := p.Wait() + if err != nil { + return nil, err + } - combinedResult := make(map[string]fgaSdk.BatchCheckSingleResult) + combinedResult := make(map[string]fgaSdk.BatchCheckSingleResult) - for _, response := range responses { - for correlationID, result := range response.GetResult() { - combinedResult[correlationID] = result - } - } + for _, response := range responses { + for correlationID, result := range response.GetResult() { + combinedResult[correlationID] = result + } + } - combinedResponse := fgaSdk.NewBatchCheckResponse() - combinedResponse.SetResult(combinedResult) + combinedResponse := fgaSdk.NewBatchCheckResponse() + combinedResponse.SetResult(combinedResult) - return combinedResponse, nil + return combinedResponse, nil } /* @@ -2422,21 +2435,21 @@ func (client *OpenFgaClient) BatchCheckExecute(request SdkClientBatchCheckReques * @return *fgaSdk.BatchCheckResponse */ func (client *OpenFgaClient) singleBatchCheck(ctx _context.Context, body fgaSdk.BatchCheckRequest, options *BatchCheckOptions) (*fgaSdk.BatchCheckResponse, error) { - storeId, err := client.getStoreId(options.StoreId) - if err != nil { - return nil, err - } + storeId, err := client.getStoreId(options.StoreId) + if err != nil { + return nil, err + } - req := client.OpenFgaApi. - BatchCheck(ctx, *storeId). - Body(body). - Options(options.RequestOptions) - response, _, err := req.Execute() - if err != nil { - return nil, err - } + req := client.OpenFgaApi. + BatchCheck(ctx, *storeId). + Body(body). + Options(options.RequestOptions) + response, _, err := req.Execute() + if err != nil { + return nil, err + } - return &response, nil + return &response, nil } /* @@ -2446,21 +2459,21 @@ func (client *OpenFgaClient) singleBatchCheck(ctx _context.Context, body fgaSdk. * @return [][]ClientBatchCheckItem - the chunked items */ func chunkClientBatchCheckItems(items []ClientBatchCheckItem, chunkSize int) [][]ClientBatchCheckItem { - if len(items) == 0 { - return [][]ClientBatchCheckItem{} - } + if len(items) == 0 { + return [][]ClientBatchCheckItem{} + } - chunks := make([][]ClientBatchCheckItem, 0, (len(items)+chunkSize-1)/chunkSize) + chunks := make([][]ClientBatchCheckItem, 0, (len(items)+chunkSize-1)/chunkSize) - for i := 0; i < len(items); i += chunkSize { - end := i + chunkSize - if end > len(items) { - end = len(items) - } - chunks = append(chunks, items[i:end]) - } + for i := 0; i < len(items); i += chunkSize { + end := i + chunkSize + if end > len(items) { + end = len(items) + } + chunks = append(chunks, items[i:end]) + } - return chunks + return chunks } /* @@ -2471,814 +2484,970 @@ func chunkClientBatchCheckItems(items []ClientBatchCheckItem, chunkSize int) [][ * @return fgaSdk.BatchCheckRequest - the created request */ func createBatchCheckRequest(items []ClientBatchCheckItem, authorizationModelId *string, consistency *fgaSdk.ConsistencyPreference) fgaSdk.BatchCheckRequest { - batchCheckItems := make([]fgaSdk.BatchCheckItem, 0, len(items)) + batchCheckItems := make([]fgaSdk.BatchCheckItem, 0, len(items)) - for _, item := range items { - tupleKey := fgaSdk.CheckRequestTupleKey{ - User: item.User, - Relation: item.Relation, - Object: item.Object, - } + for _, item := range items { + tupleKey := fgaSdk.CheckRequestTupleKey{ + User: item.User, + Relation: item.Relation, + Object: item.Object, + } - batchCheckItem := fgaSdk.BatchCheckItem{ - TupleKey: tupleKey, - CorrelationId: item.CorrelationId, - } + batchCheckItem := fgaSdk.BatchCheckItem{ + TupleKey: tupleKey, + CorrelationId: item.CorrelationId, + } - if len(item.ContextualTuples) > 0 { - contextualTuples := &fgaSdk.ContextualTupleKeys{ - TupleKeys: []fgaSdk.TupleKey{}, - } + if len(item.ContextualTuples) > 0 { + contextualTuples := &fgaSdk.ContextualTupleKeys{ + TupleKeys: []fgaSdk.TupleKey{}, + } - contextualTuples.TupleKeys = append(contextualTuples.TupleKeys, item.ContextualTuples...) + contextualTuples.TupleKeys = append(contextualTuples.TupleKeys, item.ContextualTuples...) - batchCheckItem.ContextualTuples = contextualTuples - } + batchCheckItem.ContextualTuples = contextualTuples + } - if item.Context != nil { - batchCheckItem.Context = item.Context - } + if item.Context != nil { + batchCheckItem.Context = item.Context + } - batchCheckItems = append(batchCheckItems, batchCheckItem) - } + batchCheckItems = append(batchCheckItems, batchCheckItem) + } - batchCheckRequest := fgaSdk.BatchCheckRequest{ - Checks: batchCheckItems, - } + batchCheckRequest := fgaSdk.BatchCheckRequest{ + Checks: batchCheckItems, + } - if authorizationModelId != nil && *authorizationModelId != "" { - batchCheckRequest.AuthorizationModelId = authorizationModelId - } + if authorizationModelId != nil && *authorizationModelId != "" { + batchCheckRequest.AuthorizationModelId = authorizationModelId + } - if consistency != nil { - batchCheckRequest.Consistency = consistency - } + if consistency != nil { + batchCheckRequest.Consistency = consistency + } - return batchCheckRequest + return batchCheckRequest } // / Expand type SdkClientExpandRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientExpandRequest - options *ClientExpandOptions + body *ClientExpandRequest + options *ClientExpandOptions } type SdkClientExpandRequestInterface interface { - Options(options ClientExpandOptions) SdkClientExpandRequestInterface - Body(body ClientExpandRequest) SdkClientExpandRequestInterface - Execute() (*ClientExpandResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientExpandOptions) SdkClientExpandRequestInterface + Body(body ClientExpandRequest) SdkClientExpandRequestInterface + Execute() (*ClientExpandResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientExpandRequest - GetOptions() *ClientExpandOptions + GetContext() _context.Context + GetBody() *ClientExpandRequest + GetOptions() *ClientExpandOptions } type ClientExpandRequest struct { - Relation string `json:"relation,omitempty"` - Object string `json:"object,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + Relation string `json:"relation,omitempty"` + Object string `json:"object,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientExpandOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientExpandResponse = fgaSdk.ExpandResponse func (client *OpenFgaClient) Expand(ctx _context.Context) SdkClientExpandRequestInterface { - return &SdkClientExpandRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientExpandRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientExpandRequest) Options(options ClientExpandOptions) SdkClientExpandRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientExpandRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientExpandRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientExpandRequest) Body(body ClientExpandRequest) SdkClientExpandRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientExpandRequest) Execute() (*ClientExpandResponse, error) { - return request.Client.ExpandExecute(request) + return request.Client.ExpandExecute(request) } func (request *SdkClientExpandRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientExpandRequest) GetBody() *ClientExpandRequest { - return request.body + return request.body } func (request *SdkClientExpandRequest) GetOptions() *ClientExpandOptions { - return request.options + return request.options } func (client *OpenFgaClient) ExpandExecute(request SdkClientExpandRequestInterface) (*ClientExpandResponse, error) { - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - - body := fgaSdk.ExpandRequest{ - TupleKey: fgaSdk.ExpandRequestTupleKey{ - Relation: request.GetBody().Relation, - Object: request.GetBody().Object, - }, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - AuthorizationModelId: authorizationModelId, - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - } - - data, _, err := client.OpenFgaApi. - Expand(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + + body := fgaSdk.ExpandRequest{ + TupleKey: fgaSdk.ExpandRequestTupleKey{ + Relation: request.GetBody().Relation, + Object: request.GetBody().Object, + }, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + AuthorizationModelId: authorizationModelId, + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + } + + data, _, err := client.OpenFgaApi. + Expand(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / ListObjects type SdkClientListObjectsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientListObjectsRequest - options *ClientListObjectsOptions + body *ClientListObjectsRequest + options *ClientListObjectsOptions } type SdkClientListObjectsRequestInterface interface { - Options(options ClientListObjectsOptions) SdkClientListObjectsRequestInterface - Body(body ClientListObjectsRequest) SdkClientListObjectsRequestInterface - Execute() (*ClientListObjectsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientListObjectsOptions) SdkClientListObjectsRequestInterface + Body(body ClientListObjectsRequest) SdkClientListObjectsRequestInterface + Execute() (*ClientListObjectsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientListObjectsRequest - GetOptions() *ClientListObjectsOptions + GetContext() _context.Context + GetBody() *ClientListObjectsRequest + GetOptions() *ClientListObjectsOptions } type ClientListObjectsRequest struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Type string `json:"type,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Type string `json:"type,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientListObjectsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientListObjectsResponse = fgaSdk.ListObjectsResponse func (client *OpenFgaClient) ListObjects(ctx _context.Context) SdkClientListObjectsRequestInterface { - return &SdkClientListObjectsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientListObjectsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientListObjectsRequest) Options(options ClientListObjectsOptions) SdkClientListObjectsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListObjectsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientListObjectsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientListObjectsRequest) Body(body ClientListObjectsRequest) SdkClientListObjectsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientListObjectsRequest) Execute() (*ClientListObjectsResponse, error) { - return request.Client.ListObjectsExecute(request) + return request.Client.ListObjectsExecute(request) } func (request *SdkClientListObjectsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListObjectsRequest) GetBody() *ClientListObjectsRequest { - return request.body + return request.body } func (request *SdkClientListObjectsRequest) GetOptions() *ClientListObjectsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListObjectsExecute(request SdkClientListObjectsRequestInterface) (*ClientListObjectsResponse, error) { - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - body := fgaSdk.ListObjectsRequest{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Type: request.GetBody().Type, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - Context: request.GetBody().Context, - AuthorizationModelId: authorizationModelId, - } - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - } - data, _, err := client.OpenFgaApi. - ListObjects(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + body := fgaSdk.ListObjectsRequest{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Type: request.GetBody().Type, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + Context: request.GetBody().Context, + AuthorizationModelId: authorizationModelId, + } + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + } + data, _, err := client.OpenFgaApi. + ListObjects(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } /// ListRelations type SdkClientListRelationsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientListRelationsRequest - options *ClientListRelationsOptions + body *ClientListRelationsRequest + options *ClientListRelationsOptions } type SdkClientListRelationsRequestInterface interface { - Options(options ClientListRelationsOptions) SdkClientListRelationsRequestInterface - Body(body ClientListRelationsRequest) SdkClientListRelationsRequestInterface - Execute() (*ClientListRelationsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientListRelationsOptions) SdkClientListRelationsRequestInterface + Body(body ClientListRelationsRequest) SdkClientListRelationsRequestInterface + Execute() (*ClientListRelationsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientListRelationsRequest - GetOptions() *ClientListRelationsOptions + GetContext() _context.Context + GetBody() *ClientListRelationsRequest + GetOptions() *ClientListRelationsOptions } type ClientListRelationsRequest struct { - User string `json:"user,omitempty"` - Object string `json:"object,omitempty"` - Relations []string `json:"relations,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Object string `json:"object,omitempty"` + Relations []string `json:"relations,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientListRelationsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientListRelationsResponse struct { - Relations []string `json:"response,omitempty"` + Relations []string `json:"response,omitempty"` } func (o ClientListRelationsResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - toSerialize["relations"] = o.Relations - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + toSerialize["relations"] = o.Relations + return json.Marshal(toSerialize) } func (client *OpenFgaClient) ListRelations(ctx _context.Context) SdkClientListRelationsRequestInterface { - return &SdkClientListRelationsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientListRelationsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientListRelationsRequest) Options(options ClientListRelationsOptions) SdkClientListRelationsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListRelationsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientListRelationsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientListRelationsRequest) Body(body ClientListRelationsRequest) SdkClientListRelationsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientListRelationsRequest) Execute() (*ClientListRelationsResponse, error) { - return request.Client.ListRelationsExecute(request) + return request.Client.ListRelationsExecute(request) } func (request *SdkClientListRelationsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListRelationsRequest) GetBody() *ClientListRelationsRequest { - return request.body + return request.body } func (request *SdkClientListRelationsRequest) GetOptions() *ClientListRelationsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListRelationsExecute(request SdkClientListRelationsRequestInterface) (*ClientListRelationsResponse, error) { - if len(request.GetBody().Relations) <= 0 { - return nil, fmt.Errorf("ListRelations - expected len(Relations) > 0") - } - - batchRequestBody := ClientBatchCheckClientBody{} - for index := 0; index < len(request.GetBody().Relations); index++ { - batchRequestBody = append(batchRequestBody, ClientCheckRequest{ - User: request.GetBody().User, - Relation: request.GetBody().Relations[index], - Object: request.GetBody().Object, - Context: request.GetBody().Context, - ContextualTuples: request.GetBody().ContextualTuples, - }) - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - options := &ClientBatchCheckClientOptions{ - AuthorizationModelId: authorizationModelId, - StoreId: storeId, - } - if request.GetOptions() != nil { - options.RequestOptions = request.GetOptions().RequestOptions - options.Consistency = request.GetOptions().Consistency - options.MaxParallelRequests = request.GetOptions().MaxParallelRequests - } - - batchResponse, err := client.ClientBatchCheckExecute(&SdkClientBatchCheckClientRequest{ - ctx: request.GetContext(), - Client: client, - body: &batchRequestBody, - options: options, - }) - - if err != nil { - return nil, err - } - - var relations []string - for index := 0; index < len(*batchResponse); index++ { - if (*batchResponse)[index].GetAllowed() { - relations = append(relations, (*batchResponse)[index].Request.Relation) - } - } - - return &ClientListRelationsResponse{Relations: relations}, nil + if len(request.GetBody().Relations) <= 0 { + return nil, fmt.Errorf("ListRelations - expected len(Relations) > 0") + } + + batchRequestBody := ClientBatchCheckClientBody{} + for index := 0; index < len(request.GetBody().Relations); index++ { + batchRequestBody = append(batchRequestBody, ClientCheckRequest{ + User: request.GetBody().User, + Relation: request.GetBody().Relations[index], + Object: request.GetBody().Object, + Context: request.GetBody().Context, + ContextualTuples: request.GetBody().ContextualTuples, + }) + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + options := &ClientBatchCheckClientOptions{ + AuthorizationModelId: authorizationModelId, + StoreId: storeId, + } + if request.GetOptions() != nil { + options.RequestOptions = request.GetOptions().RequestOptions + options.Consistency = request.GetOptions().Consistency + options.MaxParallelRequests = request.GetOptions().MaxParallelRequests + } + + batchResponse, err := client.ClientBatchCheckExecute(&SdkClientBatchCheckClientRequest{ + ctx: request.GetContext(), + Client: client, + body: &batchRequestBody, + options: options, + }) + + if err != nil { + return nil, err + } + + var relations []string + for index := 0; index < len(*batchResponse); index++ { + if (*batchResponse)[index].GetAllowed() { + relations = append(relations, (*batchResponse)[index].Request.Relation) + } + } + + return &ClientListRelationsResponse{Relations: relations}, nil } // / ListUsers type SdkClientListUsersRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientListUsersRequest - options *ClientListUsersOptions + body *ClientListUsersRequest + options *ClientListUsersOptions } type SdkClientListUsersRequestInterface interface { - Options(options ClientListUsersOptions) SdkClientListUsersRequestInterface - Body(body ClientListUsersRequest) SdkClientListUsersRequestInterface - Execute() (*ClientListUsersResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientListUsersOptions) SdkClientListUsersRequestInterface + Body(body ClientListUsersRequest) SdkClientListUsersRequestInterface + Execute() (*ClientListUsersResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientListUsersRequest - GetOptions() *ClientListUsersOptions + GetContext() _context.Context + GetBody() *ClientListUsersRequest + GetOptions() *ClientListUsersOptions } type ClientListUsersRequest struct { - Object fgaSdk.FgaObject `json:"object" yaml:"object"` - Relation string `json:"relation" yaml:"relation"` - UserFilters []fgaSdk.UserTypeFilter `json:"user_filters" yaml:"user_filters"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` - // Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. - Context *map[string]interface{} `json:"context,omitempty" yaml:"context,omitempty"` + Object fgaSdk.FgaObject `json:"object" yaml:"object"` + Relation string `json:"relation" yaml:"relation"` + UserFilters []fgaSdk.UserTypeFilter `json:"user_filters" yaml:"user_filters"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + // Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + Context *map[string]interface{} `json:"context,omitempty" yaml:"context,omitempty"` } type ClientListUsersOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientListUsersResponse = fgaSdk.ListUsersResponse func (client *OpenFgaClient) ListUsers(ctx _context.Context) SdkClientListUsersRequestInterface { - return &SdkClientListUsersRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientListUsersRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientListUsersRequest) Options(options ClientListUsersOptions) SdkClientListUsersRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListUsersRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientListUsersRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientListUsersRequest) Body(body ClientListUsersRequest) SdkClientListUsersRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientListUsersRequest) Execute() (*ClientListUsersResponse, error) { - return request.Client.ListUsersExecute(request) + return request.Client.ListUsersExecute(request) } func (request *SdkClientListUsersRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListUsersRequest) GetBody() *ClientListUsersRequest { - return request.body + return request.body } func (request *SdkClientListUsersRequest) GetOptions() *ClientListUsersOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListUsersExecute(request SdkClientListUsersRequestInterface) (*ClientListUsersResponse, error) { - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - body := fgaSdk.ListUsersRequest{ - Object: request.GetBody().Object, - Relation: request.GetBody().Relation, - UserFilters: request.GetBody().UserFilters, - ContextualTuples: &fgaSdk.NewContextualTupleKeys(contextualTuples).TupleKeys, - Context: request.GetBody().Context, - AuthorizationModelId: authorizationModelId, - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - } - - data, _, err := client.OpenFgaApi. - ListUsers(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + body := fgaSdk.ListUsersRequest{ + Object: request.GetBody().Object, + Relation: request.GetBody().Relation, + UserFilters: request.GetBody().UserFilters, + ContextualTuples: &fgaSdk.NewContextualTupleKeys(contextualTuples).TupleKeys, + Context: request.GetBody().Context, + AuthorizationModelId: authorizationModelId, + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + } + + data, _, err := client.OpenFgaApi. + ListUsers(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / ReadAssertions type SdkClientReadAssertionsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientReadAssertionsOptions + options *ClientReadAssertionsOptions } type SdkClientReadAssertionsRequestInterface interface { - Options(options ClientReadAssertionsOptions) SdkClientReadAssertionsRequestInterface - Execute() (*ClientReadAssertionsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientReadAssertionsOptions) SdkClientReadAssertionsRequestInterface + Execute() (*ClientReadAssertionsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientReadAssertionsOptions + GetContext() _context.Context + GetOptions() *ClientReadAssertionsOptions } type ClientReadAssertionsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientReadAssertionsResponse = fgaSdk.ReadAssertionsResponse func (client *OpenFgaClient) ReadAssertions(ctx _context.Context) SdkClientReadAssertionsRequestInterface { - return &SdkClientReadAssertionsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadAssertionsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientReadAssertionsRequest) Options(options ClientReadAssertionsOptions) SdkClientReadAssertionsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadAssertionsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientReadAssertionsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadAssertionsRequest) Execute() (*ClientReadAssertionsResponse, error) { - return request.Client.ReadAssertionsExecute(request) + return request.Client.ReadAssertionsExecute(request) } func (request *SdkClientReadAssertionsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadAssertionsRequest) GetOptions() *ClientReadAssertionsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadAssertionsExecute(request SdkClientReadAssertionsRequestInterface) (*ClientReadAssertionsResponse, error) { - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - if authorizationModelId == nil || *authorizationModelId == "" { - return nil, FgaRequiredParamError{param: "AuthorizationModelId"} - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - ReadAssertions(request.GetContext(), *storeId, *authorizationModelId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + if authorizationModelId == nil || *authorizationModelId == "" { + return nil, FgaRequiredParamError{param: "AuthorizationModelId"} + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + ReadAssertions(request.GetContext(), *storeId, *authorizationModelId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / WriteAssertions type SdkClientWriteAssertionsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteAssertionsRequest - options *ClientWriteAssertionsOptions + body *ClientWriteAssertionsRequest + options *ClientWriteAssertionsOptions } type SdkClientWriteAssertionsRequestInterface interface { - Options(options ClientWriteAssertionsOptions) SdkClientWriteAssertionsRequestInterface - Body(body ClientWriteAssertionsRequest) SdkClientWriteAssertionsRequestInterface - Execute() (*ClientWriteAssertionsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientWriteAssertionsOptions) SdkClientWriteAssertionsRequestInterface + Body(body ClientWriteAssertionsRequest) SdkClientWriteAssertionsRequestInterface + Execute() (*ClientWriteAssertionsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientWriteAssertionsRequest - GetOptions() *ClientWriteAssertionsOptions + GetContext() _context.Context + GetBody() *ClientWriteAssertionsRequest + GetOptions() *ClientWriteAssertionsOptions } type ClientAssertion struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Object string `json:"object,omitempty"` - Expectation bool `json:"expectation,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Object string `json:"object,omitempty"` + Expectation bool `json:"expectation,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientWriteAssertionsRequest = []ClientAssertion func (clientAssertion ClientAssertion) ToAssertion() fgaSdk.Assertion { - assertion := fgaSdk.Assertion{ - TupleKey: fgaSdk.AssertionTupleKey{ - User: clientAssertion.User, - Relation: clientAssertion.Relation, - Object: clientAssertion.Object, - }, - Expectation: clientAssertion.Expectation, - } - if clientAssertion.Context != nil { - assertion.Context = clientAssertion.Context - } - if clientAssertion.ContextualTuples != nil { - assertion.ContextualTuples = &clientAssertion.ContextualTuples - } - return assertion + assertion := fgaSdk.Assertion{ + TupleKey: fgaSdk.AssertionTupleKey{ + User: clientAssertion.User, + Relation: clientAssertion.Relation, + Object: clientAssertion.Object, + }, + Expectation: clientAssertion.Expectation, + } + if clientAssertion.Context != nil { + assertion.Context = clientAssertion.Context + } + if clientAssertion.ContextualTuples != nil { + assertion.ContextualTuples = &clientAssertion.ContextualTuples + } + return assertion } type ClientWriteAssertionsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientWriteAssertionsResponse struct { } func (client *OpenFgaClient) WriteAssertions(ctx _context.Context) SdkClientWriteAssertionsRequestInterface { - return &SdkClientWriteAssertionsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteAssertionsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientWriteAssertionsRequest) Options(options ClientWriteAssertionsOptions) SdkClientWriteAssertionsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteAssertionsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientWriteAssertionsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientWriteAssertionsRequest) Body(body ClientWriteAssertionsRequest) SdkClientWriteAssertionsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteAssertionsRequest) Execute() (*ClientWriteAssertionsResponse, error) { - return request.Client.WriteAssertionsExecute(request) + return request.Client.WriteAssertionsExecute(request) } func (request *SdkClientWriteAssertionsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientWriteAssertionsRequest) GetBody() *ClientWriteAssertionsRequest { - return request.body + return request.body } func (request *SdkClientWriteAssertionsRequest) GetOptions() *ClientWriteAssertionsOptions { - return request.options + return request.options } func (client *OpenFgaClient) WriteAssertionsExecute(request SdkClientWriteAssertionsRequestInterface) (*ClientWriteAssertionsResponse, error) { - writeAssertionsRequest := fgaSdk.WriteAssertionsRequest{} - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - if authorizationModelId == nil || *authorizationModelId == "" { - return nil, FgaRequiredParamError{param: "AuthorizationModelId"} - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - for index := 0; index < len(*request.GetBody()); index++ { - clientAssertion := (*request.GetBody())[index] - writeAssertionsRequest.Assertions = append(writeAssertionsRequest.Assertions, clientAssertion.ToAssertion()) - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - _, err = client.OpenFgaApi. - WriteAssertions(request.GetContext(), *storeId, *authorizationModelId). - Body(writeAssertionsRequest). - Options(requestOptions). - Execute() - - if err != nil { - return nil, err - } - return &ClientWriteAssertionsResponse{}, nil + writeAssertionsRequest := fgaSdk.WriteAssertionsRequest{} + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + if authorizationModelId == nil || *authorizationModelId == "" { + return nil, FgaRequiredParamError{param: "AuthorizationModelId"} + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + for index := 0; index < len(*request.GetBody()); index++ { + clientAssertion := (*request.GetBody())[index] + writeAssertionsRequest.Assertions = append(writeAssertionsRequest.Assertions, clientAssertion.ToAssertion()) + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + _, err = client.OpenFgaApi. + WriteAssertions(request.GetContext(), *storeId, *authorizationModelId). + Body(writeAssertionsRequest). + Options(requestOptions). + Execute() + + if err != nil { + return nil, err + } + return &ClientWriteAssertionsResponse{}, nil +} + +type SdkClientStreamedListObjectsRequest struct { + ctx _context.Context + Client *OpenFgaClient + + body *ClientStreamedListObjectsRequest + options *ClientStreamedListObjectsOptions +} + +type SdkClientStreamedListObjectsRequestInterface interface { + Options(options ClientStreamedListObjectsOptions) SdkClientStreamedListObjectsRequestInterface + Body(body ClientStreamedListObjectsRequest) SdkClientStreamedListObjectsRequestInterface + Execute() (*ClientStreamedListObjectsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string + + GetContext() _context.Context + GetBody() *ClientStreamedListObjectsRequest + GetOptions() *ClientStreamedListObjectsOptions +} + +type ClientStreamedListObjectsRequest struct { + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Type string `json:"type,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` +} + +type ClientStreamedListObjectsOptions struct { + RequestOptions + + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + // StreamBufferSize configures the buffer size for streaming response channels. + // A larger buffer improves throughput for high-volume streams but increases memory usage. + // A smaller buffer reduces memory usage but may decrease throughput. + // Defaults to 10 if not specified or if set to 0. + StreamBufferSize *int `json:"stream_buffer_size,omitempty"` +} + +type ClientStreamedListObjectsResponse struct { + Objects <-chan fgaSdk.StreamedListObjectsResponse + Errors <-chan error + close func() +} + +func (r *ClientStreamedListObjectsResponse) Close() { + if r.close != nil { + r.close() + } +} + +func (client *OpenFgaClient) StreamedListObjects(ctx _context.Context) SdkClientStreamedListObjectsRequestInterface { + return &SdkClientStreamedListObjectsRequest{ + Client: client, + ctx: ctx, + } +} + +func (request *SdkClientStreamedListObjectsRequest) Options(options ClientStreamedListObjectsOptions) SdkClientStreamedListObjectsRequestInterface { + request.options = &options + return request +} + +func (request *SdkClientStreamedListObjectsRequest) GetAuthorizationModelIdOverride() *string { + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId +} + +func (request *SdkClientStreamedListObjectsRequest) GetStoreIdOverride() *string { + if request.options == nil { + return nil + } + return request.options.StoreId +} + +func (request *SdkClientStreamedListObjectsRequest) Body(body ClientStreamedListObjectsRequest) SdkClientStreamedListObjectsRequestInterface { + request.body = &body + return request +} + +func (request *SdkClientStreamedListObjectsRequest) Execute() (*ClientStreamedListObjectsResponse, error) { + return request.Client.StreamedListObjectsExecute(request) +} + +func (request *SdkClientStreamedListObjectsRequest) GetContext() _context.Context { + return request.ctx +} + +func (request *SdkClientStreamedListObjectsRequest) GetBody() *ClientStreamedListObjectsRequest { + return request.body +} + +func (request *SdkClientStreamedListObjectsRequest) GetOptions() *ClientStreamedListObjectsOptions { + return request.options +} + +func (client *OpenFgaClient) StreamedListObjectsExecute(request SdkClientStreamedListObjectsRequestInterface) (*ClientStreamedListObjectsResponse, error) { + if request.GetBody() == nil { + return nil, FgaRequiredParamError{param: "body"} + } + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + body := fgaSdk.ListObjectsRequest{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Type: request.GetBody().Type, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + Context: request.GetBody().Context, + AuthorizationModelId: authorizationModelId, + } + requestOptions := RequestOptions{} + bufferSize := 0 + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + if request.GetOptions().StreamBufferSize != nil { + bufferSize = *request.GetOptions().StreamBufferSize + } + } + + channel, err := fgaSdk.ExecuteStreamedListObjectsWithBufferSize( + &client.APIClient, + request.GetContext(), + *storeId, + body, + requestOptions, + bufferSize, + ) + + if err != nil { + return nil, err + } + + return &ClientStreamedListObjectsResponse{ + Objects: channel.Objects, + Errors: channel.Errors, + close: channel.Close, + }, nil } diff --git a/client/streaming_test.go b/client/streaming_test.go new file mode 100644 index 0000000..272037f --- /dev/null +++ b/client/streaming_test.go @@ -0,0 +1,329 @@ +/** + * Go 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/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package client + +import ( + "context" + "net/http" + "net/http/httptest" + "strings" + "testing" + + openfga "github.com/openfga/go-sdk" +) + +func TestClientStreamedListObjects_Success(t *testing.T) { + objects := []string{"document:1", "document:2", "document:3"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + storeId := "01ARZ3NDEKTSV4RRFFQ69G5FAV" + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + expectedPath := "/stores/" + storeId + "/streamed-list-objects" + if r.URL.Path != expectedPath { + t.Errorf("Expected path %s, got %s", expectedPath, r.URL.Path) + } + + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config := ClientConfiguration{ + ApiUrl: server.URL, + StoreId: storeId, + } + + client, err := NewSdkClient(&config) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + + ctx := context.Background() + + response, err := client.StreamedListObjects(ctx). + Body(ClientStreamedListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + }). + Execute() + + if err != nil { + t.Fatalf("StreamedListObjects failed: %v", err) + } + + defer response.Close() + + receivedObjects := []string{} + for obj := range response.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-response.Errors; err != nil { + t.Fatalf("Received error from response: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } + + for i, expected := range objects { + if receivedObjects[i] != expected { + t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) + } + } +} + +func TestClientStreamedListObjects_WithOptions(t *testing.T) { + authModelId := "01ARZ3NDEKTSV4RRFFQ69G5FAV" + objects := []string{"document:1"} + responseBody := `{"result":{"object":"document:1"}}` + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config := ClientConfiguration{ + ApiUrl: server.URL, + StoreId: "01ARZ3NDEKTSV4RRFFQ69G5FAV", + } + + client, err := NewSdkClient(&config) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + + ctx := context.Background() + consistency := openfga.CONSISTENCYPREFERENCE_HIGHER_CONSISTENCY + + response, err := client.StreamedListObjects(ctx). + Body(ClientStreamedListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + }). + Options(ClientStreamedListObjectsOptions{ + AuthorizationModelId: &authModelId, + Consistency: &consistency, + }). + Execute() + + if err != nil { + t.Fatalf("StreamedListObjects with options failed: %v", err) + } + + defer response.Close() + + receivedObjects := []string{} + for obj := range response.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } +} + +func TestClientStreamedListObjects_ErrorHandling(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(`{"code":"internal_error","message":"Internal server error"}`)) + })) + defer server.Close() + + config := ClientConfiguration{ + ApiUrl: server.URL, + StoreId: "01ARZ3NDEKTSV4RRFFQ69G5FAV", + } + + client, err := NewSdkClient(&config) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + + ctx := context.Background() + + _, err = client.StreamedListObjects(ctx). + Body(ClientStreamedListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + }). + Execute() + + if err == nil { + t.Fatal("Expected error from StreamedListObjects, got nil") + } +} + +func TestClientStreamedListObjects_NoStoreId(t *testing.T) { + config := ClientConfiguration{ + ApiUrl: "http://localhost:8080", + } + + client, err := NewSdkClient(&config) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + + ctx := context.Background() + + _, err = client.StreamedListObjects(ctx). + Body(ClientStreamedListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + }). + Execute() + + if err == nil { + t.Fatal("Expected error for missing store ID, got nil") + } +} + +func TestClientStreamedListObjects_CustomBufferSize(t *testing.T) { + objects := []string{"document:1", "document:2", "document:3", "document:4", "document:5"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + storeId := "01ARZ3NDEKTSV4RRFFQ69G5FAV" + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config := ClientConfiguration{ + ApiUrl: server.URL, + StoreId: storeId, + } + + client, err := NewSdkClient(&config) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + + ctx := context.Background() + customBufferSize := 50 + + response, err := client.StreamedListObjects(ctx). + Body(ClientStreamedListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + }). + Options(ClientStreamedListObjectsOptions{ + StreamBufferSize: &customBufferSize, + }). + Execute() + + if err != nil { + t.Fatalf("StreamedListObjects with custom buffer size failed: %v", err) + } + + defer response.Close() + + receivedObjects := []string{} + for obj := range response.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-response.Errors; err != nil { + t.Fatalf("Received error from response: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } + + for i, expected := range objects { + if receivedObjects[i] != expected { + t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) + } + } +} + +func TestClientStreamedListObjects_DefaultBufferSize(t *testing.T) { + objects := []string{"document:1", "document:2"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + storeId := "01ARZ3NDEKTSV4RRFFQ69G5FAV" + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config := ClientConfiguration{ + ApiUrl: server.URL, + StoreId: storeId, + } + + client, err := NewSdkClient(&config) + if err != nil { + t.Fatalf("Failed to create client: %v", err) + } + + ctx := context.Background() + zeroBufferSize := 0 + + response, err := client.StreamedListObjects(ctx). + Body(ClientStreamedListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + }). + Options(ClientStreamedListObjectsOptions{ + StreamBufferSize: &zeroBufferSize, + }). + Execute() + + if err != nil { + t.Fatalf("StreamedListObjects with default buffer size failed: %v", err) + } + + defer response.Close() + + receivedObjects := []string{} + for obj := range response.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-response.Errors; err != nil { + t.Fatalf("Received error from response: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } +} diff --git a/docs/OpenFgaApi.md b/docs/OpenFgaApi.md index 60b61e7..16f41f0 100644 --- a/docs/OpenFgaApi.md +++ b/docs/OpenFgaApi.md @@ -18,6 +18,7 @@ Method | HTTP request | Description [**ReadAuthorizationModel**](OpenFgaApi.md#ReadAuthorizationModel) | **Get** /stores/{store_id}/authorization-models/{id} | Return a particular version of an authorization model [**ReadAuthorizationModels**](OpenFgaApi.md#ReadAuthorizationModels) | **Get** /stores/{store_id}/authorization-models | Return all the authorization models for a particular store [**ReadChanges**](OpenFgaApi.md#ReadChanges) | **Get** /stores/{store_id}/changes | Return a list of all the tuple changes +[**StreamedListObjects**](OpenFgaApi.md#StreamedListObjects) | **Post** /stores/{store_id}/streamed-list-objects | Stream all objects of the given type that the user has a relation with [**Write**](OpenFgaApi.md#Write) | **Post** /stores/{store_id}/write | Add or delete tuples from the store [**WriteAssertions**](OpenFgaApi.md#WriteAssertions) | **Put** /stores/{store_id}/assertions/{authorization_model_id} | Upsert assertions for an authorization model ID [**WriteAuthorizationModel**](OpenFgaApi.md#WriteAuthorizationModel) | **Post** /stores/{store_id}/authorization-models | Create a new authorization model @@ -1325,6 +1326,99 @@ No authorization required [[Back to README]](../README.md) +## StreamedListObjects + +> StreamResultOfStreamedListObjectsResponse StreamedListObjects(ctx).Body(body).Execute() + +Stream all objects of the given type that the user has a relation with + + + +### Example + +```go +package main + +import ( + "context" + "fmt" + "os" + openfga "github.com/openfga/go-sdk" +) + +func main() { + + body := *openapiclient.NewListObjectsRequest("document", "reader", "user:anne") // ListObjectsRequest | + + configuration, err := openfga.NewConfiguration(openfga.Configuration{ + ApiUrl: os.Getenv("FGA_API_URL"), // required, e.g. https://api.fga.example + StoreId: os.Getenv("OPENFGA_STORE_ID"), // not needed when calling `CreateStore` or `ListStores` + }) + + if err != nil { + // .. Handle error + } + + apiClient := openfga.NewAPIClient(configuration) + + resp, r, err := apiClient.OpenFgaApi.StreamedListObjects(context.Background()).Body(body).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `OpenFgaApi.StreamedListObjects``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + switch v := err.(type) { + case FgaApiAuthenticationError: + // Handle authentication error + case FgaApiValidationError: + // Handle parameter validation error + case FgaApiNotFoundError: + // Handle not found error + case FgaApiInternalError: + // Handle API internal error + case FgaApiRateLimitError: + // Exponential backoff in handling rate limit error + default: + // Handle unknown/undefined error + } + } + // response from `StreamedListObjects`: StreamResultOfStreamedListObjectsResponse + fmt.Fprintf(os.Stdout, "Response from `OpenFgaApi.StreamedListObjects`: %v\n", resp) +} +``` + +### Path Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. + +### Other Parameters + +Other parameters are passed through a pointer to a apiStreamedListObjectsRequest struct via the builder pattern + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**body** | [**ListObjectsRequest**](ListObjectsRequest.md) | | + +### Return type + +[**StreamResultOfStreamedListObjectsResponse**](StreamResultOfStreamedListObjectsResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +[[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) + + ## Write > map[string]interface{} Write(ctx).Body(body).Execute() diff --git a/docs/StreamResultOfStreamedListObjectsResponse.md b/docs/StreamResultOfStreamedListObjectsResponse.md new file mode 100644 index 0000000..4804b36 --- /dev/null +++ b/docs/StreamResultOfStreamedListObjectsResponse.md @@ -0,0 +1,82 @@ +# StreamResultOfStreamedListObjectsResponse + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Result** | Pointer to [**StreamedListObjectsResponse**](StreamedListObjectsResponse.md) | | [optional] +**Error** | Pointer to [**Status**](Status.md) | | [optional] + +## Methods + +### NewStreamResultOfStreamedListObjectsResponse + +`func NewStreamResultOfStreamedListObjectsResponse() *StreamResultOfStreamedListObjectsResponse` + +NewStreamResultOfStreamedListObjectsResponse instantiates a new StreamResultOfStreamedListObjectsResponse object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewStreamResultOfStreamedListObjectsResponseWithDefaults + +`func NewStreamResultOfStreamedListObjectsResponseWithDefaults() *StreamResultOfStreamedListObjectsResponse` + +NewStreamResultOfStreamedListObjectsResponseWithDefaults instantiates a new StreamResultOfStreamedListObjectsResponse object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetResult + +`func (o *StreamResultOfStreamedListObjectsResponse) GetResult() StreamedListObjectsResponse` + +GetResult returns the Result field if non-nil, zero value otherwise. + +### GetResultOk + +`func (o *StreamResultOfStreamedListObjectsResponse) GetResultOk() (*StreamedListObjectsResponse, bool)` + +GetResultOk returns a tuple with the Result field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetResult + +`func (o *StreamResultOfStreamedListObjectsResponse) SetResult(v StreamedListObjectsResponse)` + +SetResult sets Result field to given value. + +### HasResult + +`func (o *StreamResultOfStreamedListObjectsResponse) HasResult() bool` + +HasResult returns a boolean if a field has been set. + +### GetError + +`func (o *StreamResultOfStreamedListObjectsResponse) GetError() Status` + +GetError returns the Error field if non-nil, zero value otherwise. + +### GetErrorOk + +`func (o *StreamResultOfStreamedListObjectsResponse) GetErrorOk() (*Status, bool)` + +GetErrorOk returns a tuple with the Error field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetError + +`func (o *StreamResultOfStreamedListObjectsResponse) SetError(v Status)` + +SetError sets Error field to given value. + +### HasError + +`func (o *StreamResultOfStreamedListObjectsResponse) HasError() bool` + +HasError returns a boolean if a field has been set. + + +[[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/StreamedListObjectsResponse.md b/docs/StreamedListObjectsResponse.md new file mode 100644 index 0000000..7c5f894 --- /dev/null +++ b/docs/StreamedListObjectsResponse.md @@ -0,0 +1,51 @@ +# StreamedListObjectsResponse + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Object** | **string** | | + +## Methods + +### NewStreamedListObjectsResponse + +`func NewStreamedListObjectsResponse(object string, ) *StreamedListObjectsResponse` + +NewStreamedListObjectsResponse instantiates a new StreamedListObjectsResponse object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewStreamedListObjectsResponseWithDefaults + +`func NewStreamedListObjectsResponseWithDefaults() *StreamedListObjectsResponse` + +NewStreamedListObjectsResponseWithDefaults instantiates a new StreamedListObjectsResponse object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetObject + +`func (o *StreamedListObjectsResponse) GetObject() string` + +GetObject returns the Object field if non-nil, zero value otherwise. + +### GetObjectOk + +`func (o *StreamedListObjectsResponse) GetObjectOk() (*string, bool)` + +GetObjectOk returns a tuple with the Object field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetObject + +`func (o *StreamedListObjectsResponse) SetObject(v string)` + +SetObject sets Object field to given value. + + + +[[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/example/README.md b/example/README.md index f488e5b..97386b0 100644 --- a/example/README.md +++ b/example/README.md @@ -6,6 +6,9 @@ A set of examples on how to call the OpenFGA Go SDK Example 1: A bare bones example. It creates a store, and runs a set of calls against it including creating a model, writing tuples and checking for access. +**StreamedListObjects Example:** +Demonstrates how to use the `StreamedListObjects` API with both synchronous and asynchronous consumption patterns. +Includes support for configurable buffer sizes to optimize throughput vs memory usage. ### Running the Examples diff --git a/example/streamed_list_objects/README.md b/example/streamed_list_objects/README.md new file mode 100644 index 0000000..3e47180 --- /dev/null +++ b/example/streamed_list_objects/README.md @@ -0,0 +1,143 @@ +# StreamedListObjects Example + +This example demonstrates how to use the `StreamedListObjects` API in the OpenFGA Go SDK in both: +- Synchronous mode (range over the channel) +- Asynchronous mode (consume in a goroutine) + +It creates (if not provided) a temporary store and authorization model, writes mock tuples, streams objects, and optionally cleans up. + +## Prerequisites + +1. An OpenFGA server running (default: `http://localhost:8080`) +2. (Optional) Existing store and authorization model IDs + +## Environment Variables + +- `FGA_API_URL` (default: `http://localhost:8080`) +- `FGA_STORE_ID` (optional; if absent a new store is created and later deleted) +- `FGA_MODEL_ID` (optional; if absent a simple model is created) +- `FGA_TUPLE_COUNT` (optional; number of tuples to write; overridden by CLI arg if passed) +- `FGA_RELATION` (optional; relation used when writing and listing; must be `viewer` or `owner`; overridden by CLI arg if passed) +- `FGA_BUFFER_SIZE` (optional; buffer size for streaming channel; defaults to 10 if not set; overridden by CLI arg if passed) + +## CLI Arguments + +``` +go run . [mode] [tupleCount] [relation] [bufferSize] +``` + +- `mode`: `sync` (default) or `async` +- `tupleCount`: positive integer (default: 3 if omitted and env var not set) +- `relation`: `viewer` or `owner` (default: `viewer`) +- `bufferSize`: positive integer (optional; sets the streaming channel buffer size; defaults to 10) + +Examples: + +```bash +# Basic sync (defaults to 3 tuples, relation viewer) +go run . + +# Explicit sync, 10 tuples, relation owner +go run . sync 10 owner + +# Async mode with 50 tuples and viewer relation +go run . async 50 viewer + +# Sync mode with custom buffer size of 100 +go run . sync 10 viewer 100 + +# Using environment variables (relation owner, 25 tuples, buffer size 50) +export FGA_TUPLE_COUNT=25 +export FGA_RELATION=owner +export FGA_BUFFER_SIZE=50 +go run . async +``` + +## Buffer Size Configuration + +The `bufferSize` parameter (4th CLI argument or `FGA_BUFFER_SIZE` env var) controls the size of the internal channel buffer used for streaming responses: + +- **Larger buffers** (e.g., 100+) improve throughput for high-volume streams but use more memory +- **Smaller buffers** (e.g., 1-10) reduce memory usage but may decrease throughput +- **Default value** is 10, providing a balanced approach for most use cases + +Example with large buffer for high-volume streaming: +```bash +go run . async 1000 viewer 200 +``` + +## What Happens Internally + +1. Store creation (if `FGA_STORE_ID` not provided) +2. Authorization model creation (if `FGA_MODEL_ID` not provided) with `viewer` and `owner` relations +3. Tuple writes: `user:anne` assigned chosen relation for `document:0 .. document:N-1` +4. Streaming request (`StreamedListObjects`) for the chosen relation +5. Consumption pattern: + - Sync: range directly over `response.Objects` + - Async: consume in a goroutine while main goroutine reports progress +6. Final error check via `response.Errors` +7. Temporary store deletion (only if the example created it) + +## Expected Output (Sync Mode Example) + +``` +OpenFGA StreamedListObjects Example +==================================== +API URL: http://localhost:8080 +Store ID: 01ARZ3NDEKTSV4RRFFQ69G5FAV + +Creating authorization model... +Created authorization model: 01ARZ3NDEKTSV4RRFFQ69G5FAX + +Writing 3 test tuples for relation 'viewer'... +Wrote 3 test tuples + +Selected mode: sync | relation: viewer | tuple count: 3 (pass 'sync|async [count] [relation] [bufferSize]') +Mode: sync streaming (range over channel) +Streaming objects (sync): + 1. document:0 + 2. document:1 + 3. document:2 + +Total objects received (sync): 3 (expected up to 3) + +Deleting temporary store... +Deleted temporary store (01ARZ3NDEKTSV4RRFFQ69G5FAV) + +Done. +``` + +## Expected Output (Async Mode with Custom Buffer Size) + +``` +OpenFGA StreamedListObjects Example +==================================== +API URL: http://localhost:8080 +Store ID: 01ARZ3NDEKTSV4RRFFQ69G5FAV + +Creating authorization model... +Created authorization model: 01ARZ3NDEKTSV4RRFFQ69G5FAX + +Writing 5 test tuples for relation 'owner'... +Wrote 5 test tuples + +Selected mode: async | relation: owner | tuple count: 5 | buffer size: 50 (pass 'sync|async [count] [relation] [bufferSize]') +Mode: async streaming (consume in goroutine) +Using custom buffer size: 50 +Performing other work while streaming... + (main goroutine still free to do work) + async -> 1. document:0 + (main goroutine still free to do work) + async -> 2. document:1 + async -> 3. document:2 + (main goroutine still free to do work) + async -> 4. document:3 + async -> 5. document:4 + +Total objects received (async): 5 (expected up to 5) + +Deleting temporary store... +Deleted temporary store (01ARZ3NDEKTSV4RRFFQ69G5FAV) + +Done. +``` diff --git a/example/streamed_list_objects/go.mod b/example/streamed_list_objects/go.mod new file mode 100644 index 0000000..919206d --- /dev/null +++ b/example/streamed_list_objects/go.mod @@ -0,0 +1,20 @@ +module streamed_list_objects + +go 1.25.1 + +require github.com/openfga/go-sdk v0.7.3 + +require ( + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/sync v0.17.0 // indirect +) + +replace github.com/openfga/go-sdk => ../.. // added this to point to local module diff --git a/example/streamed_list_objects/main.go b/example/streamed_list_objects/main.go new file mode 100644 index 0000000..52a858f --- /dev/null +++ b/example/streamed_list_objects/main.go @@ -0,0 +1,255 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "strconv" + "time" + + openfga "github.com/openfga/go-sdk" + "github.com/openfga/go-sdk/client" +) + +func runSync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { + fmt.Println("Mode: sync streaming (range over channel)") + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + fmt.Println("Streaming objects (sync):") + received := 0 + for obj := range response.Objects { // synchronous consumption + received++ + fmt.Printf(" %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil { + log.Fatalf("Error during streaming: %v", err) + } + fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) +} + +// runAsync demonstrates asynchronous consumption using a goroutine; main goroutine can do other work. +func runAsync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { + fmt.Println("Mode: async streaming (consume in goroutine)") + // Use a cancellable context to show cancellation pattern (not cancelling in this example). + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + done := make(chan struct{}) + received := 0 + + go func() { + defer close(done) + for obj := range response.Objects { + received++ + fmt.Printf(" async -> %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil && err != context.Canceled { + log.Fatalf("Error during async streaming: %v", err) + } + }() + + // Simulate doing other work while streaming happens. + ticker := time.NewTicker(200 * time.Millisecond) + defer ticker.Stop() + + fmt.Println("Performing other work while streaming...") + for { + select { + case <-done: + fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) + return + case <-ticker.C: + fmt.Println(" (main goroutine still free to do work)") + } + } +} + +func createTestData(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, tupleCount int) (string, error) { + // Ensure relation is either viewer or owner for this simplified example. + if relation != "viewer" && relation != "owner" { + return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) + } + + if authModelId == "" { + fmt.Println("Creating authorization model...") + + // Provide both viewer and owner relations so user can pick. + relations := map[string]openfga.Userset{ + "viewer": {This: &map[string]interface{}{}}, + "owner": {This: &map[string]interface{}{}}, + } + + relationMetadata := map[string]openfga.RelationMetadata{ + "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + } + + model := openfga.AuthorizationModel{ + SchemaVersion: "1.1", + TypeDefinitions: []openfga.TypeDefinition{ + {Type: "user"}, + {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, + }, + } + + writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ + SchemaVersion: model.SchemaVersion, + TypeDefinitions: model.TypeDefinitions, + }).Execute() + if err != nil { + return authModelId, fmt.Errorf("failed to create authorization model: %w", err) + } + authModelId = writeModelResp.AuthorizationModelId + fmt.Printf("Created authorization model: %s\n\n", authModelId) + } + + fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) + tuples := make([]client.ClientTupleKey, 0, tupleCount) + for i := 0; i < tupleCount; i++ { + tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) + } + if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { + return authModelId, fmt.Errorf("failed to write tuples: %w", err) + } + fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) + return authModelId, nil +} + +func parseArgs() (mode string, count int, relation string, bufferSize *int) { + mode = "sync" // default + relation = "viewer" + count = 3 + if len(os.Args) > 1 { + mode = os.Args[1] + } + if len(os.Args) > 2 { + if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { + count = c + } + } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { + if c, err := strconv.Atoi(envCount); err == nil && c > 0 { + count = c + } + } + if len(os.Args) > 3 { + relation = os.Args[3] + } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { + relation = envRel + } + if len(os.Args) > 4 { + if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { + bufferSize = &b + } + } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { + if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { + bufferSize = &b + } + } + return +} + +func main() { + ctx := context.Background() + apiUrl := os.Getenv("FGA_API_URL") + if apiUrl == "" { + apiUrl = "http://localhost:8080" + } + config := client.ClientConfiguration{ApiUrl: apiUrl} + fgaClient, err := client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + // Create store unless provided via env var. + storeId := os.Getenv("FGA_STORE_ID") + createdTempStore := false + if storeId == "" { + fmt.Println("Creating Test Store for streamed list objects") + store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() + if err != nil { + panic(err) + } + storeId = store.Id + createdTempStore = true + } + + // Re-init client with storeId + config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} + fgaClient, err = client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + fmt.Println("OpenFGA StreamedListObjects Example") + fmt.Println("____________________________________") + fmt.Printf("API URL: %s\n", apiUrl) + fmt.Printf("Store ID: %s\n", storeId) + fmt.Println() + + authModelId := os.Getenv("FGA_MODEL_ID") + mode, tupleCount, relation, bufferSize := parseArgs() + if authModelId != "" { + fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) + } + authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) + if err != nil { + log.Printf("Warning: Failed to create test data: %v", err) + log.Println("Continuing with example...") + } + + fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) + if bufferSize != nil { + fmt.Printf(" | buffer size: %d", *bufferSize) + } + fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") + + switch mode { + case "async": + runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + case "sync": + runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + default: + fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) + os.Exit(1) + } + + if createdTempStore { + fmt.Println("\nDeleting temporary store...") + if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { + fmt.Printf("Failed to delete store: %v\n", err) + } else { + fmt.Printf("Deleted temporary store (%s)\n", storeId) + } + } + fmt.Println("\nDone.") +} diff --git a/model_stream_result_of_streamed_list_objects_response.go b/model_stream_result_of_streamed_list_objects_response.go new file mode 100644 index 0000000..cc7ef37 --- /dev/null +++ b/model_stream_result_of_streamed_list_objects_response.go @@ -0,0 +1,160 @@ +/** + * Go 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/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package openfga + +import ( + "bytes" + + "encoding/json" +) + +// StreamResultOfStreamedListObjectsResponse struct for StreamResultOfStreamedListObjectsResponse +type StreamResultOfStreamedListObjectsResponse struct { + Result *StreamedListObjectsResponse `json:"result,omitempty" yaml:"result,omitempty"` + Error *Status `json:"error,omitempty" yaml:"error,omitempty"` +} + +// NewStreamResultOfStreamedListObjectsResponse instantiates a new StreamResultOfStreamedListObjectsResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStreamResultOfStreamedListObjectsResponse() *StreamResultOfStreamedListObjectsResponse { + this := StreamResultOfStreamedListObjectsResponse{} + return &this +} + +// NewStreamResultOfStreamedListObjectsResponseWithDefaults instantiates a new StreamResultOfStreamedListObjectsResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStreamResultOfStreamedListObjectsResponseWithDefaults() *StreamResultOfStreamedListObjectsResponse { + this := StreamResultOfStreamedListObjectsResponse{} + return &this +} + +// GetResult returns the Result field value if set, zero value otherwise. +func (o *StreamResultOfStreamedListObjectsResponse) GetResult() StreamedListObjectsResponse { + if o == nil || o.Result == nil { + var ret StreamedListObjectsResponse + return ret + } + return *o.Result +} + +// GetResultOk returns a tuple with the Result field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StreamResultOfStreamedListObjectsResponse) GetResultOk() (*StreamedListObjectsResponse, bool) { + if o == nil || o.Result == nil { + return nil, false + } + return o.Result, true +} + +// HasResult returns a boolean if a field has been set. +func (o *StreamResultOfStreamedListObjectsResponse) HasResult() bool { + if o != nil && o.Result != nil { + return true + } + + return false +} + +// SetResult gets a reference to the given StreamedListObjectsResponse and assigns it to the Result field. +func (o *StreamResultOfStreamedListObjectsResponse) SetResult(v StreamedListObjectsResponse) { + o.Result = &v +} + +// GetError returns the Error field value if set, zero value otherwise. +func (o *StreamResultOfStreamedListObjectsResponse) GetError() Status { + if o == nil || o.Error == nil { + var ret Status + return ret + } + return *o.Error +} + +// GetErrorOk returns a tuple with the Error field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *StreamResultOfStreamedListObjectsResponse) GetErrorOk() (*Status, bool) { + if o == nil || o.Error == nil { + return nil, false + } + return o.Error, true +} + +// HasError returns a boolean if a field has been set. +func (o *StreamResultOfStreamedListObjectsResponse) HasError() bool { + if o != nil && o.Error != nil { + return true + } + + return false +} + +// SetError gets a reference to the given Status and assigns it to the Error field. +func (o *StreamResultOfStreamedListObjectsResponse) SetError(v Status) { + o.Error = &v +} + +func (o StreamResultOfStreamedListObjectsResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Result != nil { + toSerialize["result"] = o.Result + } + if o.Error != nil { + toSerialize["error"] = o.Error + } + var b bytes.Buffer + enc := json.NewEncoder(&b) + enc.SetEscapeHTML(false) + err := enc.Encode(toSerialize) + if err != nil { + return nil, err + } + return b.Bytes(), nil +} + +type NullableStreamResultOfStreamedListObjectsResponse struct { + value *StreamResultOfStreamedListObjectsResponse + isSet bool +} + +func (v NullableStreamResultOfStreamedListObjectsResponse) Get() *StreamResultOfStreamedListObjectsResponse { + return v.value +} + +func (v *NullableStreamResultOfStreamedListObjectsResponse) Set(val *StreamResultOfStreamedListObjectsResponse) { + v.value = val + v.isSet = true +} + +func (v NullableStreamResultOfStreamedListObjectsResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableStreamResultOfStreamedListObjectsResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStreamResultOfStreamedListObjectsResponse(val *StreamResultOfStreamedListObjectsResponse) *NullableStreamResultOfStreamedListObjectsResponse { + return &NullableStreamResultOfStreamedListObjectsResponse{value: val, isSet: true} +} + +func (v NullableStreamResultOfStreamedListObjectsResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStreamResultOfStreamedListObjectsResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/model_streamed_list_objects_response.go b/model_streamed_list_objects_response.go new file mode 100644 index 0000000..c32820e --- /dev/null +++ b/model_streamed_list_objects_response.go @@ -0,0 +1,115 @@ +/** + * Go 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/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package openfga + +import ( + "bytes" + + "encoding/json" +) + +// StreamedListObjectsResponse The response for a StreamedListObjects RPC. +type StreamedListObjectsResponse struct { + Object string `json:"object" yaml:"object"` +} + +// NewStreamedListObjectsResponse instantiates a new StreamedListObjectsResponse object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewStreamedListObjectsResponse(object string) *StreamedListObjectsResponse { + this := StreamedListObjectsResponse{} + this.Object = object + return &this +} + +// NewStreamedListObjectsResponseWithDefaults instantiates a new StreamedListObjectsResponse object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewStreamedListObjectsResponseWithDefaults() *StreamedListObjectsResponse { + this := StreamedListObjectsResponse{} + return &this +} + +// GetObject returns the Object field value +func (o *StreamedListObjectsResponse) GetObject() string { + if o == nil { + var ret string + return ret + } + + return o.Object +} + +// GetObjectOk returns a tuple with the Object field value +// and a boolean to check if the value has been set. +func (o *StreamedListObjectsResponse) GetObjectOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Object, true +} + +// SetObject sets field value +func (o *StreamedListObjectsResponse) SetObject(v string) { + o.Object = v +} + +func (o StreamedListObjectsResponse) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + toSerialize["object"] = o.Object + var b bytes.Buffer + enc := json.NewEncoder(&b) + enc.SetEscapeHTML(false) + err := enc.Encode(toSerialize) + if err != nil { + return nil, err + } + return b.Bytes(), nil +} + +type NullableStreamedListObjectsResponse struct { + value *StreamedListObjectsResponse + isSet bool +} + +func (v NullableStreamedListObjectsResponse) Get() *StreamedListObjectsResponse { + return v.value +} + +func (v *NullableStreamedListObjectsResponse) Set(val *StreamedListObjectsResponse) { + v.value = val + v.isSet = true +} + +func (v NullableStreamedListObjectsResponse) IsSet() bool { + return v.isSet +} + +func (v *NullableStreamedListObjectsResponse) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableStreamedListObjectsResponse(val *StreamedListObjectsResponse) *NullableStreamedListObjectsResponse { + return &NullableStreamedListObjectsResponse{value: val, isSet: true} +} + +func (v NullableStreamedListObjectsResponse) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableStreamedListObjectsResponse) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/streaming.go b/streaming.go new file mode 100644 index 0000000..864e73f --- /dev/null +++ b/streaming.go @@ -0,0 +1,153 @@ +/** + * Go 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/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package openfga + +import ( + "bufio" + "context" + "encoding/json" + "errors" + "io" + "net/http" + "net/url" + "strings" +) + +type StreamedListObjectsChannel struct { + Objects chan StreamedListObjectsResponse + Errors chan error + cancel context.CancelFunc +} + +func (s *StreamedListObjectsChannel) Close() { + if s.cancel != nil { + s.cancel() + } +} + +func ProcessStreamedListObjectsResponse(ctx context.Context, httpResponse *http.Response, bufferSize int) (*StreamedListObjectsChannel, error) { + streamCtx, cancel := context.WithCancel(ctx) + + // Use default buffer size of 10 if not specified or invalid + if bufferSize <= 0 { + bufferSize = 10 + } + + channel := &StreamedListObjectsChannel{ + Objects: make(chan StreamedListObjectsResponse, bufferSize), + Errors: make(chan error, 1), + cancel: cancel, + } + + if httpResponse == nil || httpResponse.Body == nil { + cancel() + return nil, errors.New("response or response body is nil") + } + + go func() { + defer close(channel.Objects) + defer close(channel.Errors) + defer cancel() + defer httpResponse.Body.Close() + + scanner := bufio.NewScanner(httpResponse.Body) + for scanner.Scan() { + select { + case <-streamCtx.Done(): + channel.Errors <- streamCtx.Err() + return + default: + line := scanner.Bytes() + if len(line) == 0 { + continue + } + + var streamResult StreamResultOfStreamedListObjectsResponse + if err := json.Unmarshal(line, &streamResult); err != nil { + channel.Errors <- err + return + } + + if streamResult.Error != nil { + msg := "stream error" + if streamResult.Error.Message != nil { + msg = *streamResult.Error.Message + } + channel.Errors <- errors.New(msg) + return + } + + if streamResult.Result != nil { + select { + case <-streamCtx.Done(): + channel.Errors <- streamCtx.Err() + return + case channel.Objects <- *streamResult.Result: + } + } + } + } + + if err := scanner.Err(); err != nil { + channel.Errors <- err + } + }() + + return channel, nil +} + +func ExecuteStreamedListObjects(client *APIClient, ctx context.Context, storeId string, body ListObjectsRequest, options RequestOptions) (*StreamedListObjectsChannel, error) { + return ExecuteStreamedListObjectsWithBufferSize(client, ctx, storeId, body, options, 0) +} + +func ExecuteStreamedListObjectsWithBufferSize(client *APIClient, ctx context.Context, storeId string, body ListObjectsRequest, options RequestOptions, bufferSize int) (*StreamedListObjectsChannel, error) { + path := "/stores/{store_id}/streamed-list-objects" + if storeId == "" { + return nil, reportError("storeId is required and must be specified") + } + + path = strings.ReplaceAll(path, "{"+"store_id"+"}", url.PathEscape(parameterToString(storeId, ""))) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + + localVarHTTPContentType := "application/json" + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + localVarHeaderParams["Accept"] = "application/x-ndjson" + + for header, val := range options.Headers { + localVarHeaderParams[header] = val + } + + req, err := client.prepareRequest(ctx, path, http.MethodPost, body, localVarHeaderParams, localVarQueryParams) + if err != nil { + return nil, err + } + + httpResponse, err := client.callAPI(req) + if err != nil || httpResponse == nil { + return nil, err + } + + if httpResponse.StatusCode >= http.StatusMultipleChoices { + responseBody, readErr := io.ReadAll(httpResponse.Body) + _ = httpResponse.Body.Close() + if readErr != nil { + return nil, readErr + } + err = client.handleAPIError(httpResponse, responseBody, body, "StreamedListObjects", storeId) + return nil, err + } + + return ProcessStreamedListObjectsResponse(ctx, httpResponse, bufferSize) +} diff --git a/streaming_test.go b/streaming_test.go new file mode 100644 index 0000000..b241c17 --- /dev/null +++ b/streaming_test.go @@ -0,0 +1,493 @@ +/** + * Go 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/go-sdk/blob/main/LICENSE) + * + * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. + */ + +package openfga + +import ( + "context" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "testing" + "time" +) + +func TestStreamedListObjectsChannel_Close(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + channel := &StreamedListObjectsChannel{ + Objects: make(chan StreamedListObjectsResponse), + Errors: make(chan error), + cancel: cancel, + } + + channel.Close() + + select { + case <-ctx.Done(): + case <-time.After(100 * time.Millisecond): + t.Error("Context was not cancelled") + } +} + +func TestStreamedListObjectsWithChannel_Success(t *testing.T) { + objects := []string{"document:1", "document:2", "document:3"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/stores/test-store/streamed-list-objects" { + t.Errorf("Expected path /stores/test-store/streamed-list-objects, got %s", r.URL.Path) + } + if r.Method != http.MethodPost { + t.Errorf("Expected POST method, got %s", r.Method) + } + + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } + + for i, expected := range objects { + if receivedObjects[i] != expected { + t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) + } + } +} + +func TestStreamedListObjectsWithChannel_EmptyLines(t *testing.T) { + responseBody := `{"result":{"object":"document:1"}} + +{"result":{"object":"document:2"}} + +{"result":{"object":"document:3"}}` + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if len(receivedObjects) != 3 { + t.Fatalf("Expected 3 objects, got %d", len(receivedObjects)) + } +} + +func TestStreamedListObjectsWithChannel_ErrorInStream(t *testing.T) { + responseBody := `{"result":{"object":"document:1"}} +{"error":{"code":500,"message":"Internal error"}}` + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + err = <-channel.Errors + if err == nil { + t.Fatal("Expected error from channel, got nil") + } + + if !strings.Contains(err.Error(), "Internal error") { + t.Errorf("Expected error message to contain 'Internal error', got %s", err.Error()) + } + + if len(receivedObjects) != 1 { + t.Fatalf("Expected 1 object before error, got %d", len(receivedObjects)) + } +} + +func TestStreamedListObjectsWithChannel_InvalidJSON(t *testing.T) { + responseBody := `{"result":{"object":"document:1"}} +invalid json` + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + err = <-channel.Errors + if err == nil { + t.Fatal("Expected error from channel for invalid JSON, got nil") + } + + if len(receivedObjects) != 1 { + t.Fatalf("Expected 1 object before error, got %d", len(receivedObjects)) + } +} + +func TestStreamedListObjectsWithChannel_ContextCancellation(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + for i := 0; i < 100; i++ { + w.Write([]byte(`{"result":{"object":"document:` + strconv.Itoa(i) + `"}}` + "\n")) + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + time.Sleep(10 * time.Millisecond) + } + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx, cancel := context.WithCancel(context.Background()) + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for i := 0; i < 5; i++ { + obj := <-channel.Objects + receivedObjects = append(receivedObjects, obj.Object) + } + + cancel() + + time.Sleep(100 * time.Millisecond) + + remaining := 0 + for range channel.Objects { + remaining++ + } + + if len(receivedObjects) < 5 { + t.Fatalf("Expected at least 5 objects, got %d", len(receivedObjects)) + } +} + +func TestStreamedListObjectsWithChannel_CustomBufferSize(t *testing.T) { + objects := []string{"document:1", "document:2", "document:3", "document:4", "document:5"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + // Test with custom buffer size using the new function + channel, err := ExecuteStreamedListObjectsWithBufferSize(client, ctx, "test-store", request, RequestOptions{}, 50) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } + + for i, expected := range objects { + if receivedObjects[i] != expected { + t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) + } + } +} + +func TestStreamedListObjectsWithChannel_DefaultBufferSize(t *testing.T) { + objects := []string{"document:1", "document:2"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + // Test with default buffer size (0 uses default of 10) + channel, err := ExecuteStreamedListObjectsWithBufferSize(client, ctx, "test-store", request, RequestOptions{}, 0) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } +} + +func TestStreamedListObjectsWithChannel_ProperNumericStrings(t *testing.T) { + // Test that document IDs are generated correctly for values >= 10 + // This verifies the fix: using strconv.Itoa(i) instead of string(rune('0'+i%10)) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + // Generate 15 objects to ensure we test values >= 10 + for i := 0; i < 15; i++ { + w.Write([]byte(`{"result":{"object":"document:` + strconv.Itoa(i) + `"}}` + "\n")) + } + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + expectedObjects := []string{ + "document:0", "document:1", "document:2", "document:3", "document:4", + "document:5", "document:6", "document:7", "document:8", "document:9", + "document:10", "document:11", "document:12", "document:13", "document:14", + } + + if len(receivedObjects) != len(expectedObjects) { + t.Fatalf("Expected %d objects, got %d", len(expectedObjects), len(receivedObjects)) + } + + for i, expected := range expectedObjects { + if receivedObjects[i] != expected { + t.Errorf("At index %d: expected %s, got %s", i, expected, receivedObjects[i]) + } + } +} From 64b9fd5b1526a005407bed2aa33e1932297e58fd Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Tue, 28 Oct 2025 21:06:45 +0530 Subject: [PATCH 2/9] feat: apply coderabbit suggestion for buffer size --- streaming.go | 252 ++++++++++++++++++++++++++------------------------- 1 file changed, 130 insertions(+), 122 deletions(-) diff --git a/streaming.go b/streaming.go index 864e73f..c23f370 100644 --- a/streaming.go +++ b/streaming.go @@ -13,141 +13,149 @@ package openfga import ( - "bufio" - "context" - "encoding/json" - "errors" - "io" - "net/http" - "net/url" - "strings" + "bufio" + "context" + "encoding/json" + "errors" + "io" + "net/http" + "net/url" + "strings" ) type StreamedListObjectsChannel struct { - Objects chan StreamedListObjectsResponse - Errors chan error - cancel context.CancelFunc + Objects chan StreamedListObjectsResponse + Errors chan error + cancel context.CancelFunc } func (s *StreamedListObjectsChannel) Close() { - if s.cancel != nil { - s.cancel() - } + if s.cancel != nil { + s.cancel() + } } func ProcessStreamedListObjectsResponse(ctx context.Context, httpResponse *http.Response, bufferSize int) (*StreamedListObjectsChannel, error) { - streamCtx, cancel := context.WithCancel(ctx) - - // Use default buffer size of 10 if not specified or invalid - if bufferSize <= 0 { - bufferSize = 10 - } - - channel := &StreamedListObjectsChannel{ - Objects: make(chan StreamedListObjectsResponse, bufferSize), - Errors: make(chan error, 1), - cancel: cancel, - } - - if httpResponse == nil || httpResponse.Body == nil { - cancel() - return nil, errors.New("response or response body is nil") - } - - go func() { - defer close(channel.Objects) - defer close(channel.Errors) - defer cancel() - defer httpResponse.Body.Close() - - scanner := bufio.NewScanner(httpResponse.Body) - for scanner.Scan() { - select { - case <-streamCtx.Done(): - channel.Errors <- streamCtx.Err() - return - default: - line := scanner.Bytes() - if len(line) == 0 { - continue - } - - var streamResult StreamResultOfStreamedListObjectsResponse - if err := json.Unmarshal(line, &streamResult); err != nil { - channel.Errors <- err - return - } - - if streamResult.Error != nil { - msg := "stream error" - if streamResult.Error.Message != nil { - msg = *streamResult.Error.Message - } - channel.Errors <- errors.New(msg) - return - } - - if streamResult.Result != nil { - select { - case <-streamCtx.Done(): - channel.Errors <- streamCtx.Err() - return - case channel.Objects <- *streamResult.Result: - } - } - } - } - - if err := scanner.Err(); err != nil { - channel.Errors <- err - } - }() - - return channel, nil + streamCtx, cancel := context.WithCancel(ctx) + + // Use default buffer size of 10 if not specified or invalid + if bufferSize <= 0 { + bufferSize = 10 + } + + channel := &StreamedListObjectsChannel{ + Objects: make(chan StreamedListObjectsResponse, bufferSize), + Errors: make(chan error, 1), + cancel: cancel, + } + + if httpResponse == nil || httpResponse.Body == nil { + cancel() + return nil, errors.New("response or response body is nil") + } + + go func() { + defer close(channel.Objects) + defer close(channel.Errors) + defer cancel() + defer httpResponse.Body.Close() + + scanner := bufio.NewScanner(httpResponse.Body) + // Allow large NDJSON entries (up to 10MB). Tune as needed. + buf := make([]byte, 0, 64*1024) + scanner.Buffer(buf, 10*1024*1024) + for scanner.Scan() { + select { + case <-streamCtx.Done(): + channel.Errors <- streamCtx.Err() + return + default: + line := scanner.Bytes() + if len(line) == 0 { + continue + } + + var streamResult StreamResultOfStreamedListObjectsResponse + if err := json.Unmarshal(line, &streamResult); err != nil { + channel.Errors <- err + return + } + + if streamResult.Error != nil { + msg := "stream error" + if streamResult.Error.Message != nil { + msg = *streamResult.Error.Message + } + channel.Errors <- errors.New(msg) + return + } + + if streamResult.Result != nil { + select { + case <-streamCtx.Done(): + channel.Errors <- streamCtx.Err() + return + case channel.Objects <- *streamResult.Result: + } + } + } + } + + if err := scanner.Err(); err != nil { + // Prefer context error if we were canceled to avoid surfacing net/http "use of closed network connection". + if streamCtx.Err() != nil { + channel.Errors <- streamCtx.Err() + return + } + channel.Errors <- err + } + }() + + return channel, nil } func ExecuteStreamedListObjects(client *APIClient, ctx context.Context, storeId string, body ListObjectsRequest, options RequestOptions) (*StreamedListObjectsChannel, error) { - return ExecuteStreamedListObjectsWithBufferSize(client, ctx, storeId, body, options, 0) + return ExecuteStreamedListObjectsWithBufferSize(client, ctx, storeId, body, options, 0) } func ExecuteStreamedListObjectsWithBufferSize(client *APIClient, ctx context.Context, storeId string, body ListObjectsRequest, options RequestOptions, bufferSize int) (*StreamedListObjectsChannel, error) { - path := "/stores/{store_id}/streamed-list-objects" - if storeId == "" { - return nil, reportError("storeId is required and must be specified") - } - - path = strings.ReplaceAll(path, "{"+"store_id"+"}", url.PathEscape(parameterToString(storeId, ""))) - - localVarHeaderParams := make(map[string]string) - localVarQueryParams := url.Values{} - - localVarHTTPContentType := "application/json" - localVarHeaderParams["Content-Type"] = localVarHTTPContentType - localVarHeaderParams["Accept"] = "application/x-ndjson" - - for header, val := range options.Headers { - localVarHeaderParams[header] = val - } - - req, err := client.prepareRequest(ctx, path, http.MethodPost, body, localVarHeaderParams, localVarQueryParams) - if err != nil { - return nil, err - } - - httpResponse, err := client.callAPI(req) - if err != nil || httpResponse == nil { - return nil, err - } - - if httpResponse.StatusCode >= http.StatusMultipleChoices { - responseBody, readErr := io.ReadAll(httpResponse.Body) - _ = httpResponse.Body.Close() - if readErr != nil { - return nil, readErr - } - err = client.handleAPIError(httpResponse, responseBody, body, "StreamedListObjects", storeId) - return nil, err - } - - return ProcessStreamedListObjectsResponse(ctx, httpResponse, bufferSize) + path := "/stores/{store_id}/streamed-list-objects" + if storeId == "" { + return nil, reportError("storeId is required and must be specified") + } + + path = strings.ReplaceAll(path, "{"+"store_id"+"}", url.PathEscape(parameterToString(storeId, ""))) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + + localVarHTTPContentType := "application/json" + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + localVarHeaderParams["Accept"] = "application/x-ndjson" + + for header, val := range options.Headers { + localVarHeaderParams[header] = val + } + + req, err := client.prepareRequest(ctx, path, http.MethodPost, body, localVarHeaderParams, localVarQueryParams) + if err != nil { + return nil, err + } + + httpResponse, err := client.callAPI(req) + if err != nil || httpResponse == nil { + return nil, err + } + + if httpResponse.StatusCode >= http.StatusMultipleChoices { + responseBody, readErr := io.ReadAll(httpResponse.Body) + _ = httpResponse.Body.Close() + if readErr != nil { + return nil, readErr + } + err = client.handleAPIError(httpResponse, responseBody, body, "StreamedListObjects", storeId) + return nil, err + } + + return ProcessStreamedListObjectsResponse(ctx, httpResponse, bufferSize) } From c87b904b0c22727b3b8dd75949def109f500ac81 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Wed, 29 Oct 2025 22:42:45 +0530 Subject: [PATCH 3/9] feat: gofmt --- api_open_fga.go | 1338 ++++---- client/client.go | 4486 ++++++++++++------------- example/streamed_list_objects/main.go | 470 +-- streaming.go | 260 +- streaming_test.go | 882 ++--- 5 files changed, 3718 insertions(+), 3718 deletions(-) diff --git a/api_open_fga.go b/api_open_fga.go index 045765f..d2f17f2 100644 --- a/api_open_fga.go +++ b/api_open_fga.go @@ -39,62 +39,62 @@ type RequestOptions struct { type OpenFgaApi interface { /* - * BatchCheck Send a list of `check` operations in a single request - * The `BatchCheck` API functions nearly identically to `Check`, but instead of checking a single user-object relationship BatchCheck accepts a list of relationships to check and returns a map containing `BatchCheckItem` response for each check it received. - - An associated `correlation_id` is required for each check in the batch. This ID is used to correlate a check to the appropriate response. It is a string consisting of only alphanumeric characters or hyphens with a maximum length of 36 characters. This `correlation_id` is used to map the result of each check to the item which was checked, so it must be unique for each item in the batch. We recommend using a UUID or ULID as the `correlation_id`, but you can use whatever unique identifier you need as long as it matches this regex pattern: `^[\w\d-]{1,36}$` - - NOTE: The maximum number of checks that can be passed in the `BatchCheck` API is configurable via the [OPENFGA_MAX_CHECKS_PER_BATCH_CHECK](https://openfga.dev/docs/getting-started/setup-openfga/configuration#OPENFGA_MAX_CHECKS_PER_BATCH_CHECK) environment variable. If `BatchCheck` is called using the SDK, the SDK can split the batch check requests for you. - - For more details on how `Check` functions, see the docs for `/check`. - - ### Examples - #### A BatchCheckRequest - ```json - { - "checks": [ - { - "tuple_key": { - "object": "document:2021-budget" - "relation": "reader", - "user": "user:anne", - }, - "contextual_tuples": {...} - "context": {} - "correlation_id": "01JA8PM3QM7VBPGB8KMPK8SBD5" - }, - { - "tuple_key": { - "object": "document:2021-budget" - "relation": "reader", - "user": "user:bob", - }, - "contextual_tuples": {...} - "context": {} - "correlation_id": "01JA8PMM6A90NV5ET0F28CYSZQ" - } - ] - } - ``` - - Below is a possible response to the above request. Note that the result map's keys are the `correlation_id` values from the checked items in the request: - ```json - { - "result": { - "01JA8PMM6A90NV5ET0F28CYSZQ": { - "allowed": false, - "error": {"message": ""} - }, - "01JA8PM3QM7VBPGB8KMPK8SBD5": { - "allowed": true, - "error": {"message": ""} - } - } - ``` + * BatchCheck Send a list of `check` operations in a single request + * The `BatchCheck` API functions nearly identically to `Check`, but instead of checking a single user-object relationship BatchCheck accepts a list of relationships to check and returns a map containing `BatchCheckItem` response for each check it received. + + An associated `correlation_id` is required for each check in the batch. This ID is used to correlate a check to the appropriate response. It is a string consisting of only alphanumeric characters or hyphens with a maximum length of 36 characters. This `correlation_id` is used to map the result of each check to the item which was checked, so it must be unique for each item in the batch. We recommend using a UUID or ULID as the `correlation_id`, but you can use whatever unique identifier you need as long as it matches this regex pattern: `^[\w\d-]{1,36}$` + + NOTE: The maximum number of checks that can be passed in the `BatchCheck` API is configurable via the [OPENFGA_MAX_CHECKS_PER_BATCH_CHECK](https://openfga.dev/docs/getting-started/setup-openfga/configuration#OPENFGA_MAX_CHECKS_PER_BATCH_CHECK) environment variable. If `BatchCheck` is called using the SDK, the SDK can split the batch check requests for you. + + For more details on how `Check` functions, see the docs for `/check`. + + ### Examples + #### A BatchCheckRequest + ```json + { + "checks": [ + { + "tuple_key": { + "object": "document:2021-budget" + "relation": "reader", + "user": "user:anne", + }, + "contextual_tuples": {...} + "context": {} + "correlation_id": "01JA8PM3QM7VBPGB8KMPK8SBD5" + }, + { + "tuple_key": { + "object": "document:2021-budget" + "relation": "reader", + "user": "user:bob", + }, + "contextual_tuples": {...} + "context": {} + "correlation_id": "01JA8PMM6A90NV5ET0F28CYSZQ" + } + ] + } + ``` + + Below is a possible response to the above request. Note that the result map's keys are the `correlation_id` values from the checked items in the request: + ```json + { + "result": { + "01JA8PMM6A90NV5ET0F28CYSZQ": { + "allowed": false, + "error": {"message": ""} + }, + "01JA8PM3QM7VBPGB8KMPK8SBD5": { + "allowed": true, + "error": {"message": ""} + } + } + ``` - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiBatchCheckRequest + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiBatchCheckRequest */ BatchCheck(ctx context.Context, storeId string) ApiBatchCheckRequest @@ -105,129 +105,129 @@ type OpenFgaApi interface { BatchCheckExecute(r ApiBatchCheckRequest) (BatchCheckResponse, *http.Response, error) /* - * Check Check whether a user is authorized to access an object - * 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. - By default, the Check API caches results for a short time to optimize performance. You may specify a value of `HIGHER_CONSISTENCY` for the optional `consistency` parameter in the body to inform the server that higher conisistency is preferred at the expense of increased latency. Consideration should be given to the increased latency if requesting higher consistency. - 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. - ### Requesting higher consistency - By default, the Check API caches results for a short time to optimize performance. You may request higher consistency to inform the server that higher consistency should be preferred at the expense of increased latency. Care should be taken when requesting higher consistency due to the increased latency. - ```json - { - "tuple_key": { - "user": "group:finance#member", - "relation": "reader", - "object": "document:2021-budget" - }, - "consistency": "HIGHER_CONSISTENCY" - } - ``` + * Check Check whether a user is authorized to access an object + * 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. + By default, the Check API caches results for a short time to optimize performance. You may specify a value of `HIGHER_CONSISTENCY` for the optional `consistency` parameter in the body to inform the server that higher conisistency is preferred at the expense of increased latency. Consideration should be given to the increased latency if requesting higher consistency. + 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. + ### Requesting higher consistency + By default, the Check API caches results for a short time to optimize performance. You may request higher consistency to inform the server that higher consistency should be preferred at the expense of increased latency. Care should be taken when requesting higher consistency due to the increased latency. + ```json + { + "tuple_key": { + "user": "group:finance#member", + "relation": "reader", + "object": "document:2021-budget" + }, + "consistency": "HIGHER_CONSISTENCY" + } + ``` - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiCheckRequest + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiCheckRequest */ Check(ctx context.Context, storeId string) ApiCheckRequest @@ -266,169 +266,169 @@ type OpenFgaApi interface { DeleteStoreExecute(r ApiDeleteStoreRequest) (*http.Response, error) /* - * Expand Expand all relationships in userset tree format, and following userset rewrite rules. Useful to reason about and debug a certain relationship - * The Expand API will return all users and usersets that have certain relationship with an object in a certain store. - This is different from the `/stores/{store_id}/read` API in that both users and computed usersets are returned. - Body parameters `tuple_key.object` and `tuple_key.relation` are all required. - 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`. - The response will return a tree whose leaves are the specific users and usersets. Union, intersection and difference operator are located in the intermediate nodes. - - ## Example - To expand all users that have the `reader` relationship with object `document:2021-budget`, use the Expand API with the following request body - ```json - { - "tuple_key": { - "object": "document:2021-budget", - "relation": "reader" - }, - "authorization_model_id": "01G50QVV17PECNVAHX1GG4Y5NC" - } - ``` - OpenFGA's response will be a userset tree of the users and usersets that have read access to the document. - ```json - { - "tree":{ - "root":{ - "type":"document:2021-budget#reader", - "union":{ - "nodes":[ - { - "type":"document:2021-budget#reader", - "leaf":{ - "users":{ - "users":[ - "user:bob" - ] - } - } - }, - { - "type":"document:2021-budget#reader", - "leaf":{ - "computed":{ - "userset":"document:2021-budget#writer" - } - } - } - ] - } - } - } - } - ``` - The caller can then call expand API for the `writer` relationship for the `document:2021-budget`. - ### Expand Request with Contextual Tuples - - Given the model - ```python - model - schema 1.1 - - type user - - type folder - relations - define owner: [user] - - type document - relations - define parent: [folder] - define viewer: [user] or writer - define writer: [user] or owner from parent - ``` - and the initial tuples - ```json - [{ - "user": "user:bob", - "relation": "owner", - "object": "folder:1" - }] - ``` - - To expand all `writers` of `document:1` when `document:1` is put in `folder:1`, the first call could be - - ```json - { - "tuple_key": { - "object": "document:1", - "relation": "writer" - }, - "contextual_tuples": { - "tuple_keys": [ - { - "user": "folder:1", - "relation": "parent", - "object": "document:1" - } - ] - } - } - ``` - this returns: - ```json - { - "tree": { - "root": { - "name": "document:1#writer", - "union": { - "nodes": [ - { - "name": "document:1#writer", - "leaf": { - "users": { - "users": [] - } - } - }, - { - "name": "document:1#writer", - "leaf": { - "tupleToUserset": { - "tupleset": "document:1#parent", - "computed": [ - { - "userset": "folder:1#owner" - } - ] - } - } - } - ] - } - } - } - } - ``` - This tells us that the `owner` of `folder:1` may also be a writer. So our next call could be to find the `owners` of `folder:1` - ```json - { - "tuple_key": { - "object": "folder:1", - "relation": "owner" - } - } - ``` - which gives - ```json - { - "tree": { - "root": { - "name": "folder:1#owner", - "leaf": { - "users": { - "users": [ - "user:bob" - ] - } - } - } - } - } - ``` + * Expand Expand all relationships in userset tree format, and following userset rewrite rules. Useful to reason about and debug a certain relationship + * The Expand API will return all users and usersets that have certain relationship with an object in a certain store. + This is different from the `/stores/{store_id}/read` API in that both users and computed usersets are returned. + Body parameters `tuple_key.object` and `tuple_key.relation` are all required. + 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`. + The response will return a tree whose leaves are the specific users and usersets. Union, intersection and difference operator are located in the intermediate nodes. + + ## Example + To expand all users that have the `reader` relationship with object `document:2021-budget`, use the Expand API with the following request body + ```json + { + "tuple_key": { + "object": "document:2021-budget", + "relation": "reader" + }, + "authorization_model_id": "01G50QVV17PECNVAHX1GG4Y5NC" + } + ``` + OpenFGA's response will be a userset tree of the users and usersets that have read access to the document. + ```json + { + "tree":{ + "root":{ + "type":"document:2021-budget#reader", + "union":{ + "nodes":[ + { + "type":"document:2021-budget#reader", + "leaf":{ + "users":{ + "users":[ + "user:bob" + ] + } + } + }, + { + "type":"document:2021-budget#reader", + "leaf":{ + "computed":{ + "userset":"document:2021-budget#writer" + } + } + } + ] + } + } + } + } + ``` + The caller can then call expand API for the `writer` relationship for the `document:2021-budget`. + ### Expand Request with Contextual Tuples + + Given the model + ```python + model + schema 1.1 + + type user + + type folder + relations + define owner: [user] + + type document + relations + define parent: [folder] + define viewer: [user] or writer + define writer: [user] or owner from parent + ``` + and the initial tuples + ```json + [{ + "user": "user:bob", + "relation": "owner", + "object": "folder:1" + }] + ``` + + To expand all `writers` of `document:1` when `document:1` is put in `folder:1`, the first call could be + + ```json + { + "tuple_key": { + "object": "document:1", + "relation": "writer" + }, + "contextual_tuples": { + "tuple_keys": [ + { + "user": "folder:1", + "relation": "parent", + "object": "document:1" + } + ] + } + } + ``` + this returns: + ```json + { + "tree": { + "root": { + "name": "document:1#writer", + "union": { + "nodes": [ + { + "name": "document:1#writer", + "leaf": { + "users": { + "users": [] + } + } + }, + { + "name": "document:1#writer", + "leaf": { + "tupleToUserset": { + "tupleset": "document:1#parent", + "computed": [ + { + "userset": "folder:1#owner" + } + ] + } + } + } + ] + } + } + } + } + ``` + This tells us that the `owner` of `folder:1` may also be a writer. So our next call could be to find the `owners` of `folder:1` + ```json + { + "tuple_key": { + "object": "folder:1", + "relation": "owner" + } + } + ``` + which gives + ```json + { + "tree": { + "root": { + "name": "folder:1#owner", + "leaf": { + "users": { + "users": [ + "user:bob" + ] + } + } + } + } + } + ``` - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiExpandRequest + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiExpandRequest */ Expand(ctx context.Context, storeId string) ApiExpandRequest @@ -454,19 +454,19 @@ type OpenFgaApi interface { GetStoreExecute(r ApiGetStoreRequest) (GetStoreResponse, *http.Response, error) /* - * 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 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. - By default, the Check API caches results for a short time to optimize performance. You may specify a value of `HIGHER_CONSISTENCY` for the optional `consistency` parameter in the body to inform the server that higher conisistency is preferred at the expense of increased latency. Consideration should be given to the increased latency if requesting higher consistency. - 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. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiListObjectsRequest + * 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 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. + By default, the Check API caches results for a short time to optimize performance. You may specify a value of `HIGHER_CONSISTENCY` for the optional `consistency` parameter in the body to inform the server that higher conisistency is preferred at the expense of increased latency. Consideration should be given to the increased latency if requesting higher consistency. + 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. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiListObjectsRequest */ ListObjects(ctx context.Context, storeId string) ApiListObjectsRequest @@ -477,12 +477,12 @@ type OpenFgaApi interface { ListObjectsExecute(r ApiListObjectsRequest) (ListObjectsResponse, *http.Response, error) /* - * 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. + * 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 + * @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 @@ -493,20 +493,20 @@ type OpenFgaApi interface { ListStoresExecute(r ApiListStoresRequest) (ListStoresResponse, *http.Response, error) /* - * ListUsers 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. - To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). - An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. - You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. - You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. - The response will contain the related users in an array in the "users" field of the response. These results may include specific objects, usersets - or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public access result is returned (e.g. `user:*`), it cannot be inferred that all subjects - of that type have a relation to the object; it is possible that negations exist and checks should still be queried - on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. - The returned users will not be sorted, and therefore two identical calls may yield different sets of users. - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiListUsersRequest + * ListUsers 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. + To arrive at a result, the API uses: an authorization model, explicit tuples written through the Write API, contextual tuples present in the request, and implicit tuples that exist by virtue of applying set theory (such as `document:2021-budget#viewer@document:2021-budget#viewer`; the set of users who are viewers of `document:2021-budget` are the set of users who are the viewers of `document:2021-budget`). + An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. + You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. + You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. + The response will contain the related users in an array in the "users" field of the response. These results may include specific objects, usersets + or type-bound public access. Each of these types of results is encoded in its own type and not represented as a string.In cases where a type-bound public access result is returned (e.g. `user:*`), it cannot be inferred that all subjects + of that type have a relation to the object; it is possible that negations exist and checks should still be queried + on individual subjects to ensure access to that document.The number of users in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_USERS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_USERS_MAX_RESULTS, whichever is hit first. + The returned users will not be sorted, and therefore two identical calls may yield different sets of users. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiListUsersRequest */ ListUsers(ctx context.Context, storeId string) ApiListUsersRequest @@ -517,109 +517,109 @@ type OpenFgaApi interface { ListUsersExecute(r ApiListUsersRequest) (ListUsersResponse, *http.Response, error) /* - * 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. - The API doesn't guarantee order by any field. - 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 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. If tuple_key.user is specified, it needs to be a full object (e.g., `type:user_id`). - ## 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 - ```json - { - "tuple_key": { - "user": "user:bob", - "relation": "reader", - "object": "document:" - } - } - ``` - The API will return tuples and a continuation token, something like - ```json - { - "tuples": [ - { - "key": { - "user": "user:bob", - "relation": "reader", - "object": "document:2021-budget" - }, - "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`. 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 - { - "tuple_key": { - "object": "document:2021-budget", - "relation": "reader" - } - } - ``` - The API will return something like - ```json - { - "tuples": [ - { - "key": { - "user": "user:bob", - "relation": "reader", - "object": "document:2021-budget" - }, - "timestamp": "2021-10-06T15:32:11.128Z" - } - ], - "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" - } - ``` - 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 - { - "tuple_key": { - "object": "document:2021-budget" - } - } - ``` - The API will return something like - ```json - { - "tuples": [ - { - "key": { - "user": "user:anne", - "relation": "writer", - "object": "document:2021-budget" - }, - "timestamp": "2021-10-05T13:42:12.356Z" - }, - { - "key": { - "user": "user:bob", - "relation": "reader", - "object": "document:2021-budget" - }, - "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`). + * 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. + The API doesn't guarantee order by any field. + 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 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. If tuple_key.user is specified, it needs to be a full object (e.g., `type:user_id`). + ## 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 + ```json + { + "tuple_key": { + "user": "user:bob", + "relation": "reader", + "object": "document:" + } + } + ``` + The API will return tuples and a continuation token, something like + ```json + { + "tuples": [ + { + "key": { + "user": "user:bob", + "relation": "reader", + "object": "document:2021-budget" + }, + "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`. 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 + { + "tuple_key": { + "object": "document:2021-budget", + "relation": "reader" + } + } + ``` + The API will return something like + ```json + { + "tuples": [ + { + "key": { + "user": "user:bob", + "relation": "reader", + "object": "document:2021-budget" + }, + "timestamp": "2021-10-06T15:32:11.128Z" + } + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + } + ``` + 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 + { + "tuple_key": { + "object": "document:2021-budget" + } + } + ``` + The API will return something like + ```json + { + "tuples": [ + { + "key": { + "user": "user:anne", + "relation": "writer", + "object": "document:2021-budget" + }, + "timestamp": "2021-10-05T13:42:12.356Z" + }, + { + "key": { + "user": "user:bob", + "relation": "reader", + "object": "document:2021-budget" + }, + "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`). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiReadRequest + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiReadRequest */ Read(ctx context.Context, storeId string) ApiReadRequest @@ -646,52 +646,52 @@ type OpenFgaApi interface { ReadAssertionsExecute(r ApiReadAssertionsRequest) (ReadAssertionsResponse, *http.Response, error) /* - * ReadAuthorizationModel Return a particular version of an authorization model - * The ReadAuthorizationModel API returns an authorization model by its identifier. - The response will return the authorization model for the particular version. - - ## Example - To retrieve the authorization model with ID `01G5JAVJ41T49E9TT3SKVS7X1J` for the store, call the GET authorization-models by ID API with `01G5JAVJ41T49E9TT3SKVS7X1J` as the `id` path parameter. The API will return: - ```json - { - "authorization_model":{ - "id":"01G5JAVJ41T49E9TT3SKVS7X1J", - "type_definitions":[ - { - "type":"user" - }, - { - "type":"document", - "relations":{ - "reader":{ - "union":{ - "child":[ - { - "this":{} - }, - { - "computedUserset":{ - "object":"", - "relation":"writer" - } - } - ] - } - }, - "writer":{ - "this":{} - } - } - } - ] - } - } - ``` - In the above example, there are 2 types (`user` and `document`). The `document` type has 2 relations (`writer` and `reader`). - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @param id - * @return ApiReadAuthorizationModelRequest + * ReadAuthorizationModel Return a particular version of an authorization model + * The ReadAuthorizationModel API returns an authorization model by its identifier. + The response will return the authorization model for the particular version. + + ## Example + To retrieve the authorization model with ID `01G5JAVJ41T49E9TT3SKVS7X1J` for the store, call the GET authorization-models by ID API with `01G5JAVJ41T49E9TT3SKVS7X1J` as the `id` path parameter. The API will return: + ```json + { + "authorization_model":{ + "id":"01G5JAVJ41T49E9TT3SKVS7X1J", + "type_definitions":[ + { + "type":"user" + }, + { + "type":"document", + "relations":{ + "reader":{ + "union":{ + "child":[ + { + "this":{} + }, + { + "computedUserset":{ + "object":"", + "relation":"writer" + } + } + ] + } + }, + "writer":{ + "this":{} + } + } + } + ] + } + } + ``` + In the above example, there are 2 types (`user` and `document`). The `document` type has 2 relations (`writer` and `reader`). + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @param id + * @return ApiReadAuthorizationModelRequest */ ReadAuthorizationModel(ctx context.Context, storeId string, id string) ApiReadAuthorizationModelRequest @@ -702,47 +702,47 @@ type OpenFgaApi interface { ReadAuthorizationModelExecute(r ApiReadAuthorizationModelRequest) (ReadAuthorizationModelResponse, *http.Response, error) /* - * ReadAuthorizationModels Return all the authorization models for a particular store - * The ReadAuthorizationModels API will return all the authorization models for a certain store. - OpenFGA's response will contain an array of all authorization models, sorted in descending order of creation. - - ## Example - Assume that a store's authorization model has been configured twice. To get all the authorization models that have been created in this store, call GET authorization-models. The API will return a response that looks like: - ```json - { - "authorization_models": [ - { - "id": "01G50QVV17PECNVAHX1GG4Y5NC", - "type_definitions": [...] - }, - { - "id": "01G4ZW8F4A07AKQ8RHSVG9RW04", - "type_definitions": [...] - }, - ], - "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" - } - ``` - If there are no more authorization models available, the `continuation_token` field will be empty - ```json - { - "authorization_models": [ - { - "id": "01G50QVV17PECNVAHX1GG4Y5NC", - "type_definitions": [...] - }, - { - "id": "01G4ZW8F4A07AKQ8RHSVG9RW04", - "type_definitions": [...] - }, - ], - "continuation_token": "" - } - ``` + * ReadAuthorizationModels Return all the authorization models for a particular store + * The ReadAuthorizationModels API will return all the authorization models for a certain store. + OpenFGA's response will contain an array of all authorization models, sorted in descending order of creation. + + ## Example + Assume that a store's authorization model has been configured twice. To get all the authorization models that have been created in this store, call GET authorization-models. The API will return a response that looks like: + ```json + { + "authorization_models": [ + { + "id": "01G50QVV17PECNVAHX1GG4Y5NC", + "type_definitions": [...] + }, + { + "id": "01G4ZW8F4A07AKQ8RHSVG9RW04", + "type_definitions": [...] + }, + ], + "continuation_token": "eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ==" + } + ``` + If there are no more authorization models available, the `continuation_token` field will be empty + ```json + { + "authorization_models": [ + { + "id": "01G50QVV17PECNVAHX1GG4Y5NC", + "type_definitions": [...] + }, + { + "id": "01G4ZW8F4A07AKQ8RHSVG9RW04", + "type_definitions": [...] + }, + ], + "continuation_token": "" + } + ``` - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiReadAuthorizationModelsRequest + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiReadAuthorizationModelsRequest */ ReadAuthorizationModels(ctx context.Context, storeId string) ApiReadAuthorizationModelsRequest @@ -753,15 +753,15 @@ type OpenFgaApi interface { ReadAuthorizationModelsExecute(r ApiReadAuthorizationModelsRequest) (ReadAuthorizationModelsResponse, *http.Response, error) /* - * ReadChanges Return a list of all the tuple changes - * The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. - You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. - When reading a write tuple change, if it was conditioned, the condition will be returned. - When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. - - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiReadChangesRequest + * ReadChanges Return a list of all the tuple changes + * The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. + You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. + When reading a write tuple change, if it was conditioned, the condition will be returned. + When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. + + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiReadChangesRequest */ ReadChanges(ctx context.Context, storeId string) ApiReadChangesRequest @@ -772,14 +772,14 @@ type OpenFgaApi interface { ReadChangesExecute(r ApiReadChangesRequest) (ReadChangesResponse, *http.Response, error) /* - * StreamedListObjects Stream all objects of the given type that the user has a relation with - * The Streamed ListObjects API is very similar to the the ListObjects API, with two differences: - 1. Instead of collecting all objects before returning a response, it streams them to the client as they are collected. - 2. The number of results returned is only limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE. - - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiStreamedListObjectsRequest + * StreamedListObjects Stream all objects of the given type that the user has a relation with + * The Streamed ListObjects API is very similar to the the ListObjects API, with two differences: + 1. Instead of collecting all objects before returning a response, it streams them to the client as they are collected. + 2. The number of results returned is only limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE. + + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiStreamedListObjectsRequest */ StreamedListObjects(ctx context.Context, storeId string) ApiStreamedListObjectsRequest @@ -790,53 +790,53 @@ type OpenFgaApi interface { StreamedListObjectsExecute(r ApiStreamedListObjectsRequest) (StreamResultOfStreamedListObjectsResponse, *http.Response, error) /* - * Write Add or delete tuples from the store - * 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 by default: 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. - To allow writes when an identical tuple already exists in the database, set `"on_duplicate": "ignore"` on the `writes` object. - To allow deletes when a tuple was already removed from the database, set `"on_missing": "ignore"` on the `deletes` object. - If a Write request contains both idempotent (ignore) and non-idempotent (error) operations, the most restrictive action (error) will take precedence. If a condition fails for a sub-request with an error flag, the entire transaction will be rolled back. This gives developers explicit control over the atomicity of the requests. - 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" - } - ], - "on_duplicate": "ignore" - }, - "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" - } - ], - "on_missing": "ignore" - } - } - ``` + * Write Add or delete tuples from the store + * 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 by default: 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. + To allow writes when an identical tuple already exists in the database, set `"on_duplicate": "ignore"` on the `writes` object. + To allow deletes when a tuple was already removed from the database, set `"on_missing": "ignore"` on the `deletes` object. + If a Write request contains both idempotent (ignore) and non-idempotent (error) operations, the most restrictive action (error) will take precedence. If a condition fails for a sub-request with an error flag, the entire transaction will be rolled back. This gives developers explicit control over the atomicity of the requests. + 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" + } + ], + "on_duplicate": "ignore" + }, + "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" + } + ], + "on_missing": "ignore" + } + } + ``` - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiWriteRequest + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiWriteRequest */ Write(ctx context.Context, storeId string) ApiWriteRequest @@ -862,53 +862,53 @@ type OpenFgaApi interface { WriteAssertionsExecute(r ApiWriteAssertionsRequest) (*http.Response, error) /* - * WriteAuthorizationModel Create a new authorization model - * The WriteAuthorizationModel API will add a new authorization model to a store. - Each item in the `type_definitions` array is a type definition as specified in the field `type_definition`. - The response will return the authorization model's ID in the `id` field. - - ## Example - To add an authorization model with `user` and `document` type definitions, call POST authorization-models API with the body: - ```json - { - "type_definitions":[ - { - "type":"user" - }, - { - "type":"document", - "relations":{ - "reader":{ - "union":{ - "child":[ - { - "this":{} - }, - { - "computedUserset":{ - "object":"", - "relation":"writer" - } - } - ] - } - }, - "writer":{ - "this":{} - } - } - } - ] - } - ``` - OpenFGA's response will include the version id for this authorization model, which will look like - ``` - {"authorization_model_id": "01G50QVV17PECNVAHX1GG4Y5NC"} - ``` - - * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param storeId - * @return ApiWriteAuthorizationModelRequest + * WriteAuthorizationModel Create a new authorization model + * The WriteAuthorizationModel API will add a new authorization model to a store. + Each item in the `type_definitions` array is a type definition as specified in the field `type_definition`. + The response will return the authorization model's ID in the `id` field. + + ## Example + To add an authorization model with `user` and `document` type definitions, call POST authorization-models API with the body: + ```json + { + "type_definitions":[ + { + "type":"user" + }, + { + "type":"document", + "relations":{ + "reader":{ + "union":{ + "child":[ + { + "this":{} + }, + { + "computedUserset":{ + "object":"", + "relation":"writer" + } + } + ] + } + }, + "writer":{ + "this":{} + } + } + } + ] + } + ``` + OpenFGA's response will include the version id for this authorization model, which will look like + ``` + {"authorization_model_id": "01G50QVV17PECNVAHX1GG4Y5NC"} + ``` + + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param storeId + * @return ApiWriteAuthorizationModelRequest */ WriteAuthorizationModel(ctx context.Context, storeId string) ApiWriteAuthorizationModelRequest diff --git a/client/client.go b/client/client.go index f4d045d..ed9d93e 100644 --- a/client/client.go +++ b/client/client.go @@ -1,121 +1,121 @@ package client import ( - _context "context" - "encoding/json" - "fmt" - "math" - _nethttp "net/http" - "time" - - "github.com/sourcegraph/conc/pool" - "golang.org/x/sync/errgroup" - - fgaSdk "github.com/openfga/go-sdk" - "github.com/openfga/go-sdk/credentials" - "github.com/openfga/go-sdk/internal/constants" - internalutils "github.com/openfga/go-sdk/internal/utils" - "github.com/openfga/go-sdk/telemetry" + _context "context" + "encoding/json" + "fmt" + "math" + _nethttp "net/http" + "time" + + "github.com/sourcegraph/conc/pool" + "golang.org/x/sync/errgroup" + + fgaSdk "github.com/openfga/go-sdk" + "github.com/openfga/go-sdk/credentials" + "github.com/openfga/go-sdk/internal/constants" + internalutils "github.com/openfga/go-sdk/internal/utils" + "github.com/openfga/go-sdk/telemetry" ) var ( - _ _context.Context - // Ensure the SdkClient fits OpenFgaClient interface - _ SdkClient = (*OpenFgaClient)(nil) + _ _context.Context + // Ensure the SdkClient fits OpenFgaClient interface + _ SdkClient = (*OpenFgaClient)(nil) ) var DEFAULT_MAX_METHOD_PARALLEL_REQS = int32(constants.ClientMaxMethodParallelRequests) type ClientConfiguration struct { - fgaSdk.Configuration - // ApiScheme - defines the scheme for the API: http or https - // Deprecated: use ApiUrl instead of ApiScheme and ApiHost - ApiScheme string `json:"api_scheme"` - // ApiHost - defines the host for the API without the scheme e.g. (api.fga.example) - // Deprecated: use ApiUrl instead of ApiScheme and ApiHost - ApiHost string `json:"api_host"` - ApiUrl string `json:"api_url"` - StoreId string `json:"store_id"` - AuthorizationModelId string `json:"authorization_model_id"` - Credentials *credentials.Credentials `json:"credentials"` - DefaultHeaders map[string]string `json:"default_headers"` - UserAgent string `json:"user_agent"` - Debug bool `json:"debug"` - HTTPClient *_nethttp.Client - RetryParams *fgaSdk.RetryParams - Telemetry *telemetry.Configuration `json:"telemetry,omitempty"` + fgaSdk.Configuration + // ApiScheme - defines the scheme for the API: http or https + // Deprecated: use ApiUrl instead of ApiScheme and ApiHost + ApiScheme string `json:"api_scheme"` + // ApiHost - defines the host for the API without the scheme e.g. (api.fga.example) + // Deprecated: use ApiUrl instead of ApiScheme and ApiHost + ApiHost string `json:"api_host"` + ApiUrl string `json:"api_url"` + StoreId string `json:"store_id"` + AuthorizationModelId string `json:"authorization_model_id"` + Credentials *credentials.Credentials `json:"credentials"` + DefaultHeaders map[string]string `json:"default_headers"` + UserAgent string `json:"user_agent"` + Debug bool `json:"debug"` + HTTPClient *_nethttp.Client + RetryParams *fgaSdk.RetryParams + Telemetry *telemetry.Configuration `json:"telemetry,omitempty"` } func newClientConfiguration(cfg *fgaSdk.Configuration) ClientConfiguration { - return ClientConfiguration{ - ApiScheme: cfg.ApiScheme, - ApiHost: cfg.ApiHost, - ApiUrl: cfg.ApiUrl, - Credentials: cfg.Credentials, - DefaultHeaders: cfg.DefaultHeaders, - UserAgent: cfg.UserAgent, - Debug: cfg.Debug, - HTTPClient: cfg.HTTPClient, - RetryParams: cfg.RetryParams, - Telemetry: cfg.Telemetry, - } + return ClientConfiguration{ + ApiScheme: cfg.ApiScheme, + ApiHost: cfg.ApiHost, + ApiUrl: cfg.ApiUrl, + Credentials: cfg.Credentials, + DefaultHeaders: cfg.DefaultHeaders, + UserAgent: cfg.UserAgent, + Debug: cfg.Debug, + HTTPClient: cfg.HTTPClient, + RetryParams: cfg.RetryParams, + Telemetry: cfg.Telemetry, + } } type OpenFgaClient struct { - config ClientConfiguration - SdkClient - fgaSdk.APIClient + config ClientConfiguration + SdkClient + fgaSdk.APIClient } func NewSdkClient(cfg *ClientConfiguration) (*OpenFgaClient, error) { - apiConfiguration, err := fgaSdk.NewConfiguration(fgaSdk.Configuration{ - ApiScheme: cfg.ApiScheme, - ApiHost: cfg.ApiHost, - ApiUrl: cfg.ApiUrl, - Credentials: cfg.Credentials, - DefaultHeaders: cfg.DefaultHeaders, - UserAgent: cfg.UserAgent, - Debug: cfg.Debug, - HTTPClient: cfg.HTTPClient, - RetryParams: cfg.RetryParams, - Telemetry: cfg.Telemetry, - }) + apiConfiguration, err := fgaSdk.NewConfiguration(fgaSdk.Configuration{ + ApiScheme: cfg.ApiScheme, + ApiHost: cfg.ApiHost, + ApiUrl: cfg.ApiUrl, + Credentials: cfg.Credentials, + DefaultHeaders: cfg.DefaultHeaders, + UserAgent: cfg.UserAgent, + Debug: cfg.Debug, + HTTPClient: cfg.HTTPClient, + RetryParams: cfg.RetryParams, + Telemetry: cfg.Telemetry, + }) - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - clientConfig := newClientConfiguration(apiConfiguration) - clientConfig.AuthorizationModelId = cfg.AuthorizationModelId - clientConfig.StoreId = cfg.StoreId + clientConfig := newClientConfiguration(apiConfiguration) + clientConfig.AuthorizationModelId = cfg.AuthorizationModelId + clientConfig.StoreId = cfg.StoreId - // store id is already validate as part of configuration validation + // store id is already validate as part of configuration validation - if cfg.AuthorizationModelId != "" && !internalutils.IsWellFormedUlidString(cfg.AuthorizationModelId) { - return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } + if cfg.AuthorizationModelId != "" && !internalutils.IsWellFormedUlidString(cfg.AuthorizationModelId) { + return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } - if cfg.StoreId != "" && !internalutils.IsWellFormedUlidString(cfg.StoreId) { - return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } + if cfg.StoreId != "" && !internalutils.IsWellFormedUlidString(cfg.StoreId) { + return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } - apiClient := fgaSdk.NewAPIClient(apiConfiguration) + apiClient := fgaSdk.NewAPIClient(apiConfiguration) - return &OpenFgaClient{ - config: clientConfig, - APIClient: *apiClient, - }, nil + return &OpenFgaClient{ + config: clientConfig, + APIClient: *apiClient, + }, nil } type RequestOptions = fgaSdk.RequestOptions type AuthorizationModelIdOptions struct { - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` } type ClientRequestOptionsWithAuthZModelId struct { - RequestOptions - AuthorizationModelIdOptions + RequestOptions + AuthorizationModelIdOptions } type ClientTupleKey = fgaSdk.TupleKey @@ -127,1890 +127,1890 @@ type ClientContextualTupleKey = ClientTupleKey // ClientBatchCheckItem represents a flattened check item for batch check operations type ClientBatchCheckItem struct { - User string `json:"user"` - Relation string `json:"relation"` - Object string `json:"object"` - CorrelationId string `json:"correlation_id"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` + User string `json:"user"` + Relation string `json:"relation"` + Object string `json:"object"` + CorrelationId string `json:"correlation_id"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` } // ClientBatchCheckRequest represents a request for batch check operations type ClientBatchCheckRequest struct { - Checks []ClientBatchCheckItem `json:"checks"` + Checks []ClientBatchCheckItem `json:"checks"` } // BatchCheckOptions represents options for server-side batch check operations type BatchCheckOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` - MaxBatchSize *int32 `json:"max_batch_size,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` + MaxBatchSize *int32 `json:"max_batch_size,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientPaginationOptions struct { - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` } func getPageSizeFromRequest(options *ClientPaginationOptions) *int32 { - if options == nil { - return nil - } - return options.PageSize + if options == nil { + return nil + } + return options.PageSize } func getContinuationTokenFromRequest(options *ClientPaginationOptions) *string { - if options == nil { - return nil - } - return options.ContinuationToken + if options == nil { + return nil + } + return options.ContinuationToken } type SdkClient interface { - /* Stores */ - - /* - * ListStores Get a paginated list of stores. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientListStoresRequestInterface - */ - ListStores(ctx _context.Context) SdkClientListStoresRequestInterface - - /* - * ListStoresExecute executes the ListStores request - * @return *ClientListStoresResponse - */ - ListStoresExecute(request SdkClientListStoresRequestInterface) (*ClientListStoresResponse, error) - - /* - * CreateStore Create and initialize a store - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientCreateStoreRequestInterface - */ - CreateStore(ctx _context.Context) SdkClientCreateStoreRequestInterface - - /* - * CreateStoreExecute executes the CreateStore request - * @return *ClientCreateStoreResponse - */ - CreateStoreExecute(request SdkClientCreateStoreRequestInterface) (*ClientCreateStoreResponse, error) - - /* - * GetStore Get information about the current store. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientGetStoreRequestInterface - */ - GetStore(ctx _context.Context) SdkClientGetStoreRequestInterface - - /* - * GetStoreExecute executes the GetStore request - * @return *ClientGetStoreResponse - */ - GetStoreExecute(request SdkClientGetStoreRequestInterface) (*ClientGetStoreResponse, error) - - /* - * DeleteStore Delete a store. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientDeleteStoreRequestInterface - */ - DeleteStore(ctx _context.Context) SdkClientDeleteStoreRequestInterface - - /* - * DeleteStoreExecute executes the DeleteStore request - * @return *ClientDeleteStoreResponse - */ - DeleteStoreExecute(request SdkClientDeleteStoreRequestInterface) (*ClientDeleteStoreResponse, error) - - /* Authorization Models */ - - /* - * ReadAuthorizationModels Read all authorization models in the store. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadAuthorizationModelsRequest - */ - ReadAuthorizationModels(ctx _context.Context) SdkClientReadAuthorizationModelsRequestInterface - - /* - * ReadAuthorizationModelsExecute executes the ReadAuthorizationModels request - * @return *ClientReadAuthorizationModelsResponse - */ - ReadAuthorizationModelsExecute(request SdkClientReadAuthorizationModelsRequestInterface) (*ClientReadAuthorizationModelsResponse, error) - - /* - * WriteAuthorizationModel Create a new authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteAuthorizationModelRequest - */ - WriteAuthorizationModel(ctx _context.Context) SdkClientWriteAuthorizationModelRequestInterface - - /* - * WriteAuthorizationModelExecute executes the WriteAuthorizationModel request - * @return *ClientWriteAuthorizationModelResponse - */ - WriteAuthorizationModelExecute(request SdkClientWriteAuthorizationModelRequestInterface) (*ClientWriteAuthorizationModelResponse, error) - - /* - * ReadAuthorizationModel Read a particular authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadAuthorizationModelRequestInterface - */ - ReadAuthorizationModel(ctx _context.Context) SdkClientReadAuthorizationModelRequestInterface - - /* - * ReadAuthorizationModelExecute executes the ReadAuthorizationModel request - * @return *ClientReadAuthorizationModelResponse - */ - ReadAuthorizationModelExecute(request SdkClientReadAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) - - /* - * ReadLatestAuthorizationModel Reads the latest authorization model (note: this ignores the model id in configuration). - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadLatestAuthorizationModelRequestInterface - */ - ReadLatestAuthorizationModel(ctx _context.Context) SdkClientReadLatestAuthorizationModelRequestInterface - - /* - * ReadLatestAuthorizationModelExecute executes the ReadLatestAuthorizationModel request - * @return *ClientReadAuthorizationModelResponse - */ - ReadLatestAuthorizationModelExecute(request SdkClientReadLatestAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) - - /* Relationship Tuples */ - - /* - * ReadChanges Reads the list of historical relationship tuple writes and deletes. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadChangesRequestInterface - */ - ReadChanges(ctx _context.Context) SdkClientReadChangesRequestInterface - - /* - * ReadChangesExecute executes the ReadChanges request - * @return *ClientReadChangesResponse - */ - ReadChangesExecute(request SdkClientReadChangesRequestInterface) (*ClientReadChangesResponse, error) - - /* - * Read Reads the relationship tuples stored in the database. It does not evaluate nor exclude invalid tuples according to the authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadRequestInterface - */ - Read(ctx _context.Context) SdkClientReadRequestInterface - - /* - * ReadExecute executes the Read request - * @return *ClientReadResponse - */ - ReadExecute(request SdkClientReadRequestInterface) (*ClientReadResponse, error) - - /* - * Write Create and/or delete relationship tuples to update the system state. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteRequestInterface - */ - Write(ctx _context.Context) SdkClientWriteRequestInterface - - /* - * WriteExecute executes the Write request - * @return *ClientWriteResponse - */ - WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) - - /* - * WriteTuples Utility method around Write - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteTuplesRequestInterface - */ - WriteTuples(ctx _context.Context) SdkClientWriteTuplesRequestInterface - - /* - * WriteTuplesExecute executes the WriteTuples request - * @return *ClientWriteResponse - */ - WriteTuplesExecute(request SdkClientWriteTuplesRequestInterface) (*ClientWriteResponse, error) - - /* - * DeleteTuples Utility method around Write - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientDeleteTuplesRequestInterface - */ - DeleteTuples(ctx _context.Context) SdkClientDeleteTuplesRequestInterface - - /* - * DeleteTuplesExecute executes the DeleteTuples request - * @return *ClientWriteResponse - */ - DeleteTuplesExecute(request SdkClientDeleteTuplesRequestInterface) (*ClientWriteResponse, error) - - /* Relationship Queries */ - - /* - * Check Check if a user has a particular relation with an object. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientCheckRequestInterface - */ - Check(ctx _context.Context) SdkClientCheckRequestInterface - - /* - * CheckExecute executes the Check request - * @return *ClientCheckResponse - */ - CheckExecute(request SdkClientCheckRequestInterface) (*ClientCheckResponse, error) - - /* - * ClientBatchCheck Run a set of [checks](#check). Batch Check will return `allowed: false` if it encounters an error, and will return the error in the body. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientBatchCheckRequestInterface - */ - ClientBatchCheck(ctx _context.Context) SdkClientBatchCheckClientRequestInterface - - /* - * ClientBatchCheckExecute executes the BatchCheck request - * @return *ClientBatchCheckResponse - */ - ClientBatchCheckExecute(request SdkClientBatchCheckClientRequestInterface) (*ClientBatchCheckClientResponse, error) - - /* - * BatchCheck Run a set of checks on the server. Server-side batch check allows for more efficient checking of multiple tuples. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientBatchCheckRequestInterface - */ - BatchCheck(ctx _context.Context) SdkClientBatchCheckRequestInterface - - /* - * BatchCheckExecute executes the server-side BatchCheck request - * @return *BatchCheckResponse - */ - BatchCheckExecute(request SdkClientBatchCheckRequestInterface) (*fgaSdk.BatchCheckResponse, error) - - /* - * Expand Expands the relationships in userset tree format. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientExpandRequestInterface - */ - Expand(ctx _context.Context) SdkClientExpandRequestInterface - - /* - * ExpandExecute executes the Expand request - * @return *ClientExpandResponse - */ - ExpandExecute(request SdkClientExpandRequestInterface) (*ClientExpandResponse, error) - - /* - * ListObjects List the objects of a particular type a user has access to. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientListObjectsRequestInterface - */ - ListObjects(ctx _context.Context) SdkClientListObjectsRequestInterface - - /* - * ListObjectsExecute executes the ListObjects request - * @return *ClientListObjectsResponse - */ - ListObjectsExecute(request SdkClientListObjectsRequestInterface) (*ClientListObjectsResponse, error) - - /* - * ListRelations List the relations a user has on an object. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientListRelationsRequestInterface - */ - ListRelations(ctx _context.Context) SdkClientListRelationsRequestInterface - - /* - * ListRelationsExecute executes the ListRelations request - * @return *ClientListRelationsResponse - */ - ListRelationsExecute(request SdkClientListRelationsRequestInterface) (*ClientListRelationsResponse, error) - - /* - * ListUsers List all users of the given type that the object has a relation with - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return ApiListUsersRequest - */ - ListUsers(ctx _context.Context) SdkClientListUsersRequestInterface - - /* - * ListUsersExecute executes the request - * @return ListUsersResponse - */ - ListUsersExecute(r SdkClientListUsersRequestInterface) (*ClientListUsersResponse, error) - - /* - * StreamedListObjects Stream all objects of the given type that the user has a relation with - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientStreamedListObjectsRequestInterface - */ - StreamedListObjects(ctx _context.Context) SdkClientStreamedListObjectsRequestInterface - - /* - * StreamedListObjectsExecute executes the StreamedListObjects request and returns a channel - * @return *ClientStreamedListObjectsResponse - */ - StreamedListObjectsExecute(request SdkClientStreamedListObjectsRequestInterface) (*ClientStreamedListObjectsResponse, error) - - /* Assertions */ - - /* - * ReadAssertions Read assertions for a particular authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientReadAssertionsRequestInterface - */ - ReadAssertions(ctx _context.Context) SdkClientReadAssertionsRequestInterface - - /* - * ReadAssertionsExecute executes the ReadAssertions request - * @return *ClientReadAssertionsResponse - */ - ReadAssertionsExecute(request SdkClientReadAssertionsRequestInterface) (*ClientReadAssertionsResponse, error) - - /* - * WriteAssertions Update the assertions for a particular authorization model. - * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @return SdkClientWriteAssertionsRequestInterface - */ - WriteAssertions(ctx _context.Context) SdkClientWriteAssertionsRequestInterface - - /* - * WriteAssertionsExecute executes the WriteAssertions request - * @return *ClientWriteAssertionsResponse - */ - WriteAssertionsExecute(request SdkClientWriteAssertionsRequestInterface) (*ClientWriteAssertionsResponse, error) - - /* - * SetAuthorizationModelId allows setting the Authorization Model ID for an OpenFgaClient. - * @param string authorizationModelId - The Authorization Model ID to set. - */ - SetAuthorizationModelId(authorizationModelId string) error - /* - * GetAuthorizationModelId retrieves the Authorization Model ID for an OpenFgaClient. - * @return string - */ - GetAuthorizationModelId() (string, error) - /* - * SetStoreId allows setting the Store ID for an OpenFgaClient. - * @param string storeId - The Store ID to set. - */ - SetStoreId(storeId string) error - /* - * GetStoreId retrieves the Store ID set in the OpenFgaClient. - * @return string - */ - GetStoreId() (string, error) + /* Stores */ + + /* + * ListStores Get a paginated list of stores. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientListStoresRequestInterface + */ + ListStores(ctx _context.Context) SdkClientListStoresRequestInterface + + /* + * ListStoresExecute executes the ListStores request + * @return *ClientListStoresResponse + */ + ListStoresExecute(request SdkClientListStoresRequestInterface) (*ClientListStoresResponse, error) + + /* + * CreateStore Create and initialize a store + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientCreateStoreRequestInterface + */ + CreateStore(ctx _context.Context) SdkClientCreateStoreRequestInterface + + /* + * CreateStoreExecute executes the CreateStore request + * @return *ClientCreateStoreResponse + */ + CreateStoreExecute(request SdkClientCreateStoreRequestInterface) (*ClientCreateStoreResponse, error) + + /* + * GetStore Get information about the current store. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientGetStoreRequestInterface + */ + GetStore(ctx _context.Context) SdkClientGetStoreRequestInterface + + /* + * GetStoreExecute executes the GetStore request + * @return *ClientGetStoreResponse + */ + GetStoreExecute(request SdkClientGetStoreRequestInterface) (*ClientGetStoreResponse, error) + + /* + * DeleteStore Delete a store. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientDeleteStoreRequestInterface + */ + DeleteStore(ctx _context.Context) SdkClientDeleteStoreRequestInterface + + /* + * DeleteStoreExecute executes the DeleteStore request + * @return *ClientDeleteStoreResponse + */ + DeleteStoreExecute(request SdkClientDeleteStoreRequestInterface) (*ClientDeleteStoreResponse, error) + + /* Authorization Models */ + + /* + * ReadAuthorizationModels Read all authorization models in the store. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadAuthorizationModelsRequest + */ + ReadAuthorizationModels(ctx _context.Context) SdkClientReadAuthorizationModelsRequestInterface + + /* + * ReadAuthorizationModelsExecute executes the ReadAuthorizationModels request + * @return *ClientReadAuthorizationModelsResponse + */ + ReadAuthorizationModelsExecute(request SdkClientReadAuthorizationModelsRequestInterface) (*ClientReadAuthorizationModelsResponse, error) + + /* + * WriteAuthorizationModel Create a new authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteAuthorizationModelRequest + */ + WriteAuthorizationModel(ctx _context.Context) SdkClientWriteAuthorizationModelRequestInterface + + /* + * WriteAuthorizationModelExecute executes the WriteAuthorizationModel request + * @return *ClientWriteAuthorizationModelResponse + */ + WriteAuthorizationModelExecute(request SdkClientWriteAuthorizationModelRequestInterface) (*ClientWriteAuthorizationModelResponse, error) + + /* + * ReadAuthorizationModel Read a particular authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadAuthorizationModelRequestInterface + */ + ReadAuthorizationModel(ctx _context.Context) SdkClientReadAuthorizationModelRequestInterface + + /* + * ReadAuthorizationModelExecute executes the ReadAuthorizationModel request + * @return *ClientReadAuthorizationModelResponse + */ + ReadAuthorizationModelExecute(request SdkClientReadAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) + + /* + * ReadLatestAuthorizationModel Reads the latest authorization model (note: this ignores the model id in configuration). + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadLatestAuthorizationModelRequestInterface + */ + ReadLatestAuthorizationModel(ctx _context.Context) SdkClientReadLatestAuthorizationModelRequestInterface + + /* + * ReadLatestAuthorizationModelExecute executes the ReadLatestAuthorizationModel request + * @return *ClientReadAuthorizationModelResponse + */ + ReadLatestAuthorizationModelExecute(request SdkClientReadLatestAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) + + /* Relationship Tuples */ + + /* + * ReadChanges Reads the list of historical relationship tuple writes and deletes. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadChangesRequestInterface + */ + ReadChanges(ctx _context.Context) SdkClientReadChangesRequestInterface + + /* + * ReadChangesExecute executes the ReadChanges request + * @return *ClientReadChangesResponse + */ + ReadChangesExecute(request SdkClientReadChangesRequestInterface) (*ClientReadChangesResponse, error) + + /* + * Read Reads the relationship tuples stored in the database. It does not evaluate nor exclude invalid tuples according to the authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadRequestInterface + */ + Read(ctx _context.Context) SdkClientReadRequestInterface + + /* + * ReadExecute executes the Read request + * @return *ClientReadResponse + */ + ReadExecute(request SdkClientReadRequestInterface) (*ClientReadResponse, error) + + /* + * Write Create and/or delete relationship tuples to update the system state. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteRequestInterface + */ + Write(ctx _context.Context) SdkClientWriteRequestInterface + + /* + * WriteExecute executes the Write request + * @return *ClientWriteResponse + */ + WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) + + /* + * WriteTuples Utility method around Write + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteTuplesRequestInterface + */ + WriteTuples(ctx _context.Context) SdkClientWriteTuplesRequestInterface + + /* + * WriteTuplesExecute executes the WriteTuples request + * @return *ClientWriteResponse + */ + WriteTuplesExecute(request SdkClientWriteTuplesRequestInterface) (*ClientWriteResponse, error) + + /* + * DeleteTuples Utility method around Write + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientDeleteTuplesRequestInterface + */ + DeleteTuples(ctx _context.Context) SdkClientDeleteTuplesRequestInterface + + /* + * DeleteTuplesExecute executes the DeleteTuples request + * @return *ClientWriteResponse + */ + DeleteTuplesExecute(request SdkClientDeleteTuplesRequestInterface) (*ClientWriteResponse, error) + + /* Relationship Queries */ + + /* + * Check Check if a user has a particular relation with an object. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientCheckRequestInterface + */ + Check(ctx _context.Context) SdkClientCheckRequestInterface + + /* + * CheckExecute executes the Check request + * @return *ClientCheckResponse + */ + CheckExecute(request SdkClientCheckRequestInterface) (*ClientCheckResponse, error) + + /* + * ClientBatchCheck Run a set of [checks](#check). Batch Check will return `allowed: false` if it encounters an error, and will return the error in the body. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientBatchCheckRequestInterface + */ + ClientBatchCheck(ctx _context.Context) SdkClientBatchCheckClientRequestInterface + + /* + * ClientBatchCheckExecute executes the BatchCheck request + * @return *ClientBatchCheckResponse + */ + ClientBatchCheckExecute(request SdkClientBatchCheckClientRequestInterface) (*ClientBatchCheckClientResponse, error) + + /* + * BatchCheck Run a set of checks on the server. Server-side batch check allows for more efficient checking of multiple tuples. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientBatchCheckRequestInterface + */ + BatchCheck(ctx _context.Context) SdkClientBatchCheckRequestInterface + + /* + * BatchCheckExecute executes the server-side BatchCheck request + * @return *BatchCheckResponse + */ + BatchCheckExecute(request SdkClientBatchCheckRequestInterface) (*fgaSdk.BatchCheckResponse, error) + + /* + * Expand Expands the relationships in userset tree format. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientExpandRequestInterface + */ + Expand(ctx _context.Context) SdkClientExpandRequestInterface + + /* + * ExpandExecute executes the Expand request + * @return *ClientExpandResponse + */ + ExpandExecute(request SdkClientExpandRequestInterface) (*ClientExpandResponse, error) + + /* + * ListObjects List the objects of a particular type a user has access to. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientListObjectsRequestInterface + */ + ListObjects(ctx _context.Context) SdkClientListObjectsRequestInterface + + /* + * ListObjectsExecute executes the ListObjects request + * @return *ClientListObjectsResponse + */ + ListObjectsExecute(request SdkClientListObjectsRequestInterface) (*ClientListObjectsResponse, error) + + /* + * ListRelations List the relations a user has on an object. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientListRelationsRequestInterface + */ + ListRelations(ctx _context.Context) SdkClientListRelationsRequestInterface + + /* + * ListRelationsExecute executes the ListRelations request + * @return *ClientListRelationsResponse + */ + ListRelationsExecute(request SdkClientListRelationsRequestInterface) (*ClientListRelationsResponse, error) + + /* + * ListUsers List all users of the given type that the object has a relation with + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiListUsersRequest + */ + ListUsers(ctx _context.Context) SdkClientListUsersRequestInterface + + /* + * ListUsersExecute executes the request + * @return ListUsersResponse + */ + ListUsersExecute(r SdkClientListUsersRequestInterface) (*ClientListUsersResponse, error) + + /* + * StreamedListObjects Stream all objects of the given type that the user has a relation with + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientStreamedListObjectsRequestInterface + */ + StreamedListObjects(ctx _context.Context) SdkClientStreamedListObjectsRequestInterface + + /* + * StreamedListObjectsExecute executes the StreamedListObjects request and returns a channel + * @return *ClientStreamedListObjectsResponse + */ + StreamedListObjectsExecute(request SdkClientStreamedListObjectsRequestInterface) (*ClientStreamedListObjectsResponse, error) + + /* Assertions */ + + /* + * ReadAssertions Read assertions for a particular authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientReadAssertionsRequestInterface + */ + ReadAssertions(ctx _context.Context) SdkClientReadAssertionsRequestInterface + + /* + * ReadAssertionsExecute executes the ReadAssertions request + * @return *ClientReadAssertionsResponse + */ + ReadAssertionsExecute(request SdkClientReadAssertionsRequestInterface) (*ClientReadAssertionsResponse, error) + + /* + * WriteAssertions Update the assertions for a particular authorization model. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return SdkClientWriteAssertionsRequestInterface + */ + WriteAssertions(ctx _context.Context) SdkClientWriteAssertionsRequestInterface + + /* + * WriteAssertionsExecute executes the WriteAssertions request + * @return *ClientWriteAssertionsResponse + */ + WriteAssertionsExecute(request SdkClientWriteAssertionsRequestInterface) (*ClientWriteAssertionsResponse, error) + + /* + * SetAuthorizationModelId allows setting the Authorization Model ID for an OpenFgaClient. + * @param string authorizationModelId - The Authorization Model ID to set. + */ + SetAuthorizationModelId(authorizationModelId string) error + /* + * GetAuthorizationModelId retrieves the Authorization Model ID for an OpenFgaClient. + * @return string + */ + GetAuthorizationModelId() (string, error) + /* + * SetStoreId allows setting the Store ID for an OpenFgaClient. + * @param string storeId - The Store ID to set. + */ + SetStoreId(storeId string) error + /* + * GetStoreId retrieves the Store ID set in the OpenFgaClient. + * @return string + */ + GetStoreId() (string, error) } func (client *OpenFgaClient) SetAuthorizationModelId(authorizationModelId string) error { - if authorizationModelId != "" && !internalutils.IsWellFormedUlidString(authorizationModelId) { - return FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } + if authorizationModelId != "" && !internalutils.IsWellFormedUlidString(authorizationModelId) { + return FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } - client.config.AuthorizationModelId = authorizationModelId + client.config.AuthorizationModelId = authorizationModelId - return nil + return nil } func (client *OpenFgaClient) GetAuthorizationModelId() (string, error) { - modelId := client.config.AuthorizationModelId - if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { - return "", FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } + modelId := client.config.AuthorizationModelId + if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { + return "", FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } - return modelId, nil + return modelId, nil } func (client *OpenFgaClient) getAuthorizationModelId(authorizationModelId *string) (*string, error) { - modelId := client.config.AuthorizationModelId - if authorizationModelId != nil && *authorizationModelId != "" { - modelId = *authorizationModelId - } + modelId := client.config.AuthorizationModelId + if authorizationModelId != nil && *authorizationModelId != "" { + modelId = *authorizationModelId + } - if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { - return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} - } - return &modelId, nil + if modelId != "" && !internalutils.IsWellFormedUlidString(modelId) { + return nil, FgaInvalidError{param: "AuthorizationModelId", description: "Expected ULID format"} + } + return &modelId, nil } func (client *OpenFgaClient) SetStoreId(storeId string) error { - if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { - return FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } - client.config.StoreId = storeId - return nil + if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { + return FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } + client.config.StoreId = storeId + return nil } func (client *OpenFgaClient) GetStoreId() (string, error) { - storeId := client.config.StoreId - if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { - return "", FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } - return storeId, nil + storeId := client.config.StoreId + if storeId != "" && !internalutils.IsWellFormedUlidString(storeId) { + return "", FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } + return storeId, nil } func (client *OpenFgaClient) getStoreId(storeId *string) (*string, error) { - store := client.config.StoreId - if storeId != nil && *storeId != "" { - store = *storeId - } - if store != "" && !internalutils.IsWellFormedUlidString(store) { - return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} - } + store := client.config.StoreId + if storeId != nil && *storeId != "" { + store = *storeId + } + if store != "" && !internalutils.IsWellFormedUlidString(store) { + return nil, FgaInvalidError{param: "StoreId", description: "Expected ULID format"} + } - return &store, nil + return &store, nil } /* Stores */ // / ListStores type SdkClientListStoresRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientListStoresOptions + options *ClientListStoresOptions } type SdkClientListStoresRequestInterface interface { - Options(options ClientListStoresOptions) SdkClientListStoresRequestInterface - Execute() (*ClientListStoresResponse, error) - GetContext() _context.Context - GetOptions() *ClientListStoresOptions + Options(options ClientListStoresOptions) SdkClientListStoresRequestInterface + Execute() (*ClientListStoresResponse, error) + GetContext() _context.Context + GetOptions() *ClientListStoresOptions } type ClientListStoresOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - Name *string `json:"name,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + Name *string `json:"name,omitempty"` } type ClientListStoresResponse = fgaSdk.ListStoresResponse func (request *SdkClientListStoresRequest) Options(options ClientListStoresOptions) SdkClientListStoresRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListStoresRequest) Execute() (*ClientListStoresResponse, error) { - return request.Client.ListStoresExecute(request) + return request.Client.ListStoresExecute(request) } func (request *SdkClientListStoresRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListStoresRequest) GetOptions() *ClientListStoresOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListStoresExecute(request SdkClientListStoresRequestInterface) (*ClientListStoresResponse, error) { - req := client.OpenFgaApi.ListStores(request.GetContext()) - options := request.GetOptions() - if options != nil { - req = req.Options(options.RequestOptions) - if options.PageSize != nil { - req = req.PageSize(*options.PageSize) - } - if options.ContinuationToken != nil { - req = req.ContinuationToken(*options.ContinuationToken) - } - if options.Name != nil { - req = req.Name(*options.Name) - } - } - - data, _, err := req.Execute() - if err != nil { - return nil, err - } - return &data, nil + req := client.OpenFgaApi.ListStores(request.GetContext()) + options := request.GetOptions() + if options != nil { + req = req.Options(options.RequestOptions) + if options.PageSize != nil { + req = req.PageSize(*options.PageSize) + } + if options.ContinuationToken != nil { + req = req.ContinuationToken(*options.ContinuationToken) + } + if options.Name != nil { + req = req.Name(*options.Name) + } + } + + data, _, err := req.Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) ListStores(ctx _context.Context) SdkClientListStoresRequestInterface { - return &SdkClientListStoresRequest{ - ctx: ctx, - Client: client, - } + return &SdkClientListStoresRequest{ + ctx: ctx, + Client: client, + } } // / CreateStore type SdkClientCreateStoreRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientCreateStoreRequest - options *ClientCreateStoreOptions + body *ClientCreateStoreRequest + options *ClientCreateStoreOptions } type SdkClientCreateStoreRequestInterface interface { - Options(options ClientCreateStoreOptions) SdkClientCreateStoreRequestInterface - Body(body ClientCreateStoreRequest) SdkClientCreateStoreRequestInterface - Execute() (*ClientCreateStoreResponse, error) + Options(options ClientCreateStoreOptions) SdkClientCreateStoreRequestInterface + Body(body ClientCreateStoreRequest) SdkClientCreateStoreRequestInterface + Execute() (*ClientCreateStoreResponse, error) - GetContext() _context.Context - GetOptions() *ClientCreateStoreOptions - GetBody() *ClientCreateStoreRequest + GetContext() _context.Context + GetOptions() *ClientCreateStoreOptions + GetBody() *ClientCreateStoreRequest } type ClientCreateStoreRequest struct { - Name string `json:"name"` + Name string `json:"name"` } type ClientCreateStoreOptions struct { - RequestOptions + RequestOptions } type ClientCreateStoreResponse = fgaSdk.CreateStoreResponse func (request *SdkClientCreateStoreRequest) Options(options ClientCreateStoreOptions) SdkClientCreateStoreRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientCreateStoreRequest) Body(body ClientCreateStoreRequest) SdkClientCreateStoreRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientCreateStoreRequest) Execute() (*ClientCreateStoreResponse, error) { - return request.Client.CreateStoreExecute(request) + return request.Client.CreateStoreExecute(request) } func (request *SdkClientCreateStoreRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientCreateStoreRequest) GetOptions() *ClientCreateStoreOptions { - return request.options + return request.options } func (request *SdkClientCreateStoreRequest) GetBody() *ClientCreateStoreRequest { - return request.body + return request.body } func (client *OpenFgaClient) CreateStoreExecute(request SdkClientCreateStoreRequestInterface) (*ClientCreateStoreResponse, error) { - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - requestBody := fgaSdk.CreateStoreRequest{ - Name: request.GetBody().Name, - } - - data, _, err := client.OpenFgaApi. - CreateStore(request.GetContext()). - Body(requestBody). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + requestBody := fgaSdk.CreateStoreRequest{ + Name: request.GetBody().Name, + } + + data, _, err := client.OpenFgaApi. + CreateStore(request.GetContext()). + Body(requestBody). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) CreateStore(ctx _context.Context) SdkClientCreateStoreRequestInterface { - return &SdkClientCreateStoreRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientCreateStoreRequest{ + Client: client, + ctx: ctx, + } } // / GetStore type SdkClientGetStoreRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientGetStoreOptions + options *ClientGetStoreOptions } type SdkClientGetStoreRequestInterface interface { - Options(options ClientGetStoreOptions) SdkClientGetStoreRequestInterface - Execute() (*ClientGetStoreResponse, error) - GetStoreIdOverride() *string + Options(options ClientGetStoreOptions) SdkClientGetStoreRequestInterface + Execute() (*ClientGetStoreResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientGetStoreOptions + GetContext() _context.Context + GetOptions() *ClientGetStoreOptions } type ClientGetStoreOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientGetStoreResponse = fgaSdk.GetStoreResponse func (request *SdkClientGetStoreRequest) Options(options ClientGetStoreOptions) SdkClientGetStoreRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientGetStoreRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientGetStoreRequest) Execute() (*ClientGetStoreResponse, error) { - return request.Client.GetStoreExecute(request) + return request.Client.GetStoreExecute(request) } func (request *SdkClientGetStoreRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientGetStoreRequest) GetOptions() *ClientGetStoreOptions { - return request.options + return request.options } func (client *OpenFgaClient) GetStoreExecute(request SdkClientGetStoreRequestInterface) (*ClientGetStoreResponse, error) { - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - GetStore(request.GetContext(), *storeId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + GetStore(request.GetContext(), *storeId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) GetStore(ctx _context.Context) SdkClientGetStoreRequestInterface { - return &SdkClientGetStoreRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientGetStoreRequest{ + Client: client, + ctx: ctx, + } } // / DeleteStore type SdkClientDeleteStoreRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientDeleteStoreOptions + options *ClientDeleteStoreOptions } type SdkClientDeleteStoreRequestInterface interface { - Options(options ClientDeleteStoreOptions) SdkClientDeleteStoreRequestInterface - Execute() (*ClientDeleteStoreResponse, error) - GetStoreIdOverride() *string + Options(options ClientDeleteStoreOptions) SdkClientDeleteStoreRequestInterface + Execute() (*ClientDeleteStoreResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientDeleteStoreOptions + GetContext() _context.Context + GetOptions() *ClientDeleteStoreOptions } type ClientDeleteStoreOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientDeleteStoreResponse struct{} func (request *SdkClientDeleteStoreRequest) Options(options ClientDeleteStoreOptions) SdkClientDeleteStoreRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientDeleteStoreRequest) Execute() (*ClientDeleteStoreResponse, error) { - return request.Client.DeleteStoreExecute(request) + return request.Client.DeleteStoreExecute(request) } func (request *SdkClientDeleteStoreRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientDeleteStoreRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientDeleteStoreRequest) GetOptions() *ClientDeleteStoreOptions { - return request.options + return request.options } func (client *OpenFgaClient) DeleteStoreExecute(request SdkClientDeleteStoreRequestInterface) (*ClientDeleteStoreResponse, error) { - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - _, err = client.OpenFgaApi. - DeleteStore(request.GetContext(), *storeId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &ClientDeleteStoreResponse{}, nil + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + _, err = client.OpenFgaApi. + DeleteStore(request.GetContext(), *storeId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &ClientDeleteStoreResponse{}, nil } func (client *OpenFgaClient) DeleteStore(ctx _context.Context) SdkClientDeleteStoreRequestInterface { - return &SdkClientDeleteStoreRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientDeleteStoreRequest{ + Client: client, + ctx: ctx, + } } /* Authorization Models */ // / ReadAuthorizationModels type SdkClientReadAuthorizationModelsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientReadAuthorizationModelsOptions + options *ClientReadAuthorizationModelsOptions } type SdkClientReadAuthorizationModelsRequestInterface interface { - Options(options ClientReadAuthorizationModelsOptions) SdkClientReadAuthorizationModelsRequestInterface - Execute() (*ClientReadAuthorizationModelsResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadAuthorizationModelsOptions) SdkClientReadAuthorizationModelsRequestInterface + Execute() (*ClientReadAuthorizationModelsResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientReadAuthorizationModelsOptions + GetContext() _context.Context + GetOptions() *ClientReadAuthorizationModelsOptions } type ClientReadAuthorizationModelsOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - StoreId *string `json:"store_id,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientReadAuthorizationModelsResponse = fgaSdk.ReadAuthorizationModelsResponse func (request *SdkClientReadAuthorizationModelsRequest) Options(options ClientReadAuthorizationModelsOptions) SdkClientReadAuthorizationModelsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadAuthorizationModelsRequest) Execute() (*ClientReadAuthorizationModelsResponse, error) { - return request.Client.ReadAuthorizationModelsExecute(request) + return request.Client.ReadAuthorizationModelsExecute(request) } func (request *SdkClientReadAuthorizationModelsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadAuthorizationModelsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadAuthorizationModelsRequest) GetOptions() *ClientReadAuthorizationModelsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadAuthorizationModelsExecute(request SdkClientReadAuthorizationModelsRequestInterface) (*ClientReadAuthorizationModelsResponse, error) { - pagingOpts := ClientPaginationOptions{} - if request.GetOptions() != nil { - pagingOpts.PageSize = request.GetOptions().PageSize - pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - req := client.OpenFgaApi. - ReadAuthorizationModels(request.GetContext(), *storeId). - Options(requestOptions) - - pageSize := getPageSizeFromRequest(&pagingOpts) - if pageSize != nil { - req = req.PageSize(*pageSize) - } - continuationToken := getContinuationTokenFromRequest(&pagingOpts) - if continuationToken != nil { - req = req.ContinuationToken(*continuationToken) - } - data, _, err := req.Execute() - if err != nil { - return nil, err - } - return &data, nil + pagingOpts := ClientPaginationOptions{} + if request.GetOptions() != nil { + pagingOpts.PageSize = request.GetOptions().PageSize + pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + req := client.OpenFgaApi. + ReadAuthorizationModels(request.GetContext(), *storeId). + Options(requestOptions) + + pageSize := getPageSizeFromRequest(&pagingOpts) + if pageSize != nil { + req = req.PageSize(*pageSize) + } + continuationToken := getContinuationTokenFromRequest(&pagingOpts) + if continuationToken != nil { + req = req.ContinuationToken(*continuationToken) + } + data, _, err := req.Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) ReadAuthorizationModels(ctx _context.Context) SdkClientReadAuthorizationModelsRequestInterface { - return &SdkClientReadAuthorizationModelsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadAuthorizationModelsRequest{ + Client: client, + ctx: ctx, + } } // / WriteAuthorizationModel type SdkClientWriteAuthorizationModelRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteAuthorizationModelRequest - options *ClientWriteAuthorizationModelOptions + body *ClientWriteAuthorizationModelRequest + options *ClientWriteAuthorizationModelOptions } type SdkClientWriteAuthorizationModelRequestInterface interface { - Options(options ClientWriteAuthorizationModelOptions) SdkClientWriteAuthorizationModelRequestInterface - Body(body ClientWriteAuthorizationModelRequest) SdkClientWriteAuthorizationModelRequestInterface - Execute() (*ClientWriteAuthorizationModelResponse, error) - GetStoreIdOverride() *string + Options(options ClientWriteAuthorizationModelOptions) SdkClientWriteAuthorizationModelRequestInterface + Body(body ClientWriteAuthorizationModelRequest) SdkClientWriteAuthorizationModelRequestInterface + Execute() (*ClientWriteAuthorizationModelResponse, error) + GetStoreIdOverride() *string - GetBody() *ClientWriteAuthorizationModelRequest - GetOptions() *ClientWriteAuthorizationModelOptions - GetContext() _context.Context + GetBody() *ClientWriteAuthorizationModelRequest + GetOptions() *ClientWriteAuthorizationModelOptions + GetContext() _context.Context } type ClientWriteAuthorizationModelRequest = fgaSdk.WriteAuthorizationModelRequest type ClientWriteAuthorizationModelOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientWriteAuthorizationModelResponse = fgaSdk.WriteAuthorizationModelResponse func (request *SdkClientWriteAuthorizationModelRequest) Options(options ClientWriteAuthorizationModelOptions) SdkClientWriteAuthorizationModelRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteAuthorizationModelRequest) Body(body ClientWriteAuthorizationModelRequest) SdkClientWriteAuthorizationModelRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteAuthorizationModelRequest) Execute() (*ClientWriteAuthorizationModelResponse, error) { - return request.Client.WriteAuthorizationModelExecute(request) + return request.Client.WriteAuthorizationModelExecute(request) } func (request *SdkClientWriteAuthorizationModelRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientWriteAuthorizationModelRequest) GetBody() *ClientWriteAuthorizationModelRequest { - return request.body + return request.body } func (request *SdkClientWriteAuthorizationModelRequest) GetOptions() *ClientWriteAuthorizationModelOptions { - return request.options + return request.options } func (request *SdkClientWriteAuthorizationModelRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (client *OpenFgaClient) WriteAuthorizationModelExecute(request SdkClientWriteAuthorizationModelRequestInterface) (*ClientWriteAuthorizationModelResponse, error) { - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - WriteAuthorizationModel(request.GetContext(), *storeId). - Body(*request.GetBody()). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + WriteAuthorizationModel(request.GetContext(), *storeId). + Body(*request.GetBody()). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) WriteAuthorizationModel(ctx _context.Context) SdkClientWriteAuthorizationModelRequestInterface { - return &SdkClientWriteAuthorizationModelRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteAuthorizationModelRequest{ + Client: client, + ctx: ctx, + } } // / ReadAuthorizationModel type SdkClientReadAuthorizationModelRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientReadAuthorizationModelRequest - options *ClientReadAuthorizationModelOptions + body *ClientReadAuthorizationModelRequest + options *ClientReadAuthorizationModelOptions } type SdkClientReadAuthorizationModelRequestInterface interface { - Options(options ClientReadAuthorizationModelOptions) SdkClientReadAuthorizationModelRequestInterface - Body(body ClientReadAuthorizationModelRequest) SdkClientReadAuthorizationModelRequestInterface - Execute() (*ClientReadAuthorizationModelResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientReadAuthorizationModelOptions) SdkClientReadAuthorizationModelRequestInterface + Body(body ClientReadAuthorizationModelRequest) SdkClientReadAuthorizationModelRequestInterface + Execute() (*ClientReadAuthorizationModelResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientReadAuthorizationModelRequest - GetOptions() *ClientReadAuthorizationModelOptions + GetContext() _context.Context + GetBody() *ClientReadAuthorizationModelRequest + GetOptions() *ClientReadAuthorizationModelOptions } type ClientReadAuthorizationModelRequest struct { } type ClientReadAuthorizationModelOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientReadAuthorizationModelResponse = fgaSdk.ReadAuthorizationModelResponse func (request *SdkClientReadAuthorizationModelRequest) Options(options ClientReadAuthorizationModelOptions) SdkClientReadAuthorizationModelRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadAuthorizationModelRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientReadAuthorizationModelRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadAuthorizationModelRequest) Body(body ClientReadAuthorizationModelRequest) SdkClientReadAuthorizationModelRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientReadAuthorizationModelRequest) Execute() (*ClientReadAuthorizationModelResponse, error) { - return request.Client.ReadAuthorizationModelExecute(request) + return request.Client.ReadAuthorizationModelExecute(request) } func (request *SdkClientReadAuthorizationModelRequest) GetBody() *ClientReadAuthorizationModelRequest { - return request.body + return request.body } func (request *SdkClientReadAuthorizationModelRequest) GetOptions() *ClientReadAuthorizationModelOptions { - return request.options + return request.options } func (request *SdkClientReadAuthorizationModelRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (client *OpenFgaClient) ReadAuthorizationModelExecute(request SdkClientReadAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) { - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - if authorizationModelId == nil || *authorizationModelId == "" { - return nil, FgaRequiredParamError{param: "AuthorizationModelId"} - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - ReadAuthorizationModel(request.GetContext(), *storeId, *authorizationModelId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + if authorizationModelId == nil || *authorizationModelId == "" { + return nil, FgaRequiredParamError{param: "AuthorizationModelId"} + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + ReadAuthorizationModel(request.GetContext(), *storeId, *authorizationModelId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } func (client *OpenFgaClient) ReadAuthorizationModel(ctx _context.Context) SdkClientReadAuthorizationModelRequestInterface { - return &SdkClientReadAuthorizationModelRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadAuthorizationModelRequest{ + Client: client, + ctx: ctx, + } } // / ReadLatestAuthorizationModel type SdkClientReadLatestAuthorizationModelRequest struct { - ctx _context.Context - Client OpenFgaClient + ctx _context.Context + Client OpenFgaClient - options *ClientReadLatestAuthorizationModelOptions + options *ClientReadLatestAuthorizationModelOptions } type SdkClientReadLatestAuthorizationModelRequestInterface interface { - Options(options ClientReadLatestAuthorizationModelOptions) SdkClientReadLatestAuthorizationModelRequestInterface - Execute() (*ClientReadAuthorizationModelResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadLatestAuthorizationModelOptions) SdkClientReadLatestAuthorizationModelRequestInterface + Execute() (*ClientReadAuthorizationModelResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientReadLatestAuthorizationModelOptions + GetContext() _context.Context + GetOptions() *ClientReadLatestAuthorizationModelOptions } type ClientReadLatestAuthorizationModelOptions struct { - RequestOptions + RequestOptions - StoreId *string `json:"store_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } func (client *OpenFgaClient) ReadLatestAuthorizationModel(ctx _context.Context) SdkClientReadLatestAuthorizationModelRequestInterface { - return &SdkClientReadLatestAuthorizationModelRequest{ - Client: *client, - ctx: ctx, - } + return &SdkClientReadLatestAuthorizationModelRequest{ + Client: *client, + ctx: ctx, + } } func (request *SdkClientReadLatestAuthorizationModelRequest) Options(options ClientReadLatestAuthorizationModelOptions) SdkClientReadLatestAuthorizationModelRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadLatestAuthorizationModelRequest) Execute() (*ClientReadAuthorizationModelResponse, error) { - return request.Client.ReadLatestAuthorizationModelExecute(request) + return request.Client.ReadLatestAuthorizationModelExecute(request) } func (request *SdkClientReadLatestAuthorizationModelRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadLatestAuthorizationModelRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadLatestAuthorizationModelRequest) GetOptions() *ClientReadLatestAuthorizationModelOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadLatestAuthorizationModelExecute(request SdkClientReadLatestAuthorizationModelRequestInterface) (*ClientReadAuthorizationModelResponse, error) { - opts := ClientReadAuthorizationModelsOptions{ - PageSize: fgaSdk.PtrInt32(1), - } - if request.GetOptions() != nil { - opts.StoreId = request.GetOptions().StoreId - opts.RequestOptions = request.GetOptions().RequestOptions - } - req := client.ReadAuthorizationModels(request.GetContext()).Options(opts) + opts := ClientReadAuthorizationModelsOptions{ + PageSize: fgaSdk.PtrInt32(1), + } + if request.GetOptions() != nil { + opts.StoreId = request.GetOptions().StoreId + opts.RequestOptions = request.GetOptions().RequestOptions + } + req := client.ReadAuthorizationModels(request.GetContext()).Options(opts) - response, err := req.Execute() - if err != nil { - return nil, err - } + response, err := req.Execute() + if err != nil { + return nil, err + } - var authorizationModel *fgaSdk.AuthorizationModel + var authorizationModel *fgaSdk.AuthorizationModel - if len(response.AuthorizationModels) > 0 { - authorizationModels := response.AuthorizationModels - authorizationModel = &(authorizationModels)[0] - } + if len(response.AuthorizationModels) > 0 { + authorizationModels := response.AuthorizationModels + authorizationModel = &(authorizationModels)[0] + } - return &fgaSdk.ReadAuthorizationModelResponse{ - AuthorizationModel: authorizationModel, - }, nil + return &fgaSdk.ReadAuthorizationModelResponse{ + AuthorizationModel: authorizationModel, + }, nil } /* Relationship Tuples */ // / ReadChanges type SdkClientReadChangesRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientReadChangesRequest - options *ClientReadChangesOptions + body *ClientReadChangesRequest + options *ClientReadChangesOptions } type SdkClientReadChangesRequestInterface interface { - Options(options ClientReadChangesOptions) SdkClientReadChangesRequestInterface - Body(body ClientReadChangesRequest) SdkClientReadChangesRequestInterface - Execute() (*ClientReadChangesResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadChangesOptions) SdkClientReadChangesRequestInterface + Body(body ClientReadChangesRequest) SdkClientReadChangesRequestInterface + Execute() (*ClientReadChangesResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientReadChangesRequest - GetOptions() *ClientReadChangesOptions + GetContext() _context.Context + GetBody() *ClientReadChangesRequest + GetOptions() *ClientReadChangesOptions } type ClientReadChangesRequest struct { - Type string `json:"type,omitempty"` - StartTime time.Time `json:"start_time,omitempty"` + Type string `json:"type,omitempty"` + StartTime time.Time `json:"start_time,omitempty"` } type ClientReadChangesOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - StoreId *string `json:"store_id"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + StoreId *string `json:"store_id"` } type ClientReadChangesResponse = fgaSdk.ReadChangesResponse func (client *OpenFgaClient) ReadChanges(ctx _context.Context) SdkClientReadChangesRequestInterface { - return &SdkClientReadChangesRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadChangesRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientReadChangesRequest) Options(options ClientReadChangesOptions) SdkClientReadChangesRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadChangesRequest) Body(body ClientReadChangesRequest) SdkClientReadChangesRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientReadChangesRequest) Execute() (*ClientReadChangesResponse, error) { - return request.Client.ReadChangesExecute(request) + return request.Client.ReadChangesExecute(request) } func (request *SdkClientReadChangesRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadChangesRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadChangesRequest) GetBody() *ClientReadChangesRequest { - return request.body + return request.body } func (request *SdkClientReadChangesRequest) GetOptions() *ClientReadChangesOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadChangesExecute(request SdkClientReadChangesRequestInterface) (*ClientReadChangesResponse, error) { - pagingOpts := ClientPaginationOptions{} - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - pagingOpts.PageSize = request.GetOptions().PageSize - pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - req := client.OpenFgaApi. - ReadChanges(request.GetContext(), *storeId). - Options(requestOptions) - pageSize := getPageSizeFromRequest(&pagingOpts) - if pageSize != nil { - req = req.PageSize(*pageSize) - } - continuationToken := getContinuationTokenFromRequest(&pagingOpts) - if continuationToken != nil { - req = req.ContinuationToken(*continuationToken) - } - requestBody := request.GetBody() - if requestBody != nil && requestBody.Type != "" { - req = req.Type_(requestBody.Type) - } - if requestBody != nil && !requestBody.StartTime.IsZero() { - req = req.StartTime(requestBody.StartTime) - } - - data, _, err := req.Execute() - if err != nil { - return nil, err - } - return &data, nil + pagingOpts := ClientPaginationOptions{} + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + pagingOpts.PageSize = request.GetOptions().PageSize + pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + req := client.OpenFgaApi. + ReadChanges(request.GetContext(), *storeId). + Options(requestOptions) + pageSize := getPageSizeFromRequest(&pagingOpts) + if pageSize != nil { + req = req.PageSize(*pageSize) + } + continuationToken := getContinuationTokenFromRequest(&pagingOpts) + if continuationToken != nil { + req = req.ContinuationToken(*continuationToken) + } + requestBody := request.GetBody() + if requestBody != nil && requestBody.Type != "" { + req = req.Type_(requestBody.Type) + } + if requestBody != nil && !requestBody.StartTime.IsZero() { + req = req.StartTime(requestBody.StartTime) + } + + data, _, err := req.Execute() + if err != nil { + return nil, err + } + return &data, nil } // / Read type SdkClientReadRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientReadRequest - options *ClientReadOptions + body *ClientReadRequest + options *ClientReadOptions } type SdkClientReadRequestInterface interface { - Options(options ClientReadOptions) SdkClientReadRequestInterface - Body(body ClientReadRequest) SdkClientReadRequestInterface - Execute() (*ClientReadResponse, error) - GetStoreIdOverride() *string + Options(options ClientReadOptions) SdkClientReadRequestInterface + Body(body ClientReadRequest) SdkClientReadRequestInterface + Execute() (*ClientReadResponse, error) + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientReadRequest - GetOptions() *ClientReadOptions + GetContext() _context.Context + GetBody() *ClientReadRequest + GetOptions() *ClientReadOptions } type ClientReadRequest struct { - User *string `json:"user,omitempty"` - Relation *string `json:"relation,omitempty"` - Object *string `json:"object,omitempty"` + User *string `json:"user,omitempty"` + Relation *string `json:"relation,omitempty"` + Object *string `json:"object,omitempty"` } type ClientReadOptions struct { - RequestOptions + RequestOptions - PageSize *int32 `json:"page_size,omitempty"` - ContinuationToken *string `json:"continuation_token,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + PageSize *int32 `json:"page_size,omitempty"` + ContinuationToken *string `json:"continuation_token,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientReadResponse = fgaSdk.ReadResponse func (client *OpenFgaClient) Read(ctx _context.Context) SdkClientReadRequestInterface { - return &SdkClientReadRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientReadRequest) Options(options ClientReadOptions) SdkClientReadRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadRequest) Body(body ClientReadRequest) SdkClientReadRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientReadRequest) Execute() (*ClientReadResponse, error) { - return request.Client.ReadExecute(request) + return request.Client.ReadExecute(request) } func (request *SdkClientReadRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadRequest) GetBody() *ClientReadRequest { - return request.body + return request.body } func (request *SdkClientReadRequest) GetOptions() *ClientReadOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadExecute(request SdkClientReadRequestInterface) (*ClientReadResponse, error) { - pagingOpts := ClientPaginationOptions{} - requestOptions := RequestOptions{} - var consistency *fgaSdk.ConsistencyPreference - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - pagingOpts.PageSize = request.GetOptions().PageSize - pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken - consistency = request.GetOptions().Consistency - } - - body := fgaSdk.ReadRequest{ - PageSize: getPageSizeFromRequest(&pagingOpts), - ContinuationToken: getContinuationTokenFromRequest(&pagingOpts), - Consistency: consistency, - } - if request.GetBody() != nil && (request.GetBody().User != nil || request.GetBody().Relation != nil || request.GetBody().Object != nil) { - body.TupleKey = &fgaSdk.ReadRequestTupleKey{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Object: request.GetBody().Object, - } - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - data, _, err := client.OpenFgaApi. - Read(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + pagingOpts := ClientPaginationOptions{} + requestOptions := RequestOptions{} + var consistency *fgaSdk.ConsistencyPreference + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + pagingOpts.PageSize = request.GetOptions().PageSize + pagingOpts.ContinuationToken = request.GetOptions().ContinuationToken + consistency = request.GetOptions().Consistency + } + + body := fgaSdk.ReadRequest{ + PageSize: getPageSizeFromRequest(&pagingOpts), + ContinuationToken: getContinuationTokenFromRequest(&pagingOpts), + Consistency: consistency, + } + if request.GetBody() != nil && (request.GetBody().User != nil || request.GetBody().Relation != nil || request.GetBody().Object != nil) { + body.TupleKey = &fgaSdk.ReadRequestTupleKey{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Object: request.GetBody().Object, + } + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + data, _, err := client.OpenFgaApi. + Read(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / Write type SdkClientWriteRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteRequest - options *ClientWriteOptions + body *ClientWriteRequest + options *ClientWriteOptions } type SdkClientWriteRequestInterface interface { - Options(options ClientWriteOptions) SdkClientWriteRequestInterface - Body(body ClientWriteRequest) SdkClientWriteRequestInterface - Execute() (*ClientWriteResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientWriteOptions) SdkClientWriteRequestInterface + Body(body ClientWriteRequest) SdkClientWriteRequestInterface + Execute() (*ClientWriteResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientWriteOptions - GetBody() *ClientWriteRequest + GetContext() _context.Context + GetOptions() *ClientWriteOptions + GetBody() *ClientWriteRequest } type ClientWriteRequest struct { - Writes []ClientTupleKey - Deletes []ClientTupleKeyWithoutCondition + Writes []ClientTupleKey + Deletes []ClientTupleKeyWithoutCondition } type TransactionOptions struct { - // If set to true will disable running in transaction mode (transaction mode means everything is sent in a single transaction to the server) - Disable bool `json:"disable,omitempty"` - // When transaction mode is disabled, the requests are chunked and sent separately and each chunk is a transaction (default = 1) - MaxPerChunk int32 `json:"max_per_chunk,omitempty"` - // Number of requests to issue in parallel - MaxParallelRequests int32 `json:"max_parallel_requests,omitempty"` + // If set to true will disable running in transaction mode (transaction mode means everything is sent in a single transaction to the server) + Disable bool `json:"disable,omitempty"` + // When transaction mode is disabled, the requests are chunked and sent separately and each chunk is a transaction (default = 1) + MaxPerChunk int32 `json:"max_per_chunk,omitempty"` + // Number of requests to issue in parallel + MaxParallelRequests int32 `json:"max_parallel_requests,omitempty"` } // ClientWriteRequestOnDuplicateWrites indicates what to do when a write conflicts with an existing tuple type ClientWriteRequestOnDuplicateWrites string func (w *ClientWriteRequestOnDuplicateWrites) ToString() *string { - if w == nil { - return nil - } + if w == nil { + return nil + } - str := string(*w) + str := string(*w) - return &str + return &str } const ( - // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR returns an error if a write conflicts with an existing tuple (default) - CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR ClientWriteRequestOnDuplicateWrites = "error" - // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ignores writes that conflict with existing tuples (they must match exactly, including conditions) - CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ClientWriteRequestOnDuplicateWrites = "ignore" + // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR returns an error if a write conflicts with an existing tuple (default) + CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_ERROR ClientWriteRequestOnDuplicateWrites = "error" + // CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ignores writes that conflict with existing tuples (they must match exactly, including conditions) + CLIENT_WRITE_REQUEST_ON_DUPLICATE_WRITES_IGNORE ClientWriteRequestOnDuplicateWrites = "ignore" ) // ClientWriteRequestOnMissingDeletes indicates what to do when a delete is issued for a tuple that does not exist type ClientWriteRequestOnMissingDeletes string func (d *ClientWriteRequestOnMissingDeletes) ToString() *string { - if d == nil { - return nil - } + if d == nil { + return nil + } - str := string(*d) + str := string(*d) - return &str + return &str } const ( - // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR returns an error if a delete is issued for a tuple that does not exist (default) - CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR ClientWriteRequestOnMissingDeletes = "error" - // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ignores deletes for tuples that do not exist - CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ClientWriteRequestOnMissingDeletes = "ignore" + // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR returns an error if a delete is issued for a tuple that does not exist (default) + CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_ERROR ClientWriteRequestOnMissingDeletes = "error" + // CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ignores deletes for tuples that do not exist + CLIENT_WRITE_REQUEST_ON_MISSING_DELETES_IGNORE ClientWriteRequestOnMissingDeletes = "ignore" ) type ClientWriteConflictOptions struct { - // OnDuplicateWrites defines what to do when a write conflicts with an existing tuple - // Options are: "error" (default) or "ignore" - OnDuplicateWrites ClientWriteRequestOnDuplicateWrites `json:"on_duplicate_writes,omitempty"` - // OnMissingDeletes defines what to do when a delete is issued for a tuple that does not exist - // Options are: "error" (default) or "ignore" - OnMissingDeletes ClientWriteRequestOnMissingDeletes `json:"on_missing_deletes,omitempty"` + // OnDuplicateWrites defines what to do when a write conflicts with an existing tuple + // Options are: "error" (default) or "ignore" + OnDuplicateWrites ClientWriteRequestOnDuplicateWrites `json:"on_duplicate_writes,omitempty"` + // OnMissingDeletes defines what to do when a delete is issued for a tuple that does not exist + // Options are: "error" (default) or "ignore" + OnMissingDeletes ClientWriteRequestOnMissingDeletes `json:"on_missing_deletes,omitempty"` } type ClientWriteOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Transaction *TransactionOptions `json:"transaction_options,omitempty"` - Conflict ClientWriteConflictOptions + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Transaction *TransactionOptions `json:"transaction_options,omitempty"` + Conflict ClientWriteConflictOptions } type ClientWriteStatus string // List of ClientWriteStatus const ( - SUCCESS ClientWriteStatus = "CLIENT_WRITE_STATUS_SUCCESS" - FAILURE ClientWriteStatus = "CLIENT_WRITE_STATUS_FAILURE" + SUCCESS ClientWriteStatus = "CLIENT_WRITE_STATUS_SUCCESS" + FAILURE ClientWriteStatus = "CLIENT_WRITE_STATUS_FAILURE" ) type ClientWriteRequestWriteResponse struct { - TupleKey ClientTupleKey `json:"tuple_key,omitempty"` - Status ClientWriteStatus `json:"status,omitempty"` - HttpResponse *_nethttp.Response `json:"http_response,omitempty"` - Error error `json:"error,omitempty"` + TupleKey ClientTupleKey `json:"tuple_key,omitempty"` + Status ClientWriteStatus `json:"status,omitempty"` + HttpResponse *_nethttp.Response `json:"http_response,omitempty"` + Error error `json:"error,omitempty"` } func (o ClientWriteRequestWriteResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - toSerialize["tuple_key"] = o.TupleKey - toSerialize["status"] = o.Status - if o.Error != nil { - toSerialize["error"] = o.Error - } - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + toSerialize["tuple_key"] = o.TupleKey + toSerialize["status"] = o.Status + if o.Error != nil { + toSerialize["error"] = o.Error + } + return json.Marshal(toSerialize) } type ClientWriteRequestDeleteResponse struct { - TupleKey ClientTupleKeyWithoutCondition `json:"tuple_key,omitempty"` - Status ClientWriteStatus `json:"status,omitempty"` - HttpResponse *_nethttp.Response `json:"http_response,omitempty"` - Error error `json:"error,omitempty"` + TupleKey ClientTupleKeyWithoutCondition `json:"tuple_key,omitempty"` + Status ClientWriteStatus `json:"status,omitempty"` + HttpResponse *_nethttp.Response `json:"http_response,omitempty"` + Error error `json:"error,omitempty"` } func (o ClientWriteRequestDeleteResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - toSerialize["tuple_key"] = o.TupleKey - toSerialize["status"] = o.Status - if o.Error != nil { - toSerialize["error"] = o.Error - } - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + toSerialize["tuple_key"] = o.TupleKey + toSerialize["status"] = o.Status + if o.Error != nil { + toSerialize["error"] = o.Error + } + return json.Marshal(toSerialize) } type ClientWriteResponse struct { - Writes []ClientWriteRequestWriteResponse `json:"writes,omitempty"` - Deletes []ClientWriteRequestDeleteResponse `json:"deletes,omitempty"` + Writes []ClientWriteRequestWriteResponse `json:"writes,omitempty"` + Deletes []ClientWriteRequestDeleteResponse `json:"deletes,omitempty"` } func (o ClientWriteResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - if o.Writes != nil { - toSerialize["writes"] = o.Writes - } - if o.Deletes != nil { - toSerialize["deletes"] = o.Deletes - } - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + if o.Writes != nil { + toSerialize["writes"] = o.Writes + } + if o.Deletes != nil { + toSerialize["deletes"] = o.Deletes + } + return json.Marshal(toSerialize) } func (client *OpenFgaClient) Write(ctx _context.Context) SdkClientWriteRequestInterface { - return &SdkClientWriteRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientWriteRequest) Options(options ClientWriteOptions) SdkClientWriteRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientWriteRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientWriteRequest) Body(body ClientWriteRequest) SdkClientWriteRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteRequest) Execute() (*ClientWriteResponse, error) { - return request.Client.WriteExecute(request) + return request.Client.WriteExecute(request) } func (request *SdkClientWriteRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientWriteRequest) GetOptions() *ClientWriteOptions { - return request.options + return request.options } func (request *SdkClientWriteRequest) GetBody() *ClientWriteRequest { - return request.body + return request.body } func (client *OpenFgaClient) WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) { - options := request.GetOptions() - transactionOptionsSet := options != nil && options.Transaction != nil - response := ClientWriteResponse{ - Writes: []ClientWriteRequestWriteResponse{}, - Deletes: []ClientWriteRequestDeleteResponse{}, - } - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - // Unless explicitly disabled, transaction mode is enabled - // In transaction mode, the client will send the request to the server as is - if !transactionOptionsSet || !options.Transaction.Disable { - writeRequest := fgaSdk.WriteRequest{ - AuthorizationModelId: authorizationModelId, - } - if len(request.GetBody().Writes) > 0 { - writes := fgaSdk.WriteRequestWrites{} - if options != nil { - writes.OnDuplicate = options.Conflict.OnDuplicateWrites.ToString() - } - for index := 0; index < len(request.GetBody().Writes); index++ { - writes.TupleKeys = append(writes.TupleKeys, (request.GetBody().Writes)[index]) - } - writeRequest.Writes = &writes - } - if len(request.GetBody().Deletes) > 0 { - deletes := fgaSdk.WriteRequestDeletes{} - if options != nil { - deletes.OnMissing = options.Conflict.OnMissingDeletes.ToString() - } - for index := 0; index < len(request.GetBody().Deletes); index++ { - deletes.TupleKeys = append(deletes.TupleKeys, (request.GetBody().Deletes)[index]) - } - writeRequest.Deletes = &deletes - } - - _, httpResponse, err := client.OpenFgaApi. - Write(request.GetContext(), *storeId). - Body(writeRequest). - Options(requestOptions). - Execute() - - clientWriteStatus := SUCCESS - if err != nil { - clientWriteStatus = FAILURE - } - - if request.GetBody() != nil && request.GetBody().Writes != nil { - writeRequestTupleKeys := request.GetBody().Writes - for index := 0; index < len(writeRequestTupleKeys); index++ { - response.Writes = append(response.Writes, ClientWriteRequestWriteResponse{ - TupleKey: writeRequestTupleKeys[index], - HttpResponse: httpResponse, - Status: clientWriteStatus, - Error: err, - }) - } - } - - if request.GetBody() != nil && request.GetBody().Deletes != nil { - deleteRequestTupleKeys := request.GetBody().Deletes - for index := 0; index < len(deleteRequestTupleKeys); index++ { - response.Deletes = append(response.Deletes, ClientWriteRequestDeleteResponse{ - TupleKey: deleteRequestTupleKeys[index], - HttpResponse: httpResponse, - Status: clientWriteStatus, - Error: err, - }) - } - } - - return &response, err - } - - maxPerChunk := int32(1) // 1 has to be the default otherwise the chunks will be sent in transactions - if options.Transaction.MaxPerChunk > 0 { - maxPerChunk = options.Transaction.MaxPerChunk - } - - maxParallelReqs := DEFAULT_MAX_METHOD_PARALLEL_REQS - if options.Transaction.MaxParallelRequests > 0 { - maxParallelReqs = options.Transaction.MaxParallelRequests - } - - // If the transaction mode is disabled: - // - the client will attempt to chunk the writes and deletes into multiple requests - // - each request is a transaction - // - the max items in each request are based on maxPerChunk (default=1) - var writeChunkSize = int(maxPerChunk) - var writeChunks [][]ClientTupleKey - if request.GetBody() != nil { - for i := 0; i < len(request.GetBody().Writes); i += writeChunkSize { - end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Writes)))) - - writeChunks = append(writeChunks, (request.GetBody().Writes)[i:end]) - } - } - - writeGroup, ctx := errgroup.WithContext(request.GetContext()) - - writeGroup.SetLimit(int(maxParallelReqs)) - writeResponses := make([]ClientWriteResponse, len(writeChunks)) - for index, writeBody := range writeChunks { - index, writeBody := index, writeBody - writeGroup.Go(func() error { - singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ - ctx: ctx, - Client: client, - body: &ClientWriteRequest{ - Writes: writeBody, - }, - options: &ClientWriteOptions{ - RequestOptions: options.RequestOptions, - AuthorizationModelId: authorizationModelId, - StoreId: request.GetStoreIdOverride(), - Conflict: options.Conflict, - }, - }) - - if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { - return err - } - - writeResponses[index] = *singleResponse - - return nil - }) - } - - err = writeGroup.Wait() - // If an error was returned then it will be an authentication error so we want to return - if err != nil { - return &response, err - } - - var deleteChunkSize = int(maxPerChunk) - var deleteChunks [][]ClientTupleKeyWithoutCondition - if request.GetBody() != nil { - for i := 0; i < len(request.GetBody().Deletes); i += deleteChunkSize { - end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Deletes)))) - - deleteChunks = append(deleteChunks, (request.GetBody().Deletes)[i:end]) - } - } - - deleteGroup, ctx := errgroup.WithContext(request.GetContext()) - deleteGroup.SetLimit(int(maxParallelReqs)) - deleteResponses := make([]ClientWriteResponse, len(deleteChunks)) - for index, deleteBody := range deleteChunks { - index, deleteBody := index, deleteBody - deleteGroup.Go(func() error { - singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ - ctx: ctx, - Client: client, - body: &ClientWriteRequest{ - Deletes: deleteBody, - }, - options: &ClientWriteOptions{ - RequestOptions: options.RequestOptions, - AuthorizationModelId: authorizationModelId, - StoreId: request.GetStoreIdOverride(), - Conflict: options.Conflict, - }, - }) - - if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { - return err - } - - deleteResponses[index] = *singleResponse - - return nil - }) - } - - err = deleteGroup.Wait() - if err != nil { - // If an error was returned then it will be an authentication error so we want to return - return &response, err - } - - for _, writeResponse := range writeResponses { - response.Writes = append(response.Writes, writeResponse.Writes...) - } - - for _, deleteResponse := range deleteResponses { - response.Deletes = append(response.Deletes, deleteResponse.Deletes...) - } - - return &response, nil + options := request.GetOptions() + transactionOptionsSet := options != nil && options.Transaction != nil + response := ClientWriteResponse{ + Writes: []ClientWriteRequestWriteResponse{}, + Deletes: []ClientWriteRequestDeleteResponse{}, + } + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + // Unless explicitly disabled, transaction mode is enabled + // In transaction mode, the client will send the request to the server as is + if !transactionOptionsSet || !options.Transaction.Disable { + writeRequest := fgaSdk.WriteRequest{ + AuthorizationModelId: authorizationModelId, + } + if len(request.GetBody().Writes) > 0 { + writes := fgaSdk.WriteRequestWrites{} + if options != nil { + writes.OnDuplicate = options.Conflict.OnDuplicateWrites.ToString() + } + for index := 0; index < len(request.GetBody().Writes); index++ { + writes.TupleKeys = append(writes.TupleKeys, (request.GetBody().Writes)[index]) + } + writeRequest.Writes = &writes + } + if len(request.GetBody().Deletes) > 0 { + deletes := fgaSdk.WriteRequestDeletes{} + if options != nil { + deletes.OnMissing = options.Conflict.OnMissingDeletes.ToString() + } + for index := 0; index < len(request.GetBody().Deletes); index++ { + deletes.TupleKeys = append(deletes.TupleKeys, (request.GetBody().Deletes)[index]) + } + writeRequest.Deletes = &deletes + } + + _, httpResponse, err := client.OpenFgaApi. + Write(request.GetContext(), *storeId). + Body(writeRequest). + Options(requestOptions). + Execute() + + clientWriteStatus := SUCCESS + if err != nil { + clientWriteStatus = FAILURE + } + + if request.GetBody() != nil && request.GetBody().Writes != nil { + writeRequestTupleKeys := request.GetBody().Writes + for index := 0; index < len(writeRequestTupleKeys); index++ { + response.Writes = append(response.Writes, ClientWriteRequestWriteResponse{ + TupleKey: writeRequestTupleKeys[index], + HttpResponse: httpResponse, + Status: clientWriteStatus, + Error: err, + }) + } + } + + if request.GetBody() != nil && request.GetBody().Deletes != nil { + deleteRequestTupleKeys := request.GetBody().Deletes + for index := 0; index < len(deleteRequestTupleKeys); index++ { + response.Deletes = append(response.Deletes, ClientWriteRequestDeleteResponse{ + TupleKey: deleteRequestTupleKeys[index], + HttpResponse: httpResponse, + Status: clientWriteStatus, + Error: err, + }) + } + } + + return &response, err + } + + maxPerChunk := int32(1) // 1 has to be the default otherwise the chunks will be sent in transactions + if options.Transaction.MaxPerChunk > 0 { + maxPerChunk = options.Transaction.MaxPerChunk + } + + maxParallelReqs := DEFAULT_MAX_METHOD_PARALLEL_REQS + if options.Transaction.MaxParallelRequests > 0 { + maxParallelReqs = options.Transaction.MaxParallelRequests + } + + // If the transaction mode is disabled: + // - the client will attempt to chunk the writes and deletes into multiple requests + // - each request is a transaction + // - the max items in each request are based on maxPerChunk (default=1) + var writeChunkSize = int(maxPerChunk) + var writeChunks [][]ClientTupleKey + if request.GetBody() != nil { + for i := 0; i < len(request.GetBody().Writes); i += writeChunkSize { + end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Writes)))) + + writeChunks = append(writeChunks, (request.GetBody().Writes)[i:end]) + } + } + + writeGroup, ctx := errgroup.WithContext(request.GetContext()) + + writeGroup.SetLimit(int(maxParallelReqs)) + writeResponses := make([]ClientWriteResponse, len(writeChunks)) + for index, writeBody := range writeChunks { + index, writeBody := index, writeBody + writeGroup.Go(func() error { + singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ + ctx: ctx, + Client: client, + body: &ClientWriteRequest{ + Writes: writeBody, + }, + options: &ClientWriteOptions{ + RequestOptions: options.RequestOptions, + AuthorizationModelId: authorizationModelId, + StoreId: request.GetStoreIdOverride(), + Conflict: options.Conflict, + }, + }) + + if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { + return err + } + + writeResponses[index] = *singleResponse + + return nil + }) + } + + err = writeGroup.Wait() + // If an error was returned then it will be an authentication error so we want to return + if err != nil { + return &response, err + } + + var deleteChunkSize = int(maxPerChunk) + var deleteChunks [][]ClientTupleKeyWithoutCondition + if request.GetBody() != nil { + for i := 0; i < len(request.GetBody().Deletes); i += deleteChunkSize { + end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Deletes)))) + + deleteChunks = append(deleteChunks, (request.GetBody().Deletes)[i:end]) + } + } + + deleteGroup, ctx := errgroup.WithContext(request.GetContext()) + deleteGroup.SetLimit(int(maxParallelReqs)) + deleteResponses := make([]ClientWriteResponse, len(deleteChunks)) + for index, deleteBody := range deleteChunks { + index, deleteBody := index, deleteBody + deleteGroup.Go(func() error { + singleResponse, err := client.WriteExecute(&SdkClientWriteRequest{ + ctx: ctx, + Client: client, + body: &ClientWriteRequest{ + Deletes: deleteBody, + }, + options: &ClientWriteOptions{ + RequestOptions: options.RequestOptions, + AuthorizationModelId: authorizationModelId, + StoreId: request.GetStoreIdOverride(), + Conflict: options.Conflict, + }, + }) + + if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { + return err + } + + deleteResponses[index] = *singleResponse + + return nil + }) + } + + err = deleteGroup.Wait() + if err != nil { + // If an error was returned then it will be an authentication error so we want to return + return &response, err + } + + for _, writeResponse := range writeResponses { + response.Writes = append(response.Writes, writeResponse.Writes...) + } + + for _, deleteResponse := range deleteResponses { + response.Deletes = append(response.Deletes, deleteResponse.Deletes...) + } + + return &response, nil } // / WriteTuples type SdkClientWriteTuplesRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteTuplesBody - options *ClientWriteOptions + body *ClientWriteTuplesBody + options *ClientWriteOptions } type SdkClientWriteTuplesRequestInterface interface { - Options(options ClientWriteOptions) SdkClientWriteTuplesRequestInterface - Body(body ClientWriteTuplesBody) SdkClientWriteTuplesRequestInterface - Execute() (*ClientWriteResponse, error) + Options(options ClientWriteOptions) SdkClientWriteTuplesRequestInterface + Body(body ClientWriteTuplesBody) SdkClientWriteTuplesRequestInterface + Execute() (*ClientWriteResponse, error) - GetContext() _context.Context - GetBody() *ClientWriteTuplesBody - GetOptions() *ClientWriteOptions + GetContext() _context.Context + GetBody() *ClientWriteTuplesBody + GetOptions() *ClientWriteOptions } type ClientWriteTuplesBody = []ClientTupleKey func (client *OpenFgaClient) WriteTuples(ctx _context.Context) SdkClientWriteTuplesRequestInterface { - return &SdkClientWriteTuplesRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteTuplesRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientWriteTuplesRequest) Options(options ClientWriteOptions) SdkClientWriteTuplesRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteTuplesRequest) Body(body ClientWriteTuplesBody) SdkClientWriteTuplesRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteTuplesRequest) Execute() (*ClientWriteResponse, error) { - return request.Client.WriteTuplesExecute(request) + return request.Client.WriteTuplesExecute(request) } func (request *SdkClientWriteTuplesRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientWriteTuplesRequest) GetBody() *ClientWriteTuplesBody { - return request.body + return request.body } func (request *SdkClientWriteTuplesRequest) GetOptions() *ClientWriteOptions { - return request.options + return request.options } func (client *OpenFgaClient) WriteTuplesExecute(request SdkClientWriteTuplesRequestInterface) (*ClientWriteResponse, error) { - baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ - Writes: *request.GetBody(), - }) - if request.GetOptions() != nil { - baseReq = baseReq.Options(*request.GetOptions()) - } - return baseReq.Execute() + baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ + Writes: *request.GetBody(), + }) + if request.GetOptions() != nil { + baseReq = baseReq.Options(*request.GetOptions()) + } + return baseReq.Execute() } // / DeleteTuples type SdkClientDeleteTuplesRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientDeleteTuplesBody - options *ClientWriteOptions + body *ClientDeleteTuplesBody + options *ClientWriteOptions } type SdkClientDeleteTuplesRequestInterface interface { - Options(options ClientWriteOptions) SdkClientDeleteTuplesRequestInterface - Body(body ClientDeleteTuplesBody) SdkClientDeleteTuplesRequestInterface - Execute() (*ClientWriteResponse, error) + Options(options ClientWriteOptions) SdkClientDeleteTuplesRequestInterface + Body(body ClientDeleteTuplesBody) SdkClientDeleteTuplesRequestInterface + Execute() (*ClientWriteResponse, error) - GetContext() _context.Context - GetBody() *ClientDeleteTuplesBody - GetOptions() *ClientWriteOptions + GetContext() _context.Context + GetBody() *ClientDeleteTuplesBody + GetOptions() *ClientWriteOptions } type ClientDeleteTuplesBody = []ClientTupleKeyWithoutCondition func (client *OpenFgaClient) DeleteTuples(ctx _context.Context) SdkClientDeleteTuplesRequestInterface { - return &SdkClientDeleteTuplesRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientDeleteTuplesRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientDeleteTuplesRequest) Options(options ClientWriteOptions) SdkClientDeleteTuplesRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientDeleteTuplesRequest) Body(body ClientDeleteTuplesBody) SdkClientDeleteTuplesRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientDeleteTuplesRequest) Execute() (*ClientWriteResponse, error) { - return request.Client.DeleteTuplesExecute(request) + return request.Client.DeleteTuplesExecute(request) } func (request *SdkClientDeleteTuplesRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientDeleteTuplesRequest) GetBody() *ClientDeleteTuplesBody { - return request.body + return request.body } func (request *SdkClientDeleteTuplesRequest) GetOptions() *ClientWriteOptions { - return request.options + return request.options } func (client *OpenFgaClient) DeleteTuplesExecute(request SdkClientDeleteTuplesRequestInterface) (*ClientWriteResponse, error) { - baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ - Deletes: *request.GetBody(), - }) - if request.GetOptions() != nil { - baseReq = baseReq.Options(*request.GetOptions()) - } - return baseReq.Execute() + baseReq := client.Write(request.GetContext()).Body(ClientWriteRequest{ + Deletes: *request.GetBody(), + }) + if request.GetOptions() != nil { + baseReq = baseReq.Options(*request.GetOptions()) + } + return baseReq.Execute() } /* Relationship Queries */ @@ -2018,343 +2018,343 @@ func (client *OpenFgaClient) DeleteTuplesExecute(request SdkClientDeleteTuplesRe /// Check type SdkClientCheckRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientCheckRequest - options *ClientCheckOptions + body *ClientCheckRequest + options *ClientCheckOptions } type SdkClientCheckRequestInterface interface { - Options(options ClientCheckOptions) SdkClientCheckRequestInterface - Body(body ClientCheckRequest) SdkClientCheckRequestInterface - Execute() (*ClientCheckResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientCheckOptions) SdkClientCheckRequestInterface + Body(body ClientCheckRequest) SdkClientCheckRequestInterface + Execute() (*ClientCheckResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientCheckRequest - GetOptions() *ClientCheckOptions + GetContext() _context.Context + GetBody() *ClientCheckRequest + GetOptions() *ClientCheckOptions } type ClientCheckRequest struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Object string `json:"object,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Object string `json:"object,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientCheckOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientCheckResponse struct { - fgaSdk.CheckResponse - HttpResponse *_nethttp.Response + fgaSdk.CheckResponse + HttpResponse *_nethttp.Response } func (client *OpenFgaClient) Check(ctx _context.Context) SdkClientCheckRequestInterface { - return &SdkClientCheckRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientCheckRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientCheckRequest) Options(options ClientCheckOptions) SdkClientCheckRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientCheckRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientCheckRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientCheckRequest) Body(body ClientCheckRequest) SdkClientCheckRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientCheckRequest) Execute() (*ClientCheckResponse, error) { - return request.Client.CheckExecute(request) + return request.Client.CheckExecute(request) } func (request *SdkClientCheckRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientCheckRequest) GetBody() *ClientCheckRequest { - return request.body + return request.body } func (request *SdkClientCheckRequest) GetOptions() *ClientCheckOptions { - return request.options + return request.options } func (client *OpenFgaClient) CheckExecute(request SdkClientCheckRequestInterface) (*ClientCheckResponse, error) { - if request.GetBody() == nil { - return nil, FgaRequiredParamError{param: "body"} - } - - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - requestBody := fgaSdk.CheckRequest{ - TupleKey: fgaSdk.CheckRequestTupleKey{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Object: request.GetBody().Object, - }, - Context: request.GetBody().Context, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - AuthorizationModelId: authorizationModelId, - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - requestBody.Consistency = request.GetOptions().Consistency - } - - data, httpResponse, err := client.OpenFgaApi. - Check(request.GetContext(), *storeId). - Body(requestBody). - Options(requestOptions). - Execute() - return &ClientCheckResponse{CheckResponse: data, HttpResponse: httpResponse}, err + if request.GetBody() == nil { + return nil, FgaRequiredParamError{param: "body"} + } + + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + requestBody := fgaSdk.CheckRequest{ + TupleKey: fgaSdk.CheckRequestTupleKey{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Object: request.GetBody().Object, + }, + Context: request.GetBody().Context, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + AuthorizationModelId: authorizationModelId, + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + requestBody.Consistency = request.GetOptions().Consistency + } + + data, httpResponse, err := client.OpenFgaApi. + Check(request.GetContext(), *storeId). + Body(requestBody). + Options(requestOptions). + Execute() + return &ClientCheckResponse{CheckResponse: data, HttpResponse: httpResponse}, err } /// ClientBatchCheck type SdkClientBatchCheckClientRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientBatchCheckClientBody - options *ClientBatchCheckClientOptions + body *ClientBatchCheckClientBody + options *ClientBatchCheckClientOptions } type SdkClientBatchCheckClientRequestInterface interface { - Options(options ClientBatchCheckClientOptions) SdkClientBatchCheckClientRequestInterface - Body(body ClientBatchCheckClientBody) SdkClientBatchCheckClientRequestInterface - Execute() (*ClientBatchCheckClientResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientBatchCheckClientOptions) SdkClientBatchCheckClientRequestInterface + Body(body ClientBatchCheckClientBody) SdkClientBatchCheckClientRequestInterface + Execute() (*ClientBatchCheckClientResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientBatchCheckClientBody - GetOptions() *ClientBatchCheckClientOptions + GetContext() _context.Context + GetBody() *ClientBatchCheckClientBody + GetOptions() *ClientBatchCheckClientOptions } type ClientBatchCheckClientBody = []ClientCheckRequest type ClientBatchCheckClientOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientBatchCheckClientSingleResponse struct { - ClientCheckResponse - Request ClientCheckRequest - Error error + ClientCheckResponse + Request ClientCheckRequest + Error error } type ClientBatchCheckClientResponse = []ClientBatchCheckClientSingleResponse func (client *OpenFgaClient) ClientBatchCheck(ctx _context.Context) SdkClientBatchCheckClientRequestInterface { - return &SdkClientBatchCheckClientRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientBatchCheckClientRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientBatchCheckClientRequest) Options(options ClientBatchCheckClientOptions) SdkClientBatchCheckClientRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientBatchCheckClientRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientBatchCheckClientRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientBatchCheckClientRequest) Body(body ClientBatchCheckClientBody) SdkClientBatchCheckClientRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientBatchCheckClientRequest) Execute() (*ClientBatchCheckClientResponse, error) { - return request.Client.ClientBatchCheckExecute(request) + return request.Client.ClientBatchCheckExecute(request) } func (request *SdkClientBatchCheckClientRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientBatchCheckClientRequest) GetBody() *ClientBatchCheckClientBody { - return request.body + return request.body } func (request *SdkClientBatchCheckClientRequest) GetOptions() *ClientBatchCheckClientOptions { - return request.options + return request.options } func (client *OpenFgaClient) ClientBatchCheckExecute(request SdkClientBatchCheckClientRequestInterface) (*ClientBatchCheckClientResponse, error) { - group, ctx := errgroup.WithContext(request.GetContext()) - requestOptions := RequestOptions{} - maxParallelReqs := int(DEFAULT_MAX_METHOD_PARALLEL_REQS) - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - if request.GetOptions().MaxParallelRequests != nil { - maxParallelReqs = int(*request.GetOptions().MaxParallelRequests) - } - } - - group.SetLimit(maxParallelReqs) - var numOfChecks = len(*request.GetBody()) - response := make(ClientBatchCheckClientResponse, numOfChecks) - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - checkOptions := &ClientCheckOptions{ - RequestOptions: requestOptions, - - AuthorizationModelId: authorizationModelId, - StoreId: storeId, - } - - if request.GetOptions() != nil && request.GetOptions().Consistency != nil { - checkOptions.Consistency = request.GetOptions().Consistency - } - - for index, checkBody := range *request.GetBody() { - index, checkBody := index, checkBody - group.Go(func() error { - singleResponse, err := client.CheckExecute(&SdkClientCheckRequest{ - ctx: ctx, - Client: client, - body: &checkBody, - options: checkOptions, - }) - - if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { - return err - } - - response[index] = ClientBatchCheckClientSingleResponse{ - Request: checkBody, - ClientCheckResponse: *singleResponse, - Error: err, - } - - return nil - }) - } - - if err := group.Wait(); err != nil { - return nil, err - } - - return &response, nil + group, ctx := errgroup.WithContext(request.GetContext()) + requestOptions := RequestOptions{} + maxParallelReqs := int(DEFAULT_MAX_METHOD_PARALLEL_REQS) + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + if request.GetOptions().MaxParallelRequests != nil { + maxParallelReqs = int(*request.GetOptions().MaxParallelRequests) + } + } + + group.SetLimit(maxParallelReqs) + var numOfChecks = len(*request.GetBody()) + response := make(ClientBatchCheckClientResponse, numOfChecks) + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + checkOptions := &ClientCheckOptions{ + RequestOptions: requestOptions, + + AuthorizationModelId: authorizationModelId, + StoreId: storeId, + } + + if request.GetOptions() != nil && request.GetOptions().Consistency != nil { + checkOptions.Consistency = request.GetOptions().Consistency + } + + for index, checkBody := range *request.GetBody() { + index, checkBody := index, checkBody + group.Go(func() error { + singleResponse, err := client.CheckExecute(&SdkClientCheckRequest{ + ctx: ctx, + Client: client, + body: &checkBody, + options: checkOptions, + }) + + if _, ok := err.(fgaSdk.FgaApiAuthenticationError); ok { + return err + } + + response[index] = ClientBatchCheckClientSingleResponse{ + Request: checkBody, + ClientCheckResponse: *singleResponse, + Error: err, + } + + return nil + }) + } + + if err := group.Wait(); err != nil { + return nil, err + } + + return &response, nil } // Server-side BatchCheck implementation // SdkClientBatchCheckRequest represents a server-side batch check request type SdkClientBatchCheckRequest struct { - ctx _context.Context - client *OpenFgaClient - body *ClientBatchCheckRequest - options *BatchCheckOptions + ctx _context.Context + client *OpenFgaClient + body *ClientBatchCheckRequest + options *BatchCheckOptions } // SdkClientBatchCheckRequestInterface defines the interface for server-side batch check requests type SdkClientBatchCheckRequestInterface interface { - Body(body ClientBatchCheckRequest) SdkClientBatchCheckRequestInterface - Options(options BatchCheckOptions) SdkClientBatchCheckRequestInterface - Execute() (*fgaSdk.BatchCheckResponse, error) - GetContext() _context.Context - GetBody() *ClientBatchCheckRequest - GetOptions() *BatchCheckOptions + Body(body ClientBatchCheckRequest) SdkClientBatchCheckRequestInterface + Options(options BatchCheckOptions) SdkClientBatchCheckRequestInterface + Execute() (*fgaSdk.BatchCheckResponse, error) + GetContext() _context.Context + GetBody() *ClientBatchCheckRequest + GetOptions() *BatchCheckOptions } func (r *SdkClientBatchCheckRequest) Body(body ClientBatchCheckRequest) SdkClientBatchCheckRequestInterface { - r.body = &body - return r + r.body = &body + return r } func (r *SdkClientBatchCheckRequest) Options(options BatchCheckOptions) SdkClientBatchCheckRequestInterface { - r.options = &options - return r + r.options = &options + return r } func (r *SdkClientBatchCheckRequest) Execute() (*fgaSdk.BatchCheckResponse, error) { - return r.client.BatchCheckExecute(r) + return r.client.BatchCheckExecute(r) } func (r *SdkClientBatchCheckRequest) GetContext() _context.Context { - return r.ctx + return r.ctx } func (r *SdkClientBatchCheckRequest) GetBody() *ClientBatchCheckRequest { - return r.body + return r.body } func (r *SdkClientBatchCheckRequest) GetOptions() *BatchCheckOptions { - return r.options + return r.options } // BatchCheck initializes a new batch check request func (client *OpenFgaClient) BatchCheck(ctx _context.Context) SdkClientBatchCheckRequestInterface { - return &SdkClientBatchCheckRequest{ - ctx: ctx, - client: client, - } + return &SdkClientBatchCheckRequest{ + ctx: ctx, + client: client, + } } /* @@ -2363,68 +2363,68 @@ func (client *OpenFgaClient) BatchCheck(ctx _context.Context) SdkClientBatchChec * @return *fgaSdk.BatchCheckResponse */ func (client *OpenFgaClient) BatchCheckExecute(request SdkClientBatchCheckRequestInterface) (*fgaSdk.BatchCheckResponse, error) { - ctx := request.GetContext() - body := request.GetBody() - options := request.GetOptions() + ctx := request.GetContext() + body := request.GetBody() + options := request.GetOptions() - if body == nil || len(body.Checks) == 0 { - return nil, FgaRequiredParamError{param: "checks"} - } + if body == nil || len(body.Checks) == 0 { + return nil, FgaRequiredParamError{param: "checks"} + } - if options == nil { - options = &BatchCheckOptions{} - } + if options == nil { + options = &BatchCheckOptions{} + } - maxParallelRequests := DEFAULT_MAX_METHOD_PARALLEL_REQS - if options.MaxParallelRequests != nil { - maxParallelRequests = *options.MaxParallelRequests - } + maxParallelRequests := DEFAULT_MAX_METHOD_PARALLEL_REQS + if options.MaxParallelRequests != nil { + maxParallelRequests = *options.MaxParallelRequests + } - maxBatchSize := int32(constants.ClientMaxBatchSize) - if options.MaxBatchSize != nil { - maxBatchSize = *options.MaxBatchSize - } + maxBatchSize := int32(constants.ClientMaxBatchSize) + if options.MaxBatchSize != nil { + maxBatchSize = *options.MaxBatchSize + } - _, err := client.getStoreId(options.StoreId) - if err != nil { - return nil, err - } + _, err := client.getStoreId(options.StoreId) + if err != nil { + return nil, err + } - authorizationModelId, err := client.getAuthorizationModelId(options.AuthorizationModelId) - if err != nil { - return nil, err - } + authorizationModelId, err := client.getAuthorizationModelId(options.AuthorizationModelId) + if err != nil { + return nil, err + } - chunks := chunkClientBatchCheckItems(body.Checks, int(maxBatchSize)) + chunks := chunkClientBatchCheckItems(body.Checks, int(maxBatchSize)) - p := pool.NewWithResults[*fgaSdk.BatchCheckResponse]().WithContext(ctx).WithMaxGoroutines(int(maxParallelRequests)) + p := pool.NewWithResults[*fgaSdk.BatchCheckResponse]().WithContext(ctx).WithMaxGoroutines(int(maxParallelRequests)) - for _, chunk := range chunks { - chunkCopy := chunk + for _, chunk := range chunks { + chunkCopy := chunk - p.Go(func(ctx _context.Context) (*fgaSdk.BatchCheckResponse, error) { - batchCheckRequest := createBatchCheckRequest(chunkCopy, authorizationModelId, options.Consistency) - return client.singleBatchCheck(ctx, batchCheckRequest, options) - }) - } + p.Go(func(ctx _context.Context) (*fgaSdk.BatchCheckResponse, error) { + batchCheckRequest := createBatchCheckRequest(chunkCopy, authorizationModelId, options.Consistency) + return client.singleBatchCheck(ctx, batchCheckRequest, options) + }) + } - responses, err := p.Wait() - if err != nil { - return nil, err - } + responses, err := p.Wait() + if err != nil { + return nil, err + } - combinedResult := make(map[string]fgaSdk.BatchCheckSingleResult) + combinedResult := make(map[string]fgaSdk.BatchCheckSingleResult) - for _, response := range responses { - for correlationID, result := range response.GetResult() { - combinedResult[correlationID] = result - } - } + for _, response := range responses { + for correlationID, result := range response.GetResult() { + combinedResult[correlationID] = result + } + } - combinedResponse := fgaSdk.NewBatchCheckResponse() - combinedResponse.SetResult(combinedResult) + combinedResponse := fgaSdk.NewBatchCheckResponse() + combinedResponse.SetResult(combinedResult) - return combinedResponse, nil + return combinedResponse, nil } /* @@ -2435,21 +2435,21 @@ func (client *OpenFgaClient) BatchCheckExecute(request SdkClientBatchCheckReques * @return *fgaSdk.BatchCheckResponse */ func (client *OpenFgaClient) singleBatchCheck(ctx _context.Context, body fgaSdk.BatchCheckRequest, options *BatchCheckOptions) (*fgaSdk.BatchCheckResponse, error) { - storeId, err := client.getStoreId(options.StoreId) - if err != nil { - return nil, err - } + storeId, err := client.getStoreId(options.StoreId) + if err != nil { + return nil, err + } - req := client.OpenFgaApi. - BatchCheck(ctx, *storeId). - Body(body). - Options(options.RequestOptions) - response, _, err := req.Execute() - if err != nil { - return nil, err - } + req := client.OpenFgaApi. + BatchCheck(ctx, *storeId). + Body(body). + Options(options.RequestOptions) + response, _, err := req.Execute() + if err != nil { + return nil, err + } - return &response, nil + return &response, nil } /* @@ -2459,21 +2459,21 @@ func (client *OpenFgaClient) singleBatchCheck(ctx _context.Context, body fgaSdk. * @return [][]ClientBatchCheckItem - the chunked items */ func chunkClientBatchCheckItems(items []ClientBatchCheckItem, chunkSize int) [][]ClientBatchCheckItem { - if len(items) == 0 { - return [][]ClientBatchCheckItem{} - } + if len(items) == 0 { + return [][]ClientBatchCheckItem{} + } - chunks := make([][]ClientBatchCheckItem, 0, (len(items)+chunkSize-1)/chunkSize) + chunks := make([][]ClientBatchCheckItem, 0, (len(items)+chunkSize-1)/chunkSize) - for i := 0; i < len(items); i += chunkSize { - end := i + chunkSize - if end > len(items) { - end = len(items) - } - chunks = append(chunks, items[i:end]) - } + for i := 0; i < len(items); i += chunkSize { + end := i + chunkSize + if end > len(items) { + end = len(items) + } + chunks = append(chunks, items[i:end]) + } - return chunks + return chunks } /* @@ -2484,970 +2484,970 @@ func chunkClientBatchCheckItems(items []ClientBatchCheckItem, chunkSize int) [][ * @return fgaSdk.BatchCheckRequest - the created request */ func createBatchCheckRequest(items []ClientBatchCheckItem, authorizationModelId *string, consistency *fgaSdk.ConsistencyPreference) fgaSdk.BatchCheckRequest { - batchCheckItems := make([]fgaSdk.BatchCheckItem, 0, len(items)) + batchCheckItems := make([]fgaSdk.BatchCheckItem, 0, len(items)) - for _, item := range items { - tupleKey := fgaSdk.CheckRequestTupleKey{ - User: item.User, - Relation: item.Relation, - Object: item.Object, - } + for _, item := range items { + tupleKey := fgaSdk.CheckRequestTupleKey{ + User: item.User, + Relation: item.Relation, + Object: item.Object, + } - batchCheckItem := fgaSdk.BatchCheckItem{ - TupleKey: tupleKey, - CorrelationId: item.CorrelationId, - } + batchCheckItem := fgaSdk.BatchCheckItem{ + TupleKey: tupleKey, + CorrelationId: item.CorrelationId, + } - if len(item.ContextualTuples) > 0 { - contextualTuples := &fgaSdk.ContextualTupleKeys{ - TupleKeys: []fgaSdk.TupleKey{}, - } + if len(item.ContextualTuples) > 0 { + contextualTuples := &fgaSdk.ContextualTupleKeys{ + TupleKeys: []fgaSdk.TupleKey{}, + } - contextualTuples.TupleKeys = append(contextualTuples.TupleKeys, item.ContextualTuples...) + contextualTuples.TupleKeys = append(contextualTuples.TupleKeys, item.ContextualTuples...) - batchCheckItem.ContextualTuples = contextualTuples - } + batchCheckItem.ContextualTuples = contextualTuples + } - if item.Context != nil { - batchCheckItem.Context = item.Context - } + if item.Context != nil { + batchCheckItem.Context = item.Context + } - batchCheckItems = append(batchCheckItems, batchCheckItem) - } + batchCheckItems = append(batchCheckItems, batchCheckItem) + } - batchCheckRequest := fgaSdk.BatchCheckRequest{ - Checks: batchCheckItems, - } + batchCheckRequest := fgaSdk.BatchCheckRequest{ + Checks: batchCheckItems, + } - if authorizationModelId != nil && *authorizationModelId != "" { - batchCheckRequest.AuthorizationModelId = authorizationModelId - } + if authorizationModelId != nil && *authorizationModelId != "" { + batchCheckRequest.AuthorizationModelId = authorizationModelId + } - if consistency != nil { - batchCheckRequest.Consistency = consistency - } + if consistency != nil { + batchCheckRequest.Consistency = consistency + } - return batchCheckRequest + return batchCheckRequest } // / Expand type SdkClientExpandRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientExpandRequest - options *ClientExpandOptions + body *ClientExpandRequest + options *ClientExpandOptions } type SdkClientExpandRequestInterface interface { - Options(options ClientExpandOptions) SdkClientExpandRequestInterface - Body(body ClientExpandRequest) SdkClientExpandRequestInterface - Execute() (*ClientExpandResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientExpandOptions) SdkClientExpandRequestInterface + Body(body ClientExpandRequest) SdkClientExpandRequestInterface + Execute() (*ClientExpandResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientExpandRequest - GetOptions() *ClientExpandOptions + GetContext() _context.Context + GetBody() *ClientExpandRequest + GetOptions() *ClientExpandOptions } type ClientExpandRequest struct { - Relation string `json:"relation,omitempty"` - Object string `json:"object,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + Relation string `json:"relation,omitempty"` + Object string `json:"object,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientExpandOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientExpandResponse = fgaSdk.ExpandResponse func (client *OpenFgaClient) Expand(ctx _context.Context) SdkClientExpandRequestInterface { - return &SdkClientExpandRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientExpandRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientExpandRequest) Options(options ClientExpandOptions) SdkClientExpandRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientExpandRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientExpandRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientExpandRequest) Body(body ClientExpandRequest) SdkClientExpandRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientExpandRequest) Execute() (*ClientExpandResponse, error) { - return request.Client.ExpandExecute(request) + return request.Client.ExpandExecute(request) } func (request *SdkClientExpandRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientExpandRequest) GetBody() *ClientExpandRequest { - return request.body + return request.body } func (request *SdkClientExpandRequest) GetOptions() *ClientExpandOptions { - return request.options + return request.options } func (client *OpenFgaClient) ExpandExecute(request SdkClientExpandRequestInterface) (*ClientExpandResponse, error) { - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - - body := fgaSdk.ExpandRequest{ - TupleKey: fgaSdk.ExpandRequestTupleKey{ - Relation: request.GetBody().Relation, - Object: request.GetBody().Object, - }, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - AuthorizationModelId: authorizationModelId, - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - } - - data, _, err := client.OpenFgaApi. - Expand(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + + body := fgaSdk.ExpandRequest{ + TupleKey: fgaSdk.ExpandRequestTupleKey{ + Relation: request.GetBody().Relation, + Object: request.GetBody().Object, + }, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + AuthorizationModelId: authorizationModelId, + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + } + + data, _, err := client.OpenFgaApi. + Expand(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / ListObjects type SdkClientListObjectsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientListObjectsRequest - options *ClientListObjectsOptions + body *ClientListObjectsRequest + options *ClientListObjectsOptions } type SdkClientListObjectsRequestInterface interface { - Options(options ClientListObjectsOptions) SdkClientListObjectsRequestInterface - Body(body ClientListObjectsRequest) SdkClientListObjectsRequestInterface - Execute() (*ClientListObjectsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientListObjectsOptions) SdkClientListObjectsRequestInterface + Body(body ClientListObjectsRequest) SdkClientListObjectsRequestInterface + Execute() (*ClientListObjectsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientListObjectsRequest - GetOptions() *ClientListObjectsOptions + GetContext() _context.Context + GetBody() *ClientListObjectsRequest + GetOptions() *ClientListObjectsOptions } type ClientListObjectsRequest struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Type string `json:"type,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Type string `json:"type,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientListObjectsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientListObjectsResponse = fgaSdk.ListObjectsResponse func (client *OpenFgaClient) ListObjects(ctx _context.Context) SdkClientListObjectsRequestInterface { - return &SdkClientListObjectsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientListObjectsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientListObjectsRequest) Options(options ClientListObjectsOptions) SdkClientListObjectsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListObjectsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientListObjectsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientListObjectsRequest) Body(body ClientListObjectsRequest) SdkClientListObjectsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientListObjectsRequest) Execute() (*ClientListObjectsResponse, error) { - return request.Client.ListObjectsExecute(request) + return request.Client.ListObjectsExecute(request) } func (request *SdkClientListObjectsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListObjectsRequest) GetBody() *ClientListObjectsRequest { - return request.body + return request.body } func (request *SdkClientListObjectsRequest) GetOptions() *ClientListObjectsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListObjectsExecute(request SdkClientListObjectsRequestInterface) (*ClientListObjectsResponse, error) { - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - body := fgaSdk.ListObjectsRequest{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Type: request.GetBody().Type, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - Context: request.GetBody().Context, - AuthorizationModelId: authorizationModelId, - } - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - } - data, _, err := client.OpenFgaApi. - ListObjects(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + body := fgaSdk.ListObjectsRequest{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Type: request.GetBody().Type, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + Context: request.GetBody().Context, + AuthorizationModelId: authorizationModelId, + } + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + } + data, _, err := client.OpenFgaApi. + ListObjects(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } /// ListRelations type SdkClientListRelationsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientListRelationsRequest - options *ClientListRelationsOptions + body *ClientListRelationsRequest + options *ClientListRelationsOptions } type SdkClientListRelationsRequestInterface interface { - Options(options ClientListRelationsOptions) SdkClientListRelationsRequestInterface - Body(body ClientListRelationsRequest) SdkClientListRelationsRequestInterface - Execute() (*ClientListRelationsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientListRelationsOptions) SdkClientListRelationsRequestInterface + Body(body ClientListRelationsRequest) SdkClientListRelationsRequestInterface + Execute() (*ClientListRelationsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientListRelationsRequest - GetOptions() *ClientListRelationsOptions + GetContext() _context.Context + GetBody() *ClientListRelationsRequest + GetOptions() *ClientListRelationsOptions } type ClientListRelationsRequest struct { - User string `json:"user,omitempty"` - Object string `json:"object,omitempty"` - Relations []string `json:"relations,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Object string `json:"object,omitempty"` + Relations []string `json:"relations,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientListRelationsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + MaxParallelRequests *int32 `json:"max_parallel_requests,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientListRelationsResponse struct { - Relations []string `json:"response,omitempty"` + Relations []string `json:"response,omitempty"` } func (o ClientListRelationsResponse) MarshalJSON() ([]byte, error) { - toSerialize := map[string]interface{}{} - toSerialize["relations"] = o.Relations - return json.Marshal(toSerialize) + toSerialize := map[string]interface{}{} + toSerialize["relations"] = o.Relations + return json.Marshal(toSerialize) } func (client *OpenFgaClient) ListRelations(ctx _context.Context) SdkClientListRelationsRequestInterface { - return &SdkClientListRelationsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientListRelationsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientListRelationsRequest) Options(options ClientListRelationsOptions) SdkClientListRelationsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListRelationsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientListRelationsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientListRelationsRequest) Body(body ClientListRelationsRequest) SdkClientListRelationsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientListRelationsRequest) Execute() (*ClientListRelationsResponse, error) { - return request.Client.ListRelationsExecute(request) + return request.Client.ListRelationsExecute(request) } func (request *SdkClientListRelationsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListRelationsRequest) GetBody() *ClientListRelationsRequest { - return request.body + return request.body } func (request *SdkClientListRelationsRequest) GetOptions() *ClientListRelationsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListRelationsExecute(request SdkClientListRelationsRequestInterface) (*ClientListRelationsResponse, error) { - if len(request.GetBody().Relations) <= 0 { - return nil, fmt.Errorf("ListRelations - expected len(Relations) > 0") - } - - batchRequestBody := ClientBatchCheckClientBody{} - for index := 0; index < len(request.GetBody().Relations); index++ { - batchRequestBody = append(batchRequestBody, ClientCheckRequest{ - User: request.GetBody().User, - Relation: request.GetBody().Relations[index], - Object: request.GetBody().Object, - Context: request.GetBody().Context, - ContextualTuples: request.GetBody().ContextualTuples, - }) - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - options := &ClientBatchCheckClientOptions{ - AuthorizationModelId: authorizationModelId, - StoreId: storeId, - } - if request.GetOptions() != nil { - options.RequestOptions = request.GetOptions().RequestOptions - options.Consistency = request.GetOptions().Consistency - options.MaxParallelRequests = request.GetOptions().MaxParallelRequests - } - - batchResponse, err := client.ClientBatchCheckExecute(&SdkClientBatchCheckClientRequest{ - ctx: request.GetContext(), - Client: client, - body: &batchRequestBody, - options: options, - }) - - if err != nil { - return nil, err - } - - var relations []string - for index := 0; index < len(*batchResponse); index++ { - if (*batchResponse)[index].GetAllowed() { - relations = append(relations, (*batchResponse)[index].Request.Relation) - } - } - - return &ClientListRelationsResponse{Relations: relations}, nil + if len(request.GetBody().Relations) <= 0 { + return nil, fmt.Errorf("ListRelations - expected len(Relations) > 0") + } + + batchRequestBody := ClientBatchCheckClientBody{} + for index := 0; index < len(request.GetBody().Relations); index++ { + batchRequestBody = append(batchRequestBody, ClientCheckRequest{ + User: request.GetBody().User, + Relation: request.GetBody().Relations[index], + Object: request.GetBody().Object, + Context: request.GetBody().Context, + ContextualTuples: request.GetBody().ContextualTuples, + }) + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + options := &ClientBatchCheckClientOptions{ + AuthorizationModelId: authorizationModelId, + StoreId: storeId, + } + if request.GetOptions() != nil { + options.RequestOptions = request.GetOptions().RequestOptions + options.Consistency = request.GetOptions().Consistency + options.MaxParallelRequests = request.GetOptions().MaxParallelRequests + } + + batchResponse, err := client.ClientBatchCheckExecute(&SdkClientBatchCheckClientRequest{ + ctx: request.GetContext(), + Client: client, + body: &batchRequestBody, + options: options, + }) + + if err != nil { + return nil, err + } + + var relations []string + for index := 0; index < len(*batchResponse); index++ { + if (*batchResponse)[index].GetAllowed() { + relations = append(relations, (*batchResponse)[index].Request.Relation) + } + } + + return &ClientListRelationsResponse{Relations: relations}, nil } // / ListUsers type SdkClientListUsersRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientListUsersRequest - options *ClientListUsersOptions + body *ClientListUsersRequest + options *ClientListUsersOptions } type SdkClientListUsersRequestInterface interface { - Options(options ClientListUsersOptions) SdkClientListUsersRequestInterface - Body(body ClientListUsersRequest) SdkClientListUsersRequestInterface - Execute() (*ClientListUsersResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientListUsersOptions) SdkClientListUsersRequestInterface + Body(body ClientListUsersRequest) SdkClientListUsersRequestInterface + Execute() (*ClientListUsersResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientListUsersRequest - GetOptions() *ClientListUsersOptions + GetContext() _context.Context + GetBody() *ClientListUsersRequest + GetOptions() *ClientListUsersOptions } type ClientListUsersRequest struct { - Object fgaSdk.FgaObject `json:"object" yaml:"object"` - Relation string `json:"relation" yaml:"relation"` - UserFilters []fgaSdk.UserTypeFilter `json:"user_filters" yaml:"user_filters"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` - // Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. - Context *map[string]interface{} `json:"context,omitempty" yaml:"context,omitempty"` + Object fgaSdk.FgaObject `json:"object" yaml:"object"` + Relation string `json:"relation" yaml:"relation"` + UserFilters []fgaSdk.UserTypeFilter `json:"user_filters" yaml:"user_filters"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + // Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + Context *map[string]interface{} `json:"context,omitempty" yaml:"context,omitempty"` } type ClientListUsersOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` } type ClientListUsersResponse = fgaSdk.ListUsersResponse func (client *OpenFgaClient) ListUsers(ctx _context.Context) SdkClientListUsersRequestInterface { - return &SdkClientListUsersRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientListUsersRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientListUsersRequest) Options(options ClientListUsersOptions) SdkClientListUsersRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientListUsersRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientListUsersRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientListUsersRequest) Body(body ClientListUsersRequest) SdkClientListUsersRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientListUsersRequest) Execute() (*ClientListUsersResponse, error) { - return request.Client.ListUsersExecute(request) + return request.Client.ListUsersExecute(request) } func (request *SdkClientListUsersRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientListUsersRequest) GetBody() *ClientListUsersRequest { - return request.body + return request.body } func (request *SdkClientListUsersRequest) GetOptions() *ClientListUsersOptions { - return request.options + return request.options } func (client *OpenFgaClient) ListUsersExecute(request SdkClientListUsersRequestInterface) (*ClientListUsersResponse, error) { - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - body := fgaSdk.ListUsersRequest{ - Object: request.GetBody().Object, - Relation: request.GetBody().Relation, - UserFilters: request.GetBody().UserFilters, - ContextualTuples: &fgaSdk.NewContextualTupleKeys(contextualTuples).TupleKeys, - Context: request.GetBody().Context, - AuthorizationModelId: authorizationModelId, - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - } - - data, _, err := client.OpenFgaApi. - ListUsers(request.GetContext(), *storeId). - Body(body). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + body := fgaSdk.ListUsersRequest{ + Object: request.GetBody().Object, + Relation: request.GetBody().Relation, + UserFilters: request.GetBody().UserFilters, + ContextualTuples: &fgaSdk.NewContextualTupleKeys(contextualTuples).TupleKeys, + Context: request.GetBody().Context, + AuthorizationModelId: authorizationModelId, + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + } + + data, _, err := client.OpenFgaApi. + ListUsers(request.GetContext(), *storeId). + Body(body). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / ReadAssertions type SdkClientReadAssertionsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - options *ClientReadAssertionsOptions + options *ClientReadAssertionsOptions } type SdkClientReadAssertionsRequestInterface interface { - Options(options ClientReadAssertionsOptions) SdkClientReadAssertionsRequestInterface - Execute() (*ClientReadAssertionsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientReadAssertionsOptions) SdkClientReadAssertionsRequestInterface + Execute() (*ClientReadAssertionsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetOptions() *ClientReadAssertionsOptions + GetContext() _context.Context + GetOptions() *ClientReadAssertionsOptions } type ClientReadAssertionsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientReadAssertionsResponse = fgaSdk.ReadAssertionsResponse func (client *OpenFgaClient) ReadAssertions(ctx _context.Context) SdkClientReadAssertionsRequestInterface { - return &SdkClientReadAssertionsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientReadAssertionsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientReadAssertionsRequest) Options(options ClientReadAssertionsOptions) SdkClientReadAssertionsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientReadAssertionsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientReadAssertionsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientReadAssertionsRequest) Execute() (*ClientReadAssertionsResponse, error) { - return request.Client.ReadAssertionsExecute(request) + return request.Client.ReadAssertionsExecute(request) } func (request *SdkClientReadAssertionsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientReadAssertionsRequest) GetOptions() *ClientReadAssertionsOptions { - return request.options + return request.options } func (client *OpenFgaClient) ReadAssertionsExecute(request SdkClientReadAssertionsRequestInterface) (*ClientReadAssertionsResponse, error) { - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - if authorizationModelId == nil || *authorizationModelId == "" { - return nil, FgaRequiredParamError{param: "AuthorizationModelId"} - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - data, _, err := client.OpenFgaApi. - ReadAssertions(request.GetContext(), *storeId, *authorizationModelId). - Options(requestOptions). - Execute() - if err != nil { - return nil, err - } - return &data, nil + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + if authorizationModelId == nil || *authorizationModelId == "" { + return nil, FgaRequiredParamError{param: "AuthorizationModelId"} + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + data, _, err := client.OpenFgaApi. + ReadAssertions(request.GetContext(), *storeId, *authorizationModelId). + Options(requestOptions). + Execute() + if err != nil { + return nil, err + } + return &data, nil } // / WriteAssertions type SdkClientWriteAssertionsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientWriteAssertionsRequest - options *ClientWriteAssertionsOptions + body *ClientWriteAssertionsRequest + options *ClientWriteAssertionsOptions } type SdkClientWriteAssertionsRequestInterface interface { - Options(options ClientWriteAssertionsOptions) SdkClientWriteAssertionsRequestInterface - Body(body ClientWriteAssertionsRequest) SdkClientWriteAssertionsRequestInterface - Execute() (*ClientWriteAssertionsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientWriteAssertionsOptions) SdkClientWriteAssertionsRequestInterface + Body(body ClientWriteAssertionsRequest) SdkClientWriteAssertionsRequestInterface + Execute() (*ClientWriteAssertionsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientWriteAssertionsRequest - GetOptions() *ClientWriteAssertionsOptions + GetContext() _context.Context + GetBody() *ClientWriteAssertionsRequest + GetOptions() *ClientWriteAssertionsOptions } type ClientAssertion struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Object string `json:"object,omitempty"` - Expectation bool `json:"expectation,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Object string `json:"object,omitempty"` + Expectation bool `json:"expectation,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientWriteAssertionsRequest = []ClientAssertion func (clientAssertion ClientAssertion) ToAssertion() fgaSdk.Assertion { - assertion := fgaSdk.Assertion{ - TupleKey: fgaSdk.AssertionTupleKey{ - User: clientAssertion.User, - Relation: clientAssertion.Relation, - Object: clientAssertion.Object, - }, - Expectation: clientAssertion.Expectation, - } - if clientAssertion.Context != nil { - assertion.Context = clientAssertion.Context - } - if clientAssertion.ContextualTuples != nil { - assertion.ContextualTuples = &clientAssertion.ContextualTuples - } - return assertion + assertion := fgaSdk.Assertion{ + TupleKey: fgaSdk.AssertionTupleKey{ + User: clientAssertion.User, + Relation: clientAssertion.Relation, + Object: clientAssertion.Object, + }, + Expectation: clientAssertion.Expectation, + } + if clientAssertion.Context != nil { + assertion.Context = clientAssertion.Context + } + if clientAssertion.ContextualTuples != nil { + assertion.ContextualTuples = &clientAssertion.ContextualTuples + } + return assertion } type ClientWriteAssertionsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` } type ClientWriteAssertionsResponse struct { } func (client *OpenFgaClient) WriteAssertions(ctx _context.Context) SdkClientWriteAssertionsRequestInterface { - return &SdkClientWriteAssertionsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientWriteAssertionsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientWriteAssertionsRequest) Options(options ClientWriteAssertionsOptions) SdkClientWriteAssertionsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientWriteAssertionsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientWriteAssertionsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientWriteAssertionsRequest) Body(body ClientWriteAssertionsRequest) SdkClientWriteAssertionsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientWriteAssertionsRequest) Execute() (*ClientWriteAssertionsResponse, error) { - return request.Client.WriteAssertionsExecute(request) + return request.Client.WriteAssertionsExecute(request) } func (request *SdkClientWriteAssertionsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientWriteAssertionsRequest) GetBody() *ClientWriteAssertionsRequest { - return request.body + return request.body } func (request *SdkClientWriteAssertionsRequest) GetOptions() *ClientWriteAssertionsOptions { - return request.options + return request.options } func (client *OpenFgaClient) WriteAssertionsExecute(request SdkClientWriteAssertionsRequestInterface) (*ClientWriteAssertionsResponse, error) { - writeAssertionsRequest := fgaSdk.WriteAssertionsRequest{} - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - if authorizationModelId == nil || *authorizationModelId == "" { - return nil, FgaRequiredParamError{param: "AuthorizationModelId"} - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - for index := 0; index < len(*request.GetBody()); index++ { - clientAssertion := (*request.GetBody())[index] - writeAssertionsRequest.Assertions = append(writeAssertionsRequest.Assertions, clientAssertion.ToAssertion()) - } - - requestOptions := RequestOptions{} - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - } - - _, err = client.OpenFgaApi. - WriteAssertions(request.GetContext(), *storeId, *authorizationModelId). - Body(writeAssertionsRequest). - Options(requestOptions). - Execute() - - if err != nil { - return nil, err - } - return &ClientWriteAssertionsResponse{}, nil + writeAssertionsRequest := fgaSdk.WriteAssertionsRequest{} + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + if authorizationModelId == nil || *authorizationModelId == "" { + return nil, FgaRequiredParamError{param: "AuthorizationModelId"} + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + for index := 0; index < len(*request.GetBody()); index++ { + clientAssertion := (*request.GetBody())[index] + writeAssertionsRequest.Assertions = append(writeAssertionsRequest.Assertions, clientAssertion.ToAssertion()) + } + + requestOptions := RequestOptions{} + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + } + + _, err = client.OpenFgaApi. + WriteAssertions(request.GetContext(), *storeId, *authorizationModelId). + Body(writeAssertionsRequest). + Options(requestOptions). + Execute() + + if err != nil { + return nil, err + } + return &ClientWriteAssertionsResponse{}, nil } type SdkClientStreamedListObjectsRequest struct { - ctx _context.Context - Client *OpenFgaClient + ctx _context.Context + Client *OpenFgaClient - body *ClientStreamedListObjectsRequest - options *ClientStreamedListObjectsOptions + body *ClientStreamedListObjectsRequest + options *ClientStreamedListObjectsOptions } type SdkClientStreamedListObjectsRequestInterface interface { - Options(options ClientStreamedListObjectsOptions) SdkClientStreamedListObjectsRequestInterface - Body(body ClientStreamedListObjectsRequest) SdkClientStreamedListObjectsRequestInterface - Execute() (*ClientStreamedListObjectsResponse, error) - GetAuthorizationModelIdOverride() *string - GetStoreIdOverride() *string + Options(options ClientStreamedListObjectsOptions) SdkClientStreamedListObjectsRequestInterface + Body(body ClientStreamedListObjectsRequest) SdkClientStreamedListObjectsRequestInterface + Execute() (*ClientStreamedListObjectsResponse, error) + GetAuthorizationModelIdOverride() *string + GetStoreIdOverride() *string - GetContext() _context.Context - GetBody() *ClientStreamedListObjectsRequest - GetOptions() *ClientStreamedListObjectsOptions + GetContext() _context.Context + GetBody() *ClientStreamedListObjectsRequest + GetOptions() *ClientStreamedListObjectsOptions } type ClientStreamedListObjectsRequest struct { - User string `json:"user,omitempty"` - Relation string `json:"relation,omitempty"` - Type string `json:"type,omitempty"` - Context *map[string]interface{} `json:"context,omitempty"` - ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` + User string `json:"user,omitempty"` + Relation string `json:"relation,omitempty"` + Type string `json:"type,omitempty"` + Context *map[string]interface{} `json:"context,omitempty"` + ContextualTuples []ClientContextualTupleKey `json:"contextual_tuples,omitempty"` } type ClientStreamedListObjectsOptions struct { - RequestOptions + RequestOptions - AuthorizationModelId *string `json:"authorization_model_id,omitempty"` - StoreId *string `json:"store_id,omitempty"` - Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` - // StreamBufferSize configures the buffer size for streaming response channels. - // A larger buffer improves throughput for high-volume streams but increases memory usage. - // A smaller buffer reduces memory usage but may decrease throughput. - // Defaults to 10 if not specified or if set to 0. - StreamBufferSize *int `json:"stream_buffer_size,omitempty"` + AuthorizationModelId *string `json:"authorization_model_id,omitempty"` + StoreId *string `json:"store_id,omitempty"` + Consistency *fgaSdk.ConsistencyPreference `json:"consistency,omitempty"` + // StreamBufferSize configures the buffer size for streaming response channels. + // A larger buffer improves throughput for high-volume streams but increases memory usage. + // A smaller buffer reduces memory usage but may decrease throughput. + // Defaults to 10 if not specified or if set to 0. + StreamBufferSize *int `json:"stream_buffer_size,omitempty"` } type ClientStreamedListObjectsResponse struct { - Objects <-chan fgaSdk.StreamedListObjectsResponse - Errors <-chan error - close func() + Objects <-chan fgaSdk.StreamedListObjectsResponse + Errors <-chan error + close func() } func (r *ClientStreamedListObjectsResponse) Close() { - if r.close != nil { - r.close() - } + if r.close != nil { + r.close() + } } func (client *OpenFgaClient) StreamedListObjects(ctx _context.Context) SdkClientStreamedListObjectsRequestInterface { - return &SdkClientStreamedListObjectsRequest{ - Client: client, - ctx: ctx, - } + return &SdkClientStreamedListObjectsRequest{ + Client: client, + ctx: ctx, + } } func (request *SdkClientStreamedListObjectsRequest) Options(options ClientStreamedListObjectsOptions) SdkClientStreamedListObjectsRequestInterface { - request.options = &options - return request + request.options = &options + return request } func (request *SdkClientStreamedListObjectsRequest) GetAuthorizationModelIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.AuthorizationModelId + if request.options == nil { + return nil + } + return request.options.AuthorizationModelId } func (request *SdkClientStreamedListObjectsRequest) GetStoreIdOverride() *string { - if request.options == nil { - return nil - } - return request.options.StoreId + if request.options == nil { + return nil + } + return request.options.StoreId } func (request *SdkClientStreamedListObjectsRequest) Body(body ClientStreamedListObjectsRequest) SdkClientStreamedListObjectsRequestInterface { - request.body = &body - return request + request.body = &body + return request } func (request *SdkClientStreamedListObjectsRequest) Execute() (*ClientStreamedListObjectsResponse, error) { - return request.Client.StreamedListObjectsExecute(request) + return request.Client.StreamedListObjectsExecute(request) } func (request *SdkClientStreamedListObjectsRequest) GetContext() _context.Context { - return request.ctx + return request.ctx } func (request *SdkClientStreamedListObjectsRequest) GetBody() *ClientStreamedListObjectsRequest { - return request.body + return request.body } func (request *SdkClientStreamedListObjectsRequest) GetOptions() *ClientStreamedListObjectsOptions { - return request.options + return request.options } func (client *OpenFgaClient) StreamedListObjectsExecute(request SdkClientStreamedListObjectsRequestInterface) (*ClientStreamedListObjectsResponse, error) { - if request.GetBody() == nil { - return nil, FgaRequiredParamError{param: "body"} - } - var contextualTuples []ClientContextualTupleKey - if request.GetBody().ContextualTuples != nil { - for index := 0; index < len(request.GetBody().ContextualTuples); index++ { - contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) - } - } - authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) - if err != nil { - return nil, err - } - storeId, err := client.getStoreId(request.GetStoreIdOverride()) - if err != nil { - return nil, err - } - body := fgaSdk.ListObjectsRequest{ - User: request.GetBody().User, - Relation: request.GetBody().Relation, - Type: request.GetBody().Type, - ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), - Context: request.GetBody().Context, - AuthorizationModelId: authorizationModelId, - } - requestOptions := RequestOptions{} - bufferSize := 0 - if request.GetOptions() != nil { - requestOptions = request.GetOptions().RequestOptions - body.Consistency = request.GetOptions().Consistency - if request.GetOptions().StreamBufferSize != nil { - bufferSize = *request.GetOptions().StreamBufferSize - } - } - - channel, err := fgaSdk.ExecuteStreamedListObjectsWithBufferSize( - &client.APIClient, - request.GetContext(), - *storeId, - body, - requestOptions, - bufferSize, - ) - - if err != nil { - return nil, err - } - - return &ClientStreamedListObjectsResponse{ - Objects: channel.Objects, - Errors: channel.Errors, - close: channel.Close, - }, nil + if request.GetBody() == nil { + return nil, FgaRequiredParamError{param: "body"} + } + var contextualTuples []ClientContextualTupleKey + if request.GetBody().ContextualTuples != nil { + for index := 0; index < len(request.GetBody().ContextualTuples); index++ { + contextualTuples = append(contextualTuples, (request.GetBody().ContextualTuples)[index]) + } + } + authorizationModelId, err := client.getAuthorizationModelId(request.GetAuthorizationModelIdOverride()) + if err != nil { + return nil, err + } + storeId, err := client.getStoreId(request.GetStoreIdOverride()) + if err != nil { + return nil, err + } + body := fgaSdk.ListObjectsRequest{ + User: request.GetBody().User, + Relation: request.GetBody().Relation, + Type: request.GetBody().Type, + ContextualTuples: fgaSdk.NewContextualTupleKeys(contextualTuples), + Context: request.GetBody().Context, + AuthorizationModelId: authorizationModelId, + } + requestOptions := RequestOptions{} + bufferSize := 0 + if request.GetOptions() != nil { + requestOptions = request.GetOptions().RequestOptions + body.Consistency = request.GetOptions().Consistency + if request.GetOptions().StreamBufferSize != nil { + bufferSize = *request.GetOptions().StreamBufferSize + } + } + + channel, err := fgaSdk.ExecuteStreamedListObjectsWithBufferSize( + &client.APIClient, + request.GetContext(), + *storeId, + body, + requestOptions, + bufferSize, + ) + + if err != nil { + return nil, err + } + + return &ClientStreamedListObjectsResponse{ + Objects: channel.Objects, + Errors: channel.Errors, + close: channel.Close, + }, nil } diff --git a/example/streamed_list_objects/main.go b/example/streamed_list_objects/main.go index 52a858f..381168c 100644 --- a/example/streamed_list_objects/main.go +++ b/example/streamed_list_objects/main.go @@ -1,255 +1,255 @@ package main import ( - "context" - "fmt" - "log" - "os" - "strconv" - "time" - - openfga "github.com/openfga/go-sdk" - "github.com/openfga/go-sdk/client" + "context" + "fmt" + "log" + "os" + "strconv" + "time" + + openfga "github.com/openfga/go-sdk" + "github.com/openfga/go-sdk/client" ) func runSync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: sync streaming (range over channel)") - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) - } - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() - if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) - } - defer response.Close() - - fmt.Println("Streaming objects (sync):") - received := 0 - for obj := range response.Objects { // synchronous consumption - received++ - fmt.Printf(" %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil { - log.Fatalf("Error during streaming: %v", err) - } - fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) + fmt.Println("Mode: sync streaming (range over channel)") + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + fmt.Println("Streaming objects (sync):") + received := 0 + for obj := range response.Objects { // synchronous consumption + received++ + fmt.Printf(" %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil { + log.Fatalf("Error during streaming: %v", err) + } + fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) } // runAsync demonstrates asynchronous consumption using a goroutine; main goroutine can do other work. func runAsync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: async streaming (consume in goroutine)") - // Use a cancellable context to show cancellation pattern (not cancelling in this example). - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) - } - - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() - if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) - } - defer response.Close() - - done := make(chan struct{}) - received := 0 - - go func() { - defer close(done) - for obj := range response.Objects { - received++ - fmt.Printf(" async -> %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil && err != context.Canceled { - log.Fatalf("Error during async streaming: %v", err) - } - }() - - // Simulate doing other work while streaming happens. - ticker := time.NewTicker(200 * time.Millisecond) - defer ticker.Stop() - - fmt.Println("Performing other work while streaming...") - for { - select { - case <-done: - fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) - return - case <-ticker.C: - fmt.Println(" (main goroutine still free to do work)") - } - } + fmt.Println("Mode: async streaming (consume in goroutine)") + // Use a cancellable context to show cancellation pattern (not cancelling in this example). + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + done := make(chan struct{}) + received := 0 + + go func() { + defer close(done) + for obj := range response.Objects { + received++ + fmt.Printf(" async -> %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil && err != context.Canceled { + log.Fatalf("Error during async streaming: %v", err) + } + }() + + // Simulate doing other work while streaming happens. + ticker := time.NewTicker(200 * time.Millisecond) + defer ticker.Stop() + + fmt.Println("Performing other work while streaming...") + for { + select { + case <-done: + fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) + return + case <-ticker.C: + fmt.Println(" (main goroutine still free to do work)") + } + } } func createTestData(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, tupleCount int) (string, error) { - // Ensure relation is either viewer or owner for this simplified example. - if relation != "viewer" && relation != "owner" { - return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) - } - - if authModelId == "" { - fmt.Println("Creating authorization model...") - - // Provide both viewer and owner relations so user can pick. - relations := map[string]openfga.Userset{ - "viewer": {This: &map[string]interface{}{}}, - "owner": {This: &map[string]interface{}{}}, - } - - relationMetadata := map[string]openfga.RelationMetadata{ - "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - } - - model := openfga.AuthorizationModel{ - SchemaVersion: "1.1", - TypeDefinitions: []openfga.TypeDefinition{ - {Type: "user"}, - {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, - }, - } - - writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ - SchemaVersion: model.SchemaVersion, - TypeDefinitions: model.TypeDefinitions, - }).Execute() - if err != nil { - return authModelId, fmt.Errorf("failed to create authorization model: %w", err) - } - authModelId = writeModelResp.AuthorizationModelId - fmt.Printf("Created authorization model: %s\n\n", authModelId) - } - - fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) - tuples := make([]client.ClientTupleKey, 0, tupleCount) - for i := 0; i < tupleCount; i++ { - tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) - } - if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { - return authModelId, fmt.Errorf("failed to write tuples: %w", err) - } - fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) - return authModelId, nil + // Ensure relation is either viewer or owner for this simplified example. + if relation != "viewer" && relation != "owner" { + return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) + } + + if authModelId == "" { + fmt.Println("Creating authorization model...") + + // Provide both viewer and owner relations so user can pick. + relations := map[string]openfga.Userset{ + "viewer": {This: &map[string]interface{}{}}, + "owner": {This: &map[string]interface{}{}}, + } + + relationMetadata := map[string]openfga.RelationMetadata{ + "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + } + + model := openfga.AuthorizationModel{ + SchemaVersion: "1.1", + TypeDefinitions: []openfga.TypeDefinition{ + {Type: "user"}, + {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, + }, + } + + writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ + SchemaVersion: model.SchemaVersion, + TypeDefinitions: model.TypeDefinitions, + }).Execute() + if err != nil { + return authModelId, fmt.Errorf("failed to create authorization model: %w", err) + } + authModelId = writeModelResp.AuthorizationModelId + fmt.Printf("Created authorization model: %s\n\n", authModelId) + } + + fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) + tuples := make([]client.ClientTupleKey, 0, tupleCount) + for i := 0; i < tupleCount; i++ { + tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) + } + if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { + return authModelId, fmt.Errorf("failed to write tuples: %w", err) + } + fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) + return authModelId, nil } func parseArgs() (mode string, count int, relation string, bufferSize *int) { - mode = "sync" // default - relation = "viewer" - count = 3 - if len(os.Args) > 1 { - mode = os.Args[1] - } - if len(os.Args) > 2 { - if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { - count = c - } - } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { - if c, err := strconv.Atoi(envCount); err == nil && c > 0 { - count = c - } - } - if len(os.Args) > 3 { - relation = os.Args[3] - } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { - relation = envRel - } - if len(os.Args) > 4 { - if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { - bufferSize = &b - } - } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { - if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { - bufferSize = &b - } - } - return + mode = "sync" // default + relation = "viewer" + count = 3 + if len(os.Args) > 1 { + mode = os.Args[1] + } + if len(os.Args) > 2 { + if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { + count = c + } + } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { + if c, err := strconv.Atoi(envCount); err == nil && c > 0 { + count = c + } + } + if len(os.Args) > 3 { + relation = os.Args[3] + } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { + relation = envRel + } + if len(os.Args) > 4 { + if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { + bufferSize = &b + } + } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { + if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { + bufferSize = &b + } + } + return } func main() { - ctx := context.Background() - apiUrl := os.Getenv("FGA_API_URL") - if apiUrl == "" { - apiUrl = "http://localhost:8080" - } - config := client.ClientConfiguration{ApiUrl: apiUrl} - fgaClient, err := client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - // Create store unless provided via env var. - storeId := os.Getenv("FGA_STORE_ID") - createdTempStore := false - if storeId == "" { - fmt.Println("Creating Test Store for streamed list objects") - store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() - if err != nil { - panic(err) - } - storeId = store.Id - createdTempStore = true - } - - // Re-init client with storeId - config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} - fgaClient, err = client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - fmt.Println("OpenFGA StreamedListObjects Example") - fmt.Println("____________________________________") - fmt.Printf("API URL: %s\n", apiUrl) - fmt.Printf("Store ID: %s\n", storeId) - fmt.Println() - - authModelId := os.Getenv("FGA_MODEL_ID") - mode, tupleCount, relation, bufferSize := parseArgs() - if authModelId != "" { - fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) - } - authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) - if err != nil { - log.Printf("Warning: Failed to create test data: %v", err) - log.Println("Continuing with example...") - } - - fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) - if bufferSize != nil { - fmt.Printf(" | buffer size: %d", *bufferSize) - } - fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") - - switch mode { - case "async": - runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - case "sync": - runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - default: - fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) - os.Exit(1) - } - - if createdTempStore { - fmt.Println("\nDeleting temporary store...") - if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { - fmt.Printf("Failed to delete store: %v\n", err) - } else { - fmt.Printf("Deleted temporary store (%s)\n", storeId) - } - } - fmt.Println("\nDone.") + ctx := context.Background() + apiUrl := os.Getenv("FGA_API_URL") + if apiUrl == "" { + apiUrl = "http://localhost:8080" + } + config := client.ClientConfiguration{ApiUrl: apiUrl} + fgaClient, err := client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + // Create store unless provided via env var. + storeId := os.Getenv("FGA_STORE_ID") + createdTempStore := false + if storeId == "" { + fmt.Println("Creating Test Store for streamed list objects") + store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() + if err != nil { + panic(err) + } + storeId = store.Id + createdTempStore = true + } + + // Re-init client with storeId + config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} + fgaClient, err = client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + fmt.Println("OpenFGA StreamedListObjects Example") + fmt.Println("____________________________________") + fmt.Printf("API URL: %s\n", apiUrl) + fmt.Printf("Store ID: %s\n", storeId) + fmt.Println() + + authModelId := os.Getenv("FGA_MODEL_ID") + mode, tupleCount, relation, bufferSize := parseArgs() + if authModelId != "" { + fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) + } + authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) + if err != nil { + log.Printf("Warning: Failed to create test data: %v", err) + log.Println("Continuing with example...") + } + + fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) + if bufferSize != nil { + fmt.Printf(" | buffer size: %d", *bufferSize) + } + fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") + + switch mode { + case "async": + runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + case "sync": + runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + default: + fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) + os.Exit(1) + } + + if createdTempStore { + fmt.Println("\nDeleting temporary store...") + if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { + fmt.Printf("Failed to delete store: %v\n", err) + } else { + fmt.Printf("Deleted temporary store (%s)\n", storeId) + } + } + fmt.Println("\nDone.") } diff --git a/streaming.go b/streaming.go index c23f370..acc5b30 100644 --- a/streaming.go +++ b/streaming.go @@ -13,149 +13,149 @@ package openfga import ( - "bufio" - "context" - "encoding/json" - "errors" - "io" - "net/http" - "net/url" - "strings" + "bufio" + "context" + "encoding/json" + "errors" + "io" + "net/http" + "net/url" + "strings" ) type StreamedListObjectsChannel struct { - Objects chan StreamedListObjectsResponse - Errors chan error - cancel context.CancelFunc + Objects chan StreamedListObjectsResponse + Errors chan error + cancel context.CancelFunc } func (s *StreamedListObjectsChannel) Close() { - if s.cancel != nil { - s.cancel() - } + if s.cancel != nil { + s.cancel() + } } func ProcessStreamedListObjectsResponse(ctx context.Context, httpResponse *http.Response, bufferSize int) (*StreamedListObjectsChannel, error) { - streamCtx, cancel := context.WithCancel(ctx) - - // Use default buffer size of 10 if not specified or invalid - if bufferSize <= 0 { - bufferSize = 10 - } - - channel := &StreamedListObjectsChannel{ - Objects: make(chan StreamedListObjectsResponse, bufferSize), - Errors: make(chan error, 1), - cancel: cancel, - } - - if httpResponse == nil || httpResponse.Body == nil { - cancel() - return nil, errors.New("response or response body is nil") - } - - go func() { - defer close(channel.Objects) - defer close(channel.Errors) - defer cancel() - defer httpResponse.Body.Close() - - scanner := bufio.NewScanner(httpResponse.Body) - // Allow large NDJSON entries (up to 10MB). Tune as needed. - buf := make([]byte, 0, 64*1024) - scanner.Buffer(buf, 10*1024*1024) - for scanner.Scan() { - select { - case <-streamCtx.Done(): - channel.Errors <- streamCtx.Err() - return - default: - line := scanner.Bytes() - if len(line) == 0 { - continue - } - - var streamResult StreamResultOfStreamedListObjectsResponse - if err := json.Unmarshal(line, &streamResult); err != nil { - channel.Errors <- err - return - } - - if streamResult.Error != nil { - msg := "stream error" - if streamResult.Error.Message != nil { - msg = *streamResult.Error.Message - } - channel.Errors <- errors.New(msg) - return - } - - if streamResult.Result != nil { - select { - case <-streamCtx.Done(): - channel.Errors <- streamCtx.Err() - return - case channel.Objects <- *streamResult.Result: - } - } - } - } - - if err := scanner.Err(); err != nil { - // Prefer context error if we were canceled to avoid surfacing net/http "use of closed network connection". - if streamCtx.Err() != nil { - channel.Errors <- streamCtx.Err() - return - } - channel.Errors <- err - } - }() - - return channel, nil + streamCtx, cancel := context.WithCancel(ctx) + + // Use default buffer size of 10 if not specified or invalid + if bufferSize <= 0 { + bufferSize = 10 + } + + channel := &StreamedListObjectsChannel{ + Objects: make(chan StreamedListObjectsResponse, bufferSize), + Errors: make(chan error, 1), + cancel: cancel, + } + + if httpResponse == nil || httpResponse.Body == nil { + cancel() + return nil, errors.New("response or response body is nil") + } + + go func() { + defer close(channel.Objects) + defer close(channel.Errors) + defer cancel() + defer httpResponse.Body.Close() + + scanner := bufio.NewScanner(httpResponse.Body) + // Allow large NDJSON entries (up to 10MB). Tune as needed. + buf := make([]byte, 0, 64*1024) + scanner.Buffer(buf, 10*1024*1024) + for scanner.Scan() { + select { + case <-streamCtx.Done(): + channel.Errors <- streamCtx.Err() + return + default: + line := scanner.Bytes() + if len(line) == 0 { + continue + } + + var streamResult StreamResultOfStreamedListObjectsResponse + if err := json.Unmarshal(line, &streamResult); err != nil { + channel.Errors <- err + return + } + + if streamResult.Error != nil { + msg := "stream error" + if streamResult.Error.Message != nil { + msg = *streamResult.Error.Message + } + channel.Errors <- errors.New(msg) + return + } + + if streamResult.Result != nil { + select { + case <-streamCtx.Done(): + channel.Errors <- streamCtx.Err() + return + case channel.Objects <- *streamResult.Result: + } + } + } + } + + if err := scanner.Err(); err != nil { + // Prefer context error if we were canceled to avoid surfacing net/http "use of closed network connection". + if streamCtx.Err() != nil { + channel.Errors <- streamCtx.Err() + return + } + channel.Errors <- err + } + }() + + return channel, nil } func ExecuteStreamedListObjects(client *APIClient, ctx context.Context, storeId string, body ListObjectsRequest, options RequestOptions) (*StreamedListObjectsChannel, error) { - return ExecuteStreamedListObjectsWithBufferSize(client, ctx, storeId, body, options, 0) + return ExecuteStreamedListObjectsWithBufferSize(client, ctx, storeId, body, options, 0) } func ExecuteStreamedListObjectsWithBufferSize(client *APIClient, ctx context.Context, storeId string, body ListObjectsRequest, options RequestOptions, bufferSize int) (*StreamedListObjectsChannel, error) { - path := "/stores/{store_id}/streamed-list-objects" - if storeId == "" { - return nil, reportError("storeId is required and must be specified") - } - - path = strings.ReplaceAll(path, "{"+"store_id"+"}", url.PathEscape(parameterToString(storeId, ""))) - - localVarHeaderParams := make(map[string]string) - localVarQueryParams := url.Values{} - - localVarHTTPContentType := "application/json" - localVarHeaderParams["Content-Type"] = localVarHTTPContentType - localVarHeaderParams["Accept"] = "application/x-ndjson" - - for header, val := range options.Headers { - localVarHeaderParams[header] = val - } - - req, err := client.prepareRequest(ctx, path, http.MethodPost, body, localVarHeaderParams, localVarQueryParams) - if err != nil { - return nil, err - } - - httpResponse, err := client.callAPI(req) - if err != nil || httpResponse == nil { - return nil, err - } - - if httpResponse.StatusCode >= http.StatusMultipleChoices { - responseBody, readErr := io.ReadAll(httpResponse.Body) - _ = httpResponse.Body.Close() - if readErr != nil { - return nil, readErr - } - err = client.handleAPIError(httpResponse, responseBody, body, "StreamedListObjects", storeId) - return nil, err - } - - return ProcessStreamedListObjectsResponse(ctx, httpResponse, bufferSize) + path := "/stores/{store_id}/streamed-list-objects" + if storeId == "" { + return nil, reportError("storeId is required and must be specified") + } + + path = strings.ReplaceAll(path, "{"+"store_id"+"}", url.PathEscape(parameterToString(storeId, ""))) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + + localVarHTTPContentType := "application/json" + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + localVarHeaderParams["Accept"] = "application/x-ndjson" + + for header, val := range options.Headers { + localVarHeaderParams[header] = val + } + + req, err := client.prepareRequest(ctx, path, http.MethodPost, body, localVarHeaderParams, localVarQueryParams) + if err != nil { + return nil, err + } + + httpResponse, err := client.callAPI(req) + if err != nil || httpResponse == nil { + return nil, err + } + + if httpResponse.StatusCode >= http.StatusMultipleChoices { + responseBody, readErr := io.ReadAll(httpResponse.Body) + _ = httpResponse.Body.Close() + if readErr != nil { + return nil, readErr + } + err = client.handleAPIError(httpResponse, responseBody, body, "StreamedListObjects", storeId) + return nil, err + } + + return ProcessStreamedListObjectsResponse(ctx, httpResponse, bufferSize) } diff --git a/streaming_test.go b/streaming_test.go index b241c17..66ad213 100644 --- a/streaming_test.go +++ b/streaming_test.go @@ -13,481 +13,481 @@ package openfga import ( - "context" - "net/http" - "net/http/httptest" - "strconv" - "strings" - "testing" - "time" + "context" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "testing" + "time" ) func TestStreamedListObjectsChannel_Close(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - channel := &StreamedListObjectsChannel{ - Objects: make(chan StreamedListObjectsResponse), - Errors: make(chan error), - cancel: cancel, - } - - channel.Close() - - select { - case <-ctx.Done(): - case <-time.After(100 * time.Millisecond): - t.Error("Context was not cancelled") - } + ctx, cancel := context.WithCancel(context.Background()) + channel := &StreamedListObjectsChannel{ + Objects: make(chan StreamedListObjectsResponse), + Errors: make(chan error), + cancel: cancel, + } + + channel.Close() + + select { + case <-ctx.Done(): + case <-time.After(100 * time.Millisecond): + t.Error("Context was not cancelled") + } } func TestStreamedListObjectsWithChannel_Success(t *testing.T) { - objects := []string{"document:1", "document:2", "document:3"} - expectedResults := []string{} - for _, obj := range objects { - expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) - } - responseBody := strings.Join(expectedResults, "\n") - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/stores/test-store/streamed-list-objects" { - t.Errorf("Expected path /stores/test-store/streamed-list-objects, got %s", r.URL.Path) - } - if r.Method != http.MethodPost { - t.Errorf("Expected POST method, got %s", r.Method) - } - - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - w.Write([]byte(responseBody)) - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - if err := <-channel.Errors; err != nil { - t.Fatalf("Received error from channel: %v", err) - } - - if len(receivedObjects) != len(objects) { - t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) - } - - for i, expected := range objects { - if receivedObjects[i] != expected { - t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) - } - } + objects := []string{"document:1", "document:2", "document:3"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/stores/test-store/streamed-list-objects" { + t.Errorf("Expected path /stores/test-store/streamed-list-objects, got %s", r.URL.Path) + } + if r.Method != http.MethodPost { + t.Errorf("Expected POST method, got %s", r.Method) + } + + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } + + for i, expected := range objects { + if receivedObjects[i] != expected { + t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) + } + } } func TestStreamedListObjectsWithChannel_EmptyLines(t *testing.T) { - responseBody := `{"result":{"object":"document:1"}} + responseBody := `{"result":{"object":"document:1"}} {"result":{"object":"document:2"}} {"result":{"object":"document:3"}}` - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - w.Write([]byte(responseBody)) - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - if len(receivedObjects) != 3 { - t.Fatalf("Expected 3 objects, got %d", len(receivedObjects)) - } + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if len(receivedObjects) != 3 { + t.Fatalf("Expected 3 objects, got %d", len(receivedObjects)) + } } func TestStreamedListObjectsWithChannel_ErrorInStream(t *testing.T) { - responseBody := `{"result":{"object":"document:1"}} + responseBody := `{"result":{"object":"document:1"}} {"error":{"code":500,"message":"Internal error"}}` - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - w.Write([]byte(responseBody)) - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - err = <-channel.Errors - if err == nil { - t.Fatal("Expected error from channel, got nil") - } - - if !strings.Contains(err.Error(), "Internal error") { - t.Errorf("Expected error message to contain 'Internal error', got %s", err.Error()) - } - - if len(receivedObjects) != 1 { - t.Fatalf("Expected 1 object before error, got %d", len(receivedObjects)) - } + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + err = <-channel.Errors + if err == nil { + t.Fatal("Expected error from channel, got nil") + } + + if !strings.Contains(err.Error(), "Internal error") { + t.Errorf("Expected error message to contain 'Internal error', got %s", err.Error()) + } + + if len(receivedObjects) != 1 { + t.Fatalf("Expected 1 object before error, got %d", len(receivedObjects)) + } } func TestStreamedListObjectsWithChannel_InvalidJSON(t *testing.T) { - responseBody := `{"result":{"object":"document:1"}} + responseBody := `{"result":{"object":"document:1"}} invalid json` - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - w.Write([]byte(responseBody)) - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - err = <-channel.Errors - if err == nil { - t.Fatal("Expected error from channel for invalid JSON, got nil") - } - - if len(receivedObjects) != 1 { - t.Fatalf("Expected 1 object before error, got %d", len(receivedObjects)) - } + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + err = <-channel.Errors + if err == nil { + t.Fatal("Expected error from channel for invalid JSON, got nil") + } + + if len(receivedObjects) != 1 { + t.Fatalf("Expected 1 object before error, got %d", len(receivedObjects)) + } } func TestStreamedListObjectsWithChannel_ContextCancellation(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - for i := 0; i < 100; i++ { - w.Write([]byte(`{"result":{"object":"document:` + strconv.Itoa(i) + `"}}` + "\n")) - if f, ok := w.(http.Flusher); ok { - f.Flush() - } - time.Sleep(10 * time.Millisecond) - } - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx, cancel := context.WithCancel(context.Background()) - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for i := 0; i < 5; i++ { - obj := <-channel.Objects - receivedObjects = append(receivedObjects, obj.Object) - } - - cancel() - - time.Sleep(100 * time.Millisecond) - - remaining := 0 - for range channel.Objects { - remaining++ - } - - if len(receivedObjects) < 5 { - t.Fatalf("Expected at least 5 objects, got %d", len(receivedObjects)) - } + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + for i := 0; i < 100; i++ { + w.Write([]byte(`{"result":{"object":"document:` + strconv.Itoa(i) + `"}}` + "\n")) + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + time.Sleep(10 * time.Millisecond) + } + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx, cancel := context.WithCancel(context.Background()) + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for i := 0; i < 5; i++ { + obj := <-channel.Objects + receivedObjects = append(receivedObjects, obj.Object) + } + + cancel() + + time.Sleep(100 * time.Millisecond) + + remaining := 0 + for range channel.Objects { + remaining++ + } + + if len(receivedObjects) < 5 { + t.Fatalf("Expected at least 5 objects, got %d", len(receivedObjects)) + } } func TestStreamedListObjectsWithChannel_CustomBufferSize(t *testing.T) { - objects := []string{"document:1", "document:2", "document:3", "document:4", "document:5"} - expectedResults := []string{} - for _, obj := range objects { - expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) - } - responseBody := strings.Join(expectedResults, "\n") - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - w.Write([]byte(responseBody)) - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - // Test with custom buffer size using the new function - channel, err := ExecuteStreamedListObjectsWithBufferSize(client, ctx, "test-store", request, RequestOptions{}, 50) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - if err := <-channel.Errors; err != nil { - t.Fatalf("Received error from channel: %v", err) - } - - if len(receivedObjects) != len(objects) { - t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) - } - - for i, expected := range objects { - if receivedObjects[i] != expected { - t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) - } - } + objects := []string{"document:1", "document:2", "document:3", "document:4", "document:5"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + // Test with custom buffer size using the new function + channel, err := ExecuteStreamedListObjectsWithBufferSize(client, ctx, "test-store", request, RequestOptions{}, 50) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } + + for i, expected := range objects { + if receivedObjects[i] != expected { + t.Errorf("Expected object %s at index %d, got %s", expected, i, receivedObjects[i]) + } + } } func TestStreamedListObjectsWithChannel_DefaultBufferSize(t *testing.T) { - objects := []string{"document:1", "document:2"} - expectedResults := []string{} - for _, obj := range objects { - expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) - } - responseBody := strings.Join(expectedResults, "\n") - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - w.Write([]byte(responseBody)) - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - // Test with default buffer size (0 uses default of 10) - channel, err := ExecuteStreamedListObjectsWithBufferSize(client, ctx, "test-store", request, RequestOptions{}, 0) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - if err := <-channel.Errors; err != nil { - t.Fatalf("Received error from channel: %v", err) - } - - if len(receivedObjects) != len(objects) { - t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) - } + objects := []string{"document:1", "document:2"} + expectedResults := []string{} + for _, obj := range objects { + expectedResults = append(expectedResults, `{"result":{"object":"`+obj+`"}}`) + } + responseBody := strings.Join(expectedResults, "\n") + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + w.Write([]byte(responseBody)) + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + // Test with default buffer size (0 uses default of 10) + channel, err := ExecuteStreamedListObjectsWithBufferSize(client, ctx, "test-store", request, RequestOptions{}, 0) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + if len(receivedObjects) != len(objects) { + t.Fatalf("Expected %d objects, got %d", len(objects), len(receivedObjects)) + } } func TestStreamedListObjectsWithChannel_ProperNumericStrings(t *testing.T) { - // Test that document IDs are generated correctly for values >= 10 - // This verifies the fix: using strconv.Itoa(i) instead of string(rune('0'+i%10)) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/x-ndjson") - w.WriteHeader(http.StatusOK) - // Generate 15 objects to ensure we test values >= 10 - for i := 0; i < 15; i++ { - w.Write([]byte(`{"result":{"object":"document:` + strconv.Itoa(i) + `"}}` + "\n")) - } - })) - defer server.Close() - - config, err := NewConfiguration(Configuration{ - ApiUrl: server.URL, - }) - if err != nil { - t.Fatalf("Failed to create configuration: %v", err) - } - - client := NewAPIClient(config) - ctx := context.Background() - - request := ListObjectsRequest{ - Type: "document", - Relation: "viewer", - User: "user:anne", - } - - channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) - - if err != nil { - t.Fatalf("ExecuteStreamedListObjects failed: %v", err) - } - - defer channel.Close() - - receivedObjects := []string{} - for obj := range channel.Objects { - receivedObjects = append(receivedObjects, obj.Object) - } - - if err := <-channel.Errors; err != nil { - t.Fatalf("Received error from channel: %v", err) - } - - expectedObjects := []string{ - "document:0", "document:1", "document:2", "document:3", "document:4", - "document:5", "document:6", "document:7", "document:8", "document:9", - "document:10", "document:11", "document:12", "document:13", "document:14", - } - - if len(receivedObjects) != len(expectedObjects) { - t.Fatalf("Expected %d objects, got %d", len(expectedObjects), len(receivedObjects)) - } - - for i, expected := range expectedObjects { - if receivedObjects[i] != expected { - t.Errorf("At index %d: expected %s, got %s", i, expected, receivedObjects[i]) - } - } + // Test that document IDs are generated correctly for values >= 10 + // This verifies the fix: using strconv.Itoa(i) instead of string(rune('0'+i%10)) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/x-ndjson") + w.WriteHeader(http.StatusOK) + // Generate 15 objects to ensure we test values >= 10 + for i := 0; i < 15; i++ { + w.Write([]byte(`{"result":{"object":"document:` + strconv.Itoa(i) + `"}}` + "\n")) + } + })) + defer server.Close() + + config, err := NewConfiguration(Configuration{ + ApiUrl: server.URL, + }) + if err != nil { + t.Fatalf("Failed to create configuration: %v", err) + } + + client := NewAPIClient(config) + ctx := context.Background() + + request := ListObjectsRequest{ + Type: "document", + Relation: "viewer", + User: "user:anne", + } + + channel, err := ExecuteStreamedListObjects(client, ctx, "test-store", request, RequestOptions{}) + + if err != nil { + t.Fatalf("ExecuteStreamedListObjects failed: %v", err) + } + + defer channel.Close() + + receivedObjects := []string{} + for obj := range channel.Objects { + receivedObjects = append(receivedObjects, obj.Object) + } + + if err := <-channel.Errors; err != nil { + t.Fatalf("Received error from channel: %v", err) + } + + expectedObjects := []string{ + "document:0", "document:1", "document:2", "document:3", "document:4", + "document:5", "document:6", "document:7", "document:8", "document:9", + "document:10", "document:11", "document:12", "document:13", "document:14", + } + + if len(receivedObjects) != len(expectedObjects) { + t.Fatalf("Expected %d objects, got %d", len(expectedObjects), len(receivedObjects)) + } + + for i, expected := range expectedObjects { + if receivedObjects[i] != expected { + t.Errorf("At index %d: expected %s, got %s", i, expected, receivedObjects[i]) + } + } } From 197e0e85eb9e28935ba1ada49e68e2489d075bbf Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Wed, 29 Oct 2025 23:11:25 +0530 Subject: [PATCH 4/9] feat: avoid using panic --- example/streamed_list_objects/main.go | 470 +++++++++++++------------- 1 file changed, 235 insertions(+), 235 deletions(-) diff --git a/example/streamed_list_objects/main.go b/example/streamed_list_objects/main.go index 381168c..107861d 100644 --- a/example/streamed_list_objects/main.go +++ b/example/streamed_list_objects/main.go @@ -1,255 +1,255 @@ package main import ( - "context" - "fmt" - "log" - "os" - "strconv" - "time" - - openfga "github.com/openfga/go-sdk" - "github.com/openfga/go-sdk/client" + "context" + "fmt" + "log" + "os" + "strconv" + "time" + + openfga "github.com/openfga/go-sdk" + "github.com/openfga/go-sdk/client" ) func runSync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: sync streaming (range over channel)") - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) - } - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() - if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) - } - defer response.Close() - - fmt.Println("Streaming objects (sync):") - received := 0 - for obj := range response.Objects { // synchronous consumption - received++ - fmt.Printf(" %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil { - log.Fatalf("Error during streaming: %v", err) - } - fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) + fmt.Println("Mode: sync streaming (range over channel)") + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + fmt.Println("Streaming objects (sync):") + received := 0 + for obj := range response.Objects { // synchronous consumption + received++ + fmt.Printf(" %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil { + log.Fatalf("Error during streaming: %v", err) + } + fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) } // runAsync demonstrates asynchronous consumption using a goroutine; main goroutine can do other work. func runAsync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: async streaming (consume in goroutine)") - // Use a cancellable context to show cancellation pattern (not cancelling in this example). - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) - } - - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() - if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) - } - defer response.Close() - - done := make(chan struct{}) - received := 0 - - go func() { - defer close(done) - for obj := range response.Objects { - received++ - fmt.Printf(" async -> %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil && err != context.Canceled { - log.Fatalf("Error during async streaming: %v", err) - } - }() - - // Simulate doing other work while streaming happens. - ticker := time.NewTicker(200 * time.Millisecond) - defer ticker.Stop() - - fmt.Println("Performing other work while streaming...") - for { - select { - case <-done: - fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) - return - case <-ticker.C: - fmt.Println(" (main goroutine still free to do work)") - } - } + fmt.Println("Mode: async streaming (consume in goroutine)") + // Use a cancellable context to show cancellation pattern (not cancelling in this example). + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + done := make(chan struct{}) + received := 0 + + go func() { + defer close(done) + for obj := range response.Objects { + received++ + fmt.Printf(" async -> %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil && err != context.Canceled { + log.Fatalf("Error during async streaming: %v", err) + } + }() + + // Simulate doing other work while streaming happens. + ticker := time.NewTicker(200 * time.Millisecond) + defer ticker.Stop() + + fmt.Println("Performing other work while streaming...") + for { + select { + case <-done: + fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) + return + case <-ticker.C: + fmt.Println(" (main goroutine still free to do work)") + } + } } func createTestData(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, tupleCount int) (string, error) { - // Ensure relation is either viewer or owner for this simplified example. - if relation != "viewer" && relation != "owner" { - return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) - } - - if authModelId == "" { - fmt.Println("Creating authorization model...") - - // Provide both viewer and owner relations so user can pick. - relations := map[string]openfga.Userset{ - "viewer": {This: &map[string]interface{}{}}, - "owner": {This: &map[string]interface{}{}}, - } - - relationMetadata := map[string]openfga.RelationMetadata{ - "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - } - - model := openfga.AuthorizationModel{ - SchemaVersion: "1.1", - TypeDefinitions: []openfga.TypeDefinition{ - {Type: "user"}, - {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, - }, - } - - writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ - SchemaVersion: model.SchemaVersion, - TypeDefinitions: model.TypeDefinitions, - }).Execute() - if err != nil { - return authModelId, fmt.Errorf("failed to create authorization model: %w", err) - } - authModelId = writeModelResp.AuthorizationModelId - fmt.Printf("Created authorization model: %s\n\n", authModelId) - } - - fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) - tuples := make([]client.ClientTupleKey, 0, tupleCount) - for i := 0; i < tupleCount; i++ { - tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) - } - if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { - return authModelId, fmt.Errorf("failed to write tuples: %w", err) - } - fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) - return authModelId, nil + // Ensure relation is either viewer or owner for this simplified example. + if relation != "viewer" && relation != "owner" { + return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) + } + + if authModelId == "" { + fmt.Println("Creating authorization model...") + + // Provide both viewer and owner relations so user can pick. + relations := map[string]openfga.Userset{ + "viewer": {This: &map[string]interface{}{}}, + "owner": {This: &map[string]interface{}{}}, + } + + relationMetadata := map[string]openfga.RelationMetadata{ + "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + } + + model := openfga.AuthorizationModel{ + SchemaVersion: "1.1", + TypeDefinitions: []openfga.TypeDefinition{ + {Type: "user"}, + {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, + }, + } + + writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ + SchemaVersion: model.SchemaVersion, + TypeDefinitions: model.TypeDefinitions, + }).Execute() + if err != nil { + return authModelId, fmt.Errorf("failed to create authorization model: %w", err) + } + authModelId = writeModelResp.AuthorizationModelId + fmt.Printf("Created authorization model: %s\n\n", authModelId) + } + + fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) + tuples := make([]client.ClientTupleKey, 0, tupleCount) + for i := 0; i < tupleCount; i++ { + tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) + } + if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { + return authModelId, fmt.Errorf("failed to write tuples: %w", err) + } + fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) + return authModelId, nil } func parseArgs() (mode string, count int, relation string, bufferSize *int) { - mode = "sync" // default - relation = "viewer" - count = 3 - if len(os.Args) > 1 { - mode = os.Args[1] - } - if len(os.Args) > 2 { - if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { - count = c - } - } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { - if c, err := strconv.Atoi(envCount); err == nil && c > 0 { - count = c - } - } - if len(os.Args) > 3 { - relation = os.Args[3] - } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { - relation = envRel - } - if len(os.Args) > 4 { - if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { - bufferSize = &b - } - } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { - if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { - bufferSize = &b - } - } - return + mode = "sync" // default + relation = "viewer" + count = 3 + if len(os.Args) > 1 { + mode = os.Args[1] + } + if len(os.Args) > 2 { + if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { + count = c + } + } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { + if c, err := strconv.Atoi(envCount); err == nil && c > 0 { + count = c + } + } + if len(os.Args) > 3 { + relation = os.Args[3] + } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { + relation = envRel + } + if len(os.Args) > 4 { + if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { + bufferSize = &b + } + } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { + if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { + bufferSize = &b + } + } + return } func main() { - ctx := context.Background() - apiUrl := os.Getenv("FGA_API_URL") - if apiUrl == "" { - apiUrl = "http://localhost:8080" - } - config := client.ClientConfiguration{ApiUrl: apiUrl} - fgaClient, err := client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - // Create store unless provided via env var. - storeId := os.Getenv("FGA_STORE_ID") - createdTempStore := false - if storeId == "" { - fmt.Println("Creating Test Store for streamed list objects") - store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() - if err != nil { - panic(err) - } - storeId = store.Id - createdTempStore = true - } - - // Re-init client with storeId - config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} - fgaClient, err = client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - fmt.Println("OpenFGA StreamedListObjects Example") - fmt.Println("____________________________________") - fmt.Printf("API URL: %s\n", apiUrl) - fmt.Printf("Store ID: %s\n", storeId) - fmt.Println() - - authModelId := os.Getenv("FGA_MODEL_ID") - mode, tupleCount, relation, bufferSize := parseArgs() - if authModelId != "" { - fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) - } - authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) - if err != nil { - log.Printf("Warning: Failed to create test data: %v", err) - log.Println("Continuing with example...") - } - - fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) - if bufferSize != nil { - fmt.Printf(" | buffer size: %d", *bufferSize) - } - fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") - - switch mode { - case "async": - runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - case "sync": - runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - default: - fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) - os.Exit(1) - } - - if createdTempStore { - fmt.Println("\nDeleting temporary store...") - if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { - fmt.Printf("Failed to delete store: %v\n", err) - } else { - fmt.Printf("Deleted temporary store (%s)\n", storeId) - } - } - fmt.Println("\nDone.") + ctx := context.Background() + apiUrl := os.Getenv("FGA_API_URL") + if apiUrl == "" { + apiUrl = "http://localhost:8080" + } + config := client.ClientConfiguration{ApiUrl: apiUrl} + fgaClient, err := client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + // Create store unless provided via env var. + storeId := os.Getenv("FGA_STORE_ID") + createdTempStore := false + if storeId == "" { + fmt.Println("Creating Test Store for streamed list objects") + store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() + if err != nil { + log.Fatalf("failed to create store: %v", err) + } + storeId = store.Id + createdTempStore = true + } + + // Re-init client with storeId + config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} + fgaClient, err = client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + fmt.Println("OpenFGA StreamedListObjects Example") + fmt.Println("____________________________________") + fmt.Printf("API URL: %s\n", apiUrl) + fmt.Printf("Store ID: %s\n", storeId) + fmt.Println() + + authModelId := os.Getenv("FGA_MODEL_ID") + mode, tupleCount, relation, bufferSize := parseArgs() + if authModelId != "" { + fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) + } + authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) + if err != nil { + log.Printf("Warning: Failed to create test data: %v", err) + log.Println("Continuing with example...") + } + + fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) + if bufferSize != nil { + fmt.Printf(" | buffer size: %d", *bufferSize) + } + fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") + + switch mode { + case "async": + runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + case "sync": + runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + default: + fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) + os.Exit(1) + } + + if createdTempStore { + fmt.Println("\nDeleting temporary store...") + if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { + fmt.Printf("Failed to delete store: %v\n", err) + } else { + fmt.Printf("Deleted temporary store (%s)\n", storeId) + } + } + fmt.Println("\nDone.") } From 6b0a62a4b0ea7ff3a779ec644f89e4fdd06760c6 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Wed, 29 Oct 2025 23:13:05 +0530 Subject: [PATCH 5/9] fix: gofmt --- example/streamed_list_objects/main.go | 470 +++++++++++++------------- 1 file changed, 235 insertions(+), 235 deletions(-) diff --git a/example/streamed_list_objects/main.go b/example/streamed_list_objects/main.go index 107861d..d313277 100644 --- a/example/streamed_list_objects/main.go +++ b/example/streamed_list_objects/main.go @@ -1,255 +1,255 @@ package main import ( - "context" - "fmt" - "log" - "os" - "strconv" - "time" - - openfga "github.com/openfga/go-sdk" - "github.com/openfga/go-sdk/client" + "context" + "fmt" + "log" + "os" + "strconv" + "time" + + openfga "github.com/openfga/go-sdk" + "github.com/openfga/go-sdk/client" ) func runSync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: sync streaming (range over channel)") - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) - } - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() - if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) - } - defer response.Close() - - fmt.Println("Streaming objects (sync):") - received := 0 - for obj := range response.Objects { // synchronous consumption - received++ - fmt.Printf(" %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil { - log.Fatalf("Error during streaming: %v", err) - } - fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) + fmt.Println("Mode: sync streaming (range over channel)") + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + fmt.Println("Streaming objects (sync):") + received := 0 + for obj := range response.Objects { // synchronous consumption + received++ + fmt.Printf(" %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil { + log.Fatalf("Error during streaming: %v", err) + } + fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) } // runAsync demonstrates asynchronous consumption using a goroutine; main goroutine can do other work. func runAsync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: async streaming (consume in goroutine)") - // Use a cancellable context to show cancellation pattern (not cancelling in this example). - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) - } - - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() - if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) - } - defer response.Close() - - done := make(chan struct{}) - received := 0 - - go func() { - defer close(done) - for obj := range response.Objects { - received++ - fmt.Printf(" async -> %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil && err != context.Canceled { - log.Fatalf("Error during async streaming: %v", err) - } - }() - - // Simulate doing other work while streaming happens. - ticker := time.NewTicker(200 * time.Millisecond) - defer ticker.Stop() - - fmt.Println("Performing other work while streaming...") - for { - select { - case <-done: - fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) - return - case <-ticker.C: - fmt.Println(" (main goroutine still free to do work)") - } - } + fmt.Println("Mode: async streaming (consume in goroutine)") + // Use a cancellable context to show cancellation pattern (not cancelling in this example). + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} + options := client.ClientStreamedListObjectsOptions{} + if authModelId != "" { + options.AuthorizationModelId = &authModelId + } + if bufferSize != nil { + options.StreamBufferSize = bufferSize + fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + } + + response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + if err != nil { + log.Fatalf("StreamedListObjects failed: %v", err) + } + defer response.Close() + + done := make(chan struct{}) + received := 0 + + go func() { + defer close(done) + for obj := range response.Objects { + received++ + fmt.Printf(" async -> %d. %s\n", received, obj.Object) + } + if err := <-response.Errors; err != nil && err != context.Canceled { + log.Fatalf("Error during async streaming: %v", err) + } + }() + + // Simulate doing other work while streaming happens. + ticker := time.NewTicker(200 * time.Millisecond) + defer ticker.Stop() + + fmt.Println("Performing other work while streaming...") + for { + select { + case <-done: + fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) + return + case <-ticker.C: + fmt.Println(" (main goroutine still free to do work)") + } + } } func createTestData(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, tupleCount int) (string, error) { - // Ensure relation is either viewer or owner for this simplified example. - if relation != "viewer" && relation != "owner" { - return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) - } - - if authModelId == "" { - fmt.Println("Creating authorization model...") - - // Provide both viewer and owner relations so user can pick. - relations := map[string]openfga.Userset{ - "viewer": {This: &map[string]interface{}{}}, - "owner": {This: &map[string]interface{}{}}, - } - - relationMetadata := map[string]openfga.RelationMetadata{ - "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - } - - model := openfga.AuthorizationModel{ - SchemaVersion: "1.1", - TypeDefinitions: []openfga.TypeDefinition{ - {Type: "user"}, - {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, - }, - } - - writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ - SchemaVersion: model.SchemaVersion, - TypeDefinitions: model.TypeDefinitions, - }).Execute() - if err != nil { - return authModelId, fmt.Errorf("failed to create authorization model: %w", err) - } - authModelId = writeModelResp.AuthorizationModelId - fmt.Printf("Created authorization model: %s\n\n", authModelId) - } - - fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) - tuples := make([]client.ClientTupleKey, 0, tupleCount) - for i := 0; i < tupleCount; i++ { - tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) - } - if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { - return authModelId, fmt.Errorf("failed to write tuples: %w", err) - } - fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) - return authModelId, nil + // Ensure relation is either viewer or owner for this simplified example. + if relation != "viewer" && relation != "owner" { + return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) + } + + if authModelId == "" { + fmt.Println("Creating authorization model...") + + // Provide both viewer and owner relations so user can pick. + relations := map[string]openfga.Userset{ + "viewer": {This: &map[string]interface{}{}}, + "owner": {This: &map[string]interface{}{}}, + } + + relationMetadata := map[string]openfga.RelationMetadata{ + "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, + } + + model := openfga.AuthorizationModel{ + SchemaVersion: "1.1", + TypeDefinitions: []openfga.TypeDefinition{ + {Type: "user"}, + {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, + }, + } + + writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ + SchemaVersion: model.SchemaVersion, + TypeDefinitions: model.TypeDefinitions, + }).Execute() + if err != nil { + return authModelId, fmt.Errorf("failed to create authorization model: %w", err) + } + authModelId = writeModelResp.AuthorizationModelId + fmt.Printf("Created authorization model: %s\n\n", authModelId) + } + + fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) + tuples := make([]client.ClientTupleKey, 0, tupleCount) + for i := 0; i < tupleCount; i++ { + tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) + } + if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { + return authModelId, fmt.Errorf("failed to write tuples: %w", err) + } + fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) + return authModelId, nil } func parseArgs() (mode string, count int, relation string, bufferSize *int) { - mode = "sync" // default - relation = "viewer" - count = 3 - if len(os.Args) > 1 { - mode = os.Args[1] - } - if len(os.Args) > 2 { - if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { - count = c - } - } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { - if c, err := strconv.Atoi(envCount); err == nil && c > 0 { - count = c - } - } - if len(os.Args) > 3 { - relation = os.Args[3] - } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { - relation = envRel - } - if len(os.Args) > 4 { - if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { - bufferSize = &b - } - } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { - if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { - bufferSize = &b - } - } - return + mode = "sync" // default + relation = "viewer" + count = 3 + if len(os.Args) > 1 { + mode = os.Args[1] + } + if len(os.Args) > 2 { + if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { + count = c + } + } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { + if c, err := strconv.Atoi(envCount); err == nil && c > 0 { + count = c + } + } + if len(os.Args) > 3 { + relation = os.Args[3] + } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { + relation = envRel + } + if len(os.Args) > 4 { + if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { + bufferSize = &b + } + } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { + if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { + bufferSize = &b + } + } + return } func main() { - ctx := context.Background() - apiUrl := os.Getenv("FGA_API_URL") - if apiUrl == "" { - apiUrl = "http://localhost:8080" - } - config := client.ClientConfiguration{ApiUrl: apiUrl} - fgaClient, err := client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - // Create store unless provided via env var. - storeId := os.Getenv("FGA_STORE_ID") - createdTempStore := false - if storeId == "" { - fmt.Println("Creating Test Store for streamed list objects") - store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() - if err != nil { - log.Fatalf("failed to create store: %v", err) - } - storeId = store.Id - createdTempStore = true - } - - // Re-init client with storeId - config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} - fgaClient, err = client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - fmt.Println("OpenFGA StreamedListObjects Example") - fmt.Println("____________________________________") - fmt.Printf("API URL: %s\n", apiUrl) - fmt.Printf("Store ID: %s\n", storeId) - fmt.Println() - - authModelId := os.Getenv("FGA_MODEL_ID") - mode, tupleCount, relation, bufferSize := parseArgs() - if authModelId != "" { - fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) - } - authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) - if err != nil { - log.Printf("Warning: Failed to create test data: %v", err) - log.Println("Continuing with example...") - } - - fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) - if bufferSize != nil { - fmt.Printf(" | buffer size: %d", *bufferSize) - } - fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") - - switch mode { - case "async": - runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - case "sync": - runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - default: - fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) - os.Exit(1) - } - - if createdTempStore { - fmt.Println("\nDeleting temporary store...") - if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { - fmt.Printf("Failed to delete store: %v\n", err) - } else { - fmt.Printf("Deleted temporary store (%s)\n", storeId) - } - } - fmt.Println("\nDone.") + ctx := context.Background() + apiUrl := os.Getenv("FGA_API_URL") + if apiUrl == "" { + apiUrl = "http://localhost:8080" + } + config := client.ClientConfiguration{ApiUrl: apiUrl} + fgaClient, err := client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + // Create store unless provided via env var. + storeId := os.Getenv("FGA_STORE_ID") + createdTempStore := false + if storeId == "" { + fmt.Println("Creating Test Store for streamed list objects") + store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() + if err != nil { + log.Fatalf("failed to create store: %v", err) + } + storeId = store.Id + createdTempStore = true + } + + // Re-init client with storeId + config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} + fgaClient, err = client.NewSdkClient(&config) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + fmt.Println("OpenFGA StreamedListObjects Example") + fmt.Println("____________________________________") + fmt.Printf("API URL: %s\n", apiUrl) + fmt.Printf("Store ID: %s\n", storeId) + fmt.Println() + + authModelId := os.Getenv("FGA_MODEL_ID") + mode, tupleCount, relation, bufferSize := parseArgs() + if authModelId != "" { + fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) + } + authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) + if err != nil { + log.Printf("Warning: Failed to create test data: %v", err) + log.Println("Continuing with example...") + } + + fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) + if bufferSize != nil { + fmt.Printf(" | buffer size: %d", *bufferSize) + } + fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") + + switch mode { + case "async": + runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + case "sync": + runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) + default: + fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) + os.Exit(1) + } + + if createdTempStore { + fmt.Println("\nDeleting temporary store...") + if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { + fmt.Printf("Failed to delete store: %v\n", err) + } else { + fmt.Printf("Deleted temporary store (%s)\n", storeId) + } + } + fmt.Println("\nDone.") } From 499140f77b5a334c9df9506b2672a0665b9c2587 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Thu, 6 Nov 2025 21:17:15 +0530 Subject: [PATCH 6/9] feat: don't dump body for streaming resp --- api_client.go | 798 +++++++++++++++++++++++++------------------------- 1 file changed, 402 insertions(+), 396 deletions(-) diff --git a/api_client.go b/api_client.go index eec5cdf..51b891f 100644 --- a/api_client.go +++ b/api_client.go @@ -1,493 +1,499 @@ package openfga import ( - "bytes" - "context" - "encoding/json" - "encoding/xml" - "errors" - "fmt" - "io" - "log" - "net/http" - "net/http/httputil" - "net/url" - "os" - "reflect" - "regexp" - "strings" - "time" - "unicode/utf8" - - "github.com/openfga/go-sdk/internal/utils/retryutils" - "github.com/openfga/go-sdk/telemetry" + "bytes" + "context" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "io" + "log" + "net/http" + "net/http/httputil" + "net/url" + "os" + "reflect" + "regexp" + "strings" + "time" + "unicode/utf8" + + "github.com/openfga/go-sdk/internal/utils/retryutils" + "github.com/openfga/go-sdk/telemetry" ) var ( - jsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:vnd\.[^;]+\+)?json)`) - xmlCheck = regexp.MustCompile(`(?i:(?:application|text)/xml)`) + jsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:vnd\.[^;]+\+)?json)`) + xmlCheck = regexp.MustCompile(`(?i:(?:application|text)/xml)`) ) // ErrorResponse defines the error that will be asserted by FGA API. // This will only be used for error that is not defined type ErrorResponse struct { - Code string `json:"code"` - Message string `json:"message"` + Code string `json:"code"` + Message string `json:"message"` } // APIClient manages communication with the OpenFGA API v1.x // In most cases there should be only one, shared, APIClient. type APIClient struct { - cfg *Configuration - common service // Reuse a single struct instead of allocating one for each service on the heap. + cfg *Configuration + common service // Reuse a single struct instead of allocating one for each service on the heap. - // API Services + // API Services - OpenFgaApi OpenFgaApi + OpenFgaApi OpenFgaApi } type service struct { - client *APIClient - RetryParams *RetryParams + client *APIClient + RetryParams *RetryParams } // NewAPIClient creates a new API client. Requires a userAgent string describing your application. // optionally a custom http.Client to allow for advanced features such as caching. func NewAPIClient(cfg *Configuration) *APIClient { - if cfg.Telemetry == nil { - cfg.Telemetry = telemetry.DefaultTelemetryConfiguration() - } - if cfg.HTTPClient == nil { - if cfg.Credentials == nil { - cfg.HTTPClient = http.DefaultClient - } else { - cfg.Credentials.Context = context.Background() - telemetry.Bind(cfg.Credentials.Context, telemetry.Get(telemetry.TelemetryFactoryParameters{Configuration: cfg.Telemetry})) - var httpClient, headers = cfg.Credentials.GetHttpClientAndHeaderOverrides(retryutils.GetRetryParamsOrDefault(cfg.RetryParams), cfg.Debug) - if len(headers) > 0 { - for idx := range headers { - cfg.AddDefaultHeader(headers[idx].Key, headers[idx].Value) - } - } - if httpClient != nil { - cfg.HTTPClient = httpClient - } - } - } - - c := &APIClient{} - c.cfg = cfg - c.common.client = c - c.common.RetryParams = cfg.RetryParams - - // API Services - c.OpenFgaApi = (*OpenFgaApiService)(&c.common) - - return c + if cfg.Telemetry == nil { + cfg.Telemetry = telemetry.DefaultTelemetryConfiguration() + } + if cfg.HTTPClient == nil { + if cfg.Credentials == nil { + cfg.HTTPClient = http.DefaultClient + } else { + cfg.Credentials.Context = context.Background() + telemetry.Bind(cfg.Credentials.Context, telemetry.Get(telemetry.TelemetryFactoryParameters{Configuration: cfg.Telemetry})) + var httpClient, headers = cfg.Credentials.GetHttpClientAndHeaderOverrides(retryutils.GetRetryParamsOrDefault(cfg.RetryParams), cfg.Debug) + if len(headers) > 0 { + for idx := range headers { + cfg.AddDefaultHeader(headers[idx].Key, headers[idx].Value) + } + } + if httpClient != nil { + cfg.HTTPClient = httpClient + } + } + } + + c := &APIClient{} + c.cfg = cfg + c.common.client = c + c.common.RetryParams = cfg.RetryParams + + // API Services + c.OpenFgaApi = (*OpenFgaApiService)(&c.common) + + return c } // selectHeaderContentType select a content type from the available list. func selectHeaderContentType(contentTypes []string) string { - if len(contentTypes) == 0 { - return "" - } - if contains(contentTypes, "application/json") { - return "application/json" - } - return contentTypes[0] // use the first content type specified in 'consumes' + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] // use the first content type specified in 'consumes' } // selectHeaderAccept join all accept types and return func selectHeaderAccept(accepts []string) string { - if len(accepts) == 0 { - return "" - } + if len(accepts) == 0 { + return "" + } - if contains(accepts, "application/json") { - return "application/json" - } + if contains(accepts, "application/json") { + return "application/json" + } - return strings.Join(accepts, ",") + return strings.Join(accepts, ",") } // contains is a case insensitive match, finding needle in a haystack func contains(haystack []string, needle string) bool { - loweredNeedle := strings.ToLower(needle) - for _, a := range haystack { - if strings.ToLower(a) == loweredNeedle { - return true - } - } - return false + loweredNeedle := strings.ToLower(needle) + for _, a := range haystack { + if strings.ToLower(a) == loweredNeedle { + return true + } + } + return false } // Verify optional parameters are of the correct type. func typeCheckParameter(obj interface{}, expected string, name string) error { - // Make sure there is an object. - if obj == nil { - return nil - } - - // Check the type is as expected. - if reflect.TypeOf(obj).String() != expected { - return fmt.Errorf("expected %s to be of type %s but received %s", name, expected, reflect.TypeOf(obj).String()) - } - return nil + // Make sure there is an object. + if obj == nil { + return nil + } + + // Check the type is as expected. + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("expected %s to be of type %s but received %s", name, expected, reflect.TypeOf(obj).String()) + } + return nil } // parameterToString convert interface{} parameters to string, using a delimiter if format is provided. func parameterToString(obj interface{}, collectionFormat string) string { - var delimiter string - - switch collectionFormat { - case "pipes": - delimiter = "|" - case "ssv": - delimiter = " " - case "tsv": - delimiter = "\t" - case "csv": - delimiter = "," - } - - if reflect.TypeOf(obj).Kind() == reflect.Slice { - return strings.Trim(strings.ReplaceAll(fmt.Sprint(obj), " ", delimiter), "[]") - } else if t, ok := obj.(time.Time); ok { - return t.Format(time.RFC3339) - } - - return fmt.Sprintf("%v", obj) + var delimiter string + + switch collectionFormat { + case "pipes": + delimiter = "|" + case "ssv": + delimiter = " " + case "tsv": + delimiter = "\t" + case "csv": + delimiter = "," + } + + if reflect.TypeOf(obj).Kind() == reflect.Slice { + return strings.Trim(strings.ReplaceAll(fmt.Sprint(obj), " ", delimiter), "[]") + } else if t, ok := obj.(time.Time); ok { + return t.Format(time.RFC3339) + } + + return fmt.Sprintf("%v", obj) } // helper for converting interface{} parameters to json strings func parameterToJson(obj interface{}) (string, error) { - jsonBuf, err := json.Marshal(obj) - if err != nil { - return "", err - } - return string(jsonBuf), err + jsonBuf, err := json.Marshal(obj) + if err != nil { + return "", err + } + return string(jsonBuf), err } // callAPI do the request. func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { - if c.cfg.Debug { - dump, err := httputil.DumpRequestOut(request, true) - if err != nil { - return nil, err - } - log.Printf("\n%s\n", string(dump)) - } - - resp, err := c.cfg.HTTPClient.Do(request) - if err != nil { - if resp != nil && resp.Request == nil { - resp.Request = request - } - - return resp, err - } - - if c.cfg.Debug { - dump, err := httputil.DumpResponse(resp, true) - if err != nil { - return resp, err - } - log.Printf("\n%s\n", string(dump)) - } - - if resp.Request == nil { - resp.Request = request - } - - return resp, err + if c.cfg.Debug { + dump, err := httputil.DumpRequestOut(request, true) + if err != nil { + return nil, err + } + log.Printf("\n%s\n", string(dump)) + } + + resp, err := c.cfg.HTTPClient.Do(request) + if err != nil { + if resp != nil && resp.Request == nil { + resp.Request = request + } + + return resp, err + } + + if c.cfg.Debug { + // for debugging, don't dump the body for streaming resp. as it would buffer the entire response + // only dump headers + isStreamingResponse := resp.Header.Get("Content-Type") == "application/x-ndjson" + dump, err := httputil.DumpResponse(resp, !isStreamingResponse) + if err != nil { + return resp, err + } + log.Printf("\n%s\n", string(dump)) + if isStreamingResponse { + log.Printf("Streaming response body - not dumped to preserve streaming\n") + } + } + + if resp.Request == nil { + resp.Request = request + } + + return resp, err } // Allow modification of underlying config for alternate implementations and testing // Caution: modifying the configuration while live can cause data races and potentially unwanted behavior func (c *APIClient) GetConfig() *Configuration { - return c.cfg + return c.cfg } // prepareRequest build the request func (c *APIClient) prepareRequest( - ctx context.Context, - path string, method string, - postBody interface{}, - headerParams map[string]string, - queryParams url.Values) (localVarRequest *http.Request, err error) { - - var body *bytes.Buffer - - // Detect postBody type and post. - if postBody != nil { - contentType := headerParams["Content-Type"] - if contentType == "" { - contentType = detectContentType(postBody) - headerParams["Content-Type"] = contentType - } - - body, err = setBody(postBody, contentType) - if err != nil { - return nil, err - } - } - - // Setup path and query parameters - uri, err := url.Parse(c.cfg.ApiUrl + path) - if err != nil { - return nil, err - } - - // Adding Query Param - query := uri.Query() - for k, v := range queryParams { - for _, iv := range v { - query.Add(k, iv) - } - } - - // Encode the parameters. - uri.RawQuery = query.Encode() - - // Generate a new request - if body != nil { - localVarRequest, err = http.NewRequest(method, uri.String(), body) - } else { - localVarRequest, err = http.NewRequest(method, uri.String(), nil) - } - if err != nil { - return nil, err - } - - // add header parameters, if any - if len(headerParams) > 0 { - headers := http.Header{} - for h, v := range headerParams { - headers.Set(h, v) - } - localVarRequest.Header = headers - } - - // Add the user agent to the request. - localVarRequest.Header.Set("User-Agent", c.cfg.UserAgent) - - for header, value := range c.cfg.DefaultHeaders { - if localVarRequest.Header.Get(header) == "" { - localVarRequest.Header.Set(header, value) - } - } - - if ctx != nil { - // add context to the request - localVarRequest = localVarRequest.WithContext(ctx) - } - - return localVarRequest, nil + ctx context.Context, + path string, method string, + postBody interface{}, + headerParams map[string]string, + queryParams url.Values) (localVarRequest *http.Request, err error) { + + var body *bytes.Buffer + + // Detect postBody type and post. + if postBody != nil { + contentType := headerParams["Content-Type"] + if contentType == "" { + contentType = detectContentType(postBody) + headerParams["Content-Type"] = contentType + } + + body, err = setBody(postBody, contentType) + if err != nil { + return nil, err + } + } + + // Setup path and query parameters + uri, err := url.Parse(c.cfg.ApiUrl + path) + if err != nil { + return nil, err + } + + // Adding Query Param + query := uri.Query() + for k, v := range queryParams { + for _, iv := range v { + query.Add(k, iv) + } + } + + // Encode the parameters. + uri.RawQuery = query.Encode() + + // Generate a new request + if body != nil { + localVarRequest, err = http.NewRequest(method, uri.String(), body) + } else { + localVarRequest, err = http.NewRequest(method, uri.String(), nil) + } + if err != nil { + return nil, err + } + + // add header parameters, if any + if len(headerParams) > 0 { + headers := http.Header{} + for h, v := range headerParams { + headers.Set(h, v) + } + localVarRequest.Header = headers + } + + // Add the user agent to the request. + localVarRequest.Header.Set("User-Agent", c.cfg.UserAgent) + + for header, value := range c.cfg.DefaultHeaders { + if localVarRequest.Header.Get(header) == "" { + localVarRequest.Header.Set(header, value) + } + } + + if ctx != nil { + // add context to the request + localVarRequest = localVarRequest.WithContext(ctx) + } + + return localVarRequest, nil } func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { - if len(b) == 0 { - return nil - } - if s, ok := v.(*string); ok { - *s = string(b) - return nil - } - if xmlCheck.MatchString(contentType) { - if err = xml.Unmarshal(b, v); err != nil { - return err - } - return nil - } - if jsonCheck.MatchString(contentType) { - if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas - if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined - if err = unmarshalObj.UnmarshalJSON(b); err != nil { - return err - } - } else { - return errors.New("unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined") - } - } else if err = json.Unmarshal(b, v); err != nil { // simple model - return err - } - return nil - } - return errors.New("undefined response type") + if len(b) == 0 { + return nil + } + if s, ok := v.(*string); ok { + *s = string(b) + return nil + } + if xmlCheck.MatchString(contentType) { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } + if jsonCheck.MatchString(contentType) { + if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas + if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined + if err = unmarshalObj.UnmarshalJSON(b); err != nil { + return err + } + } else { + return errors.New("unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined") + } + } else if err = json.Unmarshal(b, v); err != nil { // simple model + return err + } + return nil + } + return errors.New("undefined response type") } func (c *APIClient) handleAPIError(httpResponse *http.Response, responseBody []byte, requestBody interface{}, operationName string, storeId string) error { - switch httpResponse.StatusCode { - case http.StatusBadRequest, http.StatusUnprocessableEntity: - err := NewFgaApiValidationError(operationName, requestBody, httpResponse, responseBody, storeId) - var v ValidationErrorMessageResponse - errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) - if errBody != nil { - err.modelDecodeError = err - return err - } - err.model = v - err.responseCode = v.GetCode() - err.error += " with error code " + string(v.GetCode()) + " error message: " + v.GetMessage() - return err - - case http.StatusUnauthorized, http.StatusForbidden: - return NewFgaApiAuthenticationError(operationName, requestBody, httpResponse, responseBody, storeId) - - case http.StatusNotFound: - err := NewFgaApiNotFoundError(operationName, requestBody, httpResponse, responseBody, storeId) - var v PathUnknownErrorMessageResponse - errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) - if errBody != nil { - err.modelDecodeError = err - return err - } - err.model = v - err.responseCode = v.GetCode() - err.error += " with error code " + string(v.GetCode()) + " error message: " + v.GetMessage() - return err - - case http.StatusTooManyRequests: - return NewFgaApiRateLimitExceededError(operationName, requestBody, httpResponse, responseBody, storeId) - - default: - if httpResponse.StatusCode >= http.StatusInternalServerError { - err := NewFgaApiInternalError(operationName, requestBody, httpResponse, responseBody, storeId) - var v InternalErrorMessageResponse - errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) - if errBody != nil { - err.modelDecodeError = err - return err - } - err.model = v - err.responseCode = v.GetCode() - err.error += " with error code " + string(v.GetCode()) + " error message: " + v.GetMessage() - return err - } - - err := NewFgaApiError(operationName, requestBody, httpResponse, responseBody, storeId) - var v ErrorResponse - errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) - if errBody != nil { - err.modelDecodeError = err - return err - } - err.model = v - err.responseCode = v.Code - err.error += " with error code " + string(v.Code) + " error message: " + v.Message - return err - } + switch httpResponse.StatusCode { + case http.StatusBadRequest, http.StatusUnprocessableEntity: + err := NewFgaApiValidationError(operationName, requestBody, httpResponse, responseBody, storeId) + var v ValidationErrorMessageResponse + errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) + if errBody != nil { + err.modelDecodeError = err + return err + } + err.model = v + err.responseCode = v.GetCode() + err.error += " with error code " + string(v.GetCode()) + " error message: " + v.GetMessage() + return err + + case http.StatusUnauthorized, http.StatusForbidden: + return NewFgaApiAuthenticationError(operationName, requestBody, httpResponse, responseBody, storeId) + + case http.StatusNotFound: + err := NewFgaApiNotFoundError(operationName, requestBody, httpResponse, responseBody, storeId) + var v PathUnknownErrorMessageResponse + errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) + if errBody != nil { + err.modelDecodeError = err + return err + } + err.model = v + err.responseCode = v.GetCode() + err.error += " with error code " + string(v.GetCode()) + " error message: " + v.GetMessage() + return err + + case http.StatusTooManyRequests: + return NewFgaApiRateLimitExceededError(operationName, requestBody, httpResponse, responseBody, storeId) + + default: + if httpResponse.StatusCode >= http.StatusInternalServerError { + err := NewFgaApiInternalError(operationName, requestBody, httpResponse, responseBody, storeId) + var v InternalErrorMessageResponse + errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) + if errBody != nil { + err.modelDecodeError = err + return err + } + err.model = v + err.responseCode = v.GetCode() + err.error += " with error code " + string(v.GetCode()) + " error message: " + v.GetMessage() + return err + } + + err := NewFgaApiError(operationName, requestBody, httpResponse, responseBody, storeId) + var v ErrorResponse + errBody := c.decode(&v, responseBody, httpResponse.Header.Get("Content-Type")) + if errBody != nil { + err.modelDecodeError = err + return err + } + err.model = v + err.responseCode = v.Code + err.error += " with error code " + string(v.Code) + " error message: " + v.Message + return err + } } // Prevent trying to import "fmt" func reportError(format string, a ...interface{}) error { - return fmt.Errorf(format, a...) + return fmt.Errorf(format, a...) } // Set request body from an interface{} func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { - if bodyBuf == nil { - bodyBuf = &bytes.Buffer{} - } - - if reader, ok := body.(io.Reader); ok { - _, err = bodyBuf.ReadFrom(reader) - } else if fp, ok := body.(**os.File); ok { - _, err = bodyBuf.ReadFrom(*fp) - } else if b, ok := body.([]byte); ok { - _, err = bodyBuf.Write(b) - } else if s, ok := body.(string); ok { - _, err = bodyBuf.WriteString(s) - } else if s, ok := body.(*string); ok { - _, err = bodyBuf.WriteString(*s) - } else if jsonCheck.MatchString(contentType) { - err = json.NewEncoder(bodyBuf).Encode(body) - } else if xmlCheck.MatchString(contentType) { - err = xml.NewEncoder(bodyBuf).Encode(body) - } - - if err != nil { - return nil, err - } - - if bodyBuf.Len() == 0 { - err = fmt.Errorf("invalid body type %s", contentType) - return nil, err - } - return bodyBuf, nil + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if fp, ok := body.(**os.File); ok { + _, err = bodyBuf.ReadFrom(*fp) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if jsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if xmlCheck.MatchString(contentType) { + err = xml.NewEncoder(bodyBuf).Encode(body) + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("invalid body type %s", contentType) + return nil, err + } + return bodyBuf, nil } // detectContentType method is used to figure out `Request.Body` content type for request header func detectContentType(body interface{}) string { - contentType := "text/plain; charset=utf-8" - kind := reflect.TypeOf(body).Kind() - - switch kind { - case reflect.Struct, reflect.Map, reflect.Ptr: - contentType = "application/json; charset=utf-8" - case reflect.String: - contentType = "text/plain; charset=utf-8" - default: - if b, ok := body.([]byte); ok { - contentType = http.DetectContentType(b) - } else if kind == reflect.Slice { - contentType = "application/json; charset=utf-8" - } - } - - return contentType + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType } // Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go type cacheControl map[string]string func parseCacheControl(headers http.Header) cacheControl { - cc := cacheControl{} - ccHeader := headers.Get("Cache-Control") - for _, part := range strings.Split(ccHeader, ",") { - part = strings.Trim(part, " ") - if part == "" { - continue - } - if strings.ContainsRune(part, '=') { - keyval := strings.Split(part, "=") - cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") - } else { - cc[part] = "" - } - } - return cc + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc } // CacheExpires helper function to determine remaining time before repeating a request. func CacheExpires(r *http.Response) time.Time { - // Figure out when the cache expires. - var expires time.Time - now, err := time.Parse(time.RFC1123, r.Header.Get("date")) - if err != nil { - return time.Now() - } - respCacheControl := parseCacheControl(r.Header) - - if maxAge, ok := respCacheControl["max-age"]; ok { - lifetime, err := time.ParseDuration(maxAge + "s") - if err != nil { - expires = now - } else { - expires = now.Add(lifetime) - } - } else { - expiresHeader := r.Header.Get("Expires") - if expiresHeader != "" { - expires, err = time.Parse(time.RFC1123, expiresHeader) - if err != nil { - expires = now - } - } - } - return expires + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } else { + expires = now.Add(lifetime) + } + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires } func strlen(s string) int { - return utf8.RuneCountInString(s) + return utf8.RuneCountInString(s) } From 48f9e580826a03310bd3b2048e5439fa3b14ebee Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Thu, 13 Nov 2025 23:58:53 +0530 Subject: [PATCH 7/9] feat: update example for consistency --- example/streamed_list_objects/README.md | 213 +++++++------- example/streamed_list_objects/main.go | 372 +++++++++++------------- 2 files changed, 276 insertions(+), 309 deletions(-) diff --git a/example/streamed_list_objects/README.md b/example/streamed_list_objects/README.md index 3e47180..050013f 100644 --- a/example/streamed_list_objects/README.md +++ b/example/streamed_list_objects/README.md @@ -1,143 +1,140 @@ -# StreamedListObjects Example +# Streamed List Objects Example -This example demonstrates how to use the `StreamedListObjects` API in the OpenFGA Go SDK in both: -- Synchronous mode (range over the channel) -- Asynchronous mode (consume in a goroutine) +Demonstrates using `StreamedListObjects` to retrieve objects via the streaming API in the Go SDK. -It creates (if not provided) a temporary store and authorization model, writes mock tuples, streams objects, and optionally cleans up. +## What is StreamedListObjects? + +The Streamed ListObjects API is very similar to the ListObjects API, with two key differences: + +1. **Streaming Results**: Instead of collecting all objects before returning a response, it streams them to the client as they are collected. +2. **No Pagination Limit**: Returns all results without the 1000-object limit of the standard ListObjects API. + +This makes it ideal for scenarios where you need to retrieve large numbers of objects, especially when querying computed relations. ## Prerequisites -1. An OpenFGA server running (default: `http://localhost:8080`) -2. (Optional) Existing store and authorization model IDs +- OpenFGA server running on `http://localhost:8080` (or set `FGA_API_URL`) -## Environment Variables +## Running -- `FGA_API_URL` (default: `http://localhost:8080`) -- `FGA_STORE_ID` (optional; if absent a new store is created and later deleted) -- `FGA_MODEL_ID` (optional; if absent a simple model is created) -- `FGA_TUPLE_COUNT` (optional; number of tuples to write; overridden by CLI arg if passed) -- `FGA_RELATION` (optional; relation used when writing and listing; must be `viewer` or `owner`; overridden by CLI arg if passed) -- `FGA_BUFFER_SIZE` (optional; buffer size for streaming channel; defaults to 10 if not set; overridden by CLI arg if passed) +```bash +# From the example directory +cd example/streamed_list_objects +go run . +``` -## CLI Arguments +## What it does + +- Creates a temporary store +- Writes an authorization model with **computed relations** +- Adds 2000 tuples (1000 owners + 1000 viewers) +- Queries the **computed `can_read` relation** via `StreamedListObjects` +- Shows all 2000 results (demonstrating computed relations) +- Shows progress (first 3 objects and every 500th) +- Cleans up the store + +## Authorization Model + +The example demonstrates OpenFGA's **computed relations**: ``` -go run . [mode] [tupleCount] [relation] [bufferSize] +type user + +type document + relations + define owner: [user] + define viewer: [user] + define can_read: owner or viewer ``` -- `mode`: `sync` (default) or `async` -- `tupleCount`: positive integer (default: 3 if omitted and env var not set) -- `relation`: `viewer` or `owner` (default: `viewer`) -- `bufferSize`: positive integer (optional; sets the streaming channel buffer size; defaults to 10) +**Why this matters:** +- We write tuples to `owner` and `viewer` (base permissions) +- We query `can_read` (computed from owner OR viewer) -Examples: +**Example flow:** +1. Write: `user:anne owner document:1-1000` +2. Write: `user:anne viewer document:1001-2000` +3. Query: `StreamedListObjects(user:anne, relation:can_read, type:document)` +4. Result: All 2000 documents (because `can_read = owner OR viewer`) -```bash -# Basic sync (defaults to 3 tuples, relation viewer) -go run . +## Key Features Demonstrated -# Explicit sync, 10 tuples, relation owner -go run . sync 10 owner +### Channel-based Streaming Pattern -# Async mode with 50 tuples and viewer relation -go run . async 50 viewer +The `StreamedListObjects` method returns a response with channels, which is the idiomatic Go way to handle streaming data: -# Sync mode with custom buffer size of 100 -go run . sync 10 viewer 100 +```go +response, err := fgaClient.StreamedListObjects(ctx).Body(request).Execute() +if err != nil { + log.Fatal(err) +} +defer response.Close() -# Using environment variables (relation owner, 25 tuples, buffer size 50) -export FGA_TUPLE_COUNT=25 -export FGA_RELATION=owner -export FGA_BUFFER_SIZE=50 -go run . async -``` +for obj := range response.Objects { + fmt.Printf("Received: %s\n", obj.Object) +} -## Buffer Size Configuration +// Check for errors +if err := <-response.Errors; err != nil { + log.Fatal(err) +} +``` -The `bufferSize` parameter (4th CLI argument or `FGA_BUFFER_SIZE` env var) controls the size of the internal channel buffer used for streaming responses: +### Early Break and Cleanup -- **Larger buffers** (e.g., 100+) improve throughput for high-volume streams but use more memory -- **Smaller buffers** (e.g., 1-10) reduce memory usage but may decrease throughput -- **Default value** is 10, providing a balanced approach for most use cases +The streaming implementation properly handles early termination: -Example with large buffer for high-volume streaming: -```bash -go run . async 1000 viewer 200 +```go +for obj := range response.Objects { + fmt.Println(obj.Object) + if someCondition { + break // Stream is automatically cleaned up via defer response.Close() + } +} ``` -## What Happens Internally +### Context Cancellation Support -1. Store creation (if `FGA_STORE_ID` not provided) -2. Authorization model creation (if `FGA_MODEL_ID` not provided) with `viewer` and `owner` relations -3. Tuple writes: `user:anne` assigned chosen relation for `document:0 .. document:N-1` -4. Streaming request (`StreamedListObjects`) for the chosen relation -5. Consumption pattern: - - Sync: range directly over `response.Objects` - - Async: consume in a goroutine while main goroutine reports progress -6. Final error check via `response.Errors` -7. Temporary store deletion (only if the example created it) +Full support for `context.Context`: -## Expected Output (Sync Mode Example) +```go +ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) +defer cancel() -``` -OpenFGA StreamedListObjects Example -==================================== -API URL: http://localhost:8080 -Store ID: 01ARZ3NDEKTSV4RRFFQ69G5FAV +response, err := fgaClient.StreamedListObjects(ctx).Body(request).Execute() +if err != nil { + log.Fatal(err) +} +defer response.Close() -Creating authorization model... -Created authorization model: 01ARZ3NDEKTSV4RRFFQ69G5FAX +for obj := range response.Objects { + fmt.Println(obj.Object) +} -Writing 3 test tuples for relation 'viewer'... -Wrote 3 test tuples +if err := <-response.Errors; err != nil && err != context.Canceled { + log.Fatal(err) +} +``` -Selected mode: sync | relation: viewer | tuple count: 3 (pass 'sync|async [count] [relation] [bufferSize]') -Mode: sync streaming (range over channel) -Streaming objects (sync): - 1. document:0 - 2. document:1 - 3. document:2 +## Benefits Over ListObjects -Total objects received (sync): 3 (expected up to 3) +- **No Pagination**: Retrieve all objects in a single streaming request +- **Lower Memory**: Objects are processed as they arrive, not held in memory +- **Early Termination**: Can stop streaming at any point without wasting resources +- **Better for Large Results**: Ideal when expecting hundreds or thousands of objects -Deleting temporary store... -Deleted temporary store (01ARZ3NDEKTSV4RRFFQ69G5FAV) +## Performance Considerations -Done. -``` +- Streaming starts immediately - no need to wait for all results +- HTTP connection remains open during streaming +- Properly handles cleanup if consumer stops early +- Supports all the same options as `ListObjects` (consistency, contextual tuples, etc.) -## Expected Output (Async Mode with Custom Buffer Size) +## Error Handling + +The example includes robust error handling that: +- Catches configuration errors +- Detects connection issues +- Avoids logging sensitive data +- Provides helpful messages for common issues -``` -OpenFGA StreamedListObjects Example -==================================== -API URL: http://localhost:8080 -Store ID: 01ARZ3NDEKTSV4RRFFQ69G5FAV - -Creating authorization model... -Created authorization model: 01ARZ3NDEKTSV4RRFFQ69G5FAX - -Writing 5 test tuples for relation 'owner'... -Wrote 5 test tuples - -Selected mode: async | relation: owner | tuple count: 5 | buffer size: 50 (pass 'sync|async [count] [relation] [bufferSize]') -Mode: async streaming (consume in goroutine) -Using custom buffer size: 50 -Performing other work while streaming... - (main goroutine still free to do work) - async -> 1. document:0 - (main goroutine still free to do work) - async -> 2. document:1 - async -> 3. document:2 - (main goroutine still free to do work) - async -> 4. document:3 - async -> 5. document:4 - -Total objects received (async): 5 (expected up to 5) - -Deleting temporary store... -Deleted temporary store (01ARZ3NDEKTSV4RRFFQ69G5FAV) - -Done. -``` diff --git a/example/streamed_list_objects/main.go b/example/streamed_list_objects/main.go index d313277..d1e78ea 100644 --- a/example/streamed_list_objects/main.go +++ b/example/streamed_list_objects/main.go @@ -3,253 +3,223 @@ package main import ( "context" "fmt" - "log" "os" - "strconv" - "time" openfga "github.com/openfga/go-sdk" "github.com/openfga/go-sdk/client" ) -func runSync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: sync streaming (range over channel)") - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId +func main() { + ctx := context.Background() + + // Get API URL from environment or use default + apiUrl := os.Getenv("FGA_API_URL") + if apiUrl == "" { + apiUrl = "http://localhost:8080" } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + + // Create initial client for store creation + config := client.ClientConfiguration{ + ApiUrl: apiUrl, } - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + fgaClient, err := client.NewSdkClient(&config) if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) + handleError(err) + return } - defer response.Close() - fmt.Println("Streaming objects (sync):") - received := 0 - for obj := range response.Objects { // synchronous consumption - received++ - fmt.Printf(" %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil { - log.Fatalf("Error during streaming: %v", err) + fmt.Println("Creating temporary store") + store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{ + Name: "streamed-list-objects", + }).Execute() + if err != nil { + handleError(err) + return } - fmt.Printf("\nTotal objects received (sync): %d (expected up to %d)\n", received, count) -} -// runAsync demonstrates asynchronous consumption using a goroutine; main goroutine can do other work. -func runAsync(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, count int, bufferSize *int) { - fmt.Println("Mode: async streaming (consume in goroutine)") - // Use a cancellable context to show cancellation pattern (not cancelling in this example). - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - request := client.ClientStreamedListObjectsRequest{Type: "document", Relation: relation, User: "user:anne"} - options := client.ClientStreamedListObjectsOptions{} - if authModelId != "" { - options.AuthorizationModelId = &authModelId - } - if bufferSize != nil { - options.StreamBufferSize = bufferSize - fmt.Printf("Using custom buffer size: %d\n", *bufferSize) + // Create client with store ID + clientWithStore, err := client.NewSdkClient(&client.ClientConfiguration{ + ApiUrl: apiUrl, + StoreId: store.Id, + }) + if err != nil { + handleError(err) + return } - response, err := fgaClient.StreamedListObjects(ctx).Body(request).Options(options).Execute() + fmt.Println("Writing authorization model") + authModel, err := writeAuthorizationModel(ctx, clientWithStore) if err != nil { - log.Fatalf("StreamedListObjects failed: %v", err) + handleError(err) + return } - defer response.Close() - done := make(chan struct{}) - received := 0 - - go func() { - defer close(done) - for obj := range response.Objects { - received++ - fmt.Printf(" async -> %d. %s\n", received, obj.Object) - } - if err := <-response.Errors; err != nil && err != context.Canceled { - log.Fatalf("Error during async streaming: %v", err) - } - }() - - // Simulate doing other work while streaming happens. - ticker := time.NewTicker(200 * time.Millisecond) - defer ticker.Stop() - - fmt.Println("Performing other work while streaming...") - for { - select { - case <-done: - fmt.Printf("\nTotal objects received (async): %d (expected up to %d)\n", received, count) - return - case <-ticker.C: - fmt.Println(" (main goroutine still free to do work)") - } + // Create final client with store ID and authorization model ID + fga, err := client.NewSdkClient(&client.ClientConfiguration{ + ApiUrl: apiUrl, + StoreId: store.Id, + AuthorizationModelId: authModel.AuthorizationModelId, + }) + if err != nil { + handleError(err) + return } -} -func createTestData(ctx context.Context, fgaClient *client.OpenFgaClient, authModelId string, relation string, tupleCount int) (string, error) { - // Ensure relation is either viewer or owner for this simplified example. - if relation != "viewer" && relation != "owner" { - return authModelId, fmt.Errorf("unsupported relation '%s' (use viewer or owner)", relation) + fmt.Println("Writing tuples (1000 as owner, 1000 as viewer)") + if err := writeTuples(ctx, fga); err != nil { + handleError(err) + return } - if authModelId == "" { - fmt.Println("Creating authorization model...") + fmt.Println("Streaming objects via computed 'can_read' relation...") + if err := streamObjects(ctx, fga); err != nil { + handleError(err) + return + } - // Provide both viewer and owner relations so user can pick. - relations := map[string]openfga.Userset{ - "viewer": {This: &map[string]interface{}{}}, - "owner": {This: &map[string]interface{}{}}, - } + fmt.Println("Cleaning up...") + if _, err := fga.DeleteStore(ctx).Execute(); err != nil { + fmt.Printf("Failed to delete store: %v\n", err) + } - relationMetadata := map[string]openfga.RelationMetadata{ - "viewer": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - "owner": {DirectlyRelatedUserTypes: &[]openfga.RelationReference{{Type: "user"}}}, - } + fmt.Println("Done") +} - model := openfga.AuthorizationModel{ - SchemaVersion: "1.1", - TypeDefinitions: []openfga.TypeDefinition{ - {Type: "user"}, - {Type: "document", Relations: &relations, Metadata: &openfga.Metadata{Relations: &relationMetadata}}, +func writeAuthorizationModel(ctx context.Context, fgaClient *client.OpenFgaClient) (*client.ClientWriteAuthorizationModelResponse, error) { + // Define the authorization model with computed relations + ownerUserset := openfga.Userset{This: &map[string]interface{}{}} + viewerUserset := openfga.Userset{This: &map[string]interface{}{}} + canReadUserset := openfga.Userset{ + Union: &openfga.Usersets{ + Child: []openfga.Userset{ + {ComputedUserset: &openfga.ObjectRelation{ + Object: openfga.PtrString(""), + Relation: openfga.PtrString("owner"), + }}, + {ComputedUserset: &openfga.ObjectRelation{ + Object: openfga.PtrString(""), + Relation: openfga.PtrString("viewer"), + }}, }, - } - - writeModelResp, err := fgaClient.WriteAuthorizationModel(ctx).Body(client.ClientWriteAuthorizationModelRequest{ - SchemaVersion: model.SchemaVersion, - TypeDefinitions: model.TypeDefinitions, - }).Execute() - if err != nil { - return authModelId, fmt.Errorf("failed to create authorization model: %w", err) - } - authModelId = writeModelResp.AuthorizationModelId - fmt.Printf("Created authorization model: %s\n\n", authModelId) + }, } - fmt.Printf("Writing %d test tuples for relation '%s'...\n", tupleCount, relation) - tuples := make([]client.ClientTupleKey, 0, tupleCount) - for i := 0; i < tupleCount; i++ { - tuples = append(tuples, client.ClientTupleKey{User: "user:anne", Relation: relation, Object: fmt.Sprintf("document:%d", i)}) - } - if _, err := fgaClient.WriteTuples(ctx).Body(tuples).Execute(); err != nil { - return authModelId, fmt.Errorf("failed to write tuples: %w", err) + relations := map[string]openfga.Userset{ + "owner": ownerUserset, + "viewer": viewerUserset, + "can_read": canReadUserset, } - fmt.Printf("Wrote %d test tuples\n\n", len(tuples)) - return authModelId, nil + + relationMetadata := map[string]openfga.RelationMetadata{ + "owner": { + DirectlyRelatedUserTypes: &[]openfga.RelationReference{ + {Type: "user"}, + }, + }, + "viewer": { + DirectlyRelatedUserTypes: &[]openfga.RelationReference{ + {Type: "user"}, + }, + }, + "can_read": { + DirectlyRelatedUserTypes: &[]openfga.RelationReference{}, + }, + } + + return fgaClient.WriteAuthorizationModel(ctx).Body(openfga.WriteAuthorizationModelRequest{ + SchemaVersion: "1.1", + TypeDefinitions: []openfga.TypeDefinition{ + { + Type: "user", + Relations: &map[string]openfga.Userset{}, + }, + { + Type: "document", + Relations: &relations, + Metadata: &openfga.Metadata{Relations: &relationMetadata}, + }, + }, + }).Execute() } -func parseArgs() (mode string, count int, relation string, bufferSize *int) { - mode = "sync" // default - relation = "viewer" - count = 3 - if len(os.Args) > 1 { - mode = os.Args[1] - } - if len(os.Args) > 2 { - if c, err := strconv.Atoi(os.Args[2]); err == nil && c > 0 { - count = c +func writeTuples(ctx context.Context, fga *client.OpenFgaClient) error { + const batchSize = 100 + totalWritten := 0 + + // Write 1000 documents where anne is the owner + for batch := 0; batch < 10; batch++ { + tuples := make([]client.ClientTupleKey, 0, batchSize) + for i := 1; i <= batchSize; i++ { + tuples = append(tuples, client.ClientTupleKey{ + User: "user:anne", + Relation: "owner", + Object: fmt.Sprintf("document:%d", batch*batchSize+i), + }) } - } else if envCount := os.Getenv("FGA_TUPLE_COUNT"); envCount != "" { - if c, err := strconv.Atoi(envCount); err == nil && c > 0 { - count = c + if _, err := fga.WriteTuples(ctx).Body(tuples).Execute(); err != nil { + return fmt.Errorf("failed to write owner tuples: %w", err) } - } - if len(os.Args) > 3 { - relation = os.Args[3] - } else if envRel := os.Getenv("FGA_RELATION"); envRel != "" { - relation = envRel - } - if len(os.Args) > 4 { - if b, err := strconv.Atoi(os.Args[4]); err == nil && b > 0 { - bufferSize = &b + totalWritten += len(tuples) + } + + // Write 1000 documents where anne is a viewer + for batch := 0; batch < 10; batch++ { + tuples := make([]client.ClientTupleKey, 0, batchSize) + for i := 1; i <= batchSize; i++ { + tuples = append(tuples, client.ClientTupleKey{ + User: "user:anne", + Relation: "viewer", + Object: fmt.Sprintf("document:%d", 1000+batch*batchSize+i), + }) } - } else if envBuffer := os.Getenv("FGA_BUFFER_SIZE"); envBuffer != "" { - if b, err := strconv.Atoi(envBuffer); err == nil && b > 0 { - bufferSize = &b + if _, err := fga.WriteTuples(ctx).Body(tuples).Execute(); err != nil { + return fmt.Errorf("failed to write viewer tuples: %w", err) } + totalWritten += len(tuples) } - return -} -func main() { - ctx := context.Background() - apiUrl := os.Getenv("FGA_API_URL") - if apiUrl == "" { - apiUrl = "http://localhost:8080" - } - config := client.ClientConfiguration{ApiUrl: apiUrl} - fgaClient, err := client.NewSdkClient(&config) - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } + fmt.Printf("Wrote %d tuples\n", totalWritten) + return nil +} - // Create store unless provided via env var. - storeId := os.Getenv("FGA_STORE_ID") - createdTempStore := false - if storeId == "" { - fmt.Println("Creating Test Store for streamed list objects") - store, err := fgaClient.CreateStore(ctx).Body(client.ClientCreateStoreRequest{Name: "Test Store"}).Execute() - if err != nil { - log.Fatalf("failed to create store: %v", err) - } - storeId = store.Id - createdTempStore = true - } +func streamObjects(ctx context.Context, fga *client.OpenFgaClient) error { + consistencyPreference := openfga.CONSISTENCYPREFERENCE_HIGHER_CONSISTENCY - // Re-init client with storeId - config = client.ClientConfiguration{ApiUrl: apiUrl, StoreId: storeId} - fgaClient, err = client.NewSdkClient(&config) + response, err := fga.StreamedListObjects(ctx).Body(client.ClientStreamedListObjectsRequest{ + User: "user:anne", + Relation: "can_read", // Computed: owner OR viewer + Type: "document", + }).Options(client.ClientStreamedListObjectsOptions{ + Consistency: &consistencyPreference, + }).Execute() if err != nil { - log.Fatalf("Failed to create client: %v", err) + return fmt.Errorf("StreamedListObjects failed: %w", err) } + defer response.Close() - fmt.Println("OpenFGA StreamedListObjects Example") - fmt.Println("____________________________________") - fmt.Printf("API URL: %s\n", apiUrl) - fmt.Printf("Store ID: %s\n", storeId) - fmt.Println() - - authModelId := os.Getenv("FGA_MODEL_ID") - mode, tupleCount, relation, bufferSize := parseArgs() - if authModelId != "" { - fmt.Printf("Authorization Model ID (provided): %s\n\n", authModelId) - } - authModelId, err = createTestData(ctx, fgaClient, authModelId, relation, tupleCount) - if err != nil { - log.Printf("Warning: Failed to create test data: %v", err) - log.Println("Continuing with example...") + count := 0 + for obj := range response.Objects { + count++ + if count <= 3 || count%500 == 0 { + fmt.Printf("- %s\n", obj.Object) + } } - fmt.Printf("Selected mode: %s | relation: %s | tuple count: %d", mode, relation, tupleCount) - if bufferSize != nil { - fmt.Printf(" | buffer size: %d", *bufferSize) + // Check for streaming errors + if err := <-response.Errors; err != nil { + return fmt.Errorf("error during streaming: %w", err) } - fmt.Printf(" (pass 'sync|async [count] [relation] [bufferSize]')\n\n") - switch mode { - case "async": - runAsync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - case "sync": - runSync(ctx, fgaClient, authModelId, relation, tupleCount, bufferSize) - default: - fmt.Printf("Unknown mode '%s'. Use 'sync' or 'async'.\n", mode) - os.Exit(1) - } + fmt.Printf("✓ Streamed %d objects\n", count) + return nil +} - if createdTempStore { - fmt.Println("\nDeleting temporary store...") - if _, err := fgaClient.DeleteStore(ctx).Execute(); err != nil { - fmt.Printf("Failed to delete store: %v\n", err) - } else { - fmt.Printf("Deleted temporary store (%s)\n", storeId) - } +func handleError(err error) { + // Avoid logging sensitive data; only display generic info + if err.Error() == "connection refused" { + fmt.Fprintln(os.Stderr, "Is OpenFGA server running? Check FGA_API_URL environment variable or default http://localhost:8080") + } else { + fmt.Fprintf(os.Stderr, "An error occurred. [%T]\n", err) } - fmt.Println("\nDone.") + os.Exit(1) } From 58907cb516c4cdf6754e192795de01ef65fc4d54 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Fri, 14 Nov 2025 21:13:25 +0530 Subject: [PATCH 8/9] Feat: added readme example too --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/README.md b/README.md index d5d6c6c..103f257 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ This is an autogenerated Go SDK for OpenFGA. It provides a wrapper around the [O - [Batch Check](#batch-check) - [Expand](#expand) - [List Objects](#list-objects) + - [Streamed List Objects](#streamed-list-objects) - [List Relations](#list-relations) - [List Users](#list-users) - [Assertions](#assertions) @@ -912,6 +913,50 @@ data, err := fgaClient.ListObjects(context.Background()). // data.Objects = ["document:0192ab2a-d83f-756d-9397-c5ed9f3cb69a"] ``` +##### Streamed List Objects + +List objects of a particular type that the user has access to, using the streaming API. + +The Streamed ListObjects API is very similar to the ListObjects API, with two key differences: +1. **Streaming Results**: Instead of collecting all objects before returning a response, it streams them to the client as they are collected. +2. **No Pagination Limit**: Returns all results without the 1000-object limit of the standard ListObjects API. + +This is particularly useful when querying **computed relations** that may return large result sets. + +[API Documentation](https://openfga.dev/api/service#/Relationship%20Queries/StreamedListObjects) + +```golang +options := ClientStreamedListObjectsOptions{ + // You can rely on the model id set in the configuration or override it for this specific request + AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"), +} + +body := ClientStreamedListObjectsRequest{ + User: "user:anne", + Relation: "can_read", + Type: "document", +} + +response, err := fgaClient.StreamedListObjects(context.Background()).Body(body).Options(options).Execute() +if err != nil { + // .. Handle error +} +defer response.Close() + +// Consume objects from the stream +var objects []string +for obj := range response.Objects { + objects = append(objects, obj.Object) +} + +// Check for any errors during streaming +if err := <-response.Errors; err != nil { + // .. Handle streaming error +} + +// objects = ["document:0192ab2a-d83f-756d-9397-c5ed9f3cb69a"] +``` + #### List Relations List the relations a user has on an object. From 3112003382bdc6bd61be7289368ef983d323a88c Mon Sep 17 00:00:00 2001 From: SoulPancake Date: Mon, 17 Nov 2025 17:51:04 +0530 Subject: [PATCH 9/9] feat: address comments, rem changelog extra line --- CHANGELOG.md | 4 +- example/streamed_list_objects/go.mod | 16 ++++++ example/streamed_list_objects/main.go | 76 +++++++++------------------ 3 files changed, 43 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58f7f30..83e982d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,7 @@ - feat: add generic `ToPtr[T any](v T) *T` function for creating pointers to any type - deprecation: `PtrBool`, `PtrInt`, `PtrInt32`, `PtrInt64`, `PtrFloat32`, `PtrFloat64`, `PtrString`, and `PtrTime` are now deprecated in favor of the generic `ToPtr` function - feat: add a top-level makefile in go-sdk to simplify running tests and linters: (#250) -- feat: add support for StreamedListObjects endpoint -- feat: add configurable buffer size for streaming responses via `ClientStreamedListObjectsOptions.StreamBufferSize` - +- feat: add support for StreamedListObjects endpoint (#252) ## v0.7.3 ### [0.7.3](https://github.com/openfga/go-sdk/compare/v0.7.2...v0.7.3) (2025-10-08) diff --git a/example/streamed_list_objects/go.mod b/example/streamed_list_objects/go.mod index 919206d..bad2670 100644 --- a/example/streamed_list_objects/go.mod +++ b/example/streamed_list_objects/go.mod @@ -5,8 +5,15 @@ go 1.25.1 require github.com/openfga/go-sdk v0.7.3 require ( + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/openfga/api/proto v0.0.0-20240905181937-3583905f61a6 // indirect + github.com/openfga/language/pkg/go v0.2.0-beta.2 // indirect github.com/sourcegraph/conc v0.3.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect @@ -14,7 +21,16 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect + golang.org/x/net v0.29.0 // indirect golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.66.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/openfga/go-sdk => ../.. // added this to point to local module diff --git a/example/streamed_list_objects/main.go b/example/streamed_list_objects/main.go index d1e78ea..fe19dba 100644 --- a/example/streamed_list_objects/main.go +++ b/example/streamed_list_objects/main.go @@ -2,11 +2,13 @@ package main import ( "context" + "encoding/json" "fmt" "os" openfga "github.com/openfga/go-sdk" "github.com/openfga/go-sdk/client" + "github.com/openfga/language/pkg/go/transformer" ) func main() { @@ -86,59 +88,33 @@ func main() { } func writeAuthorizationModel(ctx context.Context, fgaClient *client.OpenFgaClient) (*client.ClientWriteAuthorizationModelResponse, error) { - // Define the authorization model with computed relations - ownerUserset := openfga.Userset{This: &map[string]interface{}{}} - viewerUserset := openfga.Userset{This: &map[string]interface{}{}} - canReadUserset := openfga.Userset{ - Union: &openfga.Usersets{ - Child: []openfga.Userset{ - {ComputedUserset: &openfga.ObjectRelation{ - Object: openfga.PtrString(""), - Relation: openfga.PtrString("owner"), - }}, - {ComputedUserset: &openfga.ObjectRelation{ - Object: openfga.PtrString(""), - Relation: openfga.PtrString("viewer"), - }}, - }, - }, - } - - relations := map[string]openfga.Userset{ - "owner": ownerUserset, - "viewer": viewerUserset, - "can_read": canReadUserset, - } - - relationMetadata := map[string]openfga.RelationMetadata{ - "owner": { - DirectlyRelatedUserTypes: &[]openfga.RelationReference{ - {Type: "user"}, - }, - }, - "viewer": { - DirectlyRelatedUserTypes: &[]openfga.RelationReference{ - {Type: "user"}, - }, - }, - "can_read": { - DirectlyRelatedUserTypes: &[]openfga.RelationReference{}, - }, + // Define the authorization model using OpenFGA DSL + dslString := `model + schema 1.1 + +type user + +type document + relations + define owner: [user] + define viewer: [user] + define can_read: owner or viewer` + + // Transform DSL to JSON string + modelJSON, err := transformer.TransformDSLToJSON(dslString) + if err != nil { + return nil, fmt.Errorf("failed to transform DSL to JSON: %w", err) + } + + // Parse the JSON into the authorization model request + var authModel openfga.AuthorizationModel + if err := json.Unmarshal([]byte(modelJSON), &authModel); err != nil { + return nil, fmt.Errorf("failed to unmarshal authorization model: %w", err) } return fgaClient.WriteAuthorizationModel(ctx).Body(openfga.WriteAuthorizationModelRequest{ - SchemaVersion: "1.1", - TypeDefinitions: []openfga.TypeDefinition{ - { - Type: "user", - Relations: &map[string]openfga.Userset{}, - }, - { - Type: "document", - Relations: &relations, - Metadata: &openfga.Metadata{Relations: &relationMetadata}, - }, - }, + SchemaVersion: authModel.SchemaVersion, + TypeDefinitions: authModel.TypeDefinitions, }).Execute() }