Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client): implement batchCheck, listRelations, and non-transaction write #32

Merged
merged 15 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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);
}
}
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