Skip to content

Commit

Permalink
Load policy files from resources (#1554)
Browse files Browse the repository at this point in the history
* Add support for loading policy files from the resources folder.

Co-authored-by: Tamas Kovacs <[email protected]>
Co-authored-by: Sam Scott <[email protected]>
Co-authored-by: Graham Kaemmer <[email protected]>
Co-authored-by: Stephen Olsen <[email protected]>
  • Loading branch information
5 people authored Aug 4, 2022
1 parent 32f4b40 commit c2ac67f
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 11 deletions.
15 changes: 14 additions & 1 deletion docs/content/any/project/changelogs/NEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down
6 changes: 6 additions & 0 deletions docs/search/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
60 changes: 50 additions & 10 deletions languages/java/oso/src/main/java/com/osohq/oso/Polar.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
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;
import java.util.Arrays;
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

Expand Down Expand Up @@ -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<String> 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)));
Expand All @@ -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.
Expand Down
27 changes: 27 additions & 0 deletions languages/java/oso/src/test/java/com/osohq/oso/PolarTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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");
Expand Down
3 changes: 3 additions & 0 deletions languages/java/oso/src/test/resources/test.polar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
f(1);
f(2);
f(3);
3 changes: 3 additions & 0 deletions languages/java/oso/src/test/resources/test2.polar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
g(1);
g(2);
g(3);

1 comment on commit c2ac67f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust Benchmark

Benchmark suite Current: c2ac67f Previous: 32f4b40 Ratio
rust_get_attribute 43897 ns/iter (± 1949) 42194 ns/iter (± 1228) 1.04
n_plus_one/100 2210657 ns/iter (± 5490) 2240461 ns/iter (± 12330) 0.99
n_plus_one/500 10627532 ns/iter (± 34720) 10850411 ns/iter (± 127283) 0.98
n_plus_one/1000 21186400 ns/iter (± 142278) 21556109 ns/iter (± 77247) 0.98
unify_once 934 ns/iter (± 428) 880 ns/iter (± 15) 1.06
unify_twice 2538 ns/iter (± 56) 2498 ns/iter (± 47) 1.02
many_rules 60711 ns/iter (± 1367) 61182 ns/iter (± 1742) 0.99
fib/5 525523 ns/iter (± 8803) 526624 ns/iter (± 8979) 1.00
prime/3 17462 ns/iter (± 763) 17919 ns/iter (± 658) 0.97
prime/23 17568 ns/iter (± 749) 17920 ns/iter (± 637) 0.98
prime/43 17491 ns/iter (± 850) 17905 ns/iter (± 706) 0.98
prime/83 17541 ns/iter (± 746) 17926 ns/iter (± 618) 0.98
prime/255 16130 ns/iter (± 626) 16633 ns/iter (± 539) 0.97
indexed/100 5756 ns/iter (± 666) 5802 ns/iter (± 493) 0.99
indexed/500 7166 ns/iter (± 1947) 6940 ns/iter (± 1457) 1.03
indexed/1000 9394 ns/iter (± 716) 8972 ns/iter (± 788) 1.05
indexed/10000 28450 ns/iter (± 3041) 21300 ns/iter (± 1666) 1.34
not 5817 ns/iter (± 116) 5862 ns/iter (± 78) 0.99
double_not 12179 ns/iter (± 233) 12278 ns/iter (± 180) 0.99
De_Morgan_not 7753 ns/iter (± 208) 7989 ns/iter (± 153) 0.97
load_policy 880617 ns/iter (± 2131) 895456 ns/iter (± 4906) 0.98
partial_and/1 31027 ns/iter (± 1429) 30774 ns/iter (± 1104) 1.01
partial_and/5 109800 ns/iter (± 3320) 106240 ns/iter (± 2743) 1.03
partial_and/10 209255 ns/iter (± 4355) 203608 ns/iter (± 4489) 1.03
partial_and/20 425753 ns/iter (± 8390) 422389 ns/iter (± 9055) 1.01
partial_and/40 902663 ns/iter (± 12114) 906328 ns/iter (± 13709) 1.00
partial_and/80 2041936 ns/iter (± 21323) 2078490 ns/iter (± 17526) 0.98
partial_and/100 2704240 ns/iter (± 29908) 2746743 ns/iter (± 19426) 0.98
partial_rule_depth/1 101373 ns/iter (± 4274) 95816 ns/iter (± 3364) 1.06
partial_rule_depth/5 333059 ns/iter (± 8178) 323935 ns/iter (± 6681) 1.03
partial_rule_depth/10 725154 ns/iter (± 16634) 725084 ns/iter (± 12744) 1.00
partial_rule_depth/20 2034898 ns/iter (± 41155) 2046512 ns/iter (± 14107) 0.99
partial_rule_depth/40 7435299 ns/iter (± 127472) 7477115 ns/iter (± 116327) 0.99
partial_rule_depth/80 44644585 ns/iter (± 441593) 39717880 ns/iter (± 227135) 1.12
partial_rule_depth/100 83233493 ns/iter (± 575365) 71785680 ns/iter (± 350772) 1.16

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.