diff --git a/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java b/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java new file mode 100644 index 00000000..afd3ae41 --- /dev/null +++ b/CedarJava/src/main/java/com/cedarpolicy/formatter/PolicyFormatter.java @@ -0,0 +1,17 @@ +package com.cedarpolicy.formatter; + +import com.cedarpolicy.loader.LibraryLoader; +import com.cedarpolicy.model.exception.InternalException; + +public final class PolicyFormatter { + + static { + LibraryLoader.loadLibrary(); + } + + private PolicyFormatter() { + } + + public static native String policiesStrToPretty(String policies) + throws InternalException, NullPointerException; +} diff --git a/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java b/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java new file mode 100644 index 00000000..2e26e19b --- /dev/null +++ b/CedarJava/src/test/java/com/cedarpolicy/PolicyFormatterTests.java @@ -0,0 +1,31 @@ +package com.cedarpolicy; + +import com.cedarpolicy.formatter.PolicyFormatter; +import com.cedarpolicy.model.exception.InternalException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class PolicyFormatterTests { + + private static final String TEST_RESOURCES_DIR = "src/test/resources/"; + + @Test + public void testPoliciesStrToPretty() throws Exception { + String unformattedCedarPolicy = Files.readString( + Path.of(TEST_RESOURCES_DIR + "unformatted_policy.cedar")); + + String formattedCedarPolicy = Files.readString( + Path.of(TEST_RESOURCES_DIR + "formatted_policy.cedar")); + + assertEquals(formattedCedarPolicy, PolicyFormatter.policiesStrToPretty(unformattedCedarPolicy)); + } + + @Test + public void testPoliciesStrToPrettyNullSafety() { + assertThrows(NullPointerException.class, () -> PolicyFormatter.policiesStrToPretty(null)); + } +} diff --git a/CedarJava/src/test/resources/formatted_policy.cedar b/CedarJava/src/test/resources/formatted_policy.cedar new file mode 100644 index 00000000..181564b4 --- /dev/null +++ b/CedarJava/src/test/resources/formatted_policy.cedar @@ -0,0 +1,6 @@ +permit ( + principal, + action == Action::"update", + resource +) +when { resource.owner == principal }; \ No newline at end of file diff --git a/CedarJava/src/test/resources/unformatted_policy.cedar b/CedarJava/src/test/resources/unformatted_policy.cedar new file mode 100644 index 00000000..35121ebb --- /dev/null +++ b/CedarJava/src/test/resources/unformatted_policy.cedar @@ -0,0 +1,6 @@ +permit( + principal, + action + == Action::"update", + resource +) when {resource.owner == principal}; \ No newline at end of file diff --git a/CedarJavaFFI/Cargo.toml b/CedarJavaFFI/Cargo.toml index bb3de2e3..abe5a371 100644 --- a/CedarJavaFFI/Cargo.toml +++ b/CedarJavaFFI/Cargo.toml @@ -27,3 +27,6 @@ crate_type = ["cdylib"] [dependencies.cedar-policy] version = "3.3" + +[dependencies.cedar-policy-formatter] +version = "3.3" diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index a8fb8bae..c115c012 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -22,6 +22,7 @@ use cedar_policy::{ }, EntityUid, Policy, PolicyId, PolicySet, Schema, SlotId, Template, }; +use cedar_policy_formatter::{policies_str_to_pretty, Config}; use jni::{ objects::{JClass, JObject, JString, JValueGen, JValueOwned}, sys::{jstring, jvalue}, @@ -637,3 +638,30 @@ mod test { }; } } +#[jni_fn("com.cedarpolicy.formatter.PolicyFormatter")] +pub fn policiesStrToPretty<'a>( + mut env: JNIEnv<'a>, + _: JClass, + policies_jstr: JString<'a>, +) -> jvalue { + match policies_str_to_pretty_internal(&mut env, policies_jstr) { + Ok(v) => v.as_jni(), + Err(e) => jni_failed(&mut env, e.as_ref()), + } +} + +fn policies_str_to_pretty_internal<'a>( + env: &mut JNIEnv<'a>, + policies_jstr: JString<'a>, +) -> Result> { + if policies_jstr.is_null() { + raise_npe(env) + } else { + let config = Config::default(); + let policies_str = String::from(env.get_string(&policies_jstr)?); + match policies_str_to_pretty(&policies_str, &config) { + Ok(formatted_policies) => Ok(env.new_string(formatted_policies)?.into()), + Err(e) => Err(e.into()), + } + } +} diff --git a/configure_ci_build.sh b/configure_ci_build.sh index 38782f52..f9d6d06a 100644 --- a/configure_ci_build.sh +++ b/configure_ci_build.sh @@ -3,8 +3,14 @@ cargo_file=CedarJavaFFI/Cargo.toml -sed -i -e '/\[dependencies.cedar-policy/,+4d' $cargo_file +sed -i -e '/\[dependencies.cedar-policy\]/,+4d' $cargo_file echo "" >> $cargo_file echo "[dependencies.cedar-policy]" >> $cargo_file echo "path = \"../cedar/cedar-policy\"" >> $cargo_file + +sed -i -e '/\[dependencies.cedar-policy-formatter\]/,+4d' $cargo_file + +echo "" >> $cargo_file +echo "[dependencies.cedar-policy-formatter]" >> $cargo_file +echo "path = \"../cedar/cedar-policy-formatter\"" >> $cargo_file