From 58c2993f12d3f5ae01a76bb4986f9d9f900ad3d9 Mon Sep 17 00:00:00 2001 From: "J.R. Hill" Date: Wed, 6 Dec 2023 09:44:37 -0800 Subject: [PATCH] feat: add ABAC support --- .github/dependabot.yaml | 18 ++ .openapi-generator/FILES | 39 ++- README.md | 50 ++-- docs/Assertion.md | 2 +- docs/AuthorizationModel.md | 5 +- docs/CheckRequest.md | 3 +- docs/CheckRequestTupleKey.md | 15 ++ docs/Computed.md | 2 +- docs/Condition.md | 15 ++ docs/ConditionParamTypeRef.md | 14 ++ docs/CreateStoreResponse.md | 8 +- docs/ExpandRequest.md | 2 +- docs/ExpandRequestTupleKey.md | 14 ++ docs/GetStoreResponse.md | 8 +- docs/ListObjectsRequest.md | 1 + docs/ListObjectsResponse.md | 2 +- docs/ListStoresResponse.md | 4 +- docs/Node.md | 2 +- docs/Nodes.md | 2 +- docs/NullValue.md | 13 + docs/OpenFgaApi.md | 16 +- docs/ReadAssertionsResponse.md | 2 +- docs/ReadAuthorizationModelsResponse.md | 2 +- docs/ReadChangesResponse.md | 2 +- docs/ReadRequest.md | 2 +- docs/ReadRequestTupleKey.md | 15 ++ docs/ReadResponse.md | 4 +- docs/RelationReference.md | 1 + docs/RelationshipCondition.md | 14 ++ docs/Store.md | 10 +- docs/Tuple.md | 4 +- docs/TupleChange.md | 6 +- docs/TupleKey.md | 7 +- docs/TupleKeyWithoutCondition.md | 15 ++ docs/TupleToUserset.md | 4 +- docs/TypeName.md | 35 +++ docs/Users.md | 2 +- docs/UsersetTreeDifference.md | 4 +- docs/UsersetTreeTupleToUserset.md | 4 +- docs/Usersets.md | 2 +- docs/WriteAuthorizationModelRequest.md | 3 +- docs/WriteAuthorizationModelResponse.md | 2 +- docs/WriteRequest.md | 4 +- docs/WriteRequestDeletes.md | 13 + docs/{TupleKeys.md => WriteRequestWrites.md} | 2 +- .../java/dev/openfga/sdk/api/OpenFgaApi.java | 16 +- .../sdk/api/client/ClientAssertion.java | 4 +- .../sdk/api/client/ClientCheckRequest.java | 11 +- .../api/client/ClientListObjectsRequest.java | 6 +- .../client/ClientRelationshipCondition.java | 42 ++++ .../sdk/api/client/ClientTupleKey.java | 53 ++-- .../client/ClientTupleKeyWithCondition.java | 76 ++++++ .../sdk/api/client/ClientWriteRequest.java | 8 +- .../sdk/api/client/HttpRequestAttempt.java | 44 ++++ .../openfga/sdk/api/client/OpenFgaClient.java | 58 +++-- .../dev/openfga/sdk/api/model/Assertion.java | 8 +- .../sdk/api/model/AuthorizationModel.java | 73 +++++- .../openfga/sdk/api/model/CheckRequest.java | 52 +++- .../sdk/api/model/CheckRequestTupleKey.java | 217 ++++++++++++++++ .../dev/openfga/sdk/api/model/Computed.java | 6 +- .../dev/openfga/sdk/api/model/Condition.java | 231 ++++++++++++++++++ .../sdk/api/model/ConditionParamTypeRef.java | 193 +++++++++++++++ .../sdk/api/model/CreateStoreResponse.java | 24 +- .../openfga/sdk/api/model/ExpandRequest.java | 8 +- .../sdk/api/model/ExpandRequestTupleKey.java | 176 +++++++++++++ .../sdk/api/model/GetStoreResponse.java | 24 +- .../sdk/api/model/ListObjectsRequest.java | 44 +++- .../sdk/api/model/ListObjectsResponse.java | 6 +- .../sdk/api/model/ListStoresResponse.java | 12 +- .../java/dev/openfga/sdk/api/model/Node.java | 6 +- .../java/dev/openfga/sdk/api/model/Nodes.java | 6 +- .../dev/openfga/sdk/api/model/NullValue.java | 65 +++++ .../sdk/api/model/ReadAssertionsResponse.java | 6 +- .../ReadAuthorizationModelsResponse.java | 6 +- .../sdk/api/model/ReadChangesResponse.java | 6 +- .../openfga/sdk/api/model/ReadRequest.java | 8 +- .../sdk/api/model/ReadRequestTupleKey.java | 217 ++++++++++++++++ .../openfga/sdk/api/model/ReadResponse.java | 12 +- .../sdk/api/model/RelationReference.java | 44 +++- .../sdk/api/model/RelationshipCondition.java | 176 +++++++++++++ .../java/dev/openfga/sdk/api/model/Store.java | 30 +-- .../java/dev/openfga/sdk/api/model/Tuple.java | 12 +- .../openfga/sdk/api/model/TupleChange.java | 18 +- .../dev/openfga/sdk/api/model/TupleKey.java | 125 ++++++---- .../api/model/TupleKeyWithoutCondition.java | 217 ++++++++++++++++ .../openfga/sdk/api/model/TupleToUserset.java | 12 +- .../dev/openfga/sdk/api/model/TypeName.java | 87 +++++++ .../java/dev/openfga/sdk/api/model/Users.java | 6 +- .../sdk/api/model/UsersetTreeDifference.java | 12 +- .../api/model/UsersetTreeTupleToUserset.java | 12 +- .../dev/openfga/sdk/api/model/Usersets.java | 6 +- .../model/WriteAuthorizationModelRequest.java | 67 ++++- .../WriteAuthorizationModelResponse.java | 6 +- .../openfga/sdk/api/model/WriteRequest.java | 16 +- .../sdk/api/model/WriteRequestDeletes.java | 154 ++++++++++++ ...TupleKeys.java => WriteRequestWrites.java} | 20 +- .../sdk/api/OpenFgaApiIntegrationTest.java | 41 ++-- .../client/OpenFgaClientIntegrationTest.java | 28 ++- .../dev/openfga/sdk/api/OpenFgaApiTest.java | 208 +++++++++++++--- .../sdk/api/auth/OAuth2ClientTest.java | 3 + .../sdk/api/client/OpenFgaClientTest.java | 180 ++++++++------ .../sdk/api/model/AuthorizationModelTest.java | 8 + .../sdk/api/model/CheckRequestTest.java | 8 + .../api/model/CheckRequestTupleKeyTest.java | 54 ++++ .../api/model/ConditionParamTypeRefTest.java | 46 ++++ .../openfga/sdk/api/model/ConditionTest.java | 54 ++++ .../api/model/ExpandRequestTupleKeyTest.java | 46 ++++ .../sdk/api/model/ListObjectsRequestTest.java | 8 + .../openfga/sdk/api/model/NullValueTest.java | 28 +++ .../api/model/ReadRequestTupleKeyTest.java | 54 ++++ .../sdk/api/model/RelationReferenceTest.java | 8 + .../api/model/RelationshipConditionTest.java | 46 ++++ .../openfga/sdk/api/model/TupleKeyTest.java | 20 +- .../model/TupleKeyWithoutConditionTest.java | 54 ++++ .../openfga/sdk/api/model/TypeNameTest.java | 28 +++ .../WriteAuthorizationModelRequestTest.java | 8 + .../api/model/WriteRequestDeletesTest.java | 38 +++ ...sTest.java => WriteRequestWritesTest.java} | 12 +- 118 files changed, 3615 insertions(+), 503 deletions(-) create mode 100644 .github/dependabot.yaml create mode 100644 docs/CheckRequestTupleKey.md create mode 100644 docs/Condition.md create mode 100644 docs/ConditionParamTypeRef.md create mode 100644 docs/ExpandRequestTupleKey.md create mode 100644 docs/NullValue.md create mode 100644 docs/ReadRequestTupleKey.md create mode 100644 docs/RelationshipCondition.md create mode 100644 docs/TupleKeyWithoutCondition.md create mode 100644 docs/TypeName.md create mode 100644 docs/WriteRequestDeletes.md rename docs/{TupleKeys.md => WriteRequestWrites.md} (89%) create mode 100644 src/main/java/dev/openfga/sdk/api/client/ClientRelationshipCondition.java create mode 100644 src/main/java/dev/openfga/sdk/api/client/ClientTupleKeyWithCondition.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/CheckRequestTupleKey.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/Condition.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/ConditionParamTypeRef.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/ExpandRequestTupleKey.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/NullValue.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/ReadRequestTupleKey.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/RelationshipCondition.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/TupleKeyWithoutCondition.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/TypeName.java create mode 100644 src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java rename src/main/java/dev/openfga/sdk/api/model/{TupleKeys.java => WriteRequestWrites.java} (87%) create mode 100644 src/test/java/dev/openfga/sdk/api/model/CheckRequestTupleKeyTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/ConditionParamTypeRefTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/ConditionTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/ExpandRequestTupleKeyTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/NullValueTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/ReadRequestTupleKeyTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/RelationshipConditionTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/TupleKeyWithoutConditionTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/TypeNameTest.java create mode 100644 src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java rename src/test/java/dev/openfga/sdk/api/model/{TupleKeysTest.java => WriteRequestWritesTest.java} (70%) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..5a916f6 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,18 @@ +version: 2 +updates: + - package-ecosystem: "gradle" + directory: "/" + schedule: + interval: "monthly" + groups: + dependencies: + patterns: + - "*" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + groups: + dependencies: + patterns: + - "*" diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 66cb427..72db90d 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -2,6 +2,7 @@ .github/CODEOWNERS .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/feature_request.md +.github/dependabot.yaml .github/workflows/main.yml .github/workflows/semgrep.yaml .gitignore @@ -17,14 +18,18 @@ docs/Any.md docs/Assertion.md docs/AuthorizationModel.md docs/CheckRequest.md +docs/CheckRequestTupleKey.md docs/CheckResponse.md docs/Computed.md +docs/Condition.md +docs/ConditionParamTypeRef.md docs/ContextualTupleKeys.md docs/CreateStoreRequest.md docs/CreateStoreResponse.md docs/Difference.md docs/ErrorCode.md docs/ExpandRequest.md +docs/ExpandRequestTupleKey.md docs/ExpandResponse.md docs/GetStoreResponse.md docs/InternalErrorCode.md @@ -37,6 +42,7 @@ docs/Metadata.md docs/Node.md docs/Nodes.md docs/NotFoundErrorCode.md +docs/NullValue.md docs/ObjectRelation.md docs/OpenFgaApi.md docs/PathUnknownErrorMessageResponse.md @@ -45,18 +51,21 @@ docs/ReadAuthorizationModelResponse.md docs/ReadAuthorizationModelsResponse.md docs/ReadChangesResponse.md docs/ReadRequest.md +docs/ReadRequestTupleKey.md docs/ReadResponse.md docs/RelationMetadata.md docs/RelationReference.md +docs/RelationshipCondition.md docs/Status.md docs/Store.md docs/Tuple.md docs/TupleChange.md docs/TupleKey.md -docs/TupleKeys.md +docs/TupleKeyWithoutCondition.md docs/TupleOperation.md docs/TupleToUserset.md docs/TypeDefinition.md +docs/TypeName.md docs/Users.md docs/Userset.md docs/UsersetTree.md @@ -68,6 +77,8 @@ docs/WriteAssertionsRequest.md docs/WriteAuthorizationModelRequest.md docs/WriteAuthorizationModelResponse.md docs/WriteRequest.md +docs/WriteRequestDeletes.md +docs/WriteRequestWrites.md gradle.properties gradle/wrapper/gradle-wrapper.jar gradle/wrapper/gradle-wrapper.properties @@ -102,7 +113,9 @@ src/main/java/dev/openfga/sdk/api/client/ClientReadAuthorizationModelsResponse.j src/main/java/dev/openfga/sdk/api/client/ClientReadChangesResponse.java src/main/java/dev/openfga/sdk/api/client/ClientReadRequest.java src/main/java/dev/openfga/sdk/api/client/ClientReadResponse.java +src/main/java/dev/openfga/sdk/api/client/ClientRelationshipCondition.java src/main/java/dev/openfga/sdk/api/client/ClientTupleKey.java +src/main/java/dev/openfga/sdk/api/client/ClientTupleKeyWithCondition.java src/main/java/dev/openfga/sdk/api/client/ClientWriteAssertionsResponse.java src/main/java/dev/openfga/sdk/api/client/ClientWriteAuthorizationModelResponse.java src/main/java/dev/openfga/sdk/api/client/ClientWriteRequest.java @@ -135,14 +148,18 @@ src/main/java/dev/openfga/sdk/api/model/Any.java src/main/java/dev/openfga/sdk/api/model/Assertion.java src/main/java/dev/openfga/sdk/api/model/AuthorizationModel.java src/main/java/dev/openfga/sdk/api/model/CheckRequest.java +src/main/java/dev/openfga/sdk/api/model/CheckRequestTupleKey.java src/main/java/dev/openfga/sdk/api/model/CheckResponse.java src/main/java/dev/openfga/sdk/api/model/Computed.java +src/main/java/dev/openfga/sdk/api/model/Condition.java +src/main/java/dev/openfga/sdk/api/model/ConditionParamTypeRef.java src/main/java/dev/openfga/sdk/api/model/ContextualTupleKeys.java src/main/java/dev/openfga/sdk/api/model/CreateStoreRequest.java src/main/java/dev/openfga/sdk/api/model/CreateStoreResponse.java src/main/java/dev/openfga/sdk/api/model/Difference.java src/main/java/dev/openfga/sdk/api/model/ErrorCode.java src/main/java/dev/openfga/sdk/api/model/ExpandRequest.java +src/main/java/dev/openfga/sdk/api/model/ExpandRequestTupleKey.java src/main/java/dev/openfga/sdk/api/model/ExpandResponse.java src/main/java/dev/openfga/sdk/api/model/GetStoreResponse.java src/main/java/dev/openfga/sdk/api/model/InternalErrorCode.java @@ -155,6 +172,7 @@ src/main/java/dev/openfga/sdk/api/model/Metadata.java src/main/java/dev/openfga/sdk/api/model/Node.java src/main/java/dev/openfga/sdk/api/model/Nodes.java src/main/java/dev/openfga/sdk/api/model/NotFoundErrorCode.java +src/main/java/dev/openfga/sdk/api/model/NullValue.java src/main/java/dev/openfga/sdk/api/model/ObjectRelation.java src/main/java/dev/openfga/sdk/api/model/PathUnknownErrorMessageResponse.java src/main/java/dev/openfga/sdk/api/model/ReadAssertionsResponse.java @@ -162,18 +180,21 @@ src/main/java/dev/openfga/sdk/api/model/ReadAuthorizationModelResponse.java src/main/java/dev/openfga/sdk/api/model/ReadAuthorizationModelsResponse.java src/main/java/dev/openfga/sdk/api/model/ReadChangesResponse.java src/main/java/dev/openfga/sdk/api/model/ReadRequest.java +src/main/java/dev/openfga/sdk/api/model/ReadRequestTupleKey.java src/main/java/dev/openfga/sdk/api/model/ReadResponse.java src/main/java/dev/openfga/sdk/api/model/RelationMetadata.java src/main/java/dev/openfga/sdk/api/model/RelationReference.java +src/main/java/dev/openfga/sdk/api/model/RelationshipCondition.java src/main/java/dev/openfga/sdk/api/model/Status.java src/main/java/dev/openfga/sdk/api/model/Store.java src/main/java/dev/openfga/sdk/api/model/Tuple.java src/main/java/dev/openfga/sdk/api/model/TupleChange.java src/main/java/dev/openfga/sdk/api/model/TupleKey.java -src/main/java/dev/openfga/sdk/api/model/TupleKeys.java +src/main/java/dev/openfga/sdk/api/model/TupleKeyWithoutCondition.java src/main/java/dev/openfga/sdk/api/model/TupleOperation.java src/main/java/dev/openfga/sdk/api/model/TupleToUserset.java src/main/java/dev/openfga/sdk/api/model/TypeDefinition.java +src/main/java/dev/openfga/sdk/api/model/TypeName.java src/main/java/dev/openfga/sdk/api/model/Users.java src/main/java/dev/openfga/sdk/api/model/Userset.java src/main/java/dev/openfga/sdk/api/model/UsersetTree.java @@ -185,6 +206,8 @@ src/main/java/dev/openfga/sdk/api/model/WriteAssertionsRequest.java src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java src/main/java/dev/openfga/sdk/api/model/WriteRequest.java +src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java +src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java src/main/java/dev/openfga/sdk/errors/ApiException.java src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java @@ -209,14 +232,18 @@ src/test/java/dev/openfga/sdk/api/model/AnyTest.java src/test/java/dev/openfga/sdk/api/model/AssertionTest.java src/test/java/dev/openfga/sdk/api/model/AuthorizationModelTest.java src/test/java/dev/openfga/sdk/api/model/CheckRequestTest.java +src/test/java/dev/openfga/sdk/api/model/CheckRequestTupleKeyTest.java src/test/java/dev/openfga/sdk/api/model/CheckResponseTest.java src/test/java/dev/openfga/sdk/api/model/ComputedTest.java +src/test/java/dev/openfga/sdk/api/model/ConditionParamTypeRefTest.java +src/test/java/dev/openfga/sdk/api/model/ConditionTest.java src/test/java/dev/openfga/sdk/api/model/ContextualTupleKeysTest.java src/test/java/dev/openfga/sdk/api/model/CreateStoreRequestTest.java src/test/java/dev/openfga/sdk/api/model/CreateStoreResponseTest.java src/test/java/dev/openfga/sdk/api/model/DifferenceTest.java src/test/java/dev/openfga/sdk/api/model/ErrorCodeTest.java src/test/java/dev/openfga/sdk/api/model/ExpandRequestTest.java +src/test/java/dev/openfga/sdk/api/model/ExpandRequestTupleKeyTest.java src/test/java/dev/openfga/sdk/api/model/ExpandResponseTest.java src/test/java/dev/openfga/sdk/api/model/GetStoreResponseTest.java src/test/java/dev/openfga/sdk/api/model/InternalErrorCodeTest.java @@ -229,6 +256,7 @@ src/test/java/dev/openfga/sdk/api/model/MetadataTest.java src/test/java/dev/openfga/sdk/api/model/NodeTest.java src/test/java/dev/openfga/sdk/api/model/NodesTest.java src/test/java/dev/openfga/sdk/api/model/NotFoundErrorCodeTest.java +src/test/java/dev/openfga/sdk/api/model/NullValueTest.java src/test/java/dev/openfga/sdk/api/model/ObjectRelationTest.java src/test/java/dev/openfga/sdk/api/model/PathUnknownErrorMessageResponseTest.java src/test/java/dev/openfga/sdk/api/model/ReadAssertionsResponseTest.java @@ -236,18 +264,21 @@ src/test/java/dev/openfga/sdk/api/model/ReadAuthorizationModelResponseTest.java src/test/java/dev/openfga/sdk/api/model/ReadAuthorizationModelsResponseTest.java src/test/java/dev/openfga/sdk/api/model/ReadChangesResponseTest.java src/test/java/dev/openfga/sdk/api/model/ReadRequestTest.java +src/test/java/dev/openfga/sdk/api/model/ReadRequestTupleKeyTest.java src/test/java/dev/openfga/sdk/api/model/ReadResponseTest.java src/test/java/dev/openfga/sdk/api/model/RelationMetadataTest.java src/test/java/dev/openfga/sdk/api/model/RelationReferenceTest.java +src/test/java/dev/openfga/sdk/api/model/RelationshipConditionTest.java src/test/java/dev/openfga/sdk/api/model/StatusTest.java src/test/java/dev/openfga/sdk/api/model/StoreTest.java src/test/java/dev/openfga/sdk/api/model/TupleChangeTest.java src/test/java/dev/openfga/sdk/api/model/TupleKeyTest.java -src/test/java/dev/openfga/sdk/api/model/TupleKeysTest.java +src/test/java/dev/openfga/sdk/api/model/TupleKeyWithoutConditionTest.java src/test/java/dev/openfga/sdk/api/model/TupleOperationTest.java src/test/java/dev/openfga/sdk/api/model/TupleTest.java src/test/java/dev/openfga/sdk/api/model/TupleToUsersetTest.java src/test/java/dev/openfga/sdk/api/model/TypeDefinitionTest.java +src/test/java/dev/openfga/sdk/api/model/TypeNameTest.java src/test/java/dev/openfga/sdk/api/model/UsersTest.java src/test/java/dev/openfga/sdk/api/model/UsersetTest.java src/test/java/dev/openfga/sdk/api/model/UsersetTreeDifferenceTest.java @@ -258,5 +289,7 @@ src/test/java/dev/openfga/sdk/api/model/ValidationErrorMessageResponseTest.java src/test/java/dev/openfga/sdk/api/model/WriteAssertionsRequestTest.java src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequestTest.java src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponseTest.java +src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java src/test/java/dev/openfga/sdk/api/model/WriteRequestTest.java +src/test/java/dev/openfga/sdk/api/model/WriteRequestWritesTest.java src/test/java/dev/openfga/sdk/util/StringUtilTest.java diff --git a/README.md b/README.md index 2ad2a0a..8dd1010 100644 --- a/README.md +++ b/README.md @@ -129,9 +129,9 @@ import java.net.http.HttpClient; public class Example { public static void main(String[] args) throws Exception { var config = new ClientConfiguration() - .apiUrl(System.getenv("OPENFGA_API_URL")) // If not specified, will default to "https://localhost:8080" - .storeId(System.getenv("OPENFGA_STORE_ID")) // Not required when calling createStore() or listStores() - .authorizationModelId(System.getenv("OPENFGA_AUTHORIZATION_MODEL_ID")); // Optional, can be overridden per request + .apiUrl(System.getenv("FGA_API_URL")) // If not specified, will default to "https://localhost:8080" + .storeId(System.getenv("FGA_STORE_ID")) // Not required when calling createStore() or listStores() + .authorizationModelId(System.getenv("FGA_AUTHORIZATION_MODEL_ID")); // Optional, can be overridden per request var fgaClient = new OpenFgaClient(config); var response = fgaClient.readAuthorizationModels().get(); @@ -152,11 +152,11 @@ import java.net.http.HttpClient; public class Example { public static void main(String[] args) throws Exception { var config = new ClientConfiguration() - .apiUrl(System.getenv("OPENFGA_API_URL")) // If not specified, will default to "https://localhost:8080" - .storeId(System.getenv("OPENFGA_STORE_ID")) // Not required when calling createStore() or listStores() - .authorizationModelId(System.getenv("OPENFGA_AUTHORIZATION_MODEL_ID")) // Optional, can be overridden per request + .apiUrl(System.getenv("FGA_API_URL")) // If not specified, will default to "https://localhost:8080" + .storeId(System.getenv("FGA_STORE_ID")) // Not required when calling createStore() or listStores() + .authorizationModelId(System.getenv("FGA_AUTHORIZATION_MODEL_ID")) // Optional, can be overridden per request .credentials(new Credentials( - new ApiToken(System.getenv("OPENFGA_API_TOKEN")) // will be passed as the "Authorization: Bearer ${ApiToken}" request header + new ApiToken(System.getenv("FGA_API_TOKEN")) // will be passed as the "Authorization: Bearer ${ApiToken}" request header )); var fgaClient = new OpenFgaClient(config); @@ -178,15 +178,15 @@ import java.net.http.HttpClient; public class Example { public static void main(String[] args) throws Exception { var config = new ClientConfiguration() - .apiUrl(System.getenv("OPENFGA_API_URL")) // If not specified, will default to "https://localhost:8080" - .storeId(System.getenv("OPENFGA_STORE_ID")) // Not required when calling createStore() or listStores() - .authorizationModelId(System.getenv("OPENFGA_AUTHORIZATION_MODEL_ID")) // Optional, can be overridden per request + .apiUrl(System.getenv("FGA_API_URL")) // If not specified, will default to "https://localhost:8080" + .storeId(System.getenv("FGA_STORE_ID")) // Not required when calling createStore() or listStores() + .authorizationModelId(System.getenv("FGA_AUTHORIZATION_MODEL_ID")) // Optional, can be overridden per request .credentials(new Credentials( new ClientCredentials() - .apiTokenIssuer(System.getenv("OPENFGA_API_TOKEN_ISSUER")) - .apiAudience(System.getenv("OPENFGA_API_AUDIENCE")) - .clientId(System.getenv("OPENFGA_CLIENT_ID")) - .clientSecret(System.getenv("OPENFGA_CLIENT_SECRET")) + .apiTokenIssuer(System.getenv("FGA_API_TOKEN_ISSUER")) + .apiAudience(System.getenv("FGA_API_AUDIENCE")) + .clientId(System.getenv("FGA_CLIENT_ID")) + .clientSecret(System.getenv("FGA_CLIENT_SECRET")) )); var fgaClient = new OpenFgaClient(config); @@ -744,10 +744,16 @@ fgaClient.writeAssertions(assertions, options).get(); - [CheckRequest](https://github.com/openfga/java-sdk/blob/main/docs/CheckRequest.md) +- [CheckRequestTupleKey](https://github.com/openfga/java-sdk/blob/main/docs/CheckRequestTupleKey.md) + - [CheckResponse](https://github.com/openfga/java-sdk/blob/main/docs/CheckResponse.md) - [Computed](https://github.com/openfga/java-sdk/blob/main/docs/Computed.md) +- [Condition](https://github.com/openfga/java-sdk/blob/main/docs/Condition.md) + +- [ConditionParamTypeRef](https://github.com/openfga/java-sdk/blob/main/docs/ConditionParamTypeRef.md) + - [ContextualTupleKeys](https://github.com/openfga/java-sdk/blob/main/docs/ContextualTupleKeys.md) - [CreateStoreRequest](https://github.com/openfga/java-sdk/blob/main/docs/CreateStoreRequest.md) @@ -760,6 +766,8 @@ fgaClient.writeAssertions(assertions, options).get(); - [ExpandRequest](https://github.com/openfga/java-sdk/blob/main/docs/ExpandRequest.md) +- [ExpandRequestTupleKey](https://github.com/openfga/java-sdk/blob/main/docs/ExpandRequestTupleKey.md) + - [ExpandResponse](https://github.com/openfga/java-sdk/blob/main/docs/ExpandResponse.md) - [GetStoreResponse](https://github.com/openfga/java-sdk/blob/main/docs/GetStoreResponse.md) @@ -784,6 +792,8 @@ fgaClient.writeAssertions(assertions, options).get(); - [NotFoundErrorCode](https://github.com/openfga/java-sdk/blob/main/docs/NotFoundErrorCode.md) +- [NullValue](https://github.com/openfga/java-sdk/blob/main/docs/NullValue.md) + - [ObjectRelation](https://github.com/openfga/java-sdk/blob/main/docs/ObjectRelation.md) - [PathUnknownErrorMessageResponse](https://github.com/openfga/java-sdk/blob/main/docs/PathUnknownErrorMessageResponse.md) @@ -798,12 +808,16 @@ fgaClient.writeAssertions(assertions, options).get(); - [ReadRequest](https://github.com/openfga/java-sdk/blob/main/docs/ReadRequest.md) +- [ReadRequestTupleKey](https://github.com/openfga/java-sdk/blob/main/docs/ReadRequestTupleKey.md) + - [ReadResponse](https://github.com/openfga/java-sdk/blob/main/docs/ReadResponse.md) - [RelationMetadata](https://github.com/openfga/java-sdk/blob/main/docs/RelationMetadata.md) - [RelationReference](https://github.com/openfga/java-sdk/blob/main/docs/RelationReference.md) +- [RelationshipCondition](https://github.com/openfga/java-sdk/blob/main/docs/RelationshipCondition.md) + - [Status](https://github.com/openfga/java-sdk/blob/main/docs/Status.md) - [Store](https://github.com/openfga/java-sdk/blob/main/docs/Store.md) @@ -814,7 +828,7 @@ fgaClient.writeAssertions(assertions, options).get(); - [TupleKey](https://github.com/openfga/java-sdk/blob/main/docs/TupleKey.md) -- [TupleKeys](https://github.com/openfga/java-sdk/blob/main/docs/TupleKeys.md) +- [TupleKeyWithoutCondition](https://github.com/openfga/java-sdk/blob/main/docs/TupleKeyWithoutCondition.md) - [TupleOperation](https://github.com/openfga/java-sdk/blob/main/docs/TupleOperation.md) @@ -822,6 +836,8 @@ fgaClient.writeAssertions(assertions, options).get(); - [TypeDefinition](https://github.com/openfga/java-sdk/blob/main/docs/TypeDefinition.md) +- [TypeName](https://github.com/openfga/java-sdk/blob/main/docs/TypeName.md) + - [Users](https://github.com/openfga/java-sdk/blob/main/docs/Users.md) - [Userset](https://github.com/openfga/java-sdk/blob/main/docs/Userset.md) @@ -844,6 +860,10 @@ fgaClient.writeAssertions(assertions, options).get(); - [WriteRequest](https://github.com/openfga/java-sdk/blob/main/docs/WriteRequest.md) +- [WriteRequestDeletes](https://github.com/openfga/java-sdk/blob/main/docs/WriteRequestDeletes.md) + +- [WriteRequestWrites](https://github.com/openfga/java-sdk/blob/main/docs/WriteRequestWrites.md) + ## Contributing diff --git a/docs/Assertion.md b/docs/Assertion.md index 3b41516..b1513a0 100644 --- a/docs/Assertion.md +++ b/docs/Assertion.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleKey** | [**TupleKey**](TupleKey.md) | | | +|**tupleKey** | [**CheckRequestTupleKey**](CheckRequestTupleKey.md) | | | |**expectation** | **Boolean** | | | diff --git a/docs/AuthorizationModel.md b/docs/AuthorizationModel.md index 88ffd2b..5ef00db 100644 --- a/docs/AuthorizationModel.md +++ b/docs/AuthorizationModel.md @@ -7,9 +7,10 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**id** | **String** | | [optional] | +|**id** | **String** | | | |**schemaVersion** | **String** | | | -|**typeDefinitions** | [**List<TypeDefinition>**](TypeDefinition.md) | | [optional] | +|**typeDefinitions** | [**List<TypeDefinition>**](TypeDefinition.md) | | | +|**conditions** | [**Map<String, Condition>**](Condition.md) | | [optional] | diff --git a/docs/CheckRequest.md b/docs/CheckRequest.md index bdce51d..af3428a 100644 --- a/docs/CheckRequest.md +++ b/docs/CheckRequest.md @@ -7,10 +7,11 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleKey** | [**TupleKey**](TupleKey.md) | | | +|**tupleKey** | [**CheckRequestTupleKey**](CheckRequestTupleKey.md) | | | |**contextualTuples** | [**ContextualTupleKeys**](ContextualTupleKeys.md) | | [optional] | |**authorizationModelId** | **String** | | [optional] | |**trace** | **Boolean** | Defaults to false. Making it true has performance implications. | [optional] [readonly] | +|**context** | **Object** | Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. | [optional] | diff --git a/docs/CheckRequestTupleKey.md b/docs/CheckRequestTupleKey.md new file mode 100644 index 0000000..abccd15 --- /dev/null +++ b/docs/CheckRequestTupleKey.md @@ -0,0 +1,15 @@ + + +# CheckRequestTupleKey + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**user** | **String** | | | +|**relation** | **String** | | | +|**_object** | **String** | | | + + + diff --git a/docs/Computed.md b/docs/Computed.md index 5d388e9..b994843 100644 --- a/docs/Computed.md +++ b/docs/Computed.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**userset** | **String** | | [optional] | +|**userset** | **String** | | | diff --git a/docs/Condition.md b/docs/Condition.md new file mode 100644 index 0000000..c2c742a --- /dev/null +++ b/docs/Condition.md @@ -0,0 +1,15 @@ + + +# Condition + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**name** | **String** | | | +|**expression** | **String** | A Google CEL expression, expressed as a string. | | +|**parameters** | [**Map<String, ConditionParamTypeRef>**](ConditionParamTypeRef.md) | A map of parameter names to the parameter's defined type reference. | [optional] | + + + diff --git a/docs/ConditionParamTypeRef.md b/docs/ConditionParamTypeRef.md new file mode 100644 index 0000000..01cd3d8 --- /dev/null +++ b/docs/ConditionParamTypeRef.md @@ -0,0 +1,14 @@ + + +# ConditionParamTypeRef + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**typeName** | **TypeName** | | | +|**genericTypes** | [**List<ConditionParamTypeRef>**](ConditionParamTypeRef.md) | | [optional] | + + + diff --git a/docs/CreateStoreResponse.md b/docs/CreateStoreResponse.md index 0a080bb..e301eb7 100644 --- a/docs/CreateStoreResponse.md +++ b/docs/CreateStoreResponse.md @@ -7,10 +7,10 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**id** | **String** | | [optional] | -|**name** | **String** | | [optional] | -|**createdAt** | **OffsetDateTime** | | [optional] | -|**updatedAt** | **OffsetDateTime** | | [optional] | +|**id** | **String** | | | +|**name** | **String** | | | +|**createdAt** | **OffsetDateTime** | | | +|**updatedAt** | **OffsetDateTime** | | | diff --git a/docs/ExpandRequest.md b/docs/ExpandRequest.md index c5b6442..347ca0c 100644 --- a/docs/ExpandRequest.md +++ b/docs/ExpandRequest.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleKey** | [**TupleKey**](TupleKey.md) | | | +|**tupleKey** | [**ExpandRequestTupleKey**](ExpandRequestTupleKey.md) | | | |**authorizationModelId** | **String** | | [optional] | diff --git a/docs/ExpandRequestTupleKey.md b/docs/ExpandRequestTupleKey.md new file mode 100644 index 0000000..1a581bc --- /dev/null +++ b/docs/ExpandRequestTupleKey.md @@ -0,0 +1,14 @@ + + +# ExpandRequestTupleKey + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**relation** | **String** | | | +|**_object** | **String** | | | + + + diff --git a/docs/GetStoreResponse.md b/docs/GetStoreResponse.md index d802015..2e7bd47 100644 --- a/docs/GetStoreResponse.md +++ b/docs/GetStoreResponse.md @@ -7,10 +7,10 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**id** | **String** | | [optional] | -|**name** | **String** | | [optional] | -|**createdAt** | **OffsetDateTime** | | [optional] | -|**updatedAt** | **OffsetDateTime** | | [optional] | +|**id** | **String** | | | +|**name** | **String** | | | +|**createdAt** | **OffsetDateTime** | | | +|**updatedAt** | **OffsetDateTime** | | | diff --git a/docs/ListObjectsRequest.md b/docs/ListObjectsRequest.md index 2919fe3..142f84a 100644 --- a/docs/ListObjectsRequest.md +++ b/docs/ListObjectsRequest.md @@ -12,6 +12,7 @@ |**relation** | **String** | | | |**user** | **String** | | | |**contextualTuples** | [**ContextualTupleKeys**](ContextualTupleKeys.md) | | [optional] | +|**context** | **Object** | Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. | [optional] | diff --git a/docs/ListObjectsResponse.md b/docs/ListObjectsResponse.md index 68a8566..1415282 100644 --- a/docs/ListObjectsResponse.md +++ b/docs/ListObjectsResponse.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**objects** | **List<String>** | | [optional] | +|**objects** | **List<String>** | | | diff --git a/docs/ListStoresResponse.md b/docs/ListStoresResponse.md index 3088fb4..1a4ecd1 100644 --- a/docs/ListStoresResponse.md +++ b/docs/ListStoresResponse.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**stores** | [**List<Store>**](Store.md) | | [optional] | -|**continuationToken** | **String** | The continuation token will be empty if there are no more stores. | [optional] | +|**stores** | [**List<Store>**](Store.md) | | | +|**continuationToken** | **String** | The continuation token will be empty if there are no more stores. | | diff --git a/docs/Node.md b/docs/Node.md index 6f89e9e..7986230 100644 --- a/docs/Node.md +++ b/docs/Node.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**name** | **String** | | [optional] | +|**name** | **String** | | | |**leaf** | [**Leaf**](Leaf.md) | | [optional] | |**difference** | [**UsersetTreeDifference**](UsersetTreeDifference.md) | | [optional] | |**union** | [**Nodes**](Nodes.md) | | [optional] | diff --git a/docs/Nodes.md b/docs/Nodes.md index d637207..88c576c 100644 --- a/docs/Nodes.md +++ b/docs/Nodes.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**nodes** | [**List<Node>**](Node.md) | | [optional] | +|**nodes** | [**List<Node>**](Node.md) | | | diff --git a/docs/NullValue.md b/docs/NullValue.md new file mode 100644 index 0000000..657a9d2 --- /dev/null +++ b/docs/NullValue.md @@ -0,0 +1,13 @@ + + +# NullValue + +## Enum + + +* `NULL_VALUE` (value: `"NULL_VALUE"`) + +* `UNKNOWN_DEFAULT_OPEN_API` (value: `"unknown_default_open_api"`) + + + diff --git a/docs/OpenFgaApi.md b/docs/OpenFgaApi.md index ec0822e..390227f 100644 --- a/docs/OpenFgaApi.md +++ b/docs/OpenFgaApi.md @@ -43,7 +43,7 @@ All URIs are relative to *http://localhost* Check whether a user is authorized to access an object -The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. +The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. ### Example @@ -114,7 +114,7 @@ No authorization required Check whether a user is authorized to access an object -The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. +The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. ### Example @@ -794,7 +794,7 @@ No authorization required List all objects of the given type that the user has a relation with -The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. +The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. ### Example @@ -865,7 +865,7 @@ No authorization required List all objects of the given type that the user has a relation with -The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. +The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. ### Example @@ -1716,7 +1716,7 @@ No authorization required Return a list of all the tuple changes -The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. +The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. When reading a write tuple change, if it was conditioned, the condition will be returned. When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. ### Example @@ -1791,7 +1791,7 @@ No authorization required Return a list of all the tuple changes -The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. +The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. When reading a write tuple change, if it was conditioned, the condition will be returned. When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. ### Example @@ -1877,7 +1877,7 @@ No authorization required Add or delete tuples from the store -The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples while `deletes` removes existing tuples. The API is not idempotent: if, later on, you try to add the same tuple, or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` +The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` ### Example @@ -1948,7 +1948,7 @@ No authorization required Add or delete tuples from the store -The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples while `deletes` removes existing tuples. The API is not idempotent: if, later on, you try to add the same tuple, or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` +The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` ### Example diff --git a/docs/ReadAssertionsResponse.md b/docs/ReadAssertionsResponse.md index 48c60ad..99f85ef 100644 --- a/docs/ReadAssertionsResponse.md +++ b/docs/ReadAssertionsResponse.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**authorizationModelId** | **String** | | [optional] | +|**authorizationModelId** | **String** | | | |**assertions** | [**List<Assertion>**](Assertion.md) | | [optional] | diff --git a/docs/ReadAuthorizationModelsResponse.md b/docs/ReadAuthorizationModelsResponse.md index 616b47c..0b89cd6 100644 --- a/docs/ReadAuthorizationModelsResponse.md +++ b/docs/ReadAuthorizationModelsResponse.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**authorizationModels** | [**List<AuthorizationModel>**](AuthorizationModel.md) | | [optional] | +|**authorizationModels** | [**List<AuthorizationModel>**](AuthorizationModel.md) | | | |**continuationToken** | **String** | The continuation token will be empty if there are no more models. | [optional] | diff --git a/docs/ReadChangesResponse.md b/docs/ReadChangesResponse.md index fca87b4..467286a 100644 --- a/docs/ReadChangesResponse.md +++ b/docs/ReadChangesResponse.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**changes** | [**List<TupleChange>**](TupleChange.md) | | [optional] | +|**changes** | [**List<TupleChange>**](TupleChange.md) | | | |**continuationToken** | **String** | The continuation token will be identical if there are no new changes. | [optional] | diff --git a/docs/ReadRequest.md b/docs/ReadRequest.md index f8f7047..832f57c 100644 --- a/docs/ReadRequest.md +++ b/docs/ReadRequest.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleKey** | [**TupleKey**](TupleKey.md) | | [optional] | +|**tupleKey** | [**ReadRequestTupleKey**](ReadRequestTupleKey.md) | | [optional] | |**pageSize** | **Integer** | | [optional] | |**continuationToken** | **String** | | [optional] | diff --git a/docs/ReadRequestTupleKey.md b/docs/ReadRequestTupleKey.md new file mode 100644 index 0000000..237849a --- /dev/null +++ b/docs/ReadRequestTupleKey.md @@ -0,0 +1,15 @@ + + +# ReadRequestTupleKey + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**user** | **String** | | [optional] | +|**relation** | **String** | | [optional] | +|**_object** | **String** | | [optional] | + + + diff --git a/docs/ReadResponse.md b/docs/ReadResponse.md index 55c981b..1410325 100644 --- a/docs/ReadResponse.md +++ b/docs/ReadResponse.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tuples** | [**List<Tuple>**](Tuple.md) | | [optional] | -|**continuationToken** | **String** | The continuation token will be empty if there are no more tuples. | [optional] | +|**tuples** | [**List<Tuple>**](Tuple.md) | | | +|**continuationToken** | **String** | The continuation token will be empty if there are no more tuples. | | diff --git a/docs/RelationReference.md b/docs/RelationReference.md index ed98991..7d64b17 100644 --- a/docs/RelationReference.md +++ b/docs/RelationReference.md @@ -11,6 +11,7 @@ RelationReference represents a relation of a particular object type (e.g. 'docum |**type** | **String** | | | |**relation** | **String** | | [optional] | |**wildcard** | **Object** | | [optional] | +|**condition** | **String** | The name of a condition that is enforced over the allowed relation. | [optional] | diff --git a/docs/RelationshipCondition.md b/docs/RelationshipCondition.md new file mode 100644 index 0000000..d10f303 --- /dev/null +++ b/docs/RelationshipCondition.md @@ -0,0 +1,14 @@ + + +# RelationshipCondition + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**name** | **String** | A reference (by name) of the relationship condition defined in the authorization model. | | +|**context** | **Object** | Additional context/data to persist along with the condition. The keys must match the parameters defined by the condition, and the value types must match the parameter type definitions. | [optional] | + + + diff --git a/docs/Store.md b/docs/Store.md index b2b74ca..5db4816 100644 --- a/docs/Store.md +++ b/docs/Store.md @@ -7,11 +7,11 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**id** | **String** | | [optional] | -|**name** | **String** | | [optional] | -|**createdAt** | **OffsetDateTime** | | [optional] | -|**updatedAt** | **OffsetDateTime** | | [optional] | -|**deletedAt** | **OffsetDateTime** | | [optional] | +|**id** | **String** | | | +|**name** | **String** | | | +|**createdAt** | **OffsetDateTime** | | | +|**updatedAt** | **OffsetDateTime** | | | +|**deletedAt** | **OffsetDateTime** | | | diff --git a/docs/Tuple.md b/docs/Tuple.md index 04d434b..7d8996d 100644 --- a/docs/Tuple.md +++ b/docs/Tuple.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**key** | [**TupleKey**](TupleKey.md) | | [optional] | -|**timestamp** | **OffsetDateTime** | | [optional] | +|**key** | [**TupleKey**](TupleKey.md) | | | +|**timestamp** | **OffsetDateTime** | | | diff --git a/docs/TupleChange.md b/docs/TupleChange.md index f6751f6..08ecfb3 100644 --- a/docs/TupleChange.md +++ b/docs/TupleChange.md @@ -7,9 +7,9 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleKey** | [**TupleKey**](TupleKey.md) | | [optional] | -|**operation** | **TupleOperation** | | [optional] | -|**timestamp** | **OffsetDateTime** | | [optional] | +|**tupleKey** | [**TupleKey**](TupleKey.md) | | | +|**operation** | **TupleOperation** | | | +|**timestamp** | **OffsetDateTime** | | | diff --git a/docs/TupleKey.md b/docs/TupleKey.md index fc35d4b..895a185 100644 --- a/docs/TupleKey.md +++ b/docs/TupleKey.md @@ -7,9 +7,10 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**_object** | **String** | | [optional] | -|**relation** | **String** | | [optional] | -|**user** | **String** | | [optional] | +|**user** | **String** | | | +|**relation** | **String** | | | +|**_object** | **String** | | | +|**condition** | [**RelationshipCondition**](RelationshipCondition.md) | | [optional] | diff --git a/docs/TupleKeyWithoutCondition.md b/docs/TupleKeyWithoutCondition.md new file mode 100644 index 0000000..9f3ea2a --- /dev/null +++ b/docs/TupleKeyWithoutCondition.md @@ -0,0 +1,15 @@ + + +# TupleKeyWithoutCondition + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**user** | **String** | | | +|**relation** | **String** | | | +|**_object** | **String** | | | + + + diff --git a/docs/TupleToUserset.md b/docs/TupleToUserset.md index 40802b3..ff33a25 100644 --- a/docs/TupleToUserset.md +++ b/docs/TupleToUserset.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleset** | [**ObjectRelation**](ObjectRelation.md) | | [optional] | -|**computedUserset** | [**ObjectRelation**](ObjectRelation.md) | | [optional] | +|**tupleset** | [**ObjectRelation**](ObjectRelation.md) | | | +|**computedUserset** | [**ObjectRelation**](ObjectRelation.md) | | | diff --git a/docs/TypeName.md b/docs/TypeName.md new file mode 100644 index 0000000..09c3150 --- /dev/null +++ b/docs/TypeName.md @@ -0,0 +1,35 @@ + + +# TypeName + +## Enum + + +* `UNSPECIFIED` (value: `"TYPE_NAME_UNSPECIFIED"`) + +* `ANY` (value: `"TYPE_NAME_ANY"`) + +* `BOOL` (value: `"TYPE_NAME_BOOL"`) + +* `STRING` (value: `"TYPE_NAME_STRING"`) + +* `INT` (value: `"TYPE_NAME_INT"`) + +* `UINT` (value: `"TYPE_NAME_UINT"`) + +* `DOUBLE` (value: `"TYPE_NAME_DOUBLE"`) + +* `DURATION` (value: `"TYPE_NAME_DURATION"`) + +* `TIMESTAMP` (value: `"TYPE_NAME_TIMESTAMP"`) + +* `MAP` (value: `"TYPE_NAME_MAP"`) + +* `LIST` (value: `"TYPE_NAME_LIST"`) + +* `IPADDRESS` (value: `"TYPE_NAME_IPADDRESS"`) + +* `UNKNOWN_DEFAULT_OPEN_API` (value: `"unknown_default_open_api"`) + + + diff --git a/docs/Users.md b/docs/Users.md index 5fa6b79..57da397 100644 --- a/docs/Users.md +++ b/docs/Users.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**users** | **List<String>** | | [optional] | +|**users** | **List<String>** | | | diff --git a/docs/UsersetTreeDifference.md b/docs/UsersetTreeDifference.md index 4370408..484d638 100644 --- a/docs/UsersetTreeDifference.md +++ b/docs/UsersetTreeDifference.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**base** | [**Node**](Node.md) | | [optional] | -|**subtract** | [**Node**](Node.md) | | [optional] | +|**base** | [**Node**](Node.md) | | | +|**subtract** | [**Node**](Node.md) | | | diff --git a/docs/UsersetTreeTupleToUserset.md b/docs/UsersetTreeTupleToUserset.md index 3cf3f37..cee3651 100644 --- a/docs/UsersetTreeTupleToUserset.md +++ b/docs/UsersetTreeTupleToUserset.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**tupleset** | **String** | | [optional] | -|**computed** | [**List<Computed>**](Computed.md) | | [optional] | +|**tupleset** | **String** | | | +|**computed** | [**List<Computed>**](Computed.md) | | | diff --git a/docs/Usersets.md b/docs/Usersets.md index 6ddd670..0ce3e48 100644 --- a/docs/Usersets.md +++ b/docs/Usersets.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**child** | [**List<Userset>**](Userset.md) | | [optional] | +|**child** | [**List<Userset>**](Userset.md) | | | diff --git a/docs/WriteAuthorizationModelRequest.md b/docs/WriteAuthorizationModelRequest.md index a99da15..8ab8fad 100644 --- a/docs/WriteAuthorizationModelRequest.md +++ b/docs/WriteAuthorizationModelRequest.md @@ -8,7 +8,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| |**typeDefinitions** | [**List<TypeDefinition>**](TypeDefinition.md) | | | -|**schemaVersion** | **String** | | [optional] | +|**schemaVersion** | **String** | | | +|**conditions** | [**Map<String, Condition>**](Condition.md) | | [optional] | diff --git a/docs/WriteAuthorizationModelResponse.md b/docs/WriteAuthorizationModelResponse.md index 5ba44eb..04a32af 100644 --- a/docs/WriteAuthorizationModelResponse.md +++ b/docs/WriteAuthorizationModelResponse.md @@ -7,7 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**authorizationModelId** | **String** | | [optional] | +|**authorizationModelId** | **String** | | | diff --git a/docs/WriteRequest.md b/docs/WriteRequest.md index 4b6b36c..1e9c266 100644 --- a/docs/WriteRequest.md +++ b/docs/WriteRequest.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**writes** | [**TupleKeys**](TupleKeys.md) | | [optional] | -|**deletes** | [**TupleKeys**](TupleKeys.md) | | [optional] | +|**writes** | [**WriteRequestWrites**](WriteRequestWrites.md) | | [optional] | +|**deletes** | [**WriteRequestDeletes**](WriteRequestDeletes.md) | | [optional] | |**authorizationModelId** | **String** | | [optional] | diff --git a/docs/WriteRequestDeletes.md b/docs/WriteRequestDeletes.md new file mode 100644 index 0000000..3e38682 --- /dev/null +++ b/docs/WriteRequestDeletes.md @@ -0,0 +1,13 @@ + + +# WriteRequestDeletes + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**tupleKeys** | [**List<TupleKeyWithoutCondition>**](TupleKeyWithoutCondition.md) | | | + + + diff --git a/docs/TupleKeys.md b/docs/WriteRequestWrites.md similarity index 89% rename from docs/TupleKeys.md rename to docs/WriteRequestWrites.md index 72dbe13..8a2fcba 100644 --- a/docs/TupleKeys.md +++ b/docs/WriteRequestWrites.md @@ -1,6 +1,6 @@ -# TupleKeys +# WriteRequestWrites ## Properties diff --git a/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java b/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java index 4823ab4..9666ab8 100644 --- a/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java +++ b/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java @@ -74,7 +74,7 @@ public OpenFgaApi(Configuration configuration, ApiClient apiClient) throws FgaIn /** * Check whether a user is authorized to access an object - * The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. + * The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. * @param storeId (required) * @param body (required) * @return CompletableFuture<ApiResponse<CheckResponse>> @@ -87,7 +87,7 @@ public CompletableFuture> check(String storeId, Check /** * Check whether a user is authorized to access an object - * The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. + * The Check API queries to check if the user has a certain relationship with an object in a certain store. A `contextual_tuples` object may also be included in the body of the request. This object contains one field `tuple_keys`, which is an array of tuple keys. Each of these tuples may have an associated `condition`. You may also provide an `authorization_model_id` in the body. This will be used to assert that the input `tuple_key` is valid for the model specified. If not specified, the assertion will be made against the latest authorization model ID. It is strongly recommended to specify authorization model id for better performance. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will return whether the relationship exists in the field `allowed`. ## Example In order to check if user `user:anne` of type `user` has a `reader` relationship with object `document:2021-budget` given the following contextual tuple ```json { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ``` the Check API can be used with the following request body: ```json { \"tuple_key\": { \"user\": \"user:anne\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" }, \"contextual_tuples\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"member\", \"object\": \"time_slot:office_hours\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` OpenFGA's response will include `{ \"allowed\": true }` if there is a relationship and `{ \"allowed\": false }` if there isn't. * @param storeId (required) * @param body (required) * @param configurationOverride Override the {@link Configuration} this OpenFgaApi was constructed with @@ -464,7 +464,7 @@ private HttpRequest.Builder getStoreRequestBuilder(String storeId, Configuration /** * List all objects of the given type that the user has a relation with - * The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. + * The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. * @param storeId (required) * @param body (required) * @return CompletableFuture<ApiResponse<ListObjectsResponse>> @@ -477,7 +477,7 @@ public CompletableFuture> listObjects(String st /** * List all objects of the given type that the user has a relation with - * The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. + * The ListObjects API returns a list of all the objects of the given type that the user has a relation with. To achieve this, both the store tuples and the authorization model are used. An `authorization_model_id` may be specified in the body. If it is not specified, the latest authorization model ID will be used. It is strongly recommended to specify authorization model id for better performance. You may also specify `contextual_tuples` that will be treated as regular tuples. Each of these tuples may have an associated `condition`. You may also provide a `context` object that will be used to evaluate the conditioned tuples in the system. It is strongly recommended to provide a value for all the input parameters of all the conditions, to ensure that all tuples be evaluated correctly. The response will contain the related objects in an array in the \"objects\" field of the response and they will be strings in the object format `<type>:<id>` (e.g. \"document:roadmap\"). The number of objects in the response array will be limited by the execution timeout specified in the flag OPENFGA_LIST_OBJECTS_DEADLINE and by the upper bound specified in the flag OPENFGA_LIST_OBJECTS_MAX_RESULTS, whichever is hit first. The objects given will not be sorted, and therefore two identical calls can give a given different set of objects. * @param storeId (required) * @param body (required) * @param configurationOverride Override the {@link Configuration} this OpenFgaApi was constructed with @@ -1001,7 +1001,7 @@ private HttpRequest.Builder readAuthorizationModelsRequestBuilder( /** * Return a list of all the tuple changes - * The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. + * The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. When reading a write tuple change, if it was conditioned, the condition will be returned. When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. * @param storeId (required) * @param type (optional) * @param pageSize (optional) @@ -1017,7 +1017,7 @@ public CompletableFuture> readChanges( /** * Return a list of all the tuple changes - * The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. + * The ReadChanges API will return a paginated list of tuple changes (additions and deletions) that occurred in a given store, sorted by ascending time. The response will include a continuation token that is used to get the next set of changes. If there are no changes after the provided continuation token, the same token will be returned in order for it to be used when new changes are recorded. If the store never had any tuples added or removed, this token will be empty. You can use the `type` parameter to only get the list of tuple changes that affect objects of that type. When reading a write tuple change, if it was conditioned, the condition will be returned. When reading a delete tuple change, the condition will NOT be returned regardless of whether it was originally conditioned or not. * @param storeId (required) * @param type (optional) * @param pageSize (optional) @@ -1108,7 +1108,7 @@ private HttpRequest.Builder readChangesRequestBuilder( /** * Add or delete tuples from the store - * The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples while `deletes` removes existing tuples. The API is not idempotent: if, later on, you try to add the same tuple, or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` + * The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` * @param storeId (required) * @param body (required) * @return CompletableFuture<ApiResponse<Object>> @@ -1121,7 +1121,7 @@ public CompletableFuture> write(String storeId, WriteRequest /** * Add or delete tuples from the store - * The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples while `deletes` removes existing tuples. The API is not idempotent: if, later on, you try to add the same tuple, or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` + * The Write API will update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user. In the body, `writes` adds new tuples and `deletes` removes existing tuples. When deleting a tuple, any `condition` specified with it is ignored. The API is not idempotent: if, later on, you try to add the same tuple key (even if the `condition` is different), or if you try to delete a non-existing tuple, it will throw an error. An `authorization_model_id` may be specified in the body. If it is, it will be used to assert that each written tuple (not deleted) is valid for the model specified. If it is not specified, the latest authorization model ID will be used. ## Example ### Adding relationships To add `user:anne` as a `writer` for `document:2021-budget`, call write API with the following ```json { \"writes\": { \"tuple_keys\": [ { \"user\": \"user:anne\", \"relation\": \"writer\", \"object\": \"document:2021-budget\" } ] }, \"authorization_model_id\": \"01G50QVV17PECNVAHX1GG4Y5NC\" } ``` ### Removing relationships To remove `user:bob` as a `reader` for `document:2021-budget`, call write API with the following ```json { \"deletes\": { \"tuple_keys\": [ { \"user\": \"user:bob\", \"relation\": \"reader\", \"object\": \"document:2021-budget\" } ] } } ``` * @param storeId (required) * @param body (required) * @param configurationOverride Override the {@link Configuration} this OpenFgaApi was constructed with diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientAssertion.java b/src/main/java/dev/openfga/sdk/api/client/ClientAssertion.java index d1722a9..8618fe1 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ClientAssertion.java +++ b/src/main/java/dev/openfga/sdk/api/client/ClientAssertion.java @@ -13,7 +13,7 @@ package dev.openfga.sdk.api.client; import dev.openfga.sdk.api.model.Assertion; -import dev.openfga.sdk.api.model.TupleKey; +import dev.openfga.sdk.api.model.CheckRequestTupleKey; import java.util.List; import java.util.stream.Collectors; @@ -72,7 +72,7 @@ public boolean getExpectation() { } public Assertion asAssertion() { - TupleKey tupleKey = new TupleKey().user(user).relation(relation)._object(_object); + var tupleKey = new CheckRequestTupleKey().user(user).relation(relation)._object(_object); return new Assertion().tupleKey(tupleKey).expectation(expectation); } diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientCheckRequest.java b/src/main/java/dev/openfga/sdk/api/client/ClientCheckRequest.java index 1ce257c..9ac6fda 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ClientCheckRequest.java +++ b/src/main/java/dev/openfga/sdk/api/client/ClientCheckRequest.java @@ -12,13 +12,18 @@ package dev.openfga.sdk.api.client; +import dev.openfga.sdk.api.model.CheckRequestTupleKey; import java.util.List; public class ClientCheckRequest { private String user; private String relation; private String _object; - private List contextualTuples; + private List contextualTuples; + + public CheckRequestTupleKey asCheckRequestTupleKey() { + return new CheckRequestTupleKey().user(user).relation(relation)._object(_object); + } public ClientCheckRequest _object(String _object) { this._object = _object; @@ -59,12 +64,12 @@ public String getUser() { return user; } - public ClientCheckRequest contextualTuples(List contextualTuples) { + public ClientCheckRequest contextualTuples(List contextualTuples) { this.contextualTuples = contextualTuples; return this; } - public List getContextualTuples() { + public List getContextualTuples() { return contextualTuples; } } diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientListObjectsRequest.java b/src/main/java/dev/openfga/sdk/api/client/ClientListObjectsRequest.java index 9f25b34..9a03bda 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ClientListObjectsRequest.java +++ b/src/main/java/dev/openfga/sdk/api/client/ClientListObjectsRequest.java @@ -18,7 +18,7 @@ public class ClientListObjectsRequest { private String user; private String relation; private String type; - private List contextualTupleKeys; + private List contextualTupleKeys; public ClientListObjectsRequest user(String user) { this.user = user; @@ -55,12 +55,12 @@ public String getType() { return type; } - public ClientListObjectsRequest contextualTupleKeys(List contextualTupleKeys) { + public ClientListObjectsRequest contextualTupleKeys(List contextualTupleKeys) { this.contextualTupleKeys = contextualTupleKeys; return this; } - public List getContextualTupleKeys() { + public List getContextualTupleKeys() { return contextualTupleKeys; } } diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientRelationshipCondition.java b/src/main/java/dev/openfga/sdk/api/client/ClientRelationshipCondition.java new file mode 100644 index 0000000..6af608e --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/client/ClientRelationshipCondition.java @@ -0,0 +1,42 @@ +/* + * 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: community@openfga.dev + * + * 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.RelationshipCondition; + +public class ClientRelationshipCondition { + private String name; + private Object context; + + public ClientRelationshipCondition name(String name) { + this.name = name; + return this; + } + + public String getName() { + return name; + } + + public ClientRelationshipCondition context(Object context) { + this.context = context; + return this; + } + + public Object getContext() { + return context; + } + + public RelationshipCondition asRelationshipCondition() { + return new RelationshipCondition().name(name).context(context); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientTupleKey.java b/src/main/java/dev/openfga/sdk/api/client/ClientTupleKey.java index e61711d..319c555 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ClientTupleKey.java +++ b/src/main/java/dev/openfga/sdk/api/client/ClientTupleKey.java @@ -12,11 +12,9 @@ package dev.openfga.sdk.api.client; -import dev.openfga.sdk.api.model.ContextualTupleKeys; -import dev.openfga.sdk.api.model.TupleKey; -import dev.openfga.sdk.api.model.TupleKeys; -import java.util.List; -import java.util.Optional; +import dev.openfga.sdk.api.model.TupleKeyWithoutCondition; +import dev.openfga.sdk.api.model.WriteRequestDeletes; +import java.util.Collection; import java.util.stream.Collectors; public class ClientTupleKey { @@ -24,6 +22,17 @@ public class ClientTupleKey { private String relation; private String _object; + public TupleKeyWithoutCondition asTupleKeyWithoutCondition() { + return new TupleKeyWithoutCondition().user(user).relation(relation)._object(_object); + } + + public static WriteRequestDeletes asWriteRequestDeletes(Collection tupleKeys) { + return new WriteRequestDeletes() + .tupleKeys(tupleKeys.stream() + .map(ClientTupleKey::asTupleKeyWithoutCondition) + .collect(Collectors.toList())); + } + public ClientTupleKey _object(String _object) { this._object = _object; return this; @@ -63,27 +72,17 @@ public String getUser() { return user; } - public TupleKey asTupleKey() { - return new TupleKey().user(user).relation(relation)._object(_object); - } - - public static Optional asTupleKeys(List clientTupleKeys) { - if (clientTupleKeys == null || clientTupleKeys.size() == 0) { - return Optional.empty(); - } - - return Optional.of(new TupleKeys().tupleKeys(asListOfTupleKey(clientTupleKeys))); - } - - public static ContextualTupleKeys asContextualTupleKeys(List clientTupleKeys) { - if (clientTupleKeys == null || clientTupleKeys.size() == 0) { - return new ContextualTupleKeys(); - } - - return new ContextualTupleKeys().tupleKeys(asListOfTupleKey(clientTupleKeys)); - } - - private static List asListOfTupleKey(List clientTupleKeys) { - return clientTupleKeys.stream().map(ClientTupleKey::asTupleKey).collect(Collectors.toList()); + /** + * Adds a condition to the tuple key. + * @param condition a {@link ClientRelationshipCondition} + * @return a new {@link ClientTupleKeyWithCondition} with this {@link ClientTupleKey}'s + * user, relation, and object, and the passed condition. + */ + public ClientTupleKeyWithCondition condition(ClientRelationshipCondition condition) { + return new ClientTupleKeyWithCondition() + .user(user) + .relation(relation) + ._object(_object) + .condition(condition); } } diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientTupleKeyWithCondition.java b/src/main/java/dev/openfga/sdk/api/client/ClientTupleKeyWithCondition.java new file mode 100644 index 0000000..097f1a8 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/client/ClientTupleKeyWithCondition.java @@ -0,0 +1,76 @@ +/* + * 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: community@openfga.dev + * + * 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.ContextualTupleKeys; +import dev.openfga.sdk.api.model.TupleKey; +import dev.openfga.sdk.api.model.WriteRequestWrites; +import java.util.Collection; +import java.util.stream.Collectors; + +public class ClientTupleKeyWithCondition extends ClientTupleKey { + private ClientRelationshipCondition condition; + + public ClientTupleKeyWithCondition condition(ClientRelationshipCondition condition) { + this.condition = condition; + return this; + } + + public ClientRelationshipCondition getCondition() { + return condition; + } + + public TupleKey asTupleKey() { + var tupleKey = new TupleKey().user(getUser()).relation(getRelation())._object(getObject()); + + if (condition != null) { + tupleKey.condition(condition.asRelationshipCondition()); + } + + return tupleKey; + } + + public static ContextualTupleKeys asContextualTupleKeys(Collection tupleKeys) { + return new ContextualTupleKeys() + .tupleKeys(tupleKeys.stream() + .map(ClientTupleKeyWithCondition::asTupleKey) + .collect(Collectors.toList())); + } + + public static WriteRequestWrites asWriteRequestWrites(Collection tupleKeys) { + return new WriteRequestWrites() + .tupleKeys(tupleKeys.stream() + .map(ClientTupleKeyWithCondition::asTupleKey) + .collect(Collectors.toList())); + } + + /* Overrides for correct typing */ + + @Override + public ClientTupleKeyWithCondition user(String user) { + super.user(user); + return this; + } + + @Override + public ClientTupleKeyWithCondition relation(String relation) { + super.relation(relation); + return this; + } + + @Override + public ClientTupleKeyWithCondition _object(String _object) { + super._object(_object); + return this; + } +} diff --git a/src/main/java/dev/openfga/sdk/api/client/ClientWriteRequest.java b/src/main/java/dev/openfga/sdk/api/client/ClientWriteRequest.java index 8dc1f35..189f39a 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ClientWriteRequest.java +++ b/src/main/java/dev/openfga/sdk/api/client/ClientWriteRequest.java @@ -15,19 +15,19 @@ import java.util.List; public class ClientWriteRequest { - private List writes; + private List writes; private List deletes; - public static ClientWriteRequest ofWrites(List writes) { + public static ClientWriteRequest ofWrites(List writes) { return new ClientWriteRequest().writes(writes); } - public ClientWriteRequest writes(List writes) { + public ClientWriteRequest writes(List writes) { this.writes = writes; return this; } - public List getWrites() { + public List getWrites() { return writes; } diff --git a/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java b/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java index 6d8cc74..ca8447e 100644 --- a/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java +++ b/src/main/java/dev/openfga/sdk/api/client/HttpRequestAttempt.java @@ -5,9 +5,12 @@ import dev.openfga.sdk.api.configuration.Configuration; import dev.openfga.sdk.errors.*; import java.io.IOException; +import java.io.PrintStream; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Optional; import java.util.concurrent.*; @@ -19,6 +22,9 @@ public class HttpRequestAttempt { private final String name; private final HttpRequest request; + // Intended for only testing the OpenFGA SDK itself. + private final boolean enableDebugLogging = "enable".equals(System.getProperty("HttpRequestAttempt.debug-logging")); + public HttpRequestAttempt( HttpRequest request, String name, Class clazz, ApiClient apiClient, Configuration configuration) throws FgaInvalidParameterException { @@ -33,6 +39,11 @@ public HttpRequestAttempt( } public CompletableFuture> attemptHttpRequest() throws ApiException { + if (enableDebugLogging) { + request.bodyPublisher() + .ifPresent(requestBodyPublisher -> + requestBodyPublisher.subscribe(new BodyLogger(System.err, "request"))); + } int retryNumber = 0; return attemptHttpRequest(apiClient.getHttpClient(), retryNumber, null); } @@ -83,4 +94,37 @@ private HttpClient getDelayedHttpClient() { .executor(CompletableFuture.delayedExecutor(retryDelay.toNanos(), TimeUnit.NANOSECONDS)) .build(); } + + private static class BodyLogger implements Flow.Subscriber { + private final PrintStream out; + private final String target; + + BodyLogger(PrintStream out, String target) { + this.out = out; + this.target = target; + } + + @Override + public void onSubscribe(Flow.Subscription subscription) { + out.printf("[%s] subscribed: %s\n", this.getClass().getName(), subscription); + subscription.request(Long.MAX_VALUE); + } + + @Override + public void onNext(ByteBuffer item) { + out.printf( + "[%s] %s: %s\n", + this.getClass().getName(), target, new String(item.array(), StandardCharsets.UTF_8)); + } + + @Override + public void onError(Throwable throwable) { + out.printf("[%s] error: %s\n", this.getClass().getName(), throwable); + } + + @Override + public void onComplete() { + out.flush(); + } + } } diff --git a/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java b/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java index b403378..7d89eb6 100644 --- a/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java +++ b/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java @@ -245,9 +245,10 @@ public CompletableFuture read(ClientReadRequest request, Cli if (request != null && (request.getUser() != null || request.getRelation() != null || request.getObject() != null)) { - TupleKey tupleKey = new TupleKey(); - tupleKey.user(request.getUser()).relation(request.getRelation())._object(request.getObject()); - body.tupleKey(tupleKey); + body.tupleKey(new ReadRequestTupleKey() + .user(request.getUser()) + .relation(request.getRelation()) + ._object(request.getObject())); } if (options != null) { @@ -289,8 +290,15 @@ private CompletableFuture writeNonTransaction( WriteRequest body = new WriteRequest(); - ClientTupleKey.asTupleKeys(request.getWrites()).ifPresent(body::writes); - ClientTupleKey.asTupleKeys(request.getDeletes()).ifPresent(body::deletes); + var writeTuples = request.getWrites(); + if (writeTuples != null && !writeTuples.isEmpty()) { + body.writes(ClientTupleKeyWithCondition.asWriteRequestWrites(writeTuples)); + } + + var deleteTuples = request.getDeletes(); + if (deleteTuples != null && !deleteTuples.isEmpty()) { + body.deletes(ClientTupleKey.asWriteRequestDeletes(deleteTuples)); + } if (options != null && !isNullOrWhitespace(options.getAuthorizationModelId())) { body.authorizationModelId(options.getAuthorizationModelId()); @@ -349,20 +357,21 @@ private Stream> chunksOf(int chunkSize, List list) { * * @throws FgaInvalidParameterException When the Store ID is null, empty, or whitespace */ - public CompletableFuture writeTuples(List tupleKeys) + public CompletableFuture writeTuples(List tupleKeys) throws FgaInvalidParameterException { configuration.assertValid(); String storeId = configuration.getStoreIdChecked(); - var request = new WriteRequest(); - ClientTupleKey.asTupleKeys(tupleKeys).ifPresent(request::writes); + var body = new WriteRequest(); + + body.writes(ClientTupleKeyWithCondition.asWriteRequestWrites(tupleKeys)); String authorizationModelId = configuration.getAuthorizationModelId(); if (!isNullOrWhitespace(authorizationModelId)) { - request.authorizationModelId(authorizationModelId); + body.authorizationModelId(authorizationModelId); } - return call(() -> api.write(storeId, request)).thenApply(ClientWriteResponse::new); + return call(() -> api.write(storeId, body)).thenApply(ClientWriteResponse::new); } /** @@ -375,15 +384,16 @@ public CompletableFuture deleteTuples(List configuration.assertValid(); String storeId = configuration.getStoreIdChecked(); - var request = new WriteRequest(); - ClientTupleKey.asTupleKeys(tupleKeys).ifPresent(request::deletes); + var body = new WriteRequest(); + + body.deletes(ClientTupleKey.asWriteRequestDeletes(tupleKeys)); String authorizationModelId = configuration.getAuthorizationModelId(); if (!isNullOrWhitespace(authorizationModelId)) { - request.authorizationModelId(authorizationModelId); + body.authorizationModelId(authorizationModelId); } - return call(() -> api.write(storeId, request)).thenApply(ClientWriteResponse::new); + return call(() -> api.write(storeId, body)).thenApply(ClientWriteResponse::new); } /* ********************** @@ -413,14 +423,11 @@ public CompletableFuture check(ClientCheckRequest request, CheckRequest body = new CheckRequest(); if (request != null) { - body.tupleKey(new TupleKey() - .user(request.getUser()) - .relation(request.getRelation()) - ._object(request.getObject())); + body.tupleKey(request.asCheckRequestTupleKey()); var contextualTuples = request.getContextualTuples(); if (contextualTuples != null && !contextualTuples.isEmpty()) { - body.contextualTuples(ClientTupleKey.asContextualTupleKeys(contextualTuples)); + body.contextualTuples(ClientTupleKeyWithCondition.asContextualTupleKeys(contextualTuples)); } } @@ -492,7 +499,8 @@ public CompletableFuture expand(ClientExpandRequest reques ExpandRequest body = new ExpandRequest(); if (request != null) { - body.tupleKey(new TupleKey().relation(request.getRelation())._object(request.getObject())); + body.tupleKey( + new ExpandRequestTupleKey().relation(request.getRelation())._object(request.getObject())); } if (options != null && !isNullOrWhitespace(options.getAuthorizationModelId())) { @@ -528,10 +536,12 @@ public CompletableFuture listObjects( ListObjectsRequest body = new ListObjectsRequest(); if (request != null) { - body.user(request.getUser()) - .relation(request.getRelation()) - .type(request.getType()) - .contextualTuples(ClientTupleKey.asContextualTupleKeys(request.getContextualTupleKeys())); + body.user(request.getUser()).relation(request.getRelation()).type(request.getType()); + if (request.getContextualTupleKeys() != null) { + var contextualTuples = request.getContextualTupleKeys(); + var bodyContextualTuples = ClientTupleKeyWithCondition.asContextualTupleKeys(contextualTuples); + body.contextualTuples(bodyContextualTuples); + } } if (options != null && !isNullOrWhitespace(options.getAuthorizationModelId())) { diff --git a/src/main/java/dev/openfga/sdk/api/model/Assertion.java b/src/main/java/dev/openfga/sdk/api/model/Assertion.java index 1c1dbda..0f1f3b5 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Assertion.java +++ b/src/main/java/dev/openfga/sdk/api/model/Assertion.java @@ -26,14 +26,14 @@ @JsonPropertyOrder({Assertion.JSON_PROPERTY_TUPLE_KEY, Assertion.JSON_PROPERTY_EXPECTATION}) public class Assertion { public static final String JSON_PROPERTY_TUPLE_KEY = "tuple_key"; - private TupleKey tupleKey; + private CheckRequestTupleKey tupleKey; public static final String JSON_PROPERTY_EXPECTATION = "expectation"; private Boolean expectation; public Assertion() {} - public Assertion tupleKey(TupleKey tupleKey) { + public Assertion tupleKey(CheckRequestTupleKey tupleKey) { this.tupleKey = tupleKey; return this; } @@ -45,13 +45,13 @@ public Assertion tupleKey(TupleKey tupleKey) { @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public TupleKey getTupleKey() { + public CheckRequestTupleKey getTupleKey() { return tupleKey; } @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setTupleKey(TupleKey tupleKey) { + public void setTupleKey(CheckRequestTupleKey tupleKey) { this.tupleKey = tupleKey; } diff --git a/src/main/java/dev/openfga/sdk/api/model/AuthorizationModel.java b/src/main/java/dev/openfga/sdk/api/model/AuthorizationModel.java index 2fb0119..d85cafd 100644 --- a/src/main/java/dev/openfga/sdk/api/model/AuthorizationModel.java +++ b/src/main/java/dev/openfga/sdk/api/model/AuthorizationModel.java @@ -18,7 +18,9 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.StringJoiner; @@ -28,7 +30,8 @@ @JsonPropertyOrder({ AuthorizationModel.JSON_PROPERTY_ID, AuthorizationModel.JSON_PROPERTY_SCHEMA_VERSION, - AuthorizationModel.JSON_PROPERTY_TYPE_DEFINITIONS + AuthorizationModel.JSON_PROPERTY_TYPE_DEFINITIONS, + AuthorizationModel.JSON_PROPERTY_CONDITIONS }) public class AuthorizationModel { public static final String JSON_PROPERTY_ID = "id"; @@ -40,6 +43,9 @@ public class AuthorizationModel { public static final String JSON_PROPERTY_TYPE_DEFINITIONS = "type_definitions"; private List typeDefinitions = new ArrayList<>(); + public static final String JSON_PROPERTY_CONDITIONS = "conditions"; + private Map conditions = new HashMap<>(); + public AuthorizationModel() {} public AuthorizationModel id(String id) { @@ -51,15 +57,15 @@ public AuthorizationModel id(String id) { * Get id * @return id **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getId() { return id; } @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setId(String id) { this.id = id; } @@ -103,19 +109,49 @@ public AuthorizationModel addTypeDefinitionsItem(TypeDefinition typeDefinitionsI * Get typeDefinitions * @return typeDefinitions **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TYPE_DEFINITIONS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getTypeDefinitions() { return typeDefinitions; } @JsonProperty(JSON_PROPERTY_TYPE_DEFINITIONS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTypeDefinitions(List typeDefinitions) { this.typeDefinitions = typeDefinitions; } + public AuthorizationModel conditions(Map conditions) { + this.conditions = conditions; + return this; + } + + public AuthorizationModel putConditionsItem(String key, Condition conditionsItem) { + if (this.conditions == null) { + this.conditions = new HashMap<>(); + } + this.conditions.put(key, conditionsItem); + return this; + } + + /** + * Get conditions + * @return conditions + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CONDITIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Map getConditions() { + return conditions; + } + + @JsonProperty(JSON_PROPERTY_CONDITIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setConditions(Map conditions) { + this.conditions = conditions; + } + /** * Return true if this AuthorizationModel object is equal to o. */ @@ -130,12 +166,13 @@ public boolean equals(Object o) { AuthorizationModel authorizationModel = (AuthorizationModel) o; return Objects.equals(this.id, authorizationModel.id) && Objects.equals(this.schemaVersion, authorizationModel.schemaVersion) - && Objects.equals(this.typeDefinitions, authorizationModel.typeDefinitions); + && Objects.equals(this.typeDefinitions, authorizationModel.typeDefinitions) + && Objects.equals(this.conditions, authorizationModel.conditions); } @Override public int hashCode() { - return Objects.hash(id, schemaVersion, typeDefinitions); + return Objects.hash(id, schemaVersion, typeDefinitions, conditions); } @Override @@ -147,6 +184,7 @@ public String toString() { sb.append(" typeDefinitions: ") .append(toIndentedString(typeDefinitions)) .append("\n"); + sb.append(" conditions: ").append(toIndentedString(conditions)).append("\n"); sb.append("}"); return sb.toString(); } @@ -231,6 +269,23 @@ public String toUrlQueryString(String prefix) { } } + // add `conditions` to the URL query string + if (getConditions() != null) { + for (String _key : getConditions().keySet()) { + if (getConditions().get(_key) != null) { + joiner.add(getConditions() + .get(_key) + .toUrlQueryString(String.format( + "%sconditions%s%s", + prefix, + suffix, + "".equals(suffix) + ? "" + : String.format("%s%d%s", containerPrefix, _key, containerSuffix)))); + } + } + } + return joiner.toString(); } } diff --git a/src/main/java/dev/openfga/sdk/api/model/CheckRequest.java b/src/main/java/dev/openfga/sdk/api/model/CheckRequest.java index c5cac07..f01b5b7 100644 --- a/src/main/java/dev/openfga/sdk/api/model/CheckRequest.java +++ b/src/main/java/dev/openfga/sdk/api/model/CheckRequest.java @@ -28,11 +28,12 @@ CheckRequest.JSON_PROPERTY_TUPLE_KEY, CheckRequest.JSON_PROPERTY_CONTEXTUAL_TUPLES, CheckRequest.JSON_PROPERTY_AUTHORIZATION_MODEL_ID, - CheckRequest.JSON_PROPERTY_TRACE + CheckRequest.JSON_PROPERTY_TRACE, + CheckRequest.JSON_PROPERTY_CONTEXT }) public class CheckRequest { public static final String JSON_PROPERTY_TUPLE_KEY = "tuple_key"; - private TupleKey tupleKey; + private CheckRequestTupleKey tupleKey; public static final String JSON_PROPERTY_CONTEXTUAL_TUPLES = "contextual_tuples"; private ContextualTupleKeys contextualTuples; @@ -43,6 +44,9 @@ public class CheckRequest { public static final String JSON_PROPERTY_TRACE = "trace"; private Boolean trace; + public static final String JSON_PROPERTY_CONTEXT = "context"; + private Object context; + public CheckRequest() {} @JsonCreator @@ -51,7 +55,7 @@ public CheckRequest(@JsonProperty(JSON_PROPERTY_TRACE) Boolean trace) { this.trace = trace; } - public CheckRequest tupleKey(TupleKey tupleKey) { + public CheckRequest tupleKey(CheckRequestTupleKey tupleKey) { this.tupleKey = tupleKey; return this; } @@ -63,13 +67,13 @@ public CheckRequest tupleKey(TupleKey tupleKey) { @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public TupleKey getTupleKey() { + public CheckRequestTupleKey getTupleKey() { return tupleKey; } @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setTupleKey(TupleKey tupleKey) { + public void setTupleKey(CheckRequestTupleKey tupleKey) { this.tupleKey = tupleKey; } @@ -128,6 +132,28 @@ public Boolean getTrace() { return trace; } + public CheckRequest context(Object context) { + this.context = context; + return this; + } + + /** + * Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + * @return context + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CONTEXT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Object getContext() { + return context; + } + + @JsonProperty(JSON_PROPERTY_CONTEXT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setContext(Object context) { + this.context = context; + } + /** * Return true if this Check_request object is equal to o. */ @@ -143,12 +169,13 @@ public boolean equals(Object o) { return Objects.equals(this.tupleKey, checkRequest.tupleKey) && Objects.equals(this.contextualTuples, checkRequest.contextualTuples) && Objects.equals(this.authorizationModelId, checkRequest.authorizationModelId) - && Objects.equals(this.trace, checkRequest.trace); + && Objects.equals(this.trace, checkRequest.trace) + && Objects.equals(this.context, checkRequest.context); } @Override public int hashCode() { - return Objects.hash(tupleKey, contextualTuples, authorizationModelId, trace); + return Objects.hash(tupleKey, contextualTuples, authorizationModelId, trace, context); } @Override @@ -163,6 +190,7 @@ public String toString() { .append(toIndentedString(authorizationModelId)) .append("\n"); sb.append(" trace: ").append(toIndentedString(trace)).append("\n"); + sb.append(" context: ").append(toIndentedString(context)).append("\n"); sb.append("}"); return sb.toString(); } @@ -240,6 +268,16 @@ public String toUrlQueryString(String prefix) { .replaceAll("\\+", "%20"))); } + // add `context` to the URL query string + if (getContext() != null) { + joiner.add(String.format( + "%scontext%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getContext()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + return joiner.toString(); } } diff --git a/src/main/java/dev/openfga/sdk/api/model/CheckRequestTupleKey.java b/src/main/java/dev/openfga/sdk/api/model/CheckRequestTupleKey.java new file mode 100644 index 0000000..cd2e637 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/CheckRequestTupleKey.java @@ -0,0 +1,217 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * CheckRequestTupleKey + */ +@JsonPropertyOrder({ + CheckRequestTupleKey.JSON_PROPERTY_USER, + CheckRequestTupleKey.JSON_PROPERTY_RELATION, + CheckRequestTupleKey.JSON_PROPERTY_OBJECT +}) +public class CheckRequestTupleKey { + public static final String JSON_PROPERTY_USER = "user"; + private String user; + + public static final String JSON_PROPERTY_RELATION = "relation"; + private String relation; + + public static final String JSON_PROPERTY_OBJECT = "object"; + private String _object; + + public CheckRequestTupleKey() {} + + public CheckRequestTupleKey user(String user) { + this.user = user; + return this; + } + + /** + * Get user + * @return user + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getUser() { + return user; + } + + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setUser(String user) { + this.user = user; + } + + public CheckRequestTupleKey relation(String relation) { + this.relation = relation; + return this; + } + + /** + * Get relation + * @return relation + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getRelation() { + return relation; + } + + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setRelation(String relation) { + this.relation = relation; + } + + public CheckRequestTupleKey _object(String _object) { + this._object = _object; + return this; + } + + /** + * Get _object + * @return _object + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getObject() { + return _object; + } + + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setObject(String _object) { + this._object = _object; + } + + /** + * Return true if this CheckRequestTupleKey object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CheckRequestTupleKey checkRequestTupleKey = (CheckRequestTupleKey) o; + return Objects.equals(this.user, checkRequestTupleKey.user) + && Objects.equals(this.relation, checkRequestTupleKey.relation) + && Objects.equals(this._object, checkRequestTupleKey._object); + } + + @Override + public int hashCode() { + return Objects.hash(user, relation, _object); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CheckRequestTupleKey {\n"); + sb.append(" user: ").append(toIndentedString(user)).append("\n"); + sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); + sb.append(" _object: ").append(toIndentedString(_object)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `user` to the URL query string + if (getUser() != null) { + joiner.add(String.format( + "%suser%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getUser()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `relation` to the URL query string + if (getRelation() != null) { + joiner.add(String.format( + "%srelation%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getRelation()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `object` to the URL query string + if (getObject() != null) { + joiner.add(String.format( + "%sobject%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getObject()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/Computed.java b/src/main/java/dev/openfga/sdk/api/model/Computed.java index 7a31ba1..042449b 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Computed.java +++ b/src/main/java/dev/openfga/sdk/api/model/Computed.java @@ -39,15 +39,15 @@ public Computed userset(String userset) { * Get userset * @return userset **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_USERSET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getUserset() { return userset; } @JsonProperty(JSON_PROPERTY_USERSET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setUserset(String userset) { this.userset = userset; } diff --git a/src/main/java/dev/openfga/sdk/api/model/Condition.java b/src/main/java/dev/openfga/sdk/api/model/Condition.java new file mode 100644 index 0000000..dc9e2c1 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/Condition.java @@ -0,0 +1,231 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * Condition + */ +@JsonPropertyOrder({Condition.JSON_PROPERTY_NAME, Condition.JSON_PROPERTY_EXPRESSION, Condition.JSON_PROPERTY_PARAMETERS +}) +public class Condition { + public static final String JSON_PROPERTY_NAME = "name"; + private String name; + + public static final String JSON_PROPERTY_EXPRESSION = "expression"; + private String expression; + + public static final String JSON_PROPERTY_PARAMETERS = "parameters"; + private Map parameters = new HashMap<>(); + + public Condition() {} + + public Condition name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getName() { + return name; + } + + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setName(String name) { + this.name = name; + } + + public Condition expression(String expression) { + this.expression = expression; + return this; + } + + /** + * A Google CEL expression, expressed as a string. + * @return expression + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_EXPRESSION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getExpression() { + return expression; + } + + @JsonProperty(JSON_PROPERTY_EXPRESSION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setExpression(String expression) { + this.expression = expression; + } + + public Condition parameters(Map parameters) { + this.parameters = parameters; + return this; + } + + public Condition putParametersItem(String key, ConditionParamTypeRef parametersItem) { + if (this.parameters == null) { + this.parameters = new HashMap<>(); + } + this.parameters.put(key, parametersItem); + return this; + } + + /** + * A map of parameter names to the parameter's defined type reference. + * @return parameters + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_PARAMETERS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Map getParameters() { + return parameters; + } + + @JsonProperty(JSON_PROPERTY_PARAMETERS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + /** + * Return true if this Condition object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Condition condition = (Condition) o; + return Objects.equals(this.name, condition.name) + && Objects.equals(this.expression, condition.expression) + && Objects.equals(this.parameters, condition.parameters); + } + + @Override + public int hashCode() { + return Objects.hash(name, expression, parameters); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Condition {\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" expression: ").append(toIndentedString(expression)).append("\n"); + sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `name` to the URL query string + if (getName() != null) { + joiner.add(String.format( + "%sname%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getName()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `expression` to the URL query string + if (getExpression() != null) { + joiner.add(String.format( + "%sexpression%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getExpression()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `parameters` to the URL query string + if (getParameters() != null) { + for (String _key : getParameters().keySet()) { + if (getParameters().get(_key) != null) { + joiner.add(getParameters() + .get(_key) + .toUrlQueryString(String.format( + "%sparameters%s%s", + prefix, + suffix, + "".equals(suffix) + ? "" + : String.format("%s%d%s", containerPrefix, _key, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/ConditionParamTypeRef.java b/src/main/java/dev/openfga/sdk/api/model/ConditionParamTypeRef.java new file mode 100644 index 0000000..e4a113d --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/ConditionParamTypeRef.java @@ -0,0 +1,193 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * ConditionParamTypeRef + */ +@JsonPropertyOrder({ConditionParamTypeRef.JSON_PROPERTY_TYPE_NAME, ConditionParamTypeRef.JSON_PROPERTY_GENERIC_TYPES}) +public class ConditionParamTypeRef { + public static final String JSON_PROPERTY_TYPE_NAME = "type_name"; + private TypeName typeName = TypeName.UNSPECIFIED; + + public static final String JSON_PROPERTY_GENERIC_TYPES = "generic_types"; + private List genericTypes = new ArrayList<>(); + + public ConditionParamTypeRef() {} + + public ConditionParamTypeRef typeName(TypeName typeName) { + this.typeName = typeName; + return this; + } + + /** + * Get typeName + * @return typeName + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_TYPE_NAME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public TypeName getTypeName() { + return typeName; + } + + @JsonProperty(JSON_PROPERTY_TYPE_NAME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setTypeName(TypeName typeName) { + this.typeName = typeName; + } + + public ConditionParamTypeRef genericTypes(List genericTypes) { + this.genericTypes = genericTypes; + return this; + } + + public ConditionParamTypeRef addGenericTypesItem(ConditionParamTypeRef genericTypesItem) { + if (this.genericTypes == null) { + this.genericTypes = new ArrayList<>(); + } + this.genericTypes.add(genericTypesItem); + return this; + } + + /** + * Get genericTypes + * @return genericTypes + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_GENERIC_TYPES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public List getGenericTypes() { + return genericTypes; + } + + @JsonProperty(JSON_PROPERTY_GENERIC_TYPES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setGenericTypes(List genericTypes) { + this.genericTypes = genericTypes; + } + + /** + * Return true if this ConditionParamTypeRef object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ConditionParamTypeRef conditionParamTypeRef = (ConditionParamTypeRef) o; + return Objects.equals(this.typeName, conditionParamTypeRef.typeName) + && Objects.equals(this.genericTypes, conditionParamTypeRef.genericTypes); + } + + @Override + public int hashCode() { + return Objects.hash(typeName, genericTypes); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ConditionParamTypeRef {\n"); + sb.append(" typeName: ").append(toIndentedString(typeName)).append("\n"); + sb.append(" genericTypes: ").append(toIndentedString(genericTypes)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `type_name` to the URL query string + if (getTypeName() != null) { + joiner.add(String.format( + "%stype_name%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getTypeName()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `generic_types` to the URL query string + if (getGenericTypes() != null) { + for (int i = 0; i < getGenericTypes().size(); i++) { + if (getGenericTypes().get(i) != null) { + joiner.add(getGenericTypes() + .get(i) + .toUrlQueryString(String.format( + "%sgeneric_types%s%s", + prefix, + suffix, + "".equals(suffix) + ? "" + : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/CreateStoreResponse.java b/src/main/java/dev/openfga/sdk/api/model/CreateStoreResponse.java index 36185e8..d1c6af4 100644 --- a/src/main/java/dev/openfga/sdk/api/model/CreateStoreResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/CreateStoreResponse.java @@ -54,15 +54,15 @@ public CreateStoreResponse id(String id) { * Get id * @return id **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getId() { return id; } @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setId(String id) { this.id = id; } @@ -76,15 +76,15 @@ public CreateStoreResponse name(String name) { * Get name * @return name **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getName() { return name; } @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setName(String name) { this.name = name; } @@ -98,15 +98,15 @@ public CreateStoreResponse createdAt(OffsetDateTime createdAt) { * Get createdAt * @return createdAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CREATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getCreatedAt() { return createdAt; } @JsonProperty(JSON_PROPERTY_CREATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; } @@ -120,15 +120,15 @@ public CreateStoreResponse updatedAt(OffsetDateTime updatedAt) { * Get updatedAt * @return updatedAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_UPDATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getUpdatedAt() { return updatedAt; } @JsonProperty(JSON_PROPERTY_UPDATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ExpandRequest.java b/src/main/java/dev/openfga/sdk/api/model/ExpandRequest.java index 79a9eca..28203e8 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ExpandRequest.java +++ b/src/main/java/dev/openfga/sdk/api/model/ExpandRequest.java @@ -26,14 +26,14 @@ @JsonPropertyOrder({ExpandRequest.JSON_PROPERTY_TUPLE_KEY, ExpandRequest.JSON_PROPERTY_AUTHORIZATION_MODEL_ID}) public class ExpandRequest { public static final String JSON_PROPERTY_TUPLE_KEY = "tuple_key"; - private TupleKey tupleKey; + private ExpandRequestTupleKey tupleKey; public static final String JSON_PROPERTY_AUTHORIZATION_MODEL_ID = "authorization_model_id"; private String authorizationModelId; public ExpandRequest() {} - public ExpandRequest tupleKey(TupleKey tupleKey) { + public ExpandRequest tupleKey(ExpandRequestTupleKey tupleKey) { this.tupleKey = tupleKey; return this; } @@ -45,13 +45,13 @@ public ExpandRequest tupleKey(TupleKey tupleKey) { @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public TupleKey getTupleKey() { + public ExpandRequestTupleKey getTupleKey() { return tupleKey; } @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.ALWAYS) - public void setTupleKey(TupleKey tupleKey) { + public void setTupleKey(ExpandRequestTupleKey tupleKey) { this.tupleKey = tupleKey; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ExpandRequestTupleKey.java b/src/main/java/dev/openfga/sdk/api/model/ExpandRequestTupleKey.java new file mode 100644 index 0000000..f233145 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/ExpandRequestTupleKey.java @@ -0,0 +1,176 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * ExpandRequestTupleKey + */ +@JsonPropertyOrder({ExpandRequestTupleKey.JSON_PROPERTY_RELATION, ExpandRequestTupleKey.JSON_PROPERTY_OBJECT}) +public class ExpandRequestTupleKey { + public static final String JSON_PROPERTY_RELATION = "relation"; + private String relation; + + public static final String JSON_PROPERTY_OBJECT = "object"; + private String _object; + + public ExpandRequestTupleKey() {} + + public ExpandRequestTupleKey relation(String relation) { + this.relation = relation; + return this; + } + + /** + * Get relation + * @return relation + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getRelation() { + return relation; + } + + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setRelation(String relation) { + this.relation = relation; + } + + public ExpandRequestTupleKey _object(String _object) { + this._object = _object; + return this; + } + + /** + * Get _object + * @return _object + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getObject() { + return _object; + } + + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setObject(String _object) { + this._object = _object; + } + + /** + * Return true if this ExpandRequestTupleKey object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ExpandRequestTupleKey expandRequestTupleKey = (ExpandRequestTupleKey) o; + return Objects.equals(this.relation, expandRequestTupleKey.relation) + && Objects.equals(this._object, expandRequestTupleKey._object); + } + + @Override + public int hashCode() { + return Objects.hash(relation, _object); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ExpandRequestTupleKey {\n"); + sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); + sb.append(" _object: ").append(toIndentedString(_object)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `relation` to the URL query string + if (getRelation() != null) { + joiner.add(String.format( + "%srelation%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getRelation()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `object` to the URL query string + if (getObject() != null) { + joiner.add(String.format( + "%sobject%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getObject()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/GetStoreResponse.java b/src/main/java/dev/openfga/sdk/api/model/GetStoreResponse.java index 2bcd2e6..af309ad 100644 --- a/src/main/java/dev/openfga/sdk/api/model/GetStoreResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/GetStoreResponse.java @@ -54,15 +54,15 @@ public GetStoreResponse id(String id) { * Get id * @return id **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getId() { return id; } @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setId(String id) { this.id = id; } @@ -76,15 +76,15 @@ public GetStoreResponse name(String name) { * Get name * @return name **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getName() { return name; } @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setName(String name) { this.name = name; } @@ -98,15 +98,15 @@ public GetStoreResponse createdAt(OffsetDateTime createdAt) { * Get createdAt * @return createdAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CREATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getCreatedAt() { return createdAt; } @JsonProperty(JSON_PROPERTY_CREATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; } @@ -120,15 +120,15 @@ public GetStoreResponse updatedAt(OffsetDateTime updatedAt) { * Get updatedAt * @return updatedAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_UPDATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getUpdatedAt() { return updatedAt; } @JsonProperty(JSON_PROPERTY_UPDATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ListObjectsRequest.java b/src/main/java/dev/openfga/sdk/api/model/ListObjectsRequest.java index 72e85ce..64090fe 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ListObjectsRequest.java +++ b/src/main/java/dev/openfga/sdk/api/model/ListObjectsRequest.java @@ -28,7 +28,8 @@ ListObjectsRequest.JSON_PROPERTY_TYPE, ListObjectsRequest.JSON_PROPERTY_RELATION, ListObjectsRequest.JSON_PROPERTY_USER, - ListObjectsRequest.JSON_PROPERTY_CONTEXTUAL_TUPLES + ListObjectsRequest.JSON_PROPERTY_CONTEXTUAL_TUPLES, + ListObjectsRequest.JSON_PROPERTY_CONTEXT }) public class ListObjectsRequest { public static final String JSON_PROPERTY_AUTHORIZATION_MODEL_ID = "authorization_model_id"; @@ -46,6 +47,9 @@ public class ListObjectsRequest { public static final String JSON_PROPERTY_CONTEXTUAL_TUPLES = "contextual_tuples"; private ContextualTupleKeys contextualTuples; + public static final String JSON_PROPERTY_CONTEXT = "context"; + private Object context; + public ListObjectsRequest() {} public ListObjectsRequest authorizationModelId(String authorizationModelId) { @@ -158,6 +162,28 @@ public void setContextualTuples(ContextualTupleKeys contextualTuples) { this.contextualTuples = contextualTuples; } + public ListObjectsRequest context(Object context) { + this.context = context; + return this; + } + + /** + * Additional request context that will be used to evaluate any ABAC conditions encountered in the query evaluation. + * @return context + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CONTEXT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Object getContext() { + return context; + } + + @JsonProperty(JSON_PROPERTY_CONTEXT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setContext(Object context) { + this.context = context; + } + /** * Return true if this ListObjects_request object is equal to o. */ @@ -174,12 +200,13 @@ public boolean equals(Object o) { && Objects.equals(this.type, listObjectsRequest.type) && Objects.equals(this.relation, listObjectsRequest.relation) && Objects.equals(this.user, listObjectsRequest.user) - && Objects.equals(this.contextualTuples, listObjectsRequest.contextualTuples); + && Objects.equals(this.contextualTuples, listObjectsRequest.contextualTuples) + && Objects.equals(this.context, listObjectsRequest.context); } @Override public int hashCode() { - return Objects.hash(authorizationModelId, type, relation, user, contextualTuples); + return Objects.hash(authorizationModelId, type, relation, user, contextualTuples, context); } @Override @@ -195,6 +222,7 @@ public String toString() { sb.append(" contextualTuples: ") .append(toIndentedString(contextualTuples)) .append("\n"); + sb.append(" context: ").append(toIndentedString(context)).append("\n"); sb.append("}"); return sb.toString(); } @@ -287,6 +315,16 @@ public String toUrlQueryString(String prefix) { joiner.add(getContextualTuples().toUrlQueryString(prefix + "contextual_tuples" + suffix)); } + // add `context` to the URL query string + if (getContext() != null) { + joiner.add(String.format( + "%scontext%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getContext()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + return joiner.toString(); } } diff --git a/src/main/java/dev/openfga/sdk/api/model/ListObjectsResponse.java b/src/main/java/dev/openfga/sdk/api/model/ListObjectsResponse.java index 27aea7a..c7ad1c7 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ListObjectsResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/ListObjectsResponse.java @@ -49,15 +49,15 @@ public ListObjectsResponse addObjectsItem(String objectsItem) { * Get objects * @return objects **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_OBJECTS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getObjects() { return objects; } @JsonProperty(JSON_PROPERTY_OBJECTS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setObjects(List objects) { this.objects = objects; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ListStoresResponse.java b/src/main/java/dev/openfga/sdk/api/model/ListStoresResponse.java index 350e052..4672246 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ListStoresResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/ListStoresResponse.java @@ -52,15 +52,15 @@ public ListStoresResponse addStoresItem(Store storesItem) { * Get stores * @return stores **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_STORES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getStores() { return stores; } @JsonProperty(JSON_PROPERTY_STORES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setStores(List stores) { this.stores = stores; } @@ -74,15 +74,15 @@ public ListStoresResponse continuationToken(String continuationToken) { * The continuation token will be empty if there are no more stores. * @return continuationToken **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CONTINUATION_TOKEN) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getContinuationToken() { return continuationToken; } @JsonProperty(JSON_PROPERTY_CONTINUATION_TOKEN) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setContinuationToken(String continuationToken) { this.continuationToken = continuationToken; } diff --git a/src/main/java/dev/openfga/sdk/api/model/Node.java b/src/main/java/dev/openfga/sdk/api/model/Node.java index 84e3333..29f903c 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Node.java +++ b/src/main/java/dev/openfga/sdk/api/model/Node.java @@ -57,15 +57,15 @@ public Node name(String name) { * Get name * @return name **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getName() { return name; } @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setName(String name) { this.name = name; } diff --git a/src/main/java/dev/openfga/sdk/api/model/Nodes.java b/src/main/java/dev/openfga/sdk/api/model/Nodes.java index a783c09..2dba8dd 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Nodes.java +++ b/src/main/java/dev/openfga/sdk/api/model/Nodes.java @@ -47,15 +47,15 @@ public Nodes addNodesItem(Node nodesItem) { * Get nodes * @return nodes **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_NODES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getNodes() { return nodes; } @JsonProperty(JSON_PROPERTY_NODES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setNodes(List nodes) { this.nodes = nodes; } diff --git a/src/main/java/dev/openfga/sdk/api/model/NullValue.java b/src/main/java/dev/openfga/sdk/api/model/NullValue.java new file mode 100644 index 0000000..d2718bf --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/NullValue.java @@ -0,0 +1,65 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * `NullValue` is a singleton enumeration to represent the null value for the `Value` type union. The JSON representation for `NullValue` is JSON `null`. - NULL_VALUE: Null value. + */ +public enum NullValue { + NULL_VALUE("NULL_VALUE"), + + UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api"); + + private String value; + + NullValue(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static NullValue fromValue(String value) { + for (NullValue b : NullValue.values()) { + if (b.value.equals(value)) { + return b; + } + } + return UNKNOWN_DEFAULT_OPEN_API; + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/ReadAssertionsResponse.java b/src/main/java/dev/openfga/sdk/api/model/ReadAssertionsResponse.java index 4314dd1..e984d69 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ReadAssertionsResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/ReadAssertionsResponse.java @@ -47,15 +47,15 @@ public ReadAssertionsResponse authorizationModelId(String authorizationModelId) * Get authorizationModelId * @return authorizationModelId **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_AUTHORIZATION_MODEL_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getAuthorizationModelId() { return authorizationModelId; } @JsonProperty(JSON_PROPERTY_AUTHORIZATION_MODEL_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setAuthorizationModelId(String authorizationModelId) { this.authorizationModelId = authorizationModelId; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ReadAuthorizationModelsResponse.java b/src/main/java/dev/openfga/sdk/api/model/ReadAuthorizationModelsResponse.java index 99ceaed..405e24c 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ReadAuthorizationModelsResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/ReadAuthorizationModelsResponse.java @@ -55,15 +55,15 @@ public ReadAuthorizationModelsResponse addAuthorizationModelsItem(AuthorizationM * Get authorizationModels * @return authorizationModels **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_AUTHORIZATION_MODELS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getAuthorizationModels() { return authorizationModels; } @JsonProperty(JSON_PROPERTY_AUTHORIZATION_MODELS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setAuthorizationModels(List authorizationModels) { this.authorizationModels = authorizationModels; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ReadChangesResponse.java b/src/main/java/dev/openfga/sdk/api/model/ReadChangesResponse.java index e376e84..525ca9f 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ReadChangesResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/ReadChangesResponse.java @@ -52,15 +52,15 @@ public ReadChangesResponse addChangesItem(TupleChange changesItem) { * Get changes * @return changes **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CHANGES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getChanges() { return changes; } @JsonProperty(JSON_PROPERTY_CHANGES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setChanges(List changes) { this.changes = changes; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ReadRequest.java b/src/main/java/dev/openfga/sdk/api/model/ReadRequest.java index 07829dc..d3583ad 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ReadRequest.java +++ b/src/main/java/dev/openfga/sdk/api/model/ReadRequest.java @@ -30,7 +30,7 @@ }) public class ReadRequest { public static final String JSON_PROPERTY_TUPLE_KEY = "tuple_key"; - private TupleKey tupleKey; + private ReadRequestTupleKey tupleKey; public static final String JSON_PROPERTY_PAGE_SIZE = "page_size"; private Integer pageSize; @@ -40,7 +40,7 @@ public class ReadRequest { public ReadRequest() {} - public ReadRequest tupleKey(TupleKey tupleKey) { + public ReadRequest tupleKey(ReadRequestTupleKey tupleKey) { this.tupleKey = tupleKey; return this; } @@ -52,13 +52,13 @@ public ReadRequest tupleKey(TupleKey tupleKey) { @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public TupleKey getTupleKey() { + public ReadRequestTupleKey getTupleKey() { return tupleKey; } @JsonProperty(JSON_PROPERTY_TUPLE_KEY) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setTupleKey(TupleKey tupleKey) { + public void setTupleKey(ReadRequestTupleKey tupleKey) { this.tupleKey = tupleKey; } diff --git a/src/main/java/dev/openfga/sdk/api/model/ReadRequestTupleKey.java b/src/main/java/dev/openfga/sdk/api/model/ReadRequestTupleKey.java new file mode 100644 index 0000000..bcc67a4 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/ReadRequestTupleKey.java @@ -0,0 +1,217 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * ReadRequestTupleKey + */ +@JsonPropertyOrder({ + ReadRequestTupleKey.JSON_PROPERTY_USER, + ReadRequestTupleKey.JSON_PROPERTY_RELATION, + ReadRequestTupleKey.JSON_PROPERTY_OBJECT +}) +public class ReadRequestTupleKey { + public static final String JSON_PROPERTY_USER = "user"; + private String user; + + public static final String JSON_PROPERTY_RELATION = "relation"; + private String relation; + + public static final String JSON_PROPERTY_OBJECT = "object"; + private String _object; + + public ReadRequestTupleKey() {} + + public ReadRequestTupleKey user(String user) { + this.user = user; + return this; + } + + /** + * Get user + * @return user + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getUser() { + return user; + } + + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setUser(String user) { + this.user = user; + } + + public ReadRequestTupleKey relation(String relation) { + this.relation = relation; + return this; + } + + /** + * Get relation + * @return relation + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getRelation() { + return relation; + } + + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setRelation(String relation) { + this.relation = relation; + } + + public ReadRequestTupleKey _object(String _object) { + this._object = _object; + return this; + } + + /** + * Get _object + * @return _object + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getObject() { + return _object; + } + + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setObject(String _object) { + this._object = _object; + } + + /** + * Return true if this ReadRequestTupleKey object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ReadRequestTupleKey readRequestTupleKey = (ReadRequestTupleKey) o; + return Objects.equals(this.user, readRequestTupleKey.user) + && Objects.equals(this.relation, readRequestTupleKey.relation) + && Objects.equals(this._object, readRequestTupleKey._object); + } + + @Override + public int hashCode() { + return Objects.hash(user, relation, _object); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ReadRequestTupleKey {\n"); + sb.append(" user: ").append(toIndentedString(user)).append("\n"); + sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); + sb.append(" _object: ").append(toIndentedString(_object)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `user` to the URL query string + if (getUser() != null) { + joiner.add(String.format( + "%suser%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getUser()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `relation` to the URL query string + if (getRelation() != null) { + joiner.add(String.format( + "%srelation%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getRelation()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `object` to the URL query string + if (getObject() != null) { + joiner.add(String.format( + "%sobject%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getObject()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/ReadResponse.java b/src/main/java/dev/openfga/sdk/api/model/ReadResponse.java index a3436a2..dfa095a 100644 --- a/src/main/java/dev/openfga/sdk/api/model/ReadResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/ReadResponse.java @@ -52,15 +52,15 @@ public ReadResponse addTuplesItem(Tuple tuplesItem) { * Get tuples * @return tuples **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getTuples() { return tuples; } @JsonProperty(JSON_PROPERTY_TUPLES) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTuples(List tuples) { this.tuples = tuples; } @@ -74,15 +74,15 @@ public ReadResponse continuationToken(String continuationToken) { * The continuation token will be empty if there are no more tuples. * @return continuationToken **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CONTINUATION_TOKEN) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getContinuationToken() { return continuationToken; } @JsonProperty(JSON_PROPERTY_CONTINUATION_TOKEN) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setContinuationToken(String continuationToken) { this.continuationToken = continuationToken; } diff --git a/src/main/java/dev/openfga/sdk/api/model/RelationReference.java b/src/main/java/dev/openfga/sdk/api/model/RelationReference.java index 7dadb43..a322e16 100644 --- a/src/main/java/dev/openfga/sdk/api/model/RelationReference.java +++ b/src/main/java/dev/openfga/sdk/api/model/RelationReference.java @@ -26,7 +26,8 @@ @JsonPropertyOrder({ RelationReference.JSON_PROPERTY_TYPE, RelationReference.JSON_PROPERTY_RELATION, - RelationReference.JSON_PROPERTY_WILDCARD + RelationReference.JSON_PROPERTY_WILDCARD, + RelationReference.JSON_PROPERTY_CONDITION }) public class RelationReference { public static final String JSON_PROPERTY_TYPE = "type"; @@ -38,6 +39,9 @@ public class RelationReference { public static final String JSON_PROPERTY_WILDCARD = "wildcard"; private Object wildcard; + public static final String JSON_PROPERTY_CONDITION = "condition"; + private String condition; + public RelationReference() {} public RelationReference type(String type) { @@ -106,6 +110,28 @@ public void setWildcard(Object wildcard) { this.wildcard = wildcard; } + public RelationReference condition(String condition) { + this.condition = condition; + return this; + } + + /** + * The name of a condition that is enforced over the allowed relation. + * @return condition + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CONDITION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public String getCondition() { + return condition; + } + + @JsonProperty(JSON_PROPERTY_CONDITION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setCondition(String condition) { + this.condition = condition; + } + /** * Return true if this RelationReference object is equal to o. */ @@ -120,12 +146,13 @@ public boolean equals(Object o) { RelationReference relationReference = (RelationReference) o; return Objects.equals(this.type, relationReference.type) && Objects.equals(this.relation, relationReference.relation) - && Objects.equals(this.wildcard, relationReference.wildcard); + && Objects.equals(this.wildcard, relationReference.wildcard) + && Objects.equals(this.condition, relationReference.condition); } @Override public int hashCode() { - return Objects.hash(type, relation, wildcard); + return Objects.hash(type, relation, wildcard, condition); } @Override @@ -135,6 +162,7 @@ public String toString() { sb.append(" type: ").append(toIndentedString(type)).append("\n"); sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); sb.append(" wildcard: ").append(toIndentedString(wildcard)).append("\n"); + sb.append(" condition: ").append(toIndentedString(condition)).append("\n"); sb.append("}"); return sb.toString(); } @@ -212,6 +240,16 @@ public String toUrlQueryString(String prefix) { .replaceAll("\\+", "%20"))); } + // add `condition` to the URL query string + if (getCondition() != null) { + joiner.add(String.format( + "%scondition%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getCondition()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + return joiner.toString(); } } diff --git a/src/main/java/dev/openfga/sdk/api/model/RelationshipCondition.java b/src/main/java/dev/openfga/sdk/api/model/RelationshipCondition.java new file mode 100644 index 0000000..e4a9f88 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/RelationshipCondition.java @@ -0,0 +1,176 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * RelationshipCondition + */ +@JsonPropertyOrder({RelationshipCondition.JSON_PROPERTY_NAME, RelationshipCondition.JSON_PROPERTY_CONTEXT}) +public class RelationshipCondition { + public static final String JSON_PROPERTY_NAME = "name"; + private String name; + + public static final String JSON_PROPERTY_CONTEXT = "context"; + private Object context; + + public RelationshipCondition() {} + + public RelationshipCondition name(String name) { + this.name = name; + return this; + } + + /** + * A reference (by name) of the relationship condition defined in the authorization model. + * @return name + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getName() { + return name; + } + + @JsonProperty(JSON_PROPERTY_NAME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setName(String name) { + this.name = name; + } + + public RelationshipCondition context(Object context) { + this.context = context; + return this; + } + + /** + * Additional context/data to persist along with the condition. The keys must match the parameters defined by the condition, and the value types must match the parameter type definitions. + * @return context + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CONTEXT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Object getContext() { + return context; + } + + @JsonProperty(JSON_PROPERTY_CONTEXT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setContext(Object context) { + this.context = context; + } + + /** + * Return true if this RelationshipCondition object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RelationshipCondition relationshipCondition = (RelationshipCondition) o; + return Objects.equals(this.name, relationshipCondition.name) + && Objects.equals(this.context, relationshipCondition.context); + } + + @Override + public int hashCode() { + return Objects.hash(name, context); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RelationshipCondition {\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" context: ").append(toIndentedString(context)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `name` to the URL query string + if (getName() != null) { + joiner.add(String.format( + "%sname%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getName()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `context` to the URL query string + if (getContext() != null) { + joiner.add(String.format( + "%scontext%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getContext()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/Store.java b/src/main/java/dev/openfga/sdk/api/model/Store.java index 30910d7..380284e 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Store.java +++ b/src/main/java/dev/openfga/sdk/api/model/Store.java @@ -58,15 +58,15 @@ public Store id(String id) { * Get id * @return id **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getId() { return id; } @JsonProperty(JSON_PROPERTY_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setId(String id) { this.id = id; } @@ -80,15 +80,15 @@ public Store name(String name) { * Get name * @return name **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getName() { return name; } @JsonProperty(JSON_PROPERTY_NAME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setName(String name) { this.name = name; } @@ -102,15 +102,15 @@ public Store createdAt(OffsetDateTime createdAt) { * Get createdAt * @return createdAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CREATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getCreatedAt() { return createdAt; } @JsonProperty(JSON_PROPERTY_CREATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; } @@ -124,15 +124,15 @@ public Store updatedAt(OffsetDateTime updatedAt) { * Get updatedAt * @return updatedAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_UPDATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getUpdatedAt() { return updatedAt; } @JsonProperty(JSON_PROPERTY_UPDATED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; } @@ -146,15 +146,15 @@ public Store deletedAt(OffsetDateTime deletedAt) { * Get deletedAt * @return deletedAt **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_DELETED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getDeletedAt() { return deletedAt; } @JsonProperty(JSON_PROPERTY_DELETED_AT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setDeletedAt(OffsetDateTime deletedAt) { this.deletedAt = deletedAt; } diff --git a/src/main/java/dev/openfga/sdk/api/model/Tuple.java b/src/main/java/dev/openfga/sdk/api/model/Tuple.java index 65f104e..606559f 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Tuple.java +++ b/src/main/java/dev/openfga/sdk/api/model/Tuple.java @@ -43,15 +43,15 @@ public Tuple key(TupleKey key) { * Get key * @return key **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_KEY) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public TupleKey getKey() { return key; } @JsonProperty(JSON_PROPERTY_KEY) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setKey(TupleKey key) { this.key = key; } @@ -65,15 +65,15 @@ public Tuple timestamp(OffsetDateTime timestamp) { * Get timestamp * @return timestamp **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TIMESTAMP) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getTimestamp() { return timestamp; } @JsonProperty(JSON_PROPERTY_TIMESTAMP) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTimestamp(OffsetDateTime timestamp) { this.timestamp = timestamp; } diff --git a/src/main/java/dev/openfga/sdk/api/model/TupleChange.java b/src/main/java/dev/openfga/sdk/api/model/TupleChange.java index d8d9949..281858b 100644 --- a/src/main/java/dev/openfga/sdk/api/model/TupleChange.java +++ b/src/main/java/dev/openfga/sdk/api/model/TupleChange.java @@ -50,15 +50,15 @@ public TupleChange tupleKey(TupleKey tupleKey) { * Get tupleKey * @return tupleKey **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLE_KEY) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public TupleKey getTupleKey() { return tupleKey; } @JsonProperty(JSON_PROPERTY_TUPLE_KEY) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTupleKey(TupleKey tupleKey) { this.tupleKey = tupleKey; } @@ -72,15 +72,15 @@ public TupleChange operation(TupleOperation operation) { * Get operation * @return operation **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_OPERATION) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public TupleOperation getOperation() { return operation; } @JsonProperty(JSON_PROPERTY_OPERATION) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setOperation(TupleOperation operation) { this.operation = operation; } @@ -94,15 +94,15 @@ public TupleChange timestamp(OffsetDateTime timestamp) { * Get timestamp * @return timestamp **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TIMESTAMP) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public OffsetDateTime getTimestamp() { return timestamp; } @JsonProperty(JSON_PROPERTY_TIMESTAMP) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTimestamp(OffsetDateTime timestamp) { this.timestamp = timestamp; } diff --git a/src/main/java/dev/openfga/sdk/api/model/TupleKey.java b/src/main/java/dev/openfga/sdk/api/model/TupleKey.java index a6e9cc6..bc4ed48 100644 --- a/src/main/java/dev/openfga/sdk/api/model/TupleKey.java +++ b/src/main/java/dev/openfga/sdk/api/model/TupleKey.java @@ -23,39 +23,47 @@ /** * TupleKey */ -@JsonPropertyOrder({TupleKey.JSON_PROPERTY_OBJECT, TupleKey.JSON_PROPERTY_RELATION, TupleKey.JSON_PROPERTY_USER}) +@JsonPropertyOrder({ + TupleKey.JSON_PROPERTY_USER, + TupleKey.JSON_PROPERTY_RELATION, + TupleKey.JSON_PROPERTY_OBJECT, + TupleKey.JSON_PROPERTY_CONDITION +}) public class TupleKey { - public static final String JSON_PROPERTY_OBJECT = "object"; - private String _object; + public static final String JSON_PROPERTY_USER = "user"; + private String user; public static final String JSON_PROPERTY_RELATION = "relation"; private String relation; - public static final String JSON_PROPERTY_USER = "user"; - private String user; + public static final String JSON_PROPERTY_OBJECT = "object"; + private String _object; + + public static final String JSON_PROPERTY_CONDITION = "condition"; + private RelationshipCondition condition; public TupleKey() {} - public TupleKey _object(String _object) { - this._object = _object; + public TupleKey user(String user) { + this.user = user; return this; } /** - * Get _object - * @return _object + * Get user + * @return user **/ - @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_OBJECT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public String getObject() { - return _object; + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getUser() { + return user; } - @JsonProperty(JSON_PROPERTY_OBJECT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setObject(String _object) { - this._object = _object; + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setUser(String user) { + this.user = user; } public TupleKey relation(String relation) { @@ -67,39 +75,61 @@ public TupleKey relation(String relation) { * Get relation * @return relation **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_RELATION) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getRelation() { return relation; } @JsonProperty(JSON_PROPERTY_RELATION) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setRelation(String relation) { this.relation = relation; } - public TupleKey user(String user) { - this.user = user; + public TupleKey _object(String _object) { + this._object = _object; return this; } /** - * Get user - * @return user + * Get _object + * @return _object + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getObject() { + return _object; + } + + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setObject(String _object) { + this._object = _object; + } + + public TupleKey condition(RelationshipCondition condition) { + this.condition = condition; + return this; + } + + /** + * Get condition + * @return condition **/ @javax.annotation.Nullable - @JsonProperty(JSON_PROPERTY_USER) + @JsonProperty(JSON_PROPERTY_CONDITION) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public String getUser() { - return user; + public RelationshipCondition getCondition() { + return condition; } - @JsonProperty(JSON_PROPERTY_USER) + @JsonProperty(JSON_PROPERTY_CONDITION) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setUser(String user) { - this.user = user; + public void setCondition(RelationshipCondition condition) { + this.condition = condition; } /** @@ -114,23 +144,25 @@ public boolean equals(Object o) { return false; } TupleKey tupleKey = (TupleKey) o; - return Objects.equals(this._object, tupleKey._object) + return Objects.equals(this.user, tupleKey.user) && Objects.equals(this.relation, tupleKey.relation) - && Objects.equals(this.user, tupleKey.user); + && Objects.equals(this._object, tupleKey._object) + && Objects.equals(this.condition, tupleKey.condition); } @Override public int hashCode() { - return Objects.hash(_object, relation, user); + return Objects.hash(user, relation, _object, condition); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class TupleKey {\n"); - sb.append(" _object: ").append(toIndentedString(_object)).append("\n"); - sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); sb.append(" user: ").append(toIndentedString(user)).append("\n"); + sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); + sb.append(" _object: ").append(toIndentedString(_object)).append("\n"); + sb.append(" condition: ").append(toIndentedString(condition)).append("\n"); sb.append("}"); return sb.toString(); } @@ -178,13 +210,13 @@ public String toUrlQueryString(String prefix) { StringJoiner joiner = new StringJoiner("&"); - // add `object` to the URL query string - if (getObject() != null) { + // add `user` to the URL query string + if (getUser() != null) { joiner.add(String.format( - "%sobject%s=%s", + "%suser%s=%s", prefix, suffix, - URLEncoder.encode(String.valueOf(getObject()), StandardCharsets.UTF_8) + URLEncoder.encode(String.valueOf(getUser()), StandardCharsets.UTF_8) .replaceAll("\\+", "%20"))); } @@ -198,16 +230,21 @@ public String toUrlQueryString(String prefix) { .replaceAll("\\+", "%20"))); } - // add `user` to the URL query string - if (getUser() != null) { + // add `object` to the URL query string + if (getObject() != null) { joiner.add(String.format( - "%suser%s=%s", + "%sobject%s=%s", prefix, suffix, - URLEncoder.encode(String.valueOf(getUser()), StandardCharsets.UTF_8) + URLEncoder.encode(String.valueOf(getObject()), StandardCharsets.UTF_8) .replaceAll("\\+", "%20"))); } + // add `condition` to the URL query string + if (getCondition() != null) { + joiner.add(getCondition().toUrlQueryString(prefix + "condition" + suffix)); + } + return joiner.toString(); } } diff --git a/src/main/java/dev/openfga/sdk/api/model/TupleKeyWithoutCondition.java b/src/main/java/dev/openfga/sdk/api/model/TupleKeyWithoutCondition.java new file mode 100644 index 0000000..e539ee6 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/TupleKeyWithoutCondition.java @@ -0,0 +1,217 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * TupleKeyWithoutCondition + */ +@JsonPropertyOrder({ + TupleKeyWithoutCondition.JSON_PROPERTY_USER, + TupleKeyWithoutCondition.JSON_PROPERTY_RELATION, + TupleKeyWithoutCondition.JSON_PROPERTY_OBJECT +}) +public class TupleKeyWithoutCondition { + public static final String JSON_PROPERTY_USER = "user"; + private String user; + + public static final String JSON_PROPERTY_RELATION = "relation"; + private String relation; + + public static final String JSON_PROPERTY_OBJECT = "object"; + private String _object; + + public TupleKeyWithoutCondition() {} + + public TupleKeyWithoutCondition user(String user) { + this.user = user; + return this; + } + + /** + * Get user + * @return user + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getUser() { + return user; + } + + @JsonProperty(JSON_PROPERTY_USER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setUser(String user) { + this.user = user; + } + + public TupleKeyWithoutCondition relation(String relation) { + this.relation = relation; + return this; + } + + /** + * Get relation + * @return relation + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getRelation() { + return relation; + } + + @JsonProperty(JSON_PROPERTY_RELATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setRelation(String relation) { + this.relation = relation; + } + + public TupleKeyWithoutCondition _object(String _object) { + this._object = _object; + return this; + } + + /** + * Get _object + * @return _object + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public String getObject() { + return _object; + } + + @JsonProperty(JSON_PROPERTY_OBJECT) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setObject(String _object) { + this._object = _object; + } + + /** + * Return true if this TupleKeyWithoutCondition object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TupleKeyWithoutCondition tupleKeyWithoutCondition = (TupleKeyWithoutCondition) o; + return Objects.equals(this.user, tupleKeyWithoutCondition.user) + && Objects.equals(this.relation, tupleKeyWithoutCondition.relation) + && Objects.equals(this._object, tupleKeyWithoutCondition._object); + } + + @Override + public int hashCode() { + return Objects.hash(user, relation, _object); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class TupleKeyWithoutCondition {\n"); + sb.append(" user: ").append(toIndentedString(user)).append("\n"); + sb.append(" relation: ").append(toIndentedString(relation)).append("\n"); + sb.append(" _object: ").append(toIndentedString(_object)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `user` to the URL query string + if (getUser() != null) { + joiner.add(String.format( + "%suser%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getUser()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `relation` to the URL query string + if (getRelation() != null) { + joiner.add(String.format( + "%srelation%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getRelation()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + // add `object` to the URL query string + if (getObject() != null) { + joiner.add(String.format( + "%sobject%s=%s", + prefix, + suffix, + URLEncoder.encode(String.valueOf(getObject()), StandardCharsets.UTF_8) + .replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/TupleToUserset.java b/src/main/java/dev/openfga/sdk/api/model/TupleToUserset.java index 851db6c..3245f44 100644 --- a/src/main/java/dev/openfga/sdk/api/model/TupleToUserset.java +++ b/src/main/java/dev/openfga/sdk/api/model/TupleToUserset.java @@ -40,15 +40,15 @@ public TupleToUserset tupleset(ObjectRelation tupleset) { * Get tupleset * @return tupleset **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLESET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public ObjectRelation getTupleset() { return tupleset; } @JsonProperty(JSON_PROPERTY_TUPLESET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTupleset(ObjectRelation tupleset) { this.tupleset = tupleset; } @@ -62,15 +62,15 @@ public TupleToUserset computedUserset(ObjectRelation computedUserset) { * Get computedUserset * @return computedUserset **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_COMPUTED_USERSET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public ObjectRelation getComputedUserset() { return computedUserset; } @JsonProperty(JSON_PROPERTY_COMPUTED_USERSET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setComputedUserset(ObjectRelation computedUserset) { this.computedUserset = computedUserset; } diff --git a/src/main/java/dev/openfga/sdk/api/model/TypeName.java b/src/main/java/dev/openfga/sdk/api/model/TypeName.java new file mode 100644 index 0000000..74f94ba --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/TypeName.java @@ -0,0 +1,87 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets TypeName + */ +public enum TypeName { + UNSPECIFIED("TYPE_NAME_UNSPECIFIED"), + + ANY("TYPE_NAME_ANY"), + + BOOL("TYPE_NAME_BOOL"), + + STRING("TYPE_NAME_STRING"), + + INT("TYPE_NAME_INT"), + + UINT("TYPE_NAME_UINT"), + + DOUBLE("TYPE_NAME_DOUBLE"), + + DURATION("TYPE_NAME_DURATION"), + + TIMESTAMP("TYPE_NAME_TIMESTAMP"), + + MAP("TYPE_NAME_MAP"), + + LIST("TYPE_NAME_LIST"), + + IPADDRESS("TYPE_NAME_IPADDRESS"), + + UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api"); + + private String value; + + TypeName(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static TypeName fromValue(String value) { + for (TypeName b : TypeName.values()) { + if (b.value.equals(value)) { + return b; + } + } + return UNKNOWN_DEFAULT_OPEN_API; + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/Users.java b/src/main/java/dev/openfga/sdk/api/model/Users.java index e5b9119..d8a6d12 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Users.java +++ b/src/main/java/dev/openfga/sdk/api/model/Users.java @@ -49,15 +49,15 @@ public Users addUsersItem(String usersItem) { * Get users * @return users **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_USERS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getUsers() { return users; } @JsonProperty(JSON_PROPERTY_USERS) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setUsers(List users) { this.users = users; } diff --git a/src/main/java/dev/openfga/sdk/api/model/UsersetTreeDifference.java b/src/main/java/dev/openfga/sdk/api/model/UsersetTreeDifference.java index d0990c2..f85115f 100644 --- a/src/main/java/dev/openfga/sdk/api/model/UsersetTreeDifference.java +++ b/src/main/java/dev/openfga/sdk/api/model/UsersetTreeDifference.java @@ -40,15 +40,15 @@ public UsersetTreeDifference base(Node base) { * Get base * @return base **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_BASE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public Node getBase() { return base; } @JsonProperty(JSON_PROPERTY_BASE) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setBase(Node base) { this.base = base; } @@ -62,15 +62,15 @@ public UsersetTreeDifference subtract(Node subtract) { * Get subtract * @return subtract **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_SUBTRACT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public Node getSubtract() { return subtract; } @JsonProperty(JSON_PROPERTY_SUBTRACT) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setSubtract(Node subtract) { this.subtract = subtract; } diff --git a/src/main/java/dev/openfga/sdk/api/model/UsersetTreeTupleToUserset.java b/src/main/java/dev/openfga/sdk/api/model/UsersetTreeTupleToUserset.java index fa50eca..d73b4b1 100644 --- a/src/main/java/dev/openfga/sdk/api/model/UsersetTreeTupleToUserset.java +++ b/src/main/java/dev/openfga/sdk/api/model/UsersetTreeTupleToUserset.java @@ -44,15 +44,15 @@ public UsersetTreeTupleToUserset tupleset(String tupleset) { * Get tupleset * @return tupleset **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_TUPLESET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getTupleset() { return tupleset; } @JsonProperty(JSON_PROPERTY_TUPLESET) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setTupleset(String tupleset) { this.tupleset = tupleset; } @@ -74,15 +74,15 @@ public UsersetTreeTupleToUserset addComputedItem(Computed computedItem) { * Get computed * @return computed **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_COMPUTED) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getComputed() { return computed; } @JsonProperty(JSON_PROPERTY_COMPUTED) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setComputed(List computed) { this.computed = computed; } diff --git a/src/main/java/dev/openfga/sdk/api/model/Usersets.java b/src/main/java/dev/openfga/sdk/api/model/Usersets.java index bcbdcab..122f9d4 100644 --- a/src/main/java/dev/openfga/sdk/api/model/Usersets.java +++ b/src/main/java/dev/openfga/sdk/api/model/Usersets.java @@ -47,15 +47,15 @@ public Usersets addChildItem(Userset childItem) { * Get child * @return child **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_CHILD) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public List getChild() { return child; } @JsonProperty(JSON_PROPERTY_CHILD) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setChild(List child) { this.child = child; } diff --git a/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java b/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java index 40147eb..567c6f7 100644 --- a/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java +++ b/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java @@ -18,7 +18,9 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.StringJoiner; @@ -27,7 +29,8 @@ */ @JsonPropertyOrder({ WriteAuthorizationModelRequest.JSON_PROPERTY_TYPE_DEFINITIONS, - WriteAuthorizationModelRequest.JSON_PROPERTY_SCHEMA_VERSION + WriteAuthorizationModelRequest.JSON_PROPERTY_SCHEMA_VERSION, + WriteAuthorizationModelRequest.JSON_PROPERTY_CONDITIONS }) public class WriteAuthorizationModelRequest { public static final String JSON_PROPERTY_TYPE_DEFINITIONS = "type_definitions"; @@ -36,6 +39,9 @@ public class WriteAuthorizationModelRequest { public static final String JSON_PROPERTY_SCHEMA_VERSION = "schema_version"; private String schemaVersion; + public static final String JSON_PROPERTY_CONDITIONS = "conditions"; + private Map conditions = new HashMap<>(); + public WriteAuthorizationModelRequest() {} public WriteAuthorizationModelRequest typeDefinitions(List typeDefinitions) { @@ -77,19 +83,49 @@ public WriteAuthorizationModelRequest schemaVersion(String schemaVersion) { * Get schemaVersion * @return schemaVersion **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_SCHEMA_VERSION) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getSchemaVersion() { return schemaVersion; } @JsonProperty(JSON_PROPERTY_SCHEMA_VERSION) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setSchemaVersion(String schemaVersion) { this.schemaVersion = schemaVersion; } + public WriteAuthorizationModelRequest conditions(Map conditions) { + this.conditions = conditions; + return this; + } + + public WriteAuthorizationModelRequest putConditionsItem(String key, Condition conditionsItem) { + if (this.conditions == null) { + this.conditions = new HashMap<>(); + } + this.conditions.put(key, conditionsItem); + return this; + } + + /** + * Get conditions + * @return conditions + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CONDITIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public Map getConditions() { + return conditions; + } + + @JsonProperty(JSON_PROPERTY_CONDITIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setConditions(Map conditions) { + this.conditions = conditions; + } + /** * Return true if this WriteAuthorizationModel_request object is equal to o. */ @@ -103,12 +139,13 @@ public boolean equals(Object o) { } WriteAuthorizationModelRequest writeAuthorizationModelRequest = (WriteAuthorizationModelRequest) o; return Objects.equals(this.typeDefinitions, writeAuthorizationModelRequest.typeDefinitions) - && Objects.equals(this.schemaVersion, writeAuthorizationModelRequest.schemaVersion); + && Objects.equals(this.schemaVersion, writeAuthorizationModelRequest.schemaVersion) + && Objects.equals(this.conditions, writeAuthorizationModelRequest.conditions); } @Override public int hashCode() { - return Objects.hash(typeDefinitions, schemaVersion); + return Objects.hash(typeDefinitions, schemaVersion, conditions); } @Override @@ -119,6 +156,7 @@ public String toString() { .append(toIndentedString(typeDefinitions)) .append("\n"); sb.append(" schemaVersion: ").append(toIndentedString(schemaVersion)).append("\n"); + sb.append(" conditions: ").append(toIndentedString(conditions)).append("\n"); sb.append("}"); return sb.toString(); } @@ -193,6 +231,23 @@ public String toUrlQueryString(String prefix) { .replaceAll("\\+", "%20"))); } + // add `conditions` to the URL query string + if (getConditions() != null) { + for (String _key : getConditions().keySet()) { + if (getConditions().get(_key) != null) { + joiner.add(getConditions() + .get(_key) + .toUrlQueryString(String.format( + "%sconditions%s%s", + prefix, + suffix, + "".equals(suffix) + ? "" + : String.format("%s%d%s", containerPrefix, _key, containerSuffix)))); + } + } + } + return joiner.toString(); } } diff --git a/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java b/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java index 42115c8..a08e646 100644 --- a/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java +++ b/src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java @@ -39,15 +39,15 @@ public WriteAuthorizationModelResponse authorizationModelId(String authorization * Get authorizationModelId * @return authorizationModelId **/ - @javax.annotation.Nullable + @javax.annotation.Nonnull @JsonProperty(JSON_PROPERTY_AUTHORIZATION_MODEL_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public String getAuthorizationModelId() { return authorizationModelId; } @JsonProperty(JSON_PROPERTY_AUTHORIZATION_MODEL_ID) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) public void setAuthorizationModelId(String authorizationModelId) { this.authorizationModelId = authorizationModelId; } diff --git a/src/main/java/dev/openfga/sdk/api/model/WriteRequest.java b/src/main/java/dev/openfga/sdk/api/model/WriteRequest.java index 6efa272..a5db942 100644 --- a/src/main/java/dev/openfga/sdk/api/model/WriteRequest.java +++ b/src/main/java/dev/openfga/sdk/api/model/WriteRequest.java @@ -30,17 +30,17 @@ }) public class WriteRequest { public static final String JSON_PROPERTY_WRITES = "writes"; - private TupleKeys writes; + private WriteRequestWrites writes; public static final String JSON_PROPERTY_DELETES = "deletes"; - private TupleKeys deletes; + private WriteRequestDeletes deletes; public static final String JSON_PROPERTY_AUTHORIZATION_MODEL_ID = "authorization_model_id"; private String authorizationModelId; public WriteRequest() {} - public WriteRequest writes(TupleKeys writes) { + public WriteRequest writes(WriteRequestWrites writes) { this.writes = writes; return this; } @@ -52,17 +52,17 @@ public WriteRequest writes(TupleKeys writes) { @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_WRITES) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public TupleKeys getWrites() { + public WriteRequestWrites getWrites() { return writes; } @JsonProperty(JSON_PROPERTY_WRITES) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setWrites(TupleKeys writes) { + public void setWrites(WriteRequestWrites writes) { this.writes = writes; } - public WriteRequest deletes(TupleKeys deletes) { + public WriteRequest deletes(WriteRequestDeletes deletes) { this.deletes = deletes; return this; } @@ -74,13 +74,13 @@ public WriteRequest deletes(TupleKeys deletes) { @javax.annotation.Nullable @JsonProperty(JSON_PROPERTY_DELETES) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public TupleKeys getDeletes() { + public WriteRequestDeletes getDeletes() { return deletes; } @JsonProperty(JSON_PROPERTY_DELETES) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setDeletes(TupleKeys deletes) { + public void setDeletes(WriteRequestDeletes deletes) { this.deletes = deletes; } diff --git a/src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java b/src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java new file mode 100644 index 0000000..ccd80b0 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java @@ -0,0 +1,154 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * WriteRequestDeletes + */ +@JsonPropertyOrder({WriteRequestDeletes.JSON_PROPERTY_TUPLE_KEYS}) +public class WriteRequestDeletes { + public static final String JSON_PROPERTY_TUPLE_KEYS = "tuple_keys"; + private List tupleKeys = new ArrayList<>(); + + public WriteRequestDeletes() {} + + public WriteRequestDeletes tupleKeys(List tupleKeys) { + this.tupleKeys = tupleKeys; + return this; + } + + public WriteRequestDeletes addTupleKeysItem(TupleKeyWithoutCondition tupleKeysItem) { + if (this.tupleKeys == null) { + this.tupleKeys = new ArrayList<>(); + } + this.tupleKeys.add(tupleKeysItem); + return this; + } + + /** + * Get tupleKeys + * @return tupleKeys + **/ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_TUPLE_KEYS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public List getTupleKeys() { + return tupleKeys; + } + + @JsonProperty(JSON_PROPERTY_TUPLE_KEYS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setTupleKeys(List tupleKeys) { + this.tupleKeys = tupleKeys; + } + + /** + * Return true if this WriteRequestDeletes object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + WriteRequestDeletes writeRequestDeletes = (WriteRequestDeletes) o; + return Objects.equals(this.tupleKeys, writeRequestDeletes.tupleKeys); + } + + @Override + public int hashCode() { + return Objects.hash(tupleKeys); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class WriteRequestDeletes {\n"); + sb.append(" tupleKeys: ").append(toIndentedString(tupleKeys)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `tuple_keys` to the URL query string + if (getTupleKeys() != null) { + for (int i = 0; i < getTupleKeys().size(); i++) { + if (getTupleKeys().get(i) != null) { + joiner.add(getTupleKeys() + .get(i) + .toUrlQueryString(String.format( + "%stuple_keys%s%s", + prefix, + suffix, + "".equals(suffix) + ? "" + : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + + return joiner.toString(); + } +} diff --git a/src/main/java/dev/openfga/sdk/api/model/TupleKeys.java b/src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java similarity index 87% rename from src/main/java/dev/openfga/sdk/api/model/TupleKeys.java rename to src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java index 764cbe6..5da9b6d 100644 --- a/src/main/java/dev/openfga/sdk/api/model/TupleKeys.java +++ b/src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java @@ -21,21 +21,21 @@ import java.util.StringJoiner; /** - * TupleKeys + * WriteRequestWrites */ -@JsonPropertyOrder({TupleKeys.JSON_PROPERTY_TUPLE_KEYS}) -public class TupleKeys { +@JsonPropertyOrder({WriteRequestWrites.JSON_PROPERTY_TUPLE_KEYS}) +public class WriteRequestWrites { public static final String JSON_PROPERTY_TUPLE_KEYS = "tuple_keys"; private List tupleKeys = new ArrayList<>(); - public TupleKeys() {} + public WriteRequestWrites() {} - public TupleKeys tupleKeys(List tupleKeys) { + public WriteRequestWrites tupleKeys(List tupleKeys) { this.tupleKeys = tupleKeys; return this; } - public TupleKeys addTupleKeysItem(TupleKey tupleKeysItem) { + public WriteRequestWrites addTupleKeysItem(TupleKey tupleKeysItem) { if (this.tupleKeys == null) { this.tupleKeys = new ArrayList<>(); } @@ -61,7 +61,7 @@ public void setTupleKeys(List tupleKeys) { } /** - * Return true if this TupleKeys object is equal to o. + * Return true if this WriteRequestWrites object is equal to o. */ @Override public boolean equals(Object o) { @@ -71,8 +71,8 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - TupleKeys tupleKeys = (TupleKeys) o; - return Objects.equals(this.tupleKeys, tupleKeys.tupleKeys); + WriteRequestWrites writeRequestWrites = (WriteRequestWrites) o; + return Objects.equals(this.tupleKeys, writeRequestWrites.tupleKeys); } @Override @@ -83,7 +83,7 @@ public int hashCode() { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("class TupleKeys {\n"); + sb.append("class WriteRequestWrites {\n"); sb.append(" tupleKeys: ").append(toIndentedString(tupleKeys)).append("\n"); sb.append("}"); return sb.toString(); diff --git a/src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java b/src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java index 74dc6b2..a1cad97 100644 --- a/src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java +++ b/src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java @@ -37,6 +37,8 @@ public class OpenFgaApiIntegrationTest { @BeforeEach public void initializeApi() throws Exception { + System.setProperty("HttpRequestAttempt.debug-logging", "enable"); + Configuration apiConfig = new Configuration().apiUrl("http://localhost:8080"); api = new OpenFgaApi(apiConfig); } @@ -120,7 +122,7 @@ public void readAuthModel() throws Exception { assertEquals(authModelId, authModel.getId()); String typeDefsJson = mapper.writeValueAsString(authModel.getTypeDefinitions()); assertEquals( - "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]}}}}]", + "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]}}}}]", typeDefsJson); } @@ -144,7 +146,7 @@ public void readAuthModels() throws Exception { String typeDefsJson = mapper.writeValueAsString(authModel.getTypeDefinitions()); assertEquals( - "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]}}}}]", + "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]}}}}]", typeDefsJson); } catch (JsonProcessingException ex) { assertNull(ex); @@ -176,9 +178,10 @@ public void write_and_read() throws Exception { String storeName = thisTestName(); String storeId = createStore(storeName); String _authModelId = writeAuthModel(storeId); - WriteRequest writeRequest = new WriteRequest().writes(new TupleKeys().tupleKeys(List.of(DEFAULT_TUPLE_KEY))); - ReadRequest readRequest = - new ReadRequest().tupleKey(new TupleKey().user(DEFAULT_USER)._object(DEFAULT_DOC)); + WriteRequest writeRequest = + new WriteRequest().writes(new WriteRequestWrites().tupleKeys(List.of(DEFAULT_TUPLE_KEY))); + ReadRequest readRequest = new ReadRequest() + .tupleKey(new ReadRequestTupleKey().user(DEFAULT_USER)._object(DEFAULT_DOC)); // When api.write(storeId, writeRequest).get(); @@ -197,9 +200,12 @@ public void write_and_check() throws Exception { String storeName = thisTestName(); String storeId = createStore(storeName); String _authModelId = writeAuthModel(storeId); - WriteRequest writeRequest = new WriteRequest().writes(new TupleKeys().tupleKeys(DEFAULT_TUPLE_KEYS)); + WriteRequest writeRequest = new WriteRequest().writes(new WriteRequestWrites().tupleKeys(DEFAULT_TUPLE_KEYS)); CheckRequest checkRequest = new CheckRequest() - .tupleKey(new TupleKey().user(DEFAULT_USER).relation("reader")._object(DEFAULT_DOC)); + .tupleKey(new CheckRequestTupleKey() + .user(DEFAULT_USER) + .relation("reader") + ._object(DEFAULT_DOC)); // When api.write(storeId, writeRequest).get(); @@ -215,9 +221,9 @@ public void write_and_expand() throws Exception { String storeName = thisTestName(); String storeId = createStore(storeName); String _authModelId = writeAuthModel(storeId); - WriteRequest writeRequest = new WriteRequest().writes(new TupleKeys().tupleKeys(DEFAULT_TUPLE_KEYS)); - ExpandRequest expandRequest = - new ExpandRequest().tupleKey(new TupleKey()._object(DEFAULT_DOC).relation("reader")); + WriteRequest writeRequest = new WriteRequest().writes(new WriteRequestWrites().tupleKeys(DEFAULT_TUPLE_KEYS)); + ExpandRequest expandRequest = new ExpandRequest() + .tupleKey(new ExpandRequestTupleKey()._object(DEFAULT_DOC).relation("reader")); // When api.write(storeId, writeRequest).get(); @@ -237,7 +243,7 @@ public void write_and_listObjects() throws Exception { String storeName = thisTestName(); String storeId = createStore(storeName); String _authModelId = writeAuthModel(storeId); - WriteRequest writeRequest = new WriteRequest().writes(new TupleKeys().tupleKeys(DEFAULT_TUPLE_KEYS)); + WriteRequest writeRequest = new WriteRequest().writes(new WriteRequestWrites().tupleKeys(DEFAULT_TUPLE_KEYS)); ListObjectsRequest listObjectsRequest = new ListObjectsRequest().user(DEFAULT_USER).relation("reader").type("document"); @@ -257,7 +263,7 @@ public void write_and_readChanges() throws Exception { String storeName = thisTestName(); String storeId = createStore(storeName); String _authModelId = writeAuthModel(storeId); - WriteRequest writeRequest = new WriteRequest().writes(new TupleKeys().tupleKeys(DEFAULT_TUPLE_KEYS)); + WriteRequest writeRequest = new WriteRequest().writes(new WriteRequestWrites().tupleKeys(DEFAULT_TUPLE_KEYS)); // When api.write(storeId, writeRequest).get(); @@ -269,7 +275,7 @@ public void write_and_readChanges() throws Exception { String firstTupleKeyJson = mapper.writeValueAsString(response.getChanges().get(0).getTupleKey()); assertEquals( - "{\"object\":\"document:2021-budget\",\"relation\":\"reader\",\"user\":\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\"}", + "{\"user\":\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\"relation\":\"reader\",\"object\":\"document:2021-budget\",\"condition\":null}", firstTupleKeyJson); } @@ -280,7 +286,12 @@ public void write_readAssertions() throws Exception { String storeId = createStore(storeName); String authModelId = writeAuthModel(storeId); WriteAssertionsRequest writeRequest = new WriteAssertionsRequest() - .assertions(List.of(new Assertion().tupleKey(DEFAULT_TUPLE_KEY).expectation(true))); + .assertions(List.of(new Assertion() + .tupleKey(new CheckRequestTupleKey() + .user(DEFAULT_USER) + .relation("reader") + ._object(DEFAULT_DOC)) + .expectation(true))); // When api.writeAssertions(storeId, authModelId, writeRequest).get(); @@ -290,7 +301,7 @@ public void write_readAssertions() throws Exception { // Then String responseJson = mapper.writeValueAsString(response.getAssertions()); assertEquals( - "[{\"tuple_key\":{\"object\":\"document:2021-budget\",\"relation\":\"reader\",\"user\":\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\"},\"expectation\":true}]", + "[{\"tuple_key\":{\"user\":\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\"relation\":\"reader\",\"object\":\"document:2021-budget\"},\"expectation\":true}]", responseJson); } diff --git a/src/test-integration/java/dev/openfga/sdk/api/client/OpenFgaClientIntegrationTest.java b/src/test-integration/java/dev/openfga/sdk/api/client/OpenFgaClientIntegrationTest.java index 59c642f..374169e 100644 --- a/src/test-integration/java/dev/openfga/sdk/api/client/OpenFgaClientIntegrationTest.java +++ b/src/test-integration/java/dev/openfga/sdk/api/client/OpenFgaClientIntegrationTest.java @@ -19,6 +19,7 @@ import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.api.model.*; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -28,10 +29,11 @@ public class OpenFgaClientIntegrationTest { "{\"schema_version\":\"1.1\",\"type_definitions\":[{\"type\":\"user\"},{\"type\":\"document\",\"relations\":{\"reader\":{\"this\":{}},\"writer\":{\"this\":{}},\"owner\":{\"this\":{}}},\"metadata\":{\"relations\":{\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\"}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\"}]},\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\"}]}}}}]}"; private static final String DEFAULT_USER = "user:81684243-9356-4421-8fbf-a4f8d36aa31b"; private static final String DEFAULT_DOC = "document:2021-budget"; - public static final ClientTupleKey DEFAULT_TUPLE_KEY = + private static final ClientTupleKey DEFAULT_TUPLE_KEY = new ClientTupleKey().user(DEFAULT_USER).relation("reader")._object(DEFAULT_DOC); - public static final List DEFAULT_TUPLE_KEYS = List.of(DEFAULT_TUPLE_KEY); - public static final ClientAssertion DEFAULT_ASSERTION = new ClientAssertion() + private static final ClientRelationshipCondition DEFAULT_CONDITION = + new ClientRelationshipCondition().name("condition").context(Map.of("some", "context")); + private static final ClientAssertion DEFAULT_ASSERTION = new ClientAssertion() .user(DEFAULT_USER) .relation("reader") ._object(DEFAULT_DOC) @@ -41,6 +43,8 @@ public class OpenFgaClientIntegrationTest { @BeforeEach public void initializeApi() throws Exception { + System.setProperty("HttpRequestAttempt.debug-logging", "enable"); + ClientConfiguration apiConfig = new ClientConfiguration().apiUrl("http://localhost:8080"); fga = new OpenFgaClient(apiConfig); } @@ -130,7 +134,7 @@ public void readAuthModel() throws Exception { assertEquals(authModelId, response.getAuthorizationModel().getId()); String typeDefsJson = mapper.writeValueAsString(authModel.getTypeDefinitions()); assertEquals( - "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]}}}}]", + "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]}}}}]", typeDefsJson); } @@ -158,7 +162,7 @@ public void readAuthModels() throws Exception { String typeDefsJson = mapper.writeValueAsString(authModel.getTypeDefinitions()); assertEquals( - "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null}]}}}}]", + "[{\"type\":\"user\",\"relations\":{},\"metadata\":null},{\"type\":\"document\",\"relations\":{\"owner\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"reader\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null},\"writer\":{\"this\":{},\"computedUserset\":null,\"tupleToUserset\":null,\"union\":null,\"intersection\":null,\"difference\":null}},\"metadata\":{\"relations\":{\"owner\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\",\"relation\":null,\"wildcard\":null,\"condition\":null}]}}}}]", typeDefsJson); } catch (JsonProcessingException ex) { assertNull(ex); @@ -194,7 +198,8 @@ public void write_and_read() throws Exception { String authModelId = writeAuthModel(storeId); fga.setAuthorizationModelId(authModelId); - ClientWriteRequest writeRequest = new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY)); + ClientWriteRequest writeRequest = + new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY.condition(DEFAULT_CONDITION))); ClientReadRequest readRequest = new ClientReadRequest().user(DEFAULT_USER)._object(DEFAULT_DOC); @@ -219,7 +224,8 @@ public void write_and_check() throws Exception { fga.setStoreId(storeId); String authModelId = writeAuthModel(storeId); fga.setAuthorizationModelId(authModelId); - ClientWriteRequest writeRequest = new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY)); + ClientWriteRequest writeRequest = + new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY.condition(DEFAULT_CONDITION))); ClientCheckRequest checkRequest = new ClientCheckRequest().user(DEFAULT_USER).relation("reader")._object(DEFAULT_DOC); @@ -240,7 +246,8 @@ public void write_and_expand() throws Exception { fga.setStoreId(storeId); String authModelId = writeAuthModel(storeId); fga.setAuthorizationModelId(authModelId); - ClientWriteRequest writeRequest = new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY)); + ClientWriteRequest writeRequest = + new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY.condition(DEFAULT_CONDITION))); ClientExpandRequest expandRequest = new ClientExpandRequest()._object(DEFAULT_DOC).relation("reader"); @@ -270,7 +277,8 @@ public void write_and_listObjects() throws Exception { fga.setStoreId(storeId); String authModelId = writeAuthModel(storeId); fga.setAuthorizationModelId(authModelId); - ClientWriteRequest writeRequest = new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY)); + ClientWriteRequest writeRequest = + new ClientWriteRequest().writes(List.of(DEFAULT_TUPLE_KEY.condition(DEFAULT_CONDITION))); ClientListObjectsRequest listObjectsRequest = new ClientListObjectsRequest() .user(DEFAULT_USER) .relation("reader") @@ -303,7 +311,7 @@ public void write_readAssertions() throws Exception { // Then String responseJson = mapper.writeValueAsString(response.getAssertions()); assertEquals( - "[{\"tuple_key\":{\"object\":\"document:2021-budget\",\"relation\":\"reader\",\"user\":\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\"},\"expectation\":true}]", + "[{\"tuple_key\":{\"user\":\"user:81684243-9356-4421-8fbf-a4f8d36aa31b\",\"relation\":\"reader\",\"object\":\"document:2021-budget\"},\"expectation\":true}]", responseJson); } diff --git a/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java b/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java index dc7585a..8de3bbf 100644 --- a/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java +++ b/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java @@ -24,7 +24,9 @@ import dev.openfga.sdk.errors.*; import java.net.http.HttpClient; import java.time.Duration; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -54,7 +56,10 @@ public class OpenFgaApiTest { @BeforeEach public void beforeEachTest() throws Exception { + System.setProperty("HttpRequestAttempt.debug-logging", "enable"); + mockHttpClient = new HttpClientMock(); + mockHttpClient.debugOn(); mockHttpClientBuilder = mock(HttpClient.Builder.class); when(mockHttpClientBuilder.executor(any())).thenReturn(mockHttpClientBuilder); @@ -570,7 +575,7 @@ public void writeAuthorizationModelTest() throws Exception { // Given String postUrl = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/authorization-models"; String expectedBody = - "{\"type_definitions\":[{\"type\":\"document\",\"relations\":{},\"metadata\":null}],\"schema_version\":\"1.1\"}"; + "{\"type_definitions\":[{\"type\":\"document\",\"relations\":{},\"metadata\":null}],\"schema_version\":\"1.1\",\"conditions\":{}}"; String responseBody = String.format("{\"authorization_model_id\":\"%s\"}", DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(201, responseBody); WriteAuthorizationModelRequest request = new WriteAuthorizationModelRequest() @@ -803,8 +808,8 @@ public void readChangesTest() throws Exception { // Given String getPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/changes"; String responseBody = String.format( - "{\"changes\":[{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}}]}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"changes\":[{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}}]}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onGet(getPath).doReturn(200, responseBody); String type = null; // Input is optional Integer pageSize = null; // Input is optional @@ -919,14 +924,57 @@ public void readTest() throws Exception { // Given String postUrl = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/read"; String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"page_size\":null,\"continuation_token\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"page_size\":null,\"continuation_token\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); String responseBody = String.format( "{\"tuples\":[{\"key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}}]}", DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, responseBody); ReadRequest request = new ReadRequest() - .tupleKey(new TupleKey() + .tupleKey(new ReadRequestTupleKey() + ._object(DEFAULT_OBJECT) + .relation(DEFAULT_RELATION) + .user(DEFAULT_USER)); + + // When + var response = fga.read(DEFAULT_STORE_ID, request).get(); + + // Then + mockHttpClient.verify().post(postUrl).withBody(is(expectedBody)).called(1); + assertNotNull(response.getData()); + assertNotNull(response.getData().getTuples()); + assertEquals(1, response.getData().getTuples().size()); + var key = response.getData().getTuples().get(0).getKey(); + assertNotNull(key); + assertEquals(DEFAULT_USER, key.getUser()); + assertEquals(DEFAULT_RELATION, key.getRelation()); + assertEquals(DEFAULT_OBJECT, key.getObject()); + } + + @Test + public void read_complexContext() throws Exception { + // Given + String postUrl = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/read"; + String expectedBody = String.format( + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"page_size\":null,\"continuation_token\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); + String responseBody = String.format( + "{\"tuples\":[{\"key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"," + + "\"condition\":{\"context\":{" + + " \"num\":1," + + " \"str\":\"banana\"," + + " \"list\":[1, \"banana\", [], {}]," + + " \"obj\":{" + + " \"num\":1," + + " \"str\":\"banana\"," + + " \"list\":[]," + + " \"obj\": {}" + + " }" + + "}}}}]}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); + mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, responseBody); + ReadRequest request = new ReadRequest() + .tupleKey(new ReadRequestTupleKey() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER)); @@ -944,6 +992,16 @@ public void readTest() throws Exception { assertEquals(DEFAULT_USER, key.getUser()); assertEquals(DEFAULT_RELATION, key.getRelation()); assertEquals(DEFAULT_OBJECT, key.getObject()); + + // The below is subject to change. + assertNotNull(key.getCondition()); + var context = key.getCondition().getContext(); + assertNotNull(context); + var contextMap = assertInstanceOf(Map.class, context); + assertEquals(1, contextMap.get("num")); + assertEquals("banana", contextMap.get("str")); + assertEquals(List.of(1, "banana", List.of(), Map.of()), contextMap.get("list")); + assertEquals(Map.of("num", 1, "str", "banana", "list", List.of(), "obj", Map.of()), contextMap.get("obj")); } @Test @@ -1041,19 +1099,19 @@ public void writeTest_writes() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; String expectedBody = String.format( - "{\"writes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":null}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); WriteRequest request = new WriteRequest() .authorizationModelId(DEFAULT_AUTH_MODEL_ID) - .writes(new TupleKeys() + .writes(new WriteRequestWrites() .tupleKeys(List.of(new TupleKey() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER)))); // When - fga.write(DEFAULT_STORE_ID, request); + fga.write(DEFAULT_STORE_ID, request).get(); // Then mockHttpClient.verify().post(postPath).withBody(is(expectedBody)).called(1); @@ -1067,19 +1125,112 @@ public void writeTest_deletes() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; String expectedBody = String.format( - "{\"writes\":null,\"deletes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":null,\"deletes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}]},\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); WriteRequest request = new WriteRequest() .authorizationModelId(DEFAULT_AUTH_MODEL_ID) - .deletes(new TupleKeys() - .tupleKeys(List.of(new TupleKey() + .deletes(new WriteRequestDeletes() + .tupleKeys(List.of(new TupleKeyWithoutCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER)))); // When - fga.write(DEFAULT_STORE_ID, request); + fga.write(DEFAULT_STORE_ID, request).get(); + + // Then + mockHttpClient.verify().post(postPath).withBody(is(expectedBody)).called(1); + } + + @Test + public void writeWithContext_map() throws Exception { + // Given + String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; + String expectedBody = String.format( + "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"conditionName\",\"context\":{\"num\":1,\"str\":\"banana\",\"list\":[],\"obj\":{}}}}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); + mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); + var context = new LinkedHashMap<>(); + context.put("num", 1); + context.put("str", "banana"); + context.put("list", List.of()); + context.put("obj", new LinkedHashMap<>()); + WriteRequest request = new WriteRequest() + .authorizationModelId(DEFAULT_AUTH_MODEL_ID) + .writes(new WriteRequestWrites() + .tupleKeys(List.of(new TupleKey() + ._object(DEFAULT_OBJECT) + .relation(DEFAULT_RELATION) + .user(DEFAULT_USER) + .condition(new RelationshipCondition() + .name("conditionName") + .context(context))))); + + // When + fga.write(DEFAULT_STORE_ID, request).get(); + + // Then + mockHttpClient.verify().post(postPath).withBody(is(expectedBody)).called(1); + } + + @Test + public void writeWithContext_modeledObj() throws Exception { + // Given + + String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; + String expectedBody = String.format( + "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"conditionName\",\"context\":{\"num\":1,\"str\":\"apple\",\"list\":[2,\"banana\",[],{\"num\":3,\"str\":\"cupcake\",\"list\":null,\"obj\":null}],\"obj\":{\"num\":4,\"str\":\"dolphin\",\"list\":null,\"obj\":null}}}}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); + mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); + + class TestObj { + int num; + String str; + List list; + Object obj; + + public int getNum() { + return num; + } + + public String getStr() { + return str; + } + + public List getList() { + return list; + } + + public Object getObj() { + return obj; + } + } + var obj = new TestObj(); + obj.num = 1; + obj.str = "apple"; + var objInList = new TestObj(); + obj.list = List.of(2, "banana", List.of(), objInList); + objInList.num = 3; + objInList.str = "cupcake"; + var objInObj = new TestObj(); + obj.obj = objInObj; + objInObj.num = 4; + objInObj.str = "dolphin"; + + WriteRequest request = new WriteRequest() + .authorizationModelId(DEFAULT_AUTH_MODEL_ID) + .writes(new WriteRequestWrites() + .tupleKeys(List.of(new TupleKey() + ._object(DEFAULT_OBJECT) + .relation(DEFAULT_RELATION) + .user(DEFAULT_USER) + .condition(new RelationshipCondition() + .name("conditionName") + .context(obj))))); + + // When + fga.write(DEFAULT_STORE_ID, request).get(); // Then mockHttpClient.verify().post(postPath).withBody(is(expectedBody)).called(1); @@ -1181,11 +1332,11 @@ public void check() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/check"; String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":{\"tuple_keys\":[]},\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":{\"tuple_keys\":[]},\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, "{\"allowed\":true}"); CheckRequest request = new CheckRequest() - .tupleKey(new TupleKey() + .tupleKey(new CheckRequestTupleKey() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER)) @@ -1299,18 +1450,15 @@ public void expandTest() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/expand"; String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"tuple_key\":{\"relation\":\"%s\",\"object\":\"%s\"},\"authorization_model_id\":\"%s\"}", + DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); String responseBody = String.format( "{\"tree\":{\"root\":{\"union\":{\"nodes\":[{\"leaf\":{\"users\":{\"users\":[\"%s\"]}}}]}}}}", DEFAULT_USER); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, responseBody); ExpandRequest request = new ExpandRequest() .authorizationModelId(DEFAULT_AUTH_MODEL_ID) - .tupleKey(new TupleKey() - ._object(DEFAULT_OBJECT) - .relation(DEFAULT_RELATION) - .user(DEFAULT_USER)); + .tupleKey(new ExpandRequestTupleKey()._object(DEFAULT_OBJECT).relation(DEFAULT_RELATION)); // When var response = fga.expand(DEFAULT_STORE_ID, request).get(); @@ -1431,7 +1579,7 @@ public void listObjectsTest() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/list-objects"; String expectedBody = String.format( - "{\"authorization_model_id\":\"%s\",\"type\":null,\"relation\":\"%s\",\"user\":\"%s\",\"contextual_tuples\":null}", + "{\"authorization_model_id\":\"%s\",\"type\":null,\"relation\":\"%s\",\"user\":\"%s\",\"contextual_tuples\":null,\"context\":null}", DEFAULT_AUTH_MODEL_ID, DEFAULT_RELATION, DEFAULT_USER); mockHttpClient .onPost(postPath) @@ -1547,8 +1695,8 @@ public void readAssertionsTest() throws Exception { // Given String getUrl = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/assertions/01G5JAVJ41T49E9TT3SKVS7X1J"; String responseBody = String.format( - "{\"assertions\":[{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"expectation\":true}]}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"assertions\":[{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"expectation\":true}]}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onGet(getUrl).doReturn(200, responseBody); // When @@ -1667,12 +1815,12 @@ public void writeAssertionsTest() throws Exception { // Given String putUrl = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/assertions/01G5JAVJ41T49E9TT3SKVS7X1J"; String expectedBody = String.format( - "{\"assertions\":[{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"expectation\":true}]}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"assertions\":[{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"expectation\":true}]}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPut(putUrl).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); WriteAssertionsRequest request = new WriteAssertionsRequest() .assertions(List.of(new Assertion() - .tupleKey(new TupleKey() + .tupleKey(new CheckRequestTupleKey() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER)) diff --git a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java index 1a6a847..a894001 100644 --- a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java @@ -29,7 +29,10 @@ class OAuth2ClientTest { @BeforeEach public void setup() throws FgaInvalidParameterException { + System.setProperty("HttpRequestAttempt.debug-logging", "enable"); + mockHttpClient = new HttpClientMock(); + mockHttpClient.debugOn(); var credentials = new Credentials(new ClientCredentials() .clientId(CLIENT_ID) diff --git a/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java b/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java index 8afcd53..157c904 100644 --- a/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java @@ -24,6 +24,7 @@ import java.net.http.HttpClient; import java.time.Duration; import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.function.Function; import java.util.stream.Collectors; @@ -45,6 +46,8 @@ public class OpenFgaClientTest { private static final String DEFAULT_OBJECT = "document:budget"; private static final String DEFAULT_SCHEMA_VERSION = "1.1"; private static final String EMPTY_RESPONSE_BODY = "{}"; + private static final ClientRelationshipCondition DEFAULT_CONDITION = + new ClientRelationshipCondition().name("condition").context(Map.of("some", "context")); private static final int DEFAULT_MAX_RETRIES = 3; private static final Duration DEFAULT_RETRY_DELAY = Duration.ofMillis(100); @@ -54,8 +57,10 @@ public class OpenFgaClientTest { @BeforeEach public void beforeEachTest() throws Exception { + System.setProperty("HttpRequestAttempt.debug-logging", "enable"); + mockHttpClient = new HttpClientMock(); - // mockHttpClient.debugOn(); // Uncomment when debugging HTTP requests. + mockHttpClient.debugOn(); var mockHttpClientBuilder = mock(HttpClient.Builder.class); when(mockHttpClientBuilder.executor(any())).thenReturn(mockHttpClientBuilder); @@ -666,7 +671,7 @@ public void writeAuthorizationModelTest() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/authorization-models", DEFAULT_STORE_ID); String expectedBody = - "{\"type_definitions\":[{\"type\":\"document\",\"relations\":{},\"metadata\":null}],\"schema_version\":\"1.1\"}"; + "{\"type_definitions\":[{\"type\":\"document\",\"relations\":{},\"metadata\":null}],\"schema_version\":\"1.1\",\"conditions\":{}}"; String responseBody = String.format("{\"authorization_model_id\":\"%s\"}", DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(201, responseBody); WriteAuthorizationModelRequest request = new WriteAuthorizationModelRequest() @@ -923,8 +928,8 @@ public void readTest() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/read", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"page_size\":null,\"continuation_token\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"page_size\":null,\"continuation_token\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); String responseBody = String.format( "{\"tuples\":[{\"key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}}]}", DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); @@ -1049,11 +1054,11 @@ public void writeTest_writes() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; String expectedBody = String.format( - "{\"writes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":null}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); ClientWriteRequest request = new ClientWriteRequest() - .writes(List.of(new ClientTupleKey() + .writes(List.of(new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER))); @@ -1074,8 +1079,8 @@ public void writeTest_deletes() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; String expectedBody = String.format( - "{\"writes\":null,\"deletes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":null,\"deletes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}]},\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); ClientWriteRequest request = new ClientWriteRequest() .deletes(List.of(new ClientTupleKey() @@ -1094,31 +1099,35 @@ public void writeTest_deletes() throws Exception { public void writeTest_transactions() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; - String tupleBody = String.format( - "{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + String writeTupleBody = String.format( + "{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"condition\",\"context\":{\"some\":\"context\"}}}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); ClientTupleKey tuple = new ClientTupleKey() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER); + ClientTupleKeyWithCondition writeTuple = tuple.condition(DEFAULT_CONDITION); String write2Body = String.format( "{\"writes\":{\"tuple_keys\":[%s,%s]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", - tupleBody, tupleBody, DEFAULT_AUTH_MODEL_ID); + writeTupleBody, writeTupleBody, DEFAULT_AUTH_MODEL_ID); String write1Body = String.format( "{\"writes\":{\"tuple_keys\":[%s]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", - tupleBody, DEFAULT_AUTH_MODEL_ID); + writeTupleBody, DEFAULT_AUTH_MODEL_ID); + String deleteTupleBody = String.format( + "{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); String delete2Body = String.format( "{\"writes\":null,\"deletes\":{\"tuple_keys\":[%s,%s]},\"authorization_model_id\":\"%s\"}", - tupleBody, tupleBody, DEFAULT_AUTH_MODEL_ID); + deleteTupleBody, deleteTupleBody, DEFAULT_AUTH_MODEL_ID); String delete1Body = String.format( "{\"writes\":null,\"deletes\":{\"tuple_keys\":[%s]},\"authorization_model_id\":\"%s\"}", - tupleBody, DEFAULT_AUTH_MODEL_ID); + deleteTupleBody, DEFAULT_AUTH_MODEL_ID); mockHttpClient .onPost(postPath) .withBody(isOneOf(write2Body, write1Body, delete2Body, delete1Body)) .doReturn(200, EMPTY_RESPONSE_BODY); ClientWriteRequest request = new ClientWriteRequest() - .writes(List.of(tuple, tuple, tuple, tuple, tuple)) + .writes(List.of(writeTuple, writeTuple, writeTuple, writeTuple, writeTuple)) .deletes(List.of(tuple, tuple, tuple, tuple, tuple)); ClientWriteOptions options = new ClientWriteOptions().disableTransactions(false).transactionChunkSize(2); @@ -1142,8 +1151,8 @@ public void writeTest_transactionsWithFailure() throws Exception { String failedUser = "user:SECOND"; String skippedUser = "user:third"; Function writeBody = user -> String.format( - "{\"writes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, user, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"condition\",\"context\":{\"some\":\"context\"}}}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", + user, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient .onPost(postPath) .withBody(isOneOf(writeBody.apply(firstUser), writeBody.apply(skippedUser))) @@ -1154,10 +1163,11 @@ public void writeTest_transactionsWithFailure() throws Exception { .doReturn(400, "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}"); ClientWriteRequest request = new ClientWriteRequest() .writes(Stream.of(firstUser, failedUser, skippedUser) - .map(user -> new ClientTupleKey() + .map(user -> new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(user)) + .user(user) + .condition(DEFAULT_CONDITION)) .collect(Collectors.toList())); ClientWriteOptions options = new ClientWriteOptions().disableTransactions(false).transactionChunkSize(1); @@ -1190,17 +1200,27 @@ public void writeTest_transactionsWithFailure() throws Exception { public void writeTest_nonTransaction() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; - String tupleBody = String.format( - "{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + String writeTupleBody = String.format( + "{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"condition\",\"context\":{\"some\":\"context\"}}}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); + String deleteTupleBody = String.format( + "{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); String expectedBody = String.format( "{\"writes\":{\"tuple_keys\":[%s,%s,%s]},\"deletes\":{\"tuple_keys\":[%s,%s,%s]},\"authorization_model_id\":\"%s\"}", - tupleBody, tupleBody, tupleBody, tupleBody, tupleBody, tupleBody, DEFAULT_AUTH_MODEL_ID); + writeTupleBody, + writeTupleBody, + writeTupleBody, + deleteTupleBody, + deleteTupleBody, + deleteTupleBody, + DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); - ClientTupleKey tuple = new ClientTupleKey() + var tuple = new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(DEFAULT_USER); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION); ClientWriteRequest request = new ClientWriteRequest().writes(List.of(tuple, tuple, tuple)).deletes(List.of(tuple, tuple, tuple)); @@ -1220,20 +1240,30 @@ public void writeTest_nonTransaction() throws Exception { public void writeTest_nonTransactionsWithFailure() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/write"; - String tupleBody = String.format( - "{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + String writeTupleBody = String.format( + "{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"condition\",\"context\":{\"some\":\"context\"}}}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); + String deleteTupleBody = String.format( + "{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); String expectedBody = String.format( "{\"writes\":{\"tuple_keys\":[%s,%s,%s]},\"deletes\":{\"tuple_keys\":[%s,%s,%s]},\"authorization_model_id\":\"%s\"}", - tupleBody, tupleBody, tupleBody, tupleBody, tupleBody, tupleBody, DEFAULT_AUTH_MODEL_ID); + writeTupleBody, + writeTupleBody, + writeTupleBody, + deleteTupleBody, + deleteTupleBody, + deleteTupleBody, + DEFAULT_AUTH_MODEL_ID); mockHttpClient .onPost(postPath) .withBody(is(expectedBody)) .doReturn(400, "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}"); - ClientTupleKey tuple = new ClientTupleKey() + var tuple = new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(DEFAULT_USER); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION); ClientWriteRequest request = new ClientWriteRequest().writes(List.of(tuple, tuple, tuple)).deletes(List.of(tuple, tuple, tuple)); @@ -1256,13 +1286,15 @@ public void writeTuplesTest() throws Exception { // Given String postPath = String.format("https://localhost/stores/%s/write", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"writes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":{\"name\":\"condition\",\"context\":{\"some\":\"context\"}}}]}," + + "\"deletes\":null,\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); - List tuples = List.of(new ClientTupleKey() + List tuples = List.of(new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(DEFAULT_USER)); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION)); // When ClientWriteResponse response = fga.writeTuples(tuples).get(); @@ -1277,8 +1309,8 @@ public void deleteTuplesTest() throws Exception { // Given String postPath = String.format("https://localhost/stores/%s/write", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"writes\":null,\"deletes\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}]},\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_AUTH_MODEL_ID); + "{\"writes\":null,\"deletes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}]},\"authorization_model_id\":\"%s\"}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postPath).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); List tuples = List.of(new ClientTupleKey() ._object(DEFAULT_OBJECT) @@ -1315,10 +1347,11 @@ public void write_400() throws Exception { .onPost(postUrl) .doReturn(400, "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}"); ClientWriteRequest request = new ClientWriteRequest() - .writes(List.of(new ClientTupleKey() + .writes(List.of(new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(DEFAULT_USER))); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION))); // When ExecutionException execException = @@ -1341,10 +1374,11 @@ public void write_404() throws Exception { .onPost(postUrl) .doReturn(404, "{\"code\":\"undefined_endpoint\",\"message\":\"Endpoint not enabled\"}"); ClientWriteRequest request = new ClientWriteRequest() - .writes(List.of(new ClientTupleKey() + .writes(List.of(new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(DEFAULT_USER))); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION))); // When ExecutionException execException = @@ -1366,10 +1400,11 @@ public void write_500() throws Exception { .onPost(postUrl) .doReturn(500, "{\"code\":\"internal_error\",\"message\":\"Internal Server Error\"}"); ClientWriteRequest request = new ClientWriteRequest() - .writes(List.of(new ClientTupleKey() + .writes(List.of(new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) - .user(DEFAULT_USER))); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION))); // When ExecutionException execException = @@ -1391,19 +1426,20 @@ public void check() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"}," - + "\"contextual_tuples\":{\"tuple_keys\":[{\"object\":\"%s\",\"relation\":\"owner\",\"user\":\"%s\"}]}," - + "\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER, DEFAULT_OBJECT, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"}," + + "\"contextual_tuples\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"owner\",\"object\":\"%s\",\"condition\":{\"name\":\"condition\",\"context\":{\"some\":\"context\"}}}]}," + + "\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_USER, DEFAULT_OBJECT); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, "{\"allowed\":true}"); ClientCheckRequest request = new ClientCheckRequest() ._object(DEFAULT_OBJECT) .relation(DEFAULT_RELATION) .user(DEFAULT_USER) - .contextualTuples(List.of(new ClientTupleKey() + .contextualTuples(List.of(new ClientTupleKeyWithCondition() ._object(DEFAULT_OBJECT) .relation("owner") - .user(DEFAULT_USER))); + .user(DEFAULT_USER) + .condition(DEFAULT_CONDITION))); ClientCheckOptions options = new ClientCheckOptions().authorizationModelId(DEFAULT_AUTH_MODEL_ID); // When @@ -1500,8 +1536,8 @@ public void batchCheck() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, "{\"allowed\":true}"); ClientCheckRequest request = new ClientCheckRequest() ._object(DEFAULT_OBJECT) @@ -1523,8 +1559,8 @@ public void batchCheck_twentyTimes() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, "{\"allowed\":true}"); List requests = IntStream.range(0, 20) .mapToObj(ignored -> new ClientCheckRequest() @@ -1641,8 +1677,8 @@ public void expandTest() throws Exception { // Given String postPath = "https://localhost/stores/01YCP46JKYM8FJCQ37NMBYHE5X/expand"; String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":null},\"authorization_model_id\":\"%s\"}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_AUTH_MODEL_ID); + "{\"tuple_key\":{\"relation\":\"%s\",\"object\":\"%s\"},\"authorization_model_id\":\"%s\"}", + DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); String responseBody = String.format( "{\"tree\":{\"root\":{\"union\":{\"nodes\":[{\"leaf\":{\"users\":{\"users\":[\"%s\"]}}}]}}}}", DEFAULT_USER); @@ -1756,7 +1792,7 @@ public void listObjectsTest() throws Exception { // Given String postPath = String.format("https://localhost/stores/%s/list-objects", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"authorization_model_id\":\"%s\",\"type\":null,\"relation\":\"%s\",\"user\":\"%s\",\"contextual_tuples\":{\"tuple_keys\":[]}}", + "{\"authorization_model_id\":\"%s\",\"type\":null,\"relation\":\"%s\",\"user\":\"%s\",\"contextual_tuples\":null,\"context\":null}", DEFAULT_AUTH_MODEL_ID, DEFAULT_RELATION, DEFAULT_USER); mockHttpClient .onPost(postPath) @@ -1860,8 +1896,8 @@ public void listRelations() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, "{\"allowed\":true}"); ClientListRelationsRequest request = new ClientListRelationsRequest() .relations(List.of(DEFAULT_RELATION)) @@ -1887,8 +1923,8 @@ public void listRelations_deny() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, "owner", DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"%s\",\"trace\":null,\"context\":null}", + DEFAULT_USER, "owner", DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID); mockHttpClient.onPost(postUrl).withBody(is(expectedBody)).doReturn(200, "{\"allowed\":false}"); ClientListRelationsRequest request = new ClientListRelationsRequest() .relations(List.of("owner")) @@ -1968,8 +2004,8 @@ public void listRelations_400() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient .onPost(postUrl) .withBody(is(expectedBody)) @@ -1998,8 +2034,8 @@ public void listRelations_404() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient .onPost(postUrl) .withBody(is(expectedBody)) @@ -2027,8 +2063,8 @@ public void listRelations_500() throws Exception { // Given String postUrl = String.format("https://localhost/stores/%s/check", DEFAULT_STORE_ID); String expectedBody = String.format( - "{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"contextual_tuples\":null,\"authorization_model_id\":\"01G5JAVJ41T49E9TT3SKVS7X1J\",\"trace\":null,\"context\":null}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient .onPost(postUrl) .withBody(is(expectedBody)) @@ -2060,8 +2096,8 @@ public void readAssertionsTest() throws Exception { String getUrl = String.format("https://localhost/stores/%s/assertions/%s", DEFAULT_STORE_ID, DEFAULT_AUTH_MODEL_ID); String responseBody = String.format( - "{\"assertions\":[{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"expectation\":true}]}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"assertions\":[{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"expectation\":true}]}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onGet(getUrl).doReturn(200, responseBody); // When @@ -2181,8 +2217,8 @@ public void writeAssertionsTest() throws Exception { String putUrl = String.format("https://localhost/stores/%s/assertions/%s", DEFAULT_STORE_ID, DEFAULT_AUTH_MODEL_ID); String expectedBody = String.format( - "{\"assertions\":[{\"tuple_key\":{\"object\":\"%s\",\"relation\":\"%s\",\"user\":\"%s\"},\"expectation\":true}]}", - DEFAULT_OBJECT, DEFAULT_RELATION, DEFAULT_USER); + "{\"assertions\":[{\"tuple_key\":{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\"},\"expectation\":true}]}", + DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT); mockHttpClient.onPut(putUrl).withBody(is(expectedBody)).doReturn(200, EMPTY_RESPONSE_BODY); List assertions = List.of(new ClientAssertion() .user(DEFAULT_USER) diff --git a/src/test/java/dev/openfga/sdk/api/model/AuthorizationModelTest.java b/src/test/java/dev/openfga/sdk/api/model/AuthorizationModelTest.java index 1500a4e..5a53deb 100644 --- a/src/test/java/dev/openfga/sdk/api/model/AuthorizationModelTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/AuthorizationModelTest.java @@ -51,4 +51,12 @@ public void schemaVersionTest() { public void typeDefinitionsTest() { // TODO: test typeDefinitions } + + /** + * Test the property 'conditions' + */ + @Test + public void conditionsTest() { + // TODO: test conditions + } } diff --git a/src/test/java/dev/openfga/sdk/api/model/CheckRequestTest.java b/src/test/java/dev/openfga/sdk/api/model/CheckRequestTest.java index fec5bbd..517a4da 100644 --- a/src/test/java/dev/openfga/sdk/api/model/CheckRequestTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/CheckRequestTest.java @@ -59,4 +59,12 @@ public void authorizationModelIdTest() { public void traceTest() { // TODO: test trace } + + /** + * Test the property 'context' + */ + @Test + public void contextTest() { + // TODO: test context + } } diff --git a/src/test/java/dev/openfga/sdk/api/model/CheckRequestTupleKeyTest.java b/src/test/java/dev/openfga/sdk/api/model/CheckRequestTupleKeyTest.java new file mode 100644 index 0000000..5b4274e --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/CheckRequestTupleKeyTest.java @@ -0,0 +1,54 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for CheckRequestTupleKey + */ +public class CheckRequestTupleKeyTest { + private final CheckRequestTupleKey model = new CheckRequestTupleKey(); + + /** + * Model tests for CheckRequestTupleKey + */ + @Test + public void testCheckRequestTupleKey() { + // TODO: test CheckRequestTupleKey + } + + /** + * Test the property 'user' + */ + @Test + public void userTest() { + // TODO: test user + } + + /** + * Test the property 'relation' + */ + @Test + public void relationTest() { + // TODO: test relation + } + + /** + * Test the property '_object' + */ + @Test + public void _objectTest() { + // TODO: test _object + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/ConditionParamTypeRefTest.java b/src/test/java/dev/openfga/sdk/api/model/ConditionParamTypeRefTest.java new file mode 100644 index 0000000..12a9a7c --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/ConditionParamTypeRefTest.java @@ -0,0 +1,46 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for ConditionParamTypeRef + */ +public class ConditionParamTypeRefTest { + private final ConditionParamTypeRef model = new ConditionParamTypeRef(); + + /** + * Model tests for ConditionParamTypeRef + */ + @Test + public void testConditionParamTypeRef() { + // TODO: test ConditionParamTypeRef + } + + /** + * Test the property 'typeName' + */ + @Test + public void typeNameTest() { + // TODO: test typeName + } + + /** + * Test the property 'genericTypes' + */ + @Test + public void genericTypesTest() { + // TODO: test genericTypes + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/ConditionTest.java b/src/test/java/dev/openfga/sdk/api/model/ConditionTest.java new file mode 100644 index 0000000..29a118e --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/ConditionTest.java @@ -0,0 +1,54 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for Condition + */ +public class ConditionTest { + private final Condition model = new Condition(); + + /** + * Model tests for Condition + */ + @Test + public void testCondition() { + // TODO: test Condition + } + + /** + * Test the property 'name' + */ + @Test + public void nameTest() { + // TODO: test name + } + + /** + * Test the property 'expression' + */ + @Test + public void expressionTest() { + // TODO: test expression + } + + /** + * Test the property 'parameters' + */ + @Test + public void parametersTest() { + // TODO: test parameters + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/ExpandRequestTupleKeyTest.java b/src/test/java/dev/openfga/sdk/api/model/ExpandRequestTupleKeyTest.java new file mode 100644 index 0000000..65ddfd7 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/ExpandRequestTupleKeyTest.java @@ -0,0 +1,46 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for ExpandRequestTupleKey + */ +public class ExpandRequestTupleKeyTest { + private final ExpandRequestTupleKey model = new ExpandRequestTupleKey(); + + /** + * Model tests for ExpandRequestTupleKey + */ + @Test + public void testExpandRequestTupleKey() { + // TODO: test ExpandRequestTupleKey + } + + /** + * Test the property 'relation' + */ + @Test + public void relationTest() { + // TODO: test relation + } + + /** + * Test the property '_object' + */ + @Test + public void _objectTest() { + // TODO: test _object + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/ListObjectsRequestTest.java b/src/test/java/dev/openfga/sdk/api/model/ListObjectsRequestTest.java index a2f5337..21d9669 100644 --- a/src/test/java/dev/openfga/sdk/api/model/ListObjectsRequestTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/ListObjectsRequestTest.java @@ -67,4 +67,12 @@ public void userTest() { public void contextualTuplesTest() { // TODO: test contextualTuples } + + /** + * Test the property 'context' + */ + @Test + public void contextTest() { + // TODO: test context + } } diff --git a/src/test/java/dev/openfga/sdk/api/model/NullValueTest.java b/src/test/java/dev/openfga/sdk/api/model/NullValueTest.java new file mode 100644 index 0000000..cba8ce3 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/NullValueTest.java @@ -0,0 +1,28 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for NullValue + */ +public class NullValueTest { + /** + * Model tests for NullValue + */ + @Test + public void testNullValue() { + // TODO: test NullValue + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/ReadRequestTupleKeyTest.java b/src/test/java/dev/openfga/sdk/api/model/ReadRequestTupleKeyTest.java new file mode 100644 index 0000000..38a8866 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/ReadRequestTupleKeyTest.java @@ -0,0 +1,54 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for ReadRequestTupleKey + */ +public class ReadRequestTupleKeyTest { + private final ReadRequestTupleKey model = new ReadRequestTupleKey(); + + /** + * Model tests for ReadRequestTupleKey + */ + @Test + public void testReadRequestTupleKey() { + // TODO: test ReadRequestTupleKey + } + + /** + * Test the property 'user' + */ + @Test + public void userTest() { + // TODO: test user + } + + /** + * Test the property 'relation' + */ + @Test + public void relationTest() { + // TODO: test relation + } + + /** + * Test the property '_object' + */ + @Test + public void _objectTest() { + // TODO: test _object + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/RelationReferenceTest.java b/src/test/java/dev/openfga/sdk/api/model/RelationReferenceTest.java index a738757..c673e09 100644 --- a/src/test/java/dev/openfga/sdk/api/model/RelationReferenceTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/RelationReferenceTest.java @@ -51,4 +51,12 @@ public void relationTest() { public void wildcardTest() { // TODO: test wildcard } + + /** + * Test the property 'condition' + */ + @Test + public void conditionTest() { + // TODO: test condition + } } diff --git a/src/test/java/dev/openfga/sdk/api/model/RelationshipConditionTest.java b/src/test/java/dev/openfga/sdk/api/model/RelationshipConditionTest.java new file mode 100644 index 0000000..0140027 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/RelationshipConditionTest.java @@ -0,0 +1,46 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for RelationshipCondition + */ +public class RelationshipConditionTest { + private final RelationshipCondition model = new RelationshipCondition(); + + /** + * Model tests for RelationshipCondition + */ + @Test + public void testRelationshipCondition() { + // TODO: test RelationshipCondition + } + + /** + * Test the property 'name' + */ + @Test + public void nameTest() { + // TODO: test name + } + + /** + * Test the property 'context' + */ + @Test + public void contextTest() { + // TODO: test context + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/TupleKeyTest.java b/src/test/java/dev/openfga/sdk/api/model/TupleKeyTest.java index ef9e315..3081c14 100644 --- a/src/test/java/dev/openfga/sdk/api/model/TupleKeyTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/TupleKeyTest.java @@ -29,11 +29,11 @@ public void testTupleKey() { } /** - * Test the property '_object' + * Test the property 'user' */ @Test - public void _objectTest() { - // TODO: test _object + public void userTest() { + // TODO: test user } /** @@ -45,10 +45,18 @@ public void relationTest() { } /** - * Test the property 'user' + * Test the property '_object' */ @Test - public void userTest() { - // TODO: test user + public void _objectTest() { + // TODO: test _object + } + + /** + * Test the property 'condition' + */ + @Test + public void conditionTest() { + // TODO: test condition } } diff --git a/src/test/java/dev/openfga/sdk/api/model/TupleKeyWithoutConditionTest.java b/src/test/java/dev/openfga/sdk/api/model/TupleKeyWithoutConditionTest.java new file mode 100644 index 0000000..c3a6348 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/TupleKeyWithoutConditionTest.java @@ -0,0 +1,54 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for TupleKeyWithoutCondition + */ +public class TupleKeyWithoutConditionTest { + private final TupleKeyWithoutCondition model = new TupleKeyWithoutCondition(); + + /** + * Model tests for TupleKeyWithoutCondition + */ + @Test + public void testTupleKeyWithoutCondition() { + // TODO: test TupleKeyWithoutCondition + } + + /** + * Test the property 'user' + */ + @Test + public void userTest() { + // TODO: test user + } + + /** + * Test the property 'relation' + */ + @Test + public void relationTest() { + // TODO: test relation + } + + /** + * Test the property '_object' + */ + @Test + public void _objectTest() { + // TODO: test _object + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/TypeNameTest.java b/src/test/java/dev/openfga/sdk/api/model/TypeNameTest.java new file mode 100644 index 0000000..3a58cb4 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/TypeNameTest.java @@ -0,0 +1,28 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for TypeName + */ +public class TypeNameTest { + /** + * Model tests for TypeName + */ + @Test + public void testTypeName() { + // TODO: test TypeName + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequestTest.java b/src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequestTest.java index de5bbcd..40331b2 100644 --- a/src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequestTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequestTest.java @@ -43,4 +43,12 @@ public void typeDefinitionsTest() { public void schemaVersionTest() { // TODO: test schemaVersion } + + /** + * Test the property 'conditions' + */ + @Test + public void conditionsTest() { + // TODO: test conditions + } } diff --git a/src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java b/src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java new file mode 100644 index 0000000..98f4164 --- /dev/null +++ b/src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java @@ -0,0 +1,38 @@ +/* + * 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: community@openfga.dev + * + * 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.model; + +import org.junit.jupiter.api.Test; + +/** + * Model tests for WriteRequestDeletes + */ +public class WriteRequestDeletesTest { + private final WriteRequestDeletes model = new WriteRequestDeletes(); + + /** + * Model tests for WriteRequestDeletes + */ + @Test + public void testWriteRequestDeletes() { + // TODO: test WriteRequestDeletes + } + + /** + * Test the property 'tupleKeys' + */ + @Test + public void tupleKeysTest() { + // TODO: test tupleKeys + } +} diff --git a/src/test/java/dev/openfga/sdk/api/model/TupleKeysTest.java b/src/test/java/dev/openfga/sdk/api/model/WriteRequestWritesTest.java similarity index 70% rename from src/test/java/dev/openfga/sdk/api/model/TupleKeysTest.java rename to src/test/java/dev/openfga/sdk/api/model/WriteRequestWritesTest.java index a57d57b..5a2b21c 100644 --- a/src/test/java/dev/openfga/sdk/api/model/TupleKeysTest.java +++ b/src/test/java/dev/openfga/sdk/api/model/WriteRequestWritesTest.java @@ -15,17 +15,17 @@ import org.junit.jupiter.api.Test; /** - * Model tests for TupleKeys + * Model tests for WriteRequestWrites */ -public class TupleKeysTest { - private final TupleKeys model = new TupleKeys(); +public class WriteRequestWritesTest { + private final WriteRequestWrites model = new WriteRequestWrites(); /** - * Model tests for TupleKeys + * Model tests for WriteRequestWrites */ @Test - public void testTupleKeys() { - // TODO: test TupleKeys + public void testWriteRequestWrites() { + // TODO: test WriteRequestWrites } /**