From 2a6b0dfe5f2f26520f56e57dd4a8b4852307e90b Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Thu, 16 Oct 2025 16:36:31 +0200 Subject: [PATCH 1/7] ACC-2351 Update OPA version and add test for abac policy --- .../opa/client/OpaClientIntegrationTests.java | 52 +++++++++++++++- .../docs/compile/abac-policy.txt | 61 +++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.txt diff --git a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java index 21e5ea1..9134af6 100644 --- a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java +++ b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java @@ -40,12 +40,12 @@ @Testcontainers class OpaClientIntegrationTests { - private static final DockerImageName OPA_IMAGE = DockerImageName.parse("openpolicyagent/opa:0.70.0"); + private static final DockerImageName OPA_IMAGE = DockerImageName.parse("openpolicyagent/opa:1.9.0"); private static final int OPA_EXPOSED_PORT = 8181; @Container private static final GenericContainer opaContainer = new GenericContainer<>(OPA_IMAGE) - .withCommand(String.format("run --server --addr :%d", OPA_EXPOSED_PORT)) + .withCommand(String.format("run --server --addr :%d --v0-compatible", OPA_EXPOSED_PORT)) .withExposedPorts(OPA_EXPOSED_PORT) .waitingFor(Wait.forHttp("/")); @@ -284,6 +284,54 @@ void compileExample() { }))); } + @Test + void abacExample() { + opaClient.upsertPolicy("abac-example", loadResourceAsString("fixtures/openpolicyagent.org/docs/compile/abac-policy.txt")).join(); + + var request = new PartialEvaluationRequest( + "data.abac.example.allow == true", + Map.of("request", + Map.of("headers", Map.of("content-type", "application/json"), + "method", "GET", + "path", List.of("tests") + ), + "auth", Map.of( + "authenticated", true, + "principal", Map.of( + "kind", "user", + "contentgrid:att1", List.of("att1v1", "att1v2"), + "contentgrid:att2", List.of("att2v1", "att2v2") + ) + ) + ), List.of("input.entity")); + + var result = opaClient.compile(request).join(); + assertThat(result).isNotNull(); + assertThat(result.getResult()).isNotNull(); + + assertThat(result.getResult().getQueries()) + .isNotNull() + // 4 queries are generated, because there are 4 combinations of the 2 attributes in the policy + .hasSize(4) + .allSatisfy( + query -> assertThat(query) + // There are 2 expressions per query, one for every user attribute in the policy + .hasSize(2) + .allSatisfy(expr -> { + // each expression has 3 terms (the 'eq' operator, the attribute value and the input value) + assertThat(expr.getTerms()).hasSize(3); + assertThat(expr.getTerms()).anySatisfy( + term -> { + assertThat(term.getClass()).isEqualTo(Ref.class); + var ref = (Ref) term; + assertThat(ref.getValue()).singleElement().satisfies( + t -> assertThat(t.toString()).isEqualTo("eq") + ); + } + ); + })); + } + @Test void example_alwaysTrue() { opaClient.upsertPolicy("compile-example", loadResourceAsString(POLICY_PATH)).join(); diff --git a/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.txt b/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.txt new file mode 100644 index 0000000..e2748e8 --- /dev/null +++ b/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.txt @@ -0,0 +1,61 @@ +package abac.example + +util.extract_content_type(header) := content_type { + mime_type := trim_space(split(header, ";")[0]) + content_type := lower(mime_type) +} +default util.content_type_in(headers, accepted_content_types) := false + +util.content_type_in(headers, accepted_content_types) { + count(headers) == 1 + extracted_mime_type := util.extract_content_type(headers[0]) + extracted_mime_type == accepted_content_types[_] +} +default util.request.content_type_in(content_types) := false + +util.request.content_type_in(content_types) { + util.content_type_in(input.request.headers["content-type"], content_types) +} +default can_read_test := false + +# - input.entity is type 'test' +can_read_test { + input.auth.authenticated == true + input.auth.principal.kind == "user" + input.entity.a == input.auth.principal["contentgrid:att1"][_] + input.entity.b == input.auth.principal["contentgrid:att2"][_] +} + +# End policy bprnvz6ldw4q +# Policy nfgusztjwpba +# - input.entity is type 'test' +can_read_test { + input.auth.authenticated == true + input.auth.principal.kind == "user" + input.auth.principal["contentgrid:admin"] == true +} + +# End policy nfgusztjwpba +default allow := false + +# Static definition Application Root +allow { + input.request.method == ["HEAD", "GET"][_] + # Path / + count(input.request.path) == 0 +} +allow { + input.request.method == ["HEAD", "GET"][_] + # Path /tests + count(input.request.path) == 1 + input.request.path[0] == "tests" + can_read_test == true +} +allow { + input.request.method == ["HEAD", "GET"][_] + # Path /tests/{id} + count(input.request.path) == 2 + input.request.path[0] == "tests" + # variable component {id} + can_read_test == true +} From e76e0ee5fb38ac58b7c995e30ec6576cb89d5968 Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Thu, 16 Oct 2025 17:31:58 +0200 Subject: [PATCH 2/7] ACC-2351 cleanup assertions --- .../opa/client/OpaClientIntegrationTests.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java index 9134af6..d9b5b0e 100644 --- a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java +++ b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java @@ -6,14 +6,14 @@ import com.contentgrid.opa.client.api.CompileApi; import com.contentgrid.opa.client.api.CompileApi.PartialEvaluationRequest; -import com.contentgrid.opa.rego.ast.Query; +import com.contentgrid.opa.client.api.DataApi; +import com.contentgrid.opa.client.api.DataApi.GetDataResponse; +import com.contentgrid.opa.client.api.PolicyApi.ListPoliciesResponse; import com.contentgrid.opa.client.rest.http.HttpStatusException; import com.contentgrid.opa.rego.ast.Expression; +import com.contentgrid.opa.rego.ast.Query; import com.contentgrid.opa.rego.ast.Term; import com.contentgrid.opa.rego.ast.Term.Ref; -import com.contentgrid.opa.client.api.DataApi; -import com.contentgrid.opa.client.api.DataApi.GetDataResponse; -import com.contentgrid.opa.client.api.PolicyApi.ListPoliciesResponse; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; @@ -322,11 +322,11 @@ void abacExample() { assertThat(expr.getTerms()).hasSize(3); assertThat(expr.getTerms()).anySatisfy( term -> { - assertThat(term.getClass()).isEqualTo(Ref.class); - var ref = (Ref) term; - assertThat(ref.getValue()).singleElement().satisfies( - t -> assertThat(t.toString()).isEqualTo("eq") - ); + assertThat(term).isInstanceOfSatisfying(Ref.class, ref -> { + assertThat(ref.getValue()).singleElement().satisfies( + t -> assertThat(t).hasToString("eq") + ); + }); } ); })); From f5c19f9637406b5a7d3f2c3a9f4c60248438c132 Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Fri, 17 Oct 2025 10:27:10 +0200 Subject: [PATCH 3/7] ACC-2351 Accept single Term as list of Terms in Expression --- .../opa/client/api/PolicyApiTest.java | 36 + .../api/policyapi/listpoliciesrsponse.json | 2433 +++++++++++++++++ .../contentgrid/opa/rego/ast/Expression.java | 3 + 3 files changed, 2472 insertions(+) create mode 100644 opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java create mode 100644 opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json diff --git a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java new file mode 100644 index 0000000..27ae07e --- /dev/null +++ b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java @@ -0,0 +1,36 @@ +package com.contentgrid.opa.client.api; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import com.contentgrid.opa.client.api.PolicyApi.ListPoliciesResponse; +import com.contentgrid.opa.rego.ast.Term; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.junit.jupiter.api.Test; + +class PolicyApiTest { + + @Test + void testPoliciesResponseObjectMapping() { + var objectMapper = JsonMapper.builder() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .build() + .registerModule(new JavaTimeModule()); + + // read listpoliciesresponse.json into ListPoliciesResponse + try (var is = getClass().getClassLoader().getResourceAsStream("com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json")) { + var response = objectMapper.readValue(is, ListPoliciesResponse.class); + assertNotNull(response); + assertThat(response.getResult().get(2).getAst().getRules().get(1).getBody()).singleElement().satisfies(expression -> { + assertThat(expression.getTerms()).singleElement().isInstanceOfSatisfying(Term.Bool.class, boolTerm -> { + assertThat(boolTerm.getValue()).isTrue(); + }); + }); + } catch (Exception e) { + fail("Failed to deserialize ListPoliciesResponse", e); + } + } + +} \ No newline at end of file diff --git a/opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json b/opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json new file mode 100644 index 0000000..d87f1f9 --- /dev/null +++ b/opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json @@ -0,0 +1,2433 @@ +{ + "result": [ + { + "id": "test", + "raw": "package test\n\nallow {\n input.method == \"GET\"\n input.path[0] == \"api\"\n input.path[1] == \"documents\"\n input.user.group[_] == data.documents[_].group\n}", + "ast": { + "package": { + "path": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "test" + } + ] + }, + "rules": [ + { + "body": [ + { + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "method" + } + ] + }, + { + "type": "string", + "value": "GET" + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "path" + }, + { + "type": "number", + "value": 0 + } + ] + }, + { + "type": "string", + "value": "api" + } + ] + }, + { + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "path" + }, + { + "type": "number", + "value": 1 + } + ] + }, + { + "type": "string", + "value": "documents" + } + ] + }, + { + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "user" + }, + { + "type": "string", + "value": "group" + }, + { + "type": "var", + "value": "$0" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "documents" + }, + { + "type": "var", + "value": "$1" + }, + { + "type": "string", + "value": "group" + } + ] + } + ] + } + ], + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + } + ] + } + }, + { + "id": "compile-example", + "raw": "package compile.example\n\nimport future.keywords.in\n\nallow {\n input.subject.clearance_level \u003e= data.reports[_].clearance_level\n}\n\nallow {\n input.break_glass == true\n}\n\ntest_set_in {\n num := input.entity.number\n num in {\"one\", \"two\", \"three\"}\n}", + "ast": { + "package": { + "path": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "compile" + }, + { + "type": "string", + "value": "example" + } + ] + }, + "rules": [ + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local31__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "subject" + }, + { + "type": "string", + "value": "clearance_level" + } + ] + } + ] + }, + { + "generated": true, + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local32__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "reports" + }, + { + "type": "var", + "value": "$0" + }, + { + "type": "string", + "value": "clearance_level" + } + ] + } + ] + }, + { + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "gte" + } + ] + }, + { + "type": "var", + "value": "__local31__" + }, + { + "type": "var", + "value": "__local32__" + } + ] + } + ], + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "break_glass" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + } + ], + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local10__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "entity" + }, + { + "type": "string", + "value": "number" + } + ] + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "internal" + }, + { + "type": "string", + "value": "member_2" + } + ] + }, + { + "type": "var", + "value": "__local10__" + }, + { + "type": "set", + "value": [ + { + "type": "string", + "value": "one" + }, + { + "type": "string", + "value": "three" + }, + { + "type": "string", + "value": "two" + } + ] + } + ] + } + ], + "head": { + "name": "test_set_in", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "test_set_in" + } + ] + } + } + ] + } + }, + { + "id": "abac-example", + "raw": "package abac.example\n\nutil.extract_content_type(header) := content_type {\n\tmime_type := trim_space(split(header, \";\")[0])\n\tcontent_type := lower(mime_type)\n}\ndefault util.content_type_in(headers, accepted_content_types) := false\n\nutil.content_type_in(headers, accepted_content_types) {\n\tcount(headers) == 1\n\textracted_mime_type := util.extract_content_type(headers[0])\n\textracted_mime_type == accepted_content_types[_]\n}\ndefault util.request.content_type_in(content_types) := false\n\nutil.request.content_type_in(content_types) {\n\tutil.content_type_in(input.request.headers[\"content-type\"], content_types)\n}\ndefault can_read_test := false\n\n# - input.entity is type 'test'\ncan_read_test {\n\tinput.auth.authenticated == true\n\tinput.auth.principal.kind == \"user\"\n\tinput.entity.a == input.auth.principal[\"contentgrid:att1\"][_]\n\tinput.entity.b == input.auth.principal[\"contentgrid:att2\"][_]\n}\n\n# End policy bprnvz6ldw4q\n# Policy nfgusztjwpba\n# - input.entity is type 'test'\ncan_read_test {\n\tinput.auth.authenticated == true\n\tinput.auth.principal.kind == \"user\"\n\tinput.auth.principal[\"contentgrid:admin\"] == true\n}\n\n# End policy nfgusztjwpba\ndefault allow := false\n\n# Static definition Application Root\nallow {\n\tinput.request.method == [\"HEAD\", \"GET\"][_]\n\t# Path /\n\tcount(input.request.path) == 0\n}\nallow {\n\tinput.request.method == [\"HEAD\", \"GET\"][_]\n\t# Path /tests\n\tcount(input.request.path) == 1\n\tinput.request.path[0] == \"tests\"\n\tcan_read_test == true\n}\nallow {\n\tinput.request.method == [\"HEAD\", \"GET\"][_]\n\t# Path /tests/{id}\n\tcount(input.request.path) == 2\n\tinput.request.path[0] == \"tests\"\n\t# variable component {id}\n\tcan_read_test == true\n}\n", + "ast": { + "package": { + "path": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "abac" + }, + { + "type": "string", + "value": "example" + } + ] + }, + "rules": [ + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "split" + } + ] + }, + { + "type": "var", + "value": "__local0__" + }, + { + "type": "string", + "value": ";" + }, + { + "type": "var", + "value": "__local14__" + } + ] + }, + { + "generated": true, + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local25__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local14__" + }, + { + "type": "number", + "value": 0 + } + ] + } + ] + }, + { + "generated": true, + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "trim_space" + } + ] + }, + { + "type": "var", + "value": "__local25__" + }, + { + "type": "var", + "value": "__local15__" + } + ] + }, + { + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local1__" + }, + { + "type": "var", + "value": "__local15__" + } + ] + }, + { + "generated": true, + "index": 4, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "lower" + } + ] + }, + { + "type": "var", + "value": "__local1__" + }, + { + "type": "var", + "value": "__local16__" + } + ] + }, + { + "index": 5, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local2__" + }, + { + "type": "var", + "value": "__local16__" + } + ] + } + ], + "head": { + "args": [ + { + "type": "var", + "value": "__local0__" + } + ], + "value": { + "type": "var", + "value": "__local2__" + }, + "assign": true, + "ref": [ + { + "type": "var", + "value": "util" + }, + { + "type": "string", + "value": "extract_content_type" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": { + "type": "boolean", + "value": true + } + } + ], + "default": true, + "head": { + "args": [ + { + "type": "var", + "value": "__local3__" + }, + { + "type": "var", + "value": "__local4__" + } + ], + "value": { + "type": "boolean", + "value": false + }, + "assign": true, + "ref": [ + { + "type": "var", + "value": "util" + }, + { + "type": "string", + "value": "content_type_in" + } + ] + } + }, + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "count" + } + ] + }, + { + "type": "var", + "value": "__local5__" + }, + { + "type": "var", + "value": "__local17__" + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local17__" + }, + { + "type": "number", + "value": 1 + } + ] + }, + { + "generated": true, + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local26__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local5__" + }, + { + "type": "number", + "value": 0 + } + ] + } + ] + }, + { + "generated": true, + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "abac" + }, + { + "type": "string", + "value": "example" + }, + { + "type": "string", + "value": "util" + }, + { + "type": "string", + "value": "extract_content_type" + } + ] + }, + { + "type": "var", + "value": "__local26__" + }, + { + "type": "var", + "value": "__local18__" + } + ] + }, + { + "index": 4, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local7__" + }, + { + "type": "var", + "value": "__local18__" + } + ] + }, + { + "index": 5, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local7__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local6__" + }, + { + "type": "var", + "value": "$0" + } + ] + } + ] + } + ], + "head": { + "args": [ + { + "type": "var", + "value": "__local5__" + }, + { + "type": "var", + "value": "__local6__" + } + ], + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "util" + }, + { + "type": "string", + "value": "content_type_in" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": { + "type": "boolean", + "value": true + } + } + ], + "default": true, + "head": { + "args": [ + { + "type": "var", + "value": "__local8__" + } + ], + "value": { + "type": "boolean", + "value": false + }, + "assign": true, + "ref": [ + { + "type": "var", + "value": "util" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "content_type_in" + } + ] + } + }, + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local27__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "headers" + }, + { + "type": "string", + "value": "content-type" + } + ] + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "abac" + }, + { + "type": "string", + "value": "example" + }, + { + "type": "string", + "value": "util" + }, + { + "type": "string", + "value": "content_type_in" + } + ] + }, + { + "type": "var", + "value": "__local27__" + }, + { + "type": "var", + "value": "__local9__" + } + ] + } + ], + "head": { + "args": [ + { + "type": "var", + "value": "__local9__" + } + ], + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "util" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "content_type_in" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": { + "type": "boolean", + "value": true + } + } + ], + "default": true, + "head": { + "name": "can_read_test", + "value": { + "type": "boolean", + "value": false + }, + "assign": true, + "ref": [ + { + "type": "var", + "value": "can_read_test" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "authenticated" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "principal" + }, + { + "type": "string", + "value": "kind" + } + ] + }, + { + "type": "string", + "value": "user" + } + ] + }, + { + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "entity" + }, + { + "type": "string", + "value": "a" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "principal" + }, + { + "type": "string", + "value": "contentgrid:att1" + }, + { + "type": "var", + "value": "$1" + } + ] + } + ] + }, + { + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "entity" + }, + { + "type": "string", + "value": "b" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "principal" + }, + { + "type": "string", + "value": "contentgrid:att2" + }, + { + "type": "var", + "value": "$2" + } + ] + } + ] + } + ], + "head": { + "name": "can_read_test", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "can_read_test" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "authenticated" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "principal" + }, + { + "type": "string", + "value": "kind" + } + ] + }, + { + "type": "string", + "value": "user" + } + ] + }, + { + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "auth" + }, + { + "type": "string", + "value": "principal" + }, + { + "type": "string", + "value": "contentgrid:admin" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + } + ], + "head": { + "name": "can_read_test", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "can_read_test" + } + ] + } + }, + { + "body": [ + { + "index": 0, + "terms": { + "type": "boolean", + "value": true + } + } + ], + "default": true, + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": false + }, + "assign": true, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + }, + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local19__" + }, + { + "type": "array", + "value": [ + { + "type": "string", + "value": "HEAD" + }, + { + "type": "string", + "value": "GET" + } + ] + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "method" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local19__" + }, + { + "type": "var", + "value": "$3" + } + ] + } + ] + }, + { + "generated": true, + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local28__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "path" + } + ] + } + ] + }, + { + "generated": true, + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "count" + } + ] + }, + { + "type": "var", + "value": "__local28__" + }, + { + "type": "var", + "value": "__local20__" + } + ] + }, + { + "index": 4, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local20__" + }, + { + "type": "number", + "value": 0 + } + ] + } + ], + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + }, + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local21__" + }, + { + "type": "array", + "value": [ + { + "type": "string", + "value": "HEAD" + }, + { + "type": "string", + "value": "GET" + } + ] + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "method" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local21__" + }, + { + "type": "var", + "value": "$4" + } + ] + } + ] + }, + { + "generated": true, + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local29__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "path" + } + ] + } + ] + }, + { + "generated": true, + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "count" + } + ] + }, + { + "type": "var", + "value": "__local29__" + }, + { + "type": "var", + "value": "__local22__" + } + ] + }, + { + "index": 4, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local22__" + }, + { + "type": "number", + "value": 1 + } + ] + }, + { + "index": 5, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "path" + }, + { + "type": "number", + "value": 0 + } + ] + }, + { + "type": "string", + "value": "tests" + } + ] + }, + { + "index": 6, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "abac" + }, + { + "type": "string", + "value": "example" + }, + { + "type": "string", + "value": "can_read_test" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + } + ], + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + }, + { + "body": [ + { + "generated": true, + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local23__" + }, + { + "type": "array", + "value": [ + { + "type": "string", + "value": "HEAD" + }, + { + "type": "string", + "value": "GET" + } + ] + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "method" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local23__" + }, + { + "type": "var", + "value": "$5" + } + ] + } + ] + }, + { + "generated": true, + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local30__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "path" + } + ] + } + ] + }, + { + "generated": true, + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "count" + } + ] + }, + { + "type": "var", + "value": "__local30__" + }, + { + "type": "var", + "value": "__local24__" + } + ] + }, + { + "index": 4, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local24__" + }, + { + "type": "number", + "value": 2 + } + ] + }, + { + "index": 5, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "input" + }, + { + "type": "string", + "value": "request" + }, + { + "type": "string", + "value": "path" + }, + { + "type": "number", + "value": 0 + } + ] + }, + { + "type": "string", + "value": "tests" + } + ] + }, + { + "index": 6, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "abac" + }, + { + "type": "string", + "value": "example" + }, + { + "type": "string", + "value": "can_read_test" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + } + ], + "head": { + "name": "allow", + "value": { + "type": "boolean", + "value": true + }, + "ref": [ + { + "type": "var", + "value": "allow" + } + ] + } + } + ], + "comments": [ + { + "Text": "IC0gaW5wdXQuZW50aXR5IGlzIHR5cGUgJ3Rlc3Qn", + "Location": { + "file": "abac-example", + "row": 21, + "col": 1 + } + }, + { + "Text": "IEVuZCBwb2xpY3kgYnBybnZ6NmxkdzRx", + "Location": { + "file": "abac-example", + "row": 29, + "col": 1 + } + }, + { + "Text": "IFBvbGljeSBuZmd1c3p0andwYmE=", + "Location": { + "file": "abac-example", + "row": 30, + "col": 1 + } + }, + { + "Text": "IC0gaW5wdXQuZW50aXR5IGlzIHR5cGUgJ3Rlc3Qn", + "Location": { + "file": "abac-example", + "row": 31, + "col": 1 + } + }, + { + "Text": "IEVuZCBwb2xpY3kgbmZndXN6dGp3cGJh", + "Location": { + "file": "abac-example", + "row": 38, + "col": 1 + } + }, + { + "Text": "IFN0YXRpYyBkZWZpbml0aW9uIEFwcGxpY2F0aW9uIFJvb3Q=", + "Location": { + "file": "abac-example", + "row": 41, + "col": 1 + } + }, + { + "Text": "IFBhdGggLw==", + "Location": { + "file": "abac-example", + "row": 44, + "col": 2 + } + }, + { + "Text": "IFBhdGggL3Rlc3Rz", + "Location": { + "file": "abac-example", + "row": 49, + "col": 2 + } + }, + { + "Text": "IFBhdGggL3Rlc3RzL3tpZH0=", + "Location": { + "file": "abac-example", + "row": 56, + "col": 2 + } + }, + { + "Text": "IHZhcmlhYmxlIGNvbXBvbmVudCB7aWR9", + "Location": { + "file": "abac-example", + "row": 59, + "col": 2 + } + } + ] + } + }, + { + "id": "example1", + "raw": "package opa.examples\n\nimport data.servers\nimport data.networks\nimport data.ports\n\npublic_servers[server] {\n some k, m\n server := servers[_]\n server.ports[_] == ports[k].id\n ports[k].networks[_] == networks[m].id\n networks[m].public == true\n}", + "ast": { + "package": { + "path": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "opa" + }, + { + "type": "string", + "value": "examples" + } + ] + }, + "rules": [ + { + "body": [ + { + "index": 0, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "var", + "value": "__local13__" + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "servers" + }, + { + "type": "var", + "value": "$0" + } + ] + } + ] + }, + { + "index": 1, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "__local13__" + }, + { + "type": "string", + "value": "ports" + }, + { + "type": "var", + "value": "$1" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "ports" + }, + { + "type": "var", + "value": "__local11__" + }, + { + "type": "string", + "value": "id" + } + ] + } + ] + }, + { + "index": 2, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "ports" + }, + { + "type": "var", + "value": "__local11__" + }, + { + "type": "string", + "value": "networks" + }, + { + "type": "var", + "value": "$2" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "networks" + }, + { + "type": "var", + "value": "__local12__" + }, + { + "type": "string", + "value": "id" + } + ] + } + ] + }, + { + "index": 3, + "terms": [ + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "eq" + } + ] + }, + { + "type": "ref", + "value": [ + { + "type": "var", + "value": "data" + }, + { + "type": "string", + "value": "networks" + }, + { + "type": "var", + "value": "__local12__" + }, + { + "type": "string", + "value": "public" + } + ] + }, + { + "type": "boolean", + "value": true + } + ] + } + ], + "head": { + "name": "public_servers", + "key": { + "type": "var", + "value": "__local13__" + }, + "ref": [ + { + "type": "var", + "value": "public_servers" + } + ] + } + } + ] + } + } + ] +} diff --git a/rego-java/src/main/java/com/contentgrid/opa/rego/ast/Expression.java b/rego-java/src/main/java/com/contentgrid/opa/rego/ast/Expression.java index d76c69a..e6473d8 100644 --- a/rego-java/src/main/java/com/contentgrid/opa/rego/ast/Expression.java +++ b/rego-java/src/main/java/com/contentgrid/opa/rego/ast/Expression.java @@ -1,5 +1,6 @@ package com.contentgrid.opa.rego.ast; +import com.fasterxml.jackson.annotation.JsonFormat; import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; @@ -10,6 +11,8 @@ @AllArgsConstructor public class Expression implements Node { long index; + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) List terms; public Expression(long index, Term ... terms) { From f3867c70f99dd675c664493965aebc79f32ffe39 Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Fri, 17 Oct 2025 10:34:54 +0200 Subject: [PATCH 4/7] ACC-2351 Give rego files the rego extension --- .../opa/client/OpaClientIntegrationTests.java | 11 ++++++----- .../compile/{abac-policy.txt => abac-policy.rego} | 0 ...compile-api-policy.txt => compile-api-policy.rego} | 0 ...policies-example-1.txt => policies-example-1.rego} | 0 ...policies-example-2.txt => policies-example-2.rego} | 0 ...documents-policy.txt => api-documents-policy.rego} | 0 6 files changed, 6 insertions(+), 5 deletions(-) rename opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/{abac-policy.txt => abac-policy.rego} (100%) rename opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/{compile-api-policy.txt => compile-api-policy.rego} (100%) rename opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/{policies-example-1.txt => policies-example-1.rego} (100%) rename opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/{policies-example-2.txt => policies-example-2.rego} (100%) rename opa-async-java-client/src/test/resources/fixtures/scenarios/{api-documents-policy.txt => api-documents-policy.rego} (100%) diff --git a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java index d9b5b0e..2207a7a 100644 --- a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java +++ b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java @@ -68,8 +68,8 @@ void opaIsRunningInDocker() { @Nested class PolicyApiTests { - private static final String PATH_EXAMPLE_1 = "fixtures/openpolicyagent.org/docs/policy/policies-example-1.txt"; - private static final String PATH_EXAMPLE_2 = "fixtures/openpolicyagent.org/docs/policy/policies-example-2.txt"; + private static final String PATH_EXAMPLE_1 = "fixtures/openpolicyagent.org/docs/policy/policies-example-1.rego"; + private static final String PATH_EXAMPLE_2 = "fixtures/openpolicyagent.org/docs/policy/policies-example-2.rego"; @Test @Order(1) @@ -195,7 +195,7 @@ void adhocQuery() throws IOException { @Nested class CompileApiTests { - public static final String POLICY_PATH = "fixtures/openpolicyagent.org/docs/compile/compile-api-policy.txt"; + public static final String POLICY_PATH = "fixtures/openpolicyagent.org/docs/compile/compile-api-policy.rego"; @Test void unknownInputX_largerThan0() { @@ -286,7 +286,8 @@ void compileExample() { @Test void abacExample() { - opaClient.upsertPolicy("abac-example", loadResourceAsString("fixtures/openpolicyagent.org/docs/compile/abac-policy.txt")).join(); + opaClient.upsertPolicy("abac-example", loadResourceAsString( + "fixtures/openpolicyagent.org/docs/compile/abac-policy.rego")).join(); var request = new PartialEvaluationRequest( "data.abac.example.allow == true", @@ -391,7 +392,7 @@ class Scenarios { */ @Test void partialEval_getApiDocuments() { - final String POLICY_PATH = "fixtures/scenarios/api-documents-policy.txt"; + final String POLICY_PATH = "fixtures/scenarios/api-documents-policy.rego"; opaClient.upsertPolicy("test", loadResourceAsString(POLICY_PATH)).join(); var result = opaClient.compile( diff --git a/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.txt b/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.rego similarity index 100% rename from opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.txt rename to opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/abac-policy.rego diff --git a/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/compile-api-policy.txt b/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/compile-api-policy.rego similarity index 100% rename from opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/compile-api-policy.txt rename to opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/compile/compile-api-policy.rego diff --git a/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-1.txt b/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-1.rego similarity index 100% rename from opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-1.txt rename to opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-1.rego diff --git a/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-2.txt b/opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-2.rego similarity index 100% rename from opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-2.txt rename to opa-async-java-client/src/test/resources/fixtures/openpolicyagent.org/docs/policy/policies-example-2.rego diff --git a/opa-async-java-client/src/test/resources/fixtures/scenarios/api-documents-policy.txt b/opa-async-java-client/src/test/resources/fixtures/scenarios/api-documents-policy.rego similarity index 100% rename from opa-async-java-client/src/test/resources/fixtures/scenarios/api-documents-policy.txt rename to opa-async-java-client/src/test/resources/fixtures/scenarios/api-documents-policy.rego From 234edb92b86b353dec0ac046766bf54a588efdbd Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Fri, 17 Oct 2025 12:23:09 +0200 Subject: [PATCH 5/7] ACC-2351 Add test for specific expression --- .../opa/client/OpaClientIntegrationTests.java | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java index 2207a7a..d89171a 100644 --- a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java +++ b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/OpaClientIntegrationTests.java @@ -14,6 +14,8 @@ import com.contentgrid.opa.rego.ast.Query; import com.contentgrid.opa.rego.ast.Term; import com.contentgrid.opa.rego.ast.Term.Ref; +import com.contentgrid.opa.rego.ast.Term.Text; +import com.contentgrid.opa.rego.ast.Term.Var; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; @@ -320,17 +322,38 @@ void abacExample() { .hasSize(2) .allSatisfy(expr -> { // each expression has 3 terms (the 'eq' operator, the attribute value and the input value) - assertThat(expr.getTerms()).hasSize(3); - assertThat(expr.getTerms()).anySatisfy( - term -> { - assertThat(term).isInstanceOfSatisfying(Ref.class, ref -> { - assertThat(ref.getValue()).singleElement().satisfies( - t -> assertThat(t).hasToString("eq") - ); - }); - } - ); - })); + assertThat(expr.getTerms()) + .hasSize(3) + .anySatisfy( + term -> { + assertThat(term).isInstanceOfSatisfying(Ref.class, ref -> { + assertThat(ref.getValue()).singleElement().satisfies( + t -> assertThat(t).hasToString("eq") + ); + }); + } + ); + }) + ) + .anySatisfy(query -> { + assertThat(query).anySatisfy( + expr -> assertThat(expr.getTerms()) + .isEqualTo(List.of( + new Ref(List.of(new Var("eq"))), + new Text("att1v1"), + new Ref(List.of( + new Var("input"), + new Text("entity"), + new Text("a") + ) + ) + ) + + ) + ); + + }) + ; } @Test From 6634d9ceab37a4cb4554c2cf159ca1b9c8887336 Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Fri, 17 Oct 2025 12:24:07 +0200 Subject: [PATCH 6/7] add ACC-2351 Add .idea to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 1b6985c..d2870b5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ # Ignore Gradle build output directory build + + +.idea \ No newline at end of file From 807b94bb141d890360e60d80edef12c667f88456 Mon Sep 17 00:00:00 2001 From: Thijs Lemmens Date: Fri, 17 Oct 2025 13:08:14 +0200 Subject: [PATCH 7/7] ACC-2351 Typo in filename --- .../java/com/contentgrid/opa/client/api/PolicyApiTest.java | 3 ++- .../{listpoliciesrsponse.json => listpoliciesresponse.json} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/{listpoliciesrsponse.json => listpoliciesresponse.json} (100%) diff --git a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java index 27ae07e..aa4e374 100644 --- a/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java +++ b/opa-async-java-client/src/test/java/com/contentgrid/opa/client/api/PolicyApiTest.java @@ -20,7 +20,8 @@ void testPoliciesResponseObjectMapping() { .registerModule(new JavaTimeModule()); // read listpoliciesresponse.json into ListPoliciesResponse - try (var is = getClass().getClassLoader().getResourceAsStream("com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json")) { + try (var is = getClass().getClassLoader().getResourceAsStream( + "com/contentgrid/opa/client/api/policyapi/listpoliciesresponse.json")) { var response = objectMapper.readValue(is, ListPoliciesResponse.class); assertNotNull(response); assertThat(response.getResult().get(2).getAst().getRules().get(1).getBody()).singleElement().satisfies(expression -> { diff --git a/opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json b/opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesresponse.json similarity index 100% rename from opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesrsponse.json rename to opa-async-java-client/src/test/resources/com/contentgrid/opa/client/api/policyapi/listpoliciesresponse.json