Skip to content

Commit

Permalink
feat(java-sdk)!: support server-side batch check endpoint (#475)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmyjames authored Feb 5, 2025
2 parents a17d052 + a6f32e2 commit aace657
Show file tree
Hide file tree
Showing 15 changed files with 657 additions and 137 deletions.
5 changes: 5 additions & 0 deletions config/clients/java/CHANGELOG.md.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

## [Unreleased](https://github.com/openfga/java-sdk/compare/v{{packageVersion}}...HEAD)

- feat!: add support for server-side `BatchCheck` method
- feat: add support for `start_time` parameter in `ReadChanges` endpoint

BREAKING CHANGES:

- Usage of the existing `batchCheck` method should now use the `clientBatchCheck` method.

## v0.7.2

### [0.7.2](https://github.com/openfga/java-sdk/compare/v0.7.1...v0.7.2) (2024-12-18)
Expand Down
24 changes: 24 additions & 0 deletions config/clients/java/config.overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,26 @@
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/ClientAssertion.java",
"templateType": "SupportingFiles"
},
"client-ClientBatchCheckClientResponse.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/model/ClientBatchCheckClientResponse.java",
"templateType": "SupportingFiles"
},
"client-ClientBatchCheckItem.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/model/ClientBatchCheckItem.java",
"templateType": "SupportingFiles"
},
"client-ClientBatchCheckRequest.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/model/ClientBatchCheckRequest.java",
"templateType": "SupportingFiles"
},
"client-ClientBatchCheckResponse.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/model/ClientBatchCheckResponse.java",
"templateType": "SupportingFiles"
},
"client-ClientBatchCheckSingleResponse.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/model/ClientBatchCheckSingleResponse.java",
"templateType": "SupportingFiles"
},
"client-ClientCheckRequest.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/model/ClientCheckRequest.java",
"templateType": "SupportingFiles"
Expand Down Expand Up @@ -221,6 +237,10 @@
"destinationFilename": "src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java",
"templateType": "SupportingFiles"
},
"config-ClientBatchCheckClientOptions.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/configuration/ClientBatchCheckClientOptions.java",
"templateType": "SupportingFiles"
},
"config-ClientBatchCheckOptions.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/configuration/ClientBatchCheckOptions.java",
"templateType": "SupportingFiles"
Expand Down Expand Up @@ -373,6 +393,10 @@
"destinationFilename": "src/main/java/dev/openfga/sdk/errors/FgaInvalidParameterException.java",
"templateType": "SupportingFiles"
},
"errors-FgaValidationError.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/errors/FgaValidationError.java",
"templateType": "SupportingFiles"
},
"errors-HttpStatusCode.java.mustache": {
"destinationFilename": "src/main/java/dev/openfga/sdk/errors/HttpStatusCode.java",
"templateType": "SupportingFiles"
Expand Down
4 changes: 2 additions & 2 deletions config/clients/java/template/README_calling_api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ var response = fgaClient.check(request, options).get();
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.
If 429s or 5xxs are encountered, the underlying check will retry up to {{defaultMaxRetry}} times before giving up.

> Passing `ClientBatchCheckOptions` is optional. All fields of `ClientBatchCheckOptions` are optional.
> Passing `ClientBatchCheckClientOptions` is optional. All fields of `ClientBatchCheckClientOptions` are optional.

```java
var request = List.of(
Expand Down Expand Up @@ -392,7 +392,7 @@ var request = List.of(
.relation("deleter")
._object("document:0192ab2a-d83f-756d-9397-c5ed9f3cb69a")
);
var options = new ClientBatchCheckOptions()
var options = new ClientBatchCheckClientOptions()
.additionalHeaders(Map.of("Some-Http-Header", "Some value"))
// You can rely on the model id set in the configuration or override it for this specific request
.authorizationModelId("01GXSA8YR785C4FYS3C0RTG7B1")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{{>licenseInfo}}
package {{clientPackage}}.model;

import {{modelPackage}}.CheckResponse;
import {{errorsPackage}}.FgaError;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

public class ClientBatchCheckClientResponse 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 ClientBatchCheckClientResponse(
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 ClientBatchCheckClientResponse#getRequest()} and the exception with
* {@link ClientBatchCheckClientResponse#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 ClientBatchCheckClientResponse#getRequest()} and the exception with
* {@link ClientBatchCheckClientResponse#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, ClientBatchCheckClientResponse> asyncHandler(
ClientCheckRequest request) {
return (response, throwable) -> new ClientBatchCheckClientResponse(request, response, throwable);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{{>licenseInfo}}
package {{invokerPackage}}.model;

import java.util.List;

public class ClientBatchCheckItem {
private String user;
private String relation;
private String _object;
private List<ClientTupleKey> contextualTuples;
private Object context;
private String correlationId;
public ClientBatchCheckItem user(String user) {
this.user = user;
return this;
}

public String getUser() {
return user;
}

public ClientBatchCheckItem relation(String relation) {
this.relation = relation;
return this;
}

public String getRelation() {
return relation;
}

public ClientBatchCheckItem _object(String _object) {
this._object = _object;
return this;
}

public String getObject() {
return _object;
}

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

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

public ClientBatchCheckItem context(Object context) {
this.context = context;
return this;
}

public Object getContext() {
return context;
}

public ClientBatchCheckItem correlationId(String correlationId) {
this.correlationId = correlationId;
return this;
}

public String getCorrelationId() {
return correlationId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{>licenseInfo}}
package {{invokerPackage}}.model;

import java.util.List;

public class ClientBatchCheckRequest {
private List<ClientBatchCheckItem> checks;
public static ClientBatchCheckRequest ofChecks(List<ClientBatchCheckItem> checks) {
return new ClientBatchCheckRequest().checks(checks);
}

public ClientBatchCheckRequest checks(List<ClientBatchCheckItem> checks) {
this.checks = checks;
return this;
}

public List<ClientBatchCheckItem> getChecks() {
return checks;
}
}
Original file line number Diff line number Diff line change
@@ -1,92 +1,16 @@
{{>licenseInfo}}
package {{clientPackage}}.model;

import {{modelPackage}}.CheckResponse;
import {{errorsPackage}}.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 class ClientBatchCheckResponse {
private final List<ClientBatchCheckSingleResponse> result;
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 ClientBatchCheckResponse(List<ClientBatchCheckSingleResponse> result) {
this.result = result;
}

public static BiFunction<ClientCheckResponse, Throwable, ClientBatchCheckResponse> asyncHandler(
ClientCheckRequest request) {
return (response, throwable) -> new ClientBatchCheckResponse(request, response, throwable);
public List<ClientBatchCheckSingleResponse> getResult() {
return result;
}
}
}
Loading

0 comments on commit aace657

Please sign in to comment.