Skip to content

Commit

Permalink
release: v0.2.3 with a fix for the interface of ClientListObjects (#18)
Browse files Browse the repository at this point in the history
- fix: changed interface of contextual tuples in `ClientListObjects` to
  be `ClientTupleKey` instead of `TupleKey`
- fix: Client `WriteAuthorizationModel` now expects
  `ClientWriteAuthorizationModelRequest` instead of
  `WriteAuthorizationModelRequest`
- chore: changed a few interfaces to expect interfaces instead of
  classes
  • Loading branch information
rhamzeh authored Apr 13, 2023
2 parents b2369dd + f0b76ab commit 163630f
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 54 deletions.
1 change: 1 addition & 0 deletions .openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ src/OpenFga.Sdk/Client/Model/ClientRequestOptsWithAuthZModelId.cs
src/OpenFga.Sdk/Client/Model/ClientTupleKey.cs
src/OpenFga.Sdk/Client/Model/ClientWriteAssertionsOptions.cs
src/OpenFga.Sdk/Client/Model/ClientWriteAssertionsRequest.cs
src/OpenFga.Sdk/Client/Model/ClientWriteAuthorizationModelRequest.cs
src/OpenFga.Sdk/Client/Model/ClientWriteOptions.cs
src/OpenFga.Sdk/Client/Model/ClientWriteRequest.cs
src/OpenFga.Sdk/Client/Model/ClientWriteResponse.cs
Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v0.2.3

### [0.2.3](https://github.com/openfga/dotnet-sdk/compare/v0.2.2...v0.2.3) (2023-04-13)
- fix: changed interface of contextual tuples in `ClientListObjects` to be `ClientTupleKey` instead of `TupleKey`
- fix: Client `WriteAuthorizationModel` now expects `ClientWriteAuthorizationModelRequest` instead of `WriteAuthorizationModelRequest`
- chore: changed a few interfaces to expect interfaces instead of classes

## v0.2.2

### [0.2.2](https://github.com/openfga/dotnet-sdk/compare/v0.2.1...v0.2.2) (2023-04-12)
Expand All @@ -8,7 +15,7 @@
- feat(client): implement `BatchCheck` to check multiple tuples in parallel
- feat(client): implement `ListRelations` to check in one call whether a user has multiple relations to an objects
- feat(client): add support for a non-transactional `Write`
- chore(config): bump default max retries to `5`
- chore(config): bump default max retries to `15`
- fix: retry on 5xx errors

## v0.2.1
Expand Down
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ Create a new authorization model.
```csharp

var body = new WriteAuthorizationModelRequest {
var body = new ClientWriteAuthorizationModelRequest {
SchemaVersion = "1.1",
TypeDefinitions = new List<TypeDefinition> {
new() {Type = "user", Relations = new Dictionary<string, Userset>()},
Expand Down Expand Up @@ -671,11 +671,13 @@ var body = new ClientListObjectsRequest {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Relation = "viewer",
Type = "document",
ContextualTuples = new List<TupleKey>() {
{
new("document:budget", "writer", "user:81684243-9356-4421-8fbf-a4f8d36aa31b")
}
}
ContextualTuples = new List<ClientTupleKey> {
new() {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Relation = "writer",
Object = "document:budget",
},
},
};
var response = await fgaClient.ListObjects(body, options);

Expand Down Expand Up @@ -718,7 +720,6 @@ var options = new ClientReadAssertionsOptions {
// You can rely on the model id set in the configuration or override it for this specific request
AuthorizationModelId = "01GXSA8YR785C4FYS3C0RTG7B1",
};

var response = await fgaClient.ReadAssertions(options);
```

Expand All @@ -733,14 +734,12 @@ var options = new ClientWriteAssertionsOptions {
// You can rely on the model id set in the configuration or override it for this specific request
AuthorizationModelId = "01GXSA8YR785C4FYS3C0RTG7B1",
};

var body = new List<ClientAssertion>() {new ClientAssertion() {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Relation = "viewer",
Object = "document:roadmap",
Expectation = true,
}};

await fgaClient.WriteAssertions(body, options);
```

Expand Down
2 changes: 1 addition & 1 deletion src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ public async Task ListStoresTest() {
}

/// <summary>
/// Test ListStores does not crash in error handling
/// Test ListStores correctly returns FgaApiNotFoundError
/// </summary>
[Fact]
public async Task ListStoresResponseErrorTest() {
Expand Down
24 changes: 16 additions & 8 deletions src/OpenFga.Sdk.Test/Client/OpenFgaClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public async Task DeleteStoreTest() {
[Fact]
public async Task WriteAuthorizationModelTest() {
const string authorizationModelId = "01GXSA8YR785C4FYS3C0RTG7B1";
var body = new WriteAuthorizationModelRequest {
var body = new ClientWriteAuthorizationModelRequest {
SchemaVersion = "1.1",
TypeDefinitions = new List<TypeDefinition> {
new() {
Expand Down Expand Up @@ -1158,10 +1158,18 @@ public async Task ListObjectsTest() {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Relation = "can_read",
Type = "document",
ContextualTuples = new List<TupleKey> {
new("folder:product", "editor", "user:81684243-9356-4421-8fbf-a4f8d36aa31b"),
new("document:roadmap", "parent", "folder:product")
}
ContextualTuples = new List<ClientTupleKey> {
new() {
User = "folder:product",
Relation = "editor",
Object = "folder:product",
},
new() {
User = "folder:product",
Relation = "parent",
Object = "document:roadmap",
},
},
};
var response = await fgaClient.ListObjects(body, new ClientWriteOptions {
AuthorizationModelId = "01GXSA8YR785C4FYS3C0RTG7B1",
Expand Down Expand Up @@ -1215,13 +1223,13 @@ public async Task ListRelationsTest() {
var httpClient = new HttpClient(mockHandler.Object);
var fgaClient = new OpenFgaClient(_config, httpClient);

ClientListRelationsRequest body =
var body =
new ClientListRelationsRequest() {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Object = "document:roadmap",
Relations = new List<string> { "can_view", "can_edit", "can_delete", "can_rename" },
ContextualTuples = new List<ClientTupleKey>() {
new ClientTupleKey {
new() {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Relation = "editor",
Object = "document:roadmap",
Expand Down Expand Up @@ -1271,7 +1279,7 @@ public async Task ListRelationsNoRelationsProvidedTest() {
new ClientListRelationsRequest() {
User = "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
Object = "document:roadmap",
Relations = new List<string> {},
Relations = new List<string> { },
};

Task<ListRelationsResponse> ApiError() => fgaClient.ListRelations(body);
Expand Down
50 changes: 27 additions & 23 deletions src/OpenFga.Sdk/Client/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public string? AuthorizationModelId {
/**
* ListStores - Get a paginated list of stores.
*/
public async Task<ListStoresResponse> ListStores(ClientListStoresOptions? options = default,
public async Task<ListStoresResponse> ListStores(IClientListStoresOptions? options = default,
CancellationToken cancellationToken = default) =>
await api.ListStores(options?.PageSize, options?.ContinuationToken, cancellationToken);

Expand Down Expand Up @@ -96,14 +96,14 @@ public async Task DeleteStore(ClientRequestOptions? options = default, Cancellat
* ReadAuthorizationModels - Read all authorization models
*/
public async Task<ReadAuthorizationModelsResponse> ReadAuthorizationModels(
ClientReadAuthorizationModelsOptions? options = default,
IClientReadAuthorizationModelsOptions? options = default,
CancellationToken cancellationToken = default) =>
await api.ReadAuthorizationModels(options?.PageSize, options?.ContinuationToken, cancellationToken);

/**
* WriteAuthorizationModel - Create a new version of the authorization model
*/
public async Task<WriteAuthorizationModelResponse> WriteAuthorizationModel(WriteAuthorizationModelRequest body,
public async Task<WriteAuthorizationModelResponse> WriteAuthorizationModel(ClientWriteAuthorizationModelRequest body,
ClientRequestOptions? options = default,
CancellationToken cancellationToken = default) =>
await api.WriteAuthorizationModel(body, cancellationToken);
Expand All @@ -112,7 +112,7 @@ public async Task<WriteAuthorizationModelResponse> WriteAuthorizationModel(Write
* ReadAuthorizationModel - Read the current authorization model
*/
public async Task<ReadAuthorizationModelResponse> ReadAuthorizationModel(
ClientReadAuthorizationModelOptions? options = default,
IClientReadAuthorizationModelOptions? options = default,
CancellationToken cancellationToken = default) {
var authorizationModelId = GetAuthorizationModelId(options);
if (authorizationModelId == null) {
Expand Down Expand Up @@ -141,14 +141,14 @@ public async Task<ReadAuthorizationModelResponse> ReadLatestAuthorizationModel(
* Read Changes - Read the list of historical relationship tuple writes and deletes
*/
public async Task<ReadChangesResponse> ReadChanges(ClientReadChangesRequest body,
ClientReadChangesOptions? options = default,
IClientReadChangesOptions? options = default,
CancellationToken cancellationToken = default) =>
await api.ReadChanges(body.Type, options?.PageSize, options?.ContinuationToken, cancellationToken);

/**
* Read - Read tuples previously written to the store (does not evaluate)
*/
public async Task<ReadResponse> Read(ClientReadRequest body, ClientReadOptions? options = default,
public async Task<ReadResponse> Read(ClientReadRequest body, IClientReadOptions? options = default,
CancellationToken cancellationToken = default) =>
await api.Read(
new ReadRequest {
Expand All @@ -160,7 +160,7 @@ await api.Read(
/**
* Write - Create or delete relationship tuples
*/
public async Task<ClientWriteResponse> Write(ClientWriteRequest body, ClientWriteOptions? options = default,
public async Task<ClientWriteResponse> Write(ClientWriteRequest body, IClientWriteOptions? options = default,
CancellationToken cancellationToken = default) {
var maxPerChunk =
options?.Transaction?.MaxPerChunk ??
Expand All @@ -184,10 +184,10 @@ public async Task<ClientWriteResponse> Write(ClientWriteRequest body, ClientWrit
return new ClientWriteResponse {
Writes =
body.Writes?.ConvertAll(tupleKey =>
new ClientWriteSingleResponse { TupleKey = tupleKey, Status = ClientWriteStatus.SUCCESS }) ??
new ClientWriteSingleResponse { TupleKey = tupleKey.ToTupleKey(), Status = ClientWriteStatus.SUCCESS }) ??
new List<ClientWriteSingleResponse>(),
Deletes = body.Deletes?.ConvertAll(tupleKey => new ClientWriteSingleResponse {
TupleKey = tupleKey,
TupleKey = tupleKey.ToTupleKey(),
Status = ClientWriteStatus.SUCCESS
}) ?? new List<ClientWriteSingleResponse>()
};
Expand All @@ -206,15 +206,15 @@ await Parallel.ForEachAsync(writeChunks,
foreach (var tupleKey in writes) {
writeResponses.Add(new ClientWriteSingleResponse {
TupleKey = tupleKey,
TupleKey = tupleKey.ToTupleKey(),
Status = ClientWriteStatus.SUCCESS,
});
}
}
catch (Exception e) {
foreach (var tupleKey in writes) {
writeResponses.Add(new ClientWriteSingleResponse {
TupleKey = tupleKey,
TupleKey = tupleKey.ToTupleKey(),
Status = ClientWriteStatus.FAILURE,
Error = e,
});
Expand All @@ -230,15 +230,15 @@ await Parallel.ForEachAsync(deleteChunks,
foreach (var tupleKey in deletes) {
deleteResponses.Add(new ClientWriteSingleResponse {
TupleKey = tupleKey,
TupleKey = tupleKey.ToTupleKey(),
Status = ClientWriteStatus.SUCCESS,
});
}
}
catch (Exception e) {
foreach (var tupleKey in deletes) {
deleteResponses.Add(new ClientWriteSingleResponse {
TupleKey = tupleKey,
TupleKey = tupleKey.ToTupleKey(),
Status = ClientWriteStatus.FAILURE,
Error = e,
});
Expand All @@ -252,14 +252,14 @@ await Parallel.ForEachAsync(deleteChunks,
/**
* WriteTuples - Utility method to write tuples, wraps Write
*/
public async Task<ClientWriteResponse> WriteTuples(List<ClientTupleKey> body, ClientWriteOptions? options = default,
public async Task<ClientWriteResponse> WriteTuples(List<ClientTupleKey> body, IClientWriteOptions? options = default,
CancellationToken cancellationToken = default) =>
await Write(new ClientWriteRequest { Writes = body }, options, cancellationToken);

/**
* DeleteTuples - Utility method to delete tuples, wraps Write
*/
public async Task<ClientWriteResponse> DeleteTuples(List<ClientTupleKey> body, ClientWriteOptions? options = default,
public async Task<ClientWriteResponse> DeleteTuples(List<ClientTupleKey> body, IClientWriteOptions? options = default,
CancellationToken cancellationToken = default) =>
await Write(new ClientWriteRequest { Deletes = body }, options, cancellationToken);

Expand All @@ -270,7 +270,7 @@ public async Task<ClientWriteResponse> DeleteTuples(List<ClientTupleKey> body, C
/**
* Check - Check if a user has a particular relation with an object (evaluates)
*/
public async Task<CheckResponse> Check(ClientCheckRequest body,
public async Task<CheckResponse> Check(IClientCheckRequest body,
IClientRequestOptionsWithAuthZModelId? options = default,
CancellationToken cancellationToken = default) =>
await api.Check(
Expand Down Expand Up @@ -313,7 +313,7 @@ await Parallel.ForEachAsync(body,
/**
* Expand - Expands the relationships in userset tree format (evaluates)
*/
public async Task<ExpandResponse> Expand(ClientExpandRequest body,
public async Task<ExpandResponse> Expand(IClientExpandRequest body,
IClientRequestOptionsWithAuthZModelId? options = default,
CancellationToken cancellationToken = default) =>
await api.Expand(
Expand All @@ -325,27 +325,31 @@ await api.Expand(
/**
* ListObjects - List the objects of a particular type that the user has a certain relation to (evaluates)
*/
public async Task<ListObjectsResponse> ListObjects(ClientListObjectsRequest body,
public async Task<ListObjectsResponse> ListObjects(IClientListObjectsRequest body,
IClientRequestOptionsWithAuthZModelId? options = default,
CancellationToken cancellationToken = default) =>
await api.ListObjects(new ListObjectsRequest {
User = body.User,
Relation = body.Relation,
Type = body.Type,
ContextualTuples = new ContextualTupleKeys { TupleKeys = body.ContextualTuples ?? new List<TupleKey>() },
ContextualTuples =
new ContextualTupleKeys {
TupleKeys = body.ContextualTuples?.ConvertAll(tupleKey => tupleKey.ToTupleKey()) ??
new List<TupleKey>()
},
AuthorizationModelId = GetAuthorizationModelId(options)
});

/**
* ListRelations - List all the relations a user has with an object (evaluates)
*/
public async Task<ListRelationsResponse> ListRelations(ClientListRelationsRequest body,
public async Task<ListRelationsResponse> ListRelations(IClientListRelationsRequest body,
IClientBatchCheckOptions? options = default,
CancellationToken cancellationToken = default) {
if (body.Relations.Count == 0) {
throw new FgaValidationError("At least 1 relation to check has to be provided when calling ListRelations");
}

var responses = new ListRelationsResponse();
var batchCheckRequests = new List<ClientCheckRequest>();
for (var index = 0; index < body.Relations.Count; index++) {
Expand Down Expand Up @@ -377,7 +381,7 @@ public async Task<ListRelationsResponse> ListRelations(ClientListRelationsReques
/**
* ReadAssertions - Read assertions for a particular authorization model
*/
public async Task<ReadAssertionsResponse> ReadAssertions(ClientReadAssertionsOptions? options = default,
public async Task<ReadAssertionsResponse> ReadAssertions(IClientReadAssertionsOptions? options = default,
CancellationToken cancellationToken = default) {
var authorizationModelId = GetAuthorizationModelId(options);
if (authorizationModelId == null) {
Expand All @@ -391,7 +395,7 @@ public async Task<ReadAssertionsResponse> ReadAssertions(ClientReadAssertionsOpt
* WriteAssertions - Updates assertions for a particular authorization model
*/
public async Task WriteAssertions(List<ClientAssertion> body,
ClientWriteAssertionsOptions? options = default,
IClientWriteAssertionsOptions? options = default,
CancellationToken cancellationToken = default) {
var authorizationModelId = GetAuthorizationModelId(options);
if (authorizationModelId == null) {
Expand Down
2 changes: 1 addition & 1 deletion src/OpenFga.Sdk/Client/Model/ClientCheckRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

namespace OpenFga.Sdk.Client.Model;

internal interface IClientCheckRequest {
public interface IClientCheckRequest : IClientContextualTuplesWrapper {
public string User { get; set; }
public string Relation { get; set; }
public string Object { get; set; }
Expand Down
13 changes: 13 additions & 0 deletions src/OpenFga.Sdk/Client/Model/ClientCreateStoreOptions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
//
// OpenFGA/.NET SDK for OpenFGA
//
// API version: 0.1
// Website: https://openfga.dev
// Documentation: https://openfga.dev/docs
// Support: https://discord.gg/8naAwJfWN6
// License: [Apache-2.0](https://github.com/openfga/dotnet-sdk/blob/main/LICENSE)
//
// NOTE: This file was auto generated. DO NOT EDIT.
//


namespace OpenFga.Sdk.Client.Model;

public interface IClientCreateStoreOptions : ClientRequestOptions { }
Expand Down
Loading

0 comments on commit 163630f

Please sign in to comment.