diff --git a/docs/content/any/project/changelogs/NEXT.md b/docs/content/any/project/changelogs/NEXT.md index e2c15a74ed..8f94d7f635 100644 --- a/docs/content/any/project/changelogs/NEXT.md +++ b/docs/content/any/project/changelogs/NEXT.md @@ -8,7 +8,20 @@ description: >- draft: true --- -## `RELEASED_PACKAGE_1` NEW_VERSION +## `oso 0.26.2` + +### Java + +#### Other bugs & improvements. + +A new `loadFilesFromResources` API has been added to allow loading policy source code from resource files contained in your packaged `.jar`. Special thanks to [`@kovacstamasx`](https://github.com/kovacstamasx) for this contribution. + +### Python + +#### Other bugs & improvements + +- Resolved an `IndexError` exception in `sqlalchemy-oso` Data Filtering. (thanks to @jackdreillyvia for the contribution) +- Resolved a false-negative in `sqlalchemy-oso` Data Filtering when comparing ORM objects. (thanks to @jackdreillyvia for the contribution) ### LANGUAGE (e.g., 'Core' or 'Python' or 'Node.js') diff --git a/docs/search/go.sum b/docs/search/go.sum index d39b629016..0217a4f292 100644 --- a/docs/search/go.sum +++ b/docs/search/go.sum @@ -2,24 +2,30 @@ github.com/algolia/algoliasearch-client-go/v3 v3.18.1 h1:FP2Xtqqs/sefR5Qluygp+jV github.com/algolia/algoliasearch-client-go/v3 v3.18.1/go.mod h1:i7tLoP7TYDmHX3Q7vkIOL4syVse/k5VJ+k0i8WqFiJk= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/hashicorp/go-hclog v0.15.0 h1:qMuK0wxsoW4D0ddCCYwPSTm4KQv1X1ke3WmPWZ0Mvsk= github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= diff --git a/languages/java/oso/src/main/java/com/osohq/oso/Polar.java b/languages/java/oso/src/main/java/com/osohq/oso/Polar.java index b2f4856301..bf59c7093c 100644 --- a/languages/java/oso/src/main/java/com/osohq/oso/Polar.java +++ b/languages/java/oso/src/main/java/com/osohq/oso/Polar.java @@ -1,11 +1,15 @@ package com.osohq.oso; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Optional.ofNullable; + import com.osohq.oso.Exceptions.OsoException; import com.osohq.oso.Exceptions.ParseError; import com.osohq.oso.Exceptions.PolarRuntimeException; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Paths; @@ -13,10 +17,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import org.json.JSONArray; public class Polar { + + private static final String POLAR_EXTENTION = "polar"; + private Ffi.Polar ffiPolar; protected Host host; // visible for tests only @@ -55,22 +61,19 @@ public void clearRules() throws Exceptions.OsoException { * @throws IOException If unable to open or read the file. */ public void loadFiles(String[] filenames) throws IOException, OsoException { - if (filenames.length == 0) { + if (filenames == null || filenames.length == 0) { return; } JSONArray sources = new JSONArray(); for (String filename : filenames) { - Optional ext = - Optional.ofNullable(filename) - .filter(f -> f.contains(".")) - .map(f -> f.substring(filename.lastIndexOf(".") + 1)); - // check file extension - if (!ext.isPresent() || !ext.get().equals("polar")) { - throw new Exceptions.PolarFileExtensionError(filename); - } + ofNullable(filename) + .filter(f -> f.contains(".")) + .map(f -> f.substring(filename.lastIndexOf(".") + 1)) + .filter(extention -> extention.equals(POLAR_EXTENTION)) + .orElseThrow(() -> new Exceptions.PolarFileExtensionError(filename)); try { String contents = new String(Files.readAllBytes(Paths.get(filename))); @@ -84,6 +87,43 @@ public void loadFiles(String[] filenames) throws IOException, OsoException { loadSources(sources); } + /** + * Load Polar policy files from resources. File contents are loaded into a String and saved here, + * so changes to a file made after a call to loadFiles will not be recognized. + * + * @throws Exceptions.PolarFileExtensionError On incorrect file extension. + * @throws Exceptions.PolarFileNotFoundError On nonexistent file. + * @throws Exceptions.InlineQueryFailedError On a failed inline query. + * @throws IOException If unable to open or read the file. + */ + public void loadFilesFromResources(String... filenames) throws IOException, OsoException { + if (filenames == null || filenames.length == 0) { + return; + } + + JSONArray sources = new JSONArray(); + for (String filename : filenames) { + // check file extension + ofNullable(filename) + .filter(f -> f.contains(".")) + .map(f -> f.substring(filename.lastIndexOf(".") + 1)) + .filter(extention -> extention.equals(POLAR_EXTENTION)) + .orElseThrow(() -> new Exceptions.PolarFileExtensionError(filename)); + + try (InputStream inputStream = getClass().getResourceAsStream(filename)) { + if (inputStream == null) { + throw new Exceptions.PolarFileNotFoundError(filename); + } + + String contents = new String(inputStream.readAllBytes(), UTF_8); + + sources.put(new Source(contents, filename).toJSON()); + } + } + + loadSources(sources); + } + /** * Load a Polar policy file. File contents are loaded into a String and saved here, so changes to * the file made after a call to loadFile will not be recognized. diff --git a/languages/java/oso/src/test/java/com/osohq/oso/PolarTest.java b/languages/java/oso/src/test/java/com/osohq/oso/PolarTest.java index 9311c5cb06..0874413517 100644 --- a/languages/java/oso/src/test/java/com/osohq/oso/PolarTest.java +++ b/languages/java/oso/src/test/java/com/osohq/oso/PolarTest.java @@ -20,6 +20,7 @@ import java.util.Map; import org.json.JSONObject; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class PolarTest { @@ -526,6 +527,32 @@ public void testLoadMultipleFilesSameNameDifferentPath() throws Exception { p.query("g(x)").results().equals(List.of(Map.of("x", 1), Map.of("x", 2), Map.of("x", 3)))); } + @Test + @DisplayName("testLoadFilesFromResources loads multiple files from resources folder") + public void testLoadFilesFromResources() throws Exception { + p.loadFilesFromResources("/test.polar", "/test2.polar"); + assertTrue( + p.query("f(x)").results().equals(List.of(Map.of("x", 1), Map.of("x", 2), Map.of("x", 3)))); + assertTrue( + p.query("g(x)").results().equals(List.of(Map.of("x", 1), Map.of("x", 2), Map.of("x", 3)))); + } + + @Test + @DisplayName("testLoadFilesFromResources throws exception when tries loading missing file") + public void testLoadFilesFromResourcesTriesLoadingMissingFile() throws Exception { + assertThrows( + Exceptions.PolarFileNotFoundError.class, () -> p.loadFilesFromResources("/missing.polar")); + } + + @Test + @DisplayName( + "testLoadFilesFromResources throws exception when tries loading file with non-polar" + + " extension") + public void testLoadFilesFromResourcesTriesLoadingNonPolarFile() throws Exception { + assertThrows( + Exceptions.PolarFileExtensionError.class, () -> p.loadFilesFromResources("/test.file")); + } + @Test public void testClearRules() throws Exception { p.loadFile("src/test/java/com/osohq/oso/test.polar"); diff --git a/languages/java/oso/src/test/resources/test.polar b/languages/java/oso/src/test/resources/test.polar new file mode 100644 index 0000000000..890c369abd --- /dev/null +++ b/languages/java/oso/src/test/resources/test.polar @@ -0,0 +1,3 @@ +f(1); +f(2); +f(3); \ No newline at end of file diff --git a/languages/java/oso/src/test/resources/test2.polar b/languages/java/oso/src/test/resources/test2.polar new file mode 100644 index 0000000000..73c9ed22e4 --- /dev/null +++ b/languages/java/oso/src/test/resources/test2.polar @@ -0,0 +1,3 @@ +g(1); +g(2); +g(3); \ No newline at end of file