Skip to content

Commit

Permalink
Merge pull request #32 from openfga/feat/batching
Browse files Browse the repository at this point in the history
feat(client): implement batchCheck, listRelations, and non-transaction write
  • Loading branch information
adriantam authored Nov 22, 2023
2 parents d790fc0 + 1495f14 commit 6d6a615
Show file tree
Hide file tree
Showing 19 changed files with 1,106 additions and 52 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/semgrep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ jobs:
image: returntocorp/semgrep
if: (github.actor != 'dependabot[bot]' && github.actor != 'snyk-bot')
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.2
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
- run: semgrep ci
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
4 changes: 4 additions & 0 deletions .openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java
src/main/java/dev/openfga/sdk/api/client/ApiClient.java
src/main/java/dev/openfga/sdk/api/client/ApiResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientAssertion.java
src/main/java/dev/openfga/sdk/api/client/ClientBatchCheckResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientCheckRequest.java
src/main/java/dev/openfga/sdk/api/client/ClientCheckResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientCreateStoreResponse.java
Expand All @@ -93,6 +94,7 @@ src/main/java/dev/openfga/sdk/api/client/ClientGetStoreResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientListObjectsRequest.java
src/main/java/dev/openfga/sdk/api/client/ClientListObjectsResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientListRelationsRequest.java
src/main/java/dev/openfga/sdk/api/client/ClientListRelationsResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientListStoresResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientReadAssertionsResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientReadAuthorizationModelResponse.java
Expand All @@ -109,11 +111,13 @@ src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java
src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java
src/main/java/dev/openfga/sdk/api/configuration/ApiToken.java
src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java
src/main/java/dev/openfga/sdk/api/configuration/ClientBatchCheckOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientCheckOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientConfiguration.java
src/main/java/dev/openfga/sdk/api/configuration/ClientCredentials.java
src/main/java/dev/openfga/sdk/api/configuration/ClientExpandOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientListObjectsOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientListRelationsOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientListStoresOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientReadAssertionsOptions.java
src/main/java/dev/openfga/sdk/api/configuration/ClientReadAuthorizationModelOptions.java
Expand Down
7 changes: 7 additions & 0 deletions 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/java-sdk/compare/v0.2.2...v0.2.3) (2023-11-21)

- feat(client): implement batchCheck, listRelations, and non-transaction write
- fix(client): adds missing "contextual tuples" field to check request

## v0.2.2

### [0.2.2](https://github.com/openfga/java-sdk/compare/v0.2.1...v0.2.2) (2023-10-31)
Expand Down
138 changes: 129 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ It can be used with the following:
* Gradle (Groovy)

```groovy
implementation 'dev.openfga:openfga-sdk:0.2.2'
implementation 'dev.openfga:openfga-sdk:0.2.3'
```

* Gradle (Kotlin)

```kotlin
implementation("dev.openfga:openfga-sdk:0.2.2")
implementation("dev.openfga:openfga-sdk:0.2.3")
```

* Apache Maven
Expand All @@ -89,26 +89,26 @@ implementation("dev.openfga:openfga-sdk:0.2.2")
<dependency>
<groupId>dev.openfga</groupId>
<artifactId>openfga-sdk</artifactId>
<version>0.2.2</version>
<version>0.2.3</version>
</dependency>
```

* Ivy

```xml
<dependency org="dev.openfga" name="openfga-sdk" rev="0.2.2"/>
<dependency org="dev.openfga" name="openfga-sdk" rev="0.2.3"/>
```

* SBT

```scala
libraryDependencies += "dev.openfga" % "openfga-sdk" % "0.2.2"
libraryDependencies += "dev.openfga" % "openfga-sdk" % "0.2.3"
```

* Leiningen

```edn
[dev.openfga/openfga-sdk "0.2.2"]
[dev.openfga/openfga-sdk "0.2.3"]
```


Expand Down Expand Up @@ -471,7 +471,30 @@ Convenience `WriteTuples` and `DeleteTuples` methods are also available.
The SDK will split the writes into separate requests and send them sequentially to avoid violating rate limits.

```java
// Coming soon
var request = new ClientWriteRequest()
.writes(List.of(
new ClientTupleKey()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("viewer")
._object("document:roadmap"),
new ClientTupleKey()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("viewer")
._object("document:budget")
))
.deletes(List.of(
new ClientTupleKey()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("writer")
._object("document:roadmap")
));
var options = new ClientWriteOptions()
// You can rely on the model id set in the configuration or override it for this specific request
.authorizationModelId("01GXSA8YR785C4FYS3C0RTG7B1")
.disableTransactions(true)
.transactionChunkSize(5); // Maximum number of requests to be sent in a transaction in a particular chunk

var response = fgaClient.write(request, options).get();
```

#### Relationship Queries
Expand Down Expand Up @@ -501,7 +524,85 @@ Run a set of [checks](#check). Batch Check will return `allowed: false` if it en
If 429s or 5xxs are encountered, the underlying check will retry up to 15 times before giving up.

```java
// Coming soon
var request = List.of(
new ClientCheckRequest()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("viewer")
._object("document:roadmap")
.contextualTuples(List.of(
new ClientTupleKey()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("editor")
._object("document:roadmap")
)),
new ClientCheckRequest()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("admin")
._object("document:roadmap"),
.contextualTuples(List.of(
new ClientTupleKey()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("editor")
._object("document:roadmap")
)),
new ClientCheckRequest()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("creator")
._object("document:roadmap"),
new ClientCheckRequest()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("deleter")
._object("document:roadmap")
);
var options = new ClientBatchCheckOptions()
// You can rely on the model id set in the configuration or override it for this specific request
.authorizationModelId("01GXSA8YR785C4FYS3C0RTG7B1")
.maxParallelRequests(5); // Max number of requests to issue in parallel, defaults to 10

var response = fgaClient.batchCheck(request, options).get();

/*
response.getResponses() = [{
allowed: false,
request: {
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
relation: "viewer",
_object: "document:roadmap",
contextualTuples: [{
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
relation: "editor",
_object: "document:roadmap"
}]
}
}, {
allowed: false,
request: {
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
relation: "admin",
_object: "document:roadmap",
contextualTuples: [{
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
relation: "editor",
_object: "document:roadmap"
}]
}
}, {
allowed: false,
request: {
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
relation: "creator",
_object: "document:roadmap",
},
error: <FgaError ...>
}, {
allowed: true,
request: {
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
relation: "deleter",
_object: "document:roadmap",
}},
]
*/
```

##### Expand
Expand Down Expand Up @@ -554,7 +655,26 @@ var response = fgaClient.listObjects(request, options).get();
List the relations a user has on an object.

```java
// Coming soon.
var request = new ClientListRelationsRequest()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
._object("document:roadmap")
.relations(List.of("can_view", "can_edit", "can_delete", "can_rename"))
.contextualTuples(List.of(
new ClientTupleKey()
.user("user:81684243-9356-4421-8fbf-a4f8d36aa31b")
.relation("editor")
._object("document:roadmap")
)
);
var options = new ClientListRelationsOptions()
// When unspecified, defaults to 10
.maxParallelRequests()
// You can rely on the model id set in the configuration or override it for this specific request
.authorizationModelId(DEFAULT_AUTH_MODEL_ID);

var response = fgaClient.listRelations(request, options).get();

// response.getRelations() = ["can_view", "can_edit"]
```

#### Assertions
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ plugins {
apply from: 'publish.gradle'

group = 'dev.openfga'
version = '0.2.2'
version = '0.2.3'

repositories {
mavenCentral()
Expand Down
2 changes: 1 addition & 1 deletion publish.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ publishing {
pom {
group = 'dev.openfga'
name = 'openfga-sdk'
version = '0.2.2'
version = '0.2.3'
description = 'This is an autogenerated Java SDK for OpenFGA. It provides a wrapper around the [OpenFGA API definition](https://openfga.dev/api).'
url = 'https://openfga.dev'
licenses {
Expand Down
103 changes: 103 additions & 0 deletions src/main/java/dev/openfga/sdk/api/client/ClientBatchCheckResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* OpenFGA
* A high performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.
*
* The version of the OpenAPI document: 0.1
* Contact: [email protected]
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package dev.openfga.sdk.api.client;

import dev.openfga.sdk.api.model.CheckResponse;
import dev.openfga.sdk.errors.FgaError;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

public class ClientBatchCheckResponse extends CheckResponse {
private final ClientCheckRequest request;
private final Throwable throwable;
private final Integer statusCode;
private final Map<String, List<String>> headers;
private final String rawResponse;

public ClientBatchCheckResponse(
ClientCheckRequest request, ClientCheckResponse clientCheckResponse, Throwable throwable) {
this.request = request;
this.throwable = throwable;

if (clientCheckResponse != null) {
this.statusCode = clientCheckResponse.getStatusCode();
this.headers = clientCheckResponse.getHeaders();
this.rawResponse = clientCheckResponse.getRawResponse();
this.setAllowed(clientCheckResponse.getAllowed());
this.setResolution(clientCheckResponse.getResolution());
} else if (throwable instanceof FgaError) {
FgaError error = (FgaError) throwable;
this.statusCode = error.getStatusCode();
this.headers = error.getResponseHeaders().map();
this.rawResponse = error.getResponseData();
} else {
// Should be unreachable, but required for type completion
this.statusCode = null;
this.headers = null;
this.rawResponse = null;
}
}

public ClientCheckRequest getRequest() {
return request;
}

/**
* Returns the result of the check.
* <p>
* If the HTTP request was unsuccessful, this result will be null. If this is the case, you can examine the
* original request with {@link ClientBatchCheckResponse#getRequest()} and the exception with
* {@link ClientBatchCheckResponse#getThrowable()}.
*
* @return the check result. Is null if the HTTP request was unsuccessful.
*/
@Override
public Boolean getAllowed() {
return super.getAllowed();
}

/**
* Returns the caught exception if the HTTP request was unsuccessful.
* <p>
* If the HTTP request was unsuccessful, this result will be null. If this is the case, you can examine the
* original request with {@link ClientBatchCheckResponse#getRequest()} and the exception with
* {@link ClientBatchCheckResponse#getThrowable()}.
*
* @return the caught exception. Is null if the HTTP request was successful.
*/
public Throwable getThrowable() {
return throwable;
}

public int getStatusCode() {
return statusCode;
}

public Map<String, List<String>> getHeaders() {
return headers;
}

public String getRawResponse() {
return rawResponse;
}

public String getRelation() {
return request == null ? null : request.getRelation();
}

public static BiFunction<ClientCheckResponse, Throwable, ClientBatchCheckResponse> asyncHandler(
ClientCheckRequest request) {
return (response, throwable) -> new ClientBatchCheckResponse(request, response, throwable);
}
}
12 changes: 12 additions & 0 deletions src/main/java/dev/openfga/sdk/api/client/ClientCheckRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@

package dev.openfga.sdk.api.client;

import java.util.List;

public class ClientCheckRequest {
private String user;
private String relation;
private String _object;
private List<ClientTupleKey> contextualTuples;

public ClientCheckRequest _object(String _object) {
this._object = _object;
Expand Down Expand Up @@ -55,4 +58,13 @@ public ClientCheckRequest user(String user) {
public String getUser() {
return user;
}

public ClientCheckRequest contextualTuples(List<ClientTupleKey> contextualTuples) {
this.contextualTuples = contextualTuples;
return this;
}

public List<ClientTupleKey> getContextualTuples() {
return contextualTuples;
}
}
Loading

0 comments on commit 6d6a615

Please sign in to comment.