Skip to content

Commit

Permalink
refactor(java-sdk): use common functions in OpenFgaApi, update some v…
Browse files Browse the repository at this point in the history
…alidation exceptions (#253)
  • Loading branch information
rhamzeh authored Dec 15, 2023
2 parents 8bbf9d6 + fe22947 commit f5c6e5b
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 501 deletions.
13 changes: 13 additions & 0 deletions config/clients/java/CHANGELOG.md.mustache
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## v0.3.0

### [0.3.0](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v0.2.3...v0.3.0) (2023-12-13)

- feat: support for Conditions
- feat: standard OpenFGA headers have been added to Write, BatchCheck, and ListRelations calls
- feat: apiTokenIssuer has been expanded to support arbitrary http and https URLs. previously it supported
only configuring a hostname - thanks @le-yams
- feat: allow setting and overriding http headers
- [BREAKING] chore: use latest API interfaces
- chore: dependency updates
- refactor: abstract common functionality; update validation and exception types

## v0.2.3

### [0.2.3](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v0.2.2...v0.2.3) (2023-11-21)
Expand Down
6 changes: 5 additions & 1 deletion config/clients/java/config.overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"gitRepoId": "java-sdk",
"artifactId": "openfga-sdk",
"groupId": "dev.openfga",
"packageVersion": "0.2.3",
"packageVersion": "0.3.0",
"apiPackage": "dev.openfga.sdk.api",
"authPackage": "dev.openfga.sdk.api.auth",
"clientPackage": "dev.openfga.sdk.api.client",
Expand Down Expand Up @@ -363,6 +363,10 @@
"destinationFilename": "src/test/java/dev/openfga/sdk/util/StringUtilTest.java",
"templateType": "SupportingFiles"
},
"util-Validation.java.mustache" : {
"destinationFilename": "src/main/java/dev/openfga/sdk/util/Validation.java",
"templateType": "SupportingFiles"
},
"libraries/native/apiException.mustache" : {
"destinationFilename": "src/main/java/dev/openfga/sdk/errors/ApiException.java",
"templateType": "SupportingFiles"
Expand Down
215 changes: 88 additions & 127 deletions config/clients/java/template/OpenFgaApiTest.java.mustache

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions config/clients/java/template/Pair.mustache
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{{>licenseInfo}}
package {{utilPackage}};

import static {{clientPackage}}.ApiClient.urlEncode;
import static {{utilPackage}}.StringUtil.isNullOrWhitespace;

import java.util.Optional;

public class Pair {
private String name = "";
private String value = "";
Expand All @@ -10,6 +15,17 @@ public class Pair {
setValue(value);
}

public static Optional<Pair> of(String name, Object value) {
if (isNullOrWhitespace(name) || value == null) {
return Optional.empty();
}
return Optional.of(new Pair(name, value.toString()));
}

public String asQueryStringPair() {
return urlEncode(name) + "=" + urlEncode(value);
}

private void setName(String name) {
if (!isValidString(name)) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package {{invokerPackage}};

import static {{utilPackage}}.StringUtil.isNullOrWhitespace;
import static {{utilPackage}}.Validation.assertParamExists;

import {{clientPackage}}.ApiResponse;
import {{configPackage}}.Configuration;
Expand Down Expand Up @@ -30,9 +31,7 @@ public class HttpRequestAttempt<T> {
public HttpRequestAttempt(
HttpRequest request, String name, Class<T> clazz, ApiClient apiClient, Configuration configuration)
throws FgaInvalidParameterException {
if (configuration.getMaxRetries() == null) {
throw new FgaInvalidParameterException("maxRetries", "Configuration");
}
assertParamExists(configuration.getMaxRetries(), "maxRetries", "Configuration");
this.apiClient = apiClient;
this.configuration = configuration;
this.name = name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ public class OpenFgaClientTest {
ExecutionException.class, () -> fga.createStore(null).get());
// Then
var exception = assertInstanceOf(ApiException.class, execException.getCause());
assertEquals("Missing the required parameter 'body' when calling createStore", exception.getMessage());
var exception = assertInstanceOf(FgaInvalidParameterException.class, execException.getCause());
assertEquals("Required parameter body was invalid when calling createStore.", exception.getMessage());
}

@Test
Expand Down Expand Up @@ -708,9 +708,9 @@ public class OpenFgaClientTest {
.get());
// Then
var exception = assertInstanceOf(ApiException.class, execException.getCause());
var exception = assertInstanceOf(FgaInvalidParameterException.class, execException.getCause());
assertEquals(
"Missing the required parameter 'body' when calling writeAuthorizationModel", exception.getMessage());
"Required parameter body was invalid when calling writeAuthorizationModel.", exception.getMessage());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{>licenseInfo}}
package {{configPackage}};

import static {{utilPackage}}.StringUtil.isNullOrWhitespace;
import static {{utilPackage}}.Validation.assertParamExists;

import {{errorsPackage}}.FgaInvalidParameterException;
import java.time.Duration;
Expand All @@ -11,15 +11,11 @@ public class ClientConfiguration extends Configuration {
private String authorizationModelId;
public void assertValidStoreId() throws FgaInvalidParameterException {
if (isNullOrWhitespace(storeId)) {
throw new FgaInvalidParameterException("storeId", "ClientConfiguration");
}
assertParamExists(storeId, "storeId", "ClientConfiguration");
}

public void assertValidAuthorizationModelId() throws FgaInvalidParameterException {
if (isNullOrWhitespace(authorizationModelId)) {
throw new FgaInvalidParameterException("authorizationModelId", "ClientConfiguration");
}
assertParamExists(authorizationModelId, "authorizationModelId", "ClientConfiguration");
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{>licenseInfo}}
package {{configPackage}};

import static {{utilPackage}}.StringUtil.isNullOrWhitespace;
import static {{utilPackage}}.Validation.assertParamExists;

import {{errorsPackage}}.FgaInvalidParameterException;

Expand All @@ -19,21 +19,10 @@ public class ClientCredentials {
}

public void assertValid() throws FgaInvalidParameterException {
if (isNullOrWhitespace(clientId)) {
throw new FgaInvalidParameterException("clientId", "ClientCredentials");
}

if (isNullOrWhitespace(clientSecret)) {
throw new FgaInvalidParameterException("clientSecret", "ClientCredentials");
}

if (isNullOrWhitespace(apiTokenIssuer)) {
throw new FgaInvalidParameterException("apiTokenIssuer", "ClientCredentials");
}

if (isNullOrWhitespace(apiAudience)) {
throw new FgaInvalidParameterException("apiAudience", "ClientCredentials");
}
assertParamExists(clientId, "clientId", "ClientCredentials");
assertParamExists(clientSecret, "clientSecret", "ClientCredentials");
assertParamExists(apiTokenIssuer, "apiTokenIssuer", "ClientCredentials");
assertParamExists(apiAudience, "apiAudience", "ClientCredentials");
}

public String getClientId() {
Expand Down
10 changes: 3 additions & 7 deletions config/clients/java/template/config-Configuration.java.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package {{configPackage}};

import static {{utilPackage}}.StringUtil.isNullOrWhitespace;
import static {{utilPackage}}.Validation.assertParamExists;

import {{errorsPackage}}.FgaInvalidParameterException;
import java.net.MalformedURLException;
Expand Down Expand Up @@ -57,13 +58,8 @@ public class Configuration implements BaseConfiguration {
throw new FgaInvalidParameterException("apiUrl", "Configuration", cause);
}

if (isNullOrWhitespace(uri.getScheme())) {
throw new FgaInvalidParameterException("scheme", "Configuration");
}

if (isNullOrWhitespace(uri.getHost())) {
throw new FgaInvalidParameterException("hostname", "Configuration");
}
assertParamExists(uri.getScheme(), "scheme", "Configuration");
assertParamExists(uri.getHost(), "hostname", "Configuration");
}

if (credentials != null) {
Expand Down
74 changes: 0 additions & 74 deletions config/clients/java/template/libraries/native/ApiClient.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -137,80 +137,6 @@ public class ApiClient {
return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20");
}

/**
* Convert a URL query name/value parameter to a list of encoded {@link Pair}
* objects.
*
* <p>The value can be null, in which case an empty list is returned.</p>
*
* @param name The query name parameter.
* @param value The query value, which may not be a collection but may be
* null.
* @return A singleton list of the {@link Pair} objects representing the input
* parameters, which is encoded for use in a URL. If the value is null, an
* empty list is returned.
*/
public static List<Pair> parameterToPairs(String name, Object value) {
if (name == null || name.isEmpty() || value == null) {
return Collections.emptyList();
}
return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value))));
}

/**
* Convert a URL query name/collection parameter to a list of encoded
* {@link Pair} objects.
*
* @param collectionFormat The swagger collectionFormat string (csv, tsv, etc).
* @param name The query name parameter.
* @param values A collection of values for the given query name, which may be
* null.
* @return A list of {@link Pair} objects representing the input parameters,
* which is encoded for use in a URL. If the values collection is null, an
* empty list is returned.
*/
public static List<Pair> parameterToPairs(
String collectionFormat, String name, Collection<?> values) {
if (name == null || name.isEmpty() || values == null || values.isEmpty()) {
return Collections.emptyList();
}

// get the collection format (default: csv)
String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat;

// create the params based on the collection format
if ("multi".equals(format)) {
return values.stream()
.map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value))))
.collect(Collectors.toList());
}

String delimiter;
switch(format) {
case "csv":
delimiter = urlEncode(",");
break;
case "ssv":
delimiter = urlEncode(" ");
break;
case "tsv":
delimiter = urlEncode("\t");
break;
case "pipes":
delimiter = urlEncode("|");
break;
default:
throw new IllegalArgumentException("Illegal collection format: " + collectionFormat);
}

StringJoiner joiner = new StringJoiner(delimiter);
for (Object value : values) {
joiner.add(urlEncode(valueToString(value)));
}

return Collections.singletonList(new Pair(urlEncode(name), joiner.toString()));
}

protected ObjectMapper createDefaultObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Expand Down
Loading

0 comments on commit f5c6e5b

Please sign in to comment.