From b9b3179d52dfce5395b22521177d1dd1b14b7955 Mon Sep 17 00:00:00 2001 From: Vincent Emonet Date: Fri, 1 Mar 2024 18:17:17 +0100 Subject: [PATCH] enable the profile to be null on the rust side (still need to improve JS and py bindings). Related to https://github.com/vemonet/nanopub-rs/issues/4 --- cli/src/main.rs | 6 ++++-- js/src/nanopub.rs | 4 ++-- lib/docs/use_rust.md | 4 ++-- lib/src/lib.rs | 2 +- lib/src/nanopub.rs | 13 +++++++++---- lib/src/utils.rs | 2 ++ lib/tests/nanopub_test.rs | 12 ++++++------ lib/tests/testsuite_test.rs | 18 +++++++++++++----- python/src/nanopub.rs | 2 +- 9 files changed, 40 insertions(+), 23 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 0750f84..2e19c5b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -112,11 +112,13 @@ async fn main() -> Result<(), Box> { }; if test_server { println!("🧪 Publishing {np_file} to test server"); - let _ = Nanopub::new(&np_rdf)?.publish(&profile, None).await; + let _ = Nanopub::new(&np_rdf)?.publish(Some(&profile), None).await; } else { let server = get_np_server(true); println!("📬️ Publishing {np_file} to {server}"); - let _ = Nanopub::new(&np_rdf)?.publish(&profile, Some(server)).await; + let _ = Nanopub::new(&np_rdf)? + .publish(Some(&profile), Some(server)) + .await; } } Some(("check", sub)) => { diff --git a/js/src/nanopub.rs b/js/src/nanopub.rs index 5cfda26..7886b33 100644 --- a/js/src/nanopub.rs +++ b/js/src/nanopub.rs @@ -59,7 +59,7 @@ impl NanopubJs { } .to_string(); future_to_promise(async move { - match self.np.publish(&profile, Some(&server_url)).await { + match self.np.publish(Some(&profile), Some(&server_url)).await { Ok(np) => Ok(JsValue::from(NanopubJs { np })), Err(e) => Err(JsValue::from_str(&format!( "Error publishing the Nanopub: {e}" @@ -86,7 +86,7 @@ impl NanopubJs { ))) } }; - match np.publish(&profile, Some(&server_url)).await { + match np.publish(Some(&profile), Some(&server_url)).await { Ok(np) => Ok(JsValue::from(NanopubJs { np })), Err(e) => Err(JsValue::from_str(&format!( "Error publishing Nanopub Introduction: {e}" diff --git a/lib/docs/use_rust.md b/lib/docs/use_rust.md index e31edc0..c1247e9 100644 --- a/lib/docs/use_rust.md +++ b/lib/docs/use_rust.md @@ -51,7 +51,7 @@ let checked_np = Nanopub::new(&signed_np.get_rdf().unwrap()).unwrap().check(); let rt = runtime::Runtime::new().expect("Failed to create Tokio runtime"); let published_np = rt.block_on(async { - Nanopub::new(np_rdf).unwrap().publish(&profile, None).await.unwrap() + Nanopub::new(np_rdf).unwrap().publish(Some(&profile), None).await.unwrap() }); println!("{}", published_np) ``` @@ -85,7 +85,7 @@ async fn np_from_scratch() -> Result<(), NpError> { let private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCjY1gsFxmak6SOCouJPuEzHNForkqFhgfHE3aAIAx+Y5q6UDEDM9Q0EksheNffJB4iPqsAfiFpY0ARQY92K5r8P4+a78eu9reYrb2WxZb1qPJmvR7XZ6sN1oHD7dd/EyQoJmQsmOKdrqaLRbzR7tZrf52yvKkwNWXcIVhW8uxe7iUgxiojZpW9srKoK/qFRpaUZSKn7Z/zgtDH9FJkYbBsGPDMqp78Kzt+sJb+U2W+wCSSy34jIUxx6QRbzvn6uexc/emFw/1DU5y7zBudhgC7mVk8vX1gUNKyjZBzlOmRcretrANgffqs5fx/TMHN1xtkA/H1u1IKBfKoyk/xThMLAgMBAAECggEAECuG0GZA3HF8OaqFgMG+W+agOvH04h4Pqv4cHjYNxnxpFcNV9nEssTKWSOvCwYy7hrwZBGV3PQzbjFmmrxVFs20+8yCD7KbyKKQZPVC0zf84bj6NTNgvr6DpGtDxINxuGaMjCt7enqhoRyRRuZ0fj2gD3Wqae/Ds8cpDCefkyMg0TvauHSUj244vGq5nt93txUv1Sa+/8tWZ77Dm0s5a3wUYB2IeAMl5WrO2GMvgzwH+zT+4kvNWg5S0Ze4KE+dG3lSIYZjo99h14LcQS9eALC/VBcAJ6pRXaCTT/TULtcLNeOpoc9Fu25f0yTsDt6Ga5ApliYkb7rDhV+OFrw1sYQKBgQDCE9so+dPg7qbp0cV+lbb7rrV43m5s9Klq0riS7u8m71oTwhmvm6gSLfjzqb8GLrmflCK4lKPDSTdwyvd+2SSmOXySw94zr1Pvc7sHdmMRyA7mH3m+zSOOgyCTTKyhDRCNcRIkysoL+DecDhNo4Fumf71tsqDYogfxpAQhn0re8wKBgQDXhMmmT2oXiMnYHhi2k7CJe3HUqkZgmW4W44SWqKHp0V6sjcHm0N0RT5Hz1BFFUd5Y0ZB3JLcah19myD1kKYCj7xz6oVLb8O7LeAZNlb0FsrtD7NU+Hciywo8qESiA7UYDkU6+hsmxaI01DsttMIdG4lSBbEjA7t4IQC5lyr7xiQKBgQCN87YGJ40Y5ZXCSgOZDepz9hqX2KGOIfnUv2HvXsIfiUwqTXs6HbD18xg3KL4myIBOvywSM+4ABYp+foY+Cpcq2btLIeZhiWjsKIrw71+Q/vIe0YDb1PGf6DsoYhmWBpdHzR9HN+hGjvwlsYny2L9Qbfhgxxmsuf7zeFLpQLijjwKBgH7TD28k8IOk5VKec2CNjKd600OYaA3UfCpP/OhDl/RmVtYoHWDcrBrRvkvEEd2/DZ8qw165Zl7gJs3vK+FTYvYVcfIzGPWA1KU7nkntwewmf3i7V8lT8ZTwVRsmObWU60ySJ8qKuwoBQodki2VX12NpMN1wgWe3qUUlr6gLJU4xAoGAet6nD3QKwk6TTmcGVfSWOzvpaDEzGkXjCLaxLKh9GreM/OE+h5aN2gUoFeQapG5rUwI/7Qq0xiLbRXw+OmfAoV2XKv7iI8DjdIh0F06mlEAwQ/B0CpbqkuuxphIbchtdcz/5ra233r3BMNIqBl3VDDVoJlgHPg9msOTRy13lFqc="; let profile = NpProfile::new(&private_key, "https://orcid.org/0000-0000-0000-0000", "", None)?; - let np = np.publish(&profile, None).await?; + let np = np.publish(Some(&profile), None).await?; Ok(()) } ``` diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 5719b73..137c498 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -36,7 +36,7 @@ pub use error::NpError; /// let checked_np = Nanopub::new(&signed_np.get_rdf().unwrap()).unwrap().check(); /// let rt = runtime::Runtime::new().expect("Failed to create Tokio runtime"); /// let published_np = rt.block_on(async { -/// Nanopub::new(&np_rdf).unwrap().publish(&profile, None).await.unwrap() +/// Nanopub::new(&np_rdf).unwrap().publish(Some(&profile), None).await.unwrap() /// }); /// println!("{}", published_np) /// ``` diff --git a/lib/src/nanopub.rs b/lib/src/nanopub.rs index 0b806e1..4eadb19 100644 --- a/lib/src/nanopub.rs +++ b/lib/src/nanopub.rs @@ -350,17 +350,22 @@ impl Nanopub { /// let rt = runtime::Runtime::new().expect("Failed to create Tokio runtime"); /// /// let np = rt.block_on(async { - /// Nanopub::new(&np_rdf).unwrap().publish(&profile, None).await + /// Nanopub::new(&np_rdf).unwrap().publish(Some(&profile), None).await /// }).unwrap(); /// ``` pub async fn publish( mut self, - profile: &NpProfile, + profile: Option<&NpProfile>, server_url: Option<&str>, ) -> Result { - self = if self.info.signature.is_empty() { + self = if let Some(profile) = profile { println!("Nanopub not signed, signing it before publishing"); self.sign(profile)? + } else if self.info.signature.is_empty() { + return Err(NpError(format!( + "No profile provided and nanopub not signed, could not sign the Nanopublication \n{}", + self + ))); } else { // If the nanopub is already signed we verify it, then publish it self.check()? @@ -419,7 +424,7 @@ impl Nanopub { /// let rt = runtime::Runtime::new().expect("Failed to create Tokio runtime"); /// /// let np = rt.block_on(async { - /// Nanopub::new_intro(&profile).unwrap().publish(&profile, None).await.unwrap() + /// Nanopub::new_intro(&profile).unwrap().publish(Some(&profile), None).await.unwrap() /// }); /// ``` pub fn new_intro(profile: &NpProfile) -> Result { diff --git a/lib/src/utils.rs b/lib/src/utils.rs index a96df73..8ba820d 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -85,6 +85,7 @@ pub fn ns(ns: &str) -> Namespace { } } +// TODO: improve to extract prefixes from the input RDF /// Get the prefixes of a Nanopub pub fn get_prefixes(np_uri: &str, np_ns: &str) -> [(Prefix, Iri); 14] { [ @@ -108,6 +109,7 @@ pub fn get_prefixes(np_uri: &str, np_ns: &str) -> [(Prefix, Iri) Prefix::new_unchecked("xsd".to_string()), Iri::new_unchecked("http://www.w3.org/2001/XMLSchema#".to_string()), ), + // TODO: use https:// by default? ( Prefix::new_unchecked("schema".to_string()), Iri::new_unchecked("http://schema.org/".to_string()), diff --git a/lib/tests/nanopub_test.rs b/lib/tests/nanopub_test.rs index bb5ceaf..298773a 100644 --- a/lib/tests/nanopub_test.rs +++ b/lib/tests/nanopub_test.rs @@ -20,7 +20,7 @@ fn get_test_key() -> String { async fn publish_nanopub_simple_rsa() -> Result<(), Box> { let np_rdf = fs::read_to_string("./tests/resources/simple1-rsa.trig")?; let profile = NpProfile::new(&get_test_key(), "", "", None)?; - let np = Nanopub::new(&np_rdf)?.publish(&profile, None).await?; + let np = Nanopub::new(&np_rdf)?.publish(Some(&profile), None).await?; println!("{}", np.get_rdf()?); assert!(np.info.published); // Values compiled with the nanopub java lib using the exact same RDF @@ -37,7 +37,7 @@ async fn publish_proteinatlas() -> Result<(), Box> { let np_rdf = fs::read_to_string("tests/testsuite/valid/plain/proteinatlas-16-1.trig")?; // let np_rdf = fs::read_to_string("./tests/resources/nanopub_test_blank.trig")?; let profile = NpProfile::new(&get_test_key(), "", "", None)?; - let np = Nanopub::new(&np_rdf)?.publish(&profile, None).await?; + let np = Nanopub::new(&np_rdf)?.publish(Some(&profile), None).await?; assert!(np.info.published); Ok(()) } @@ -84,7 +84,7 @@ async fn publish_fail() -> Result<(), Box> { let np_rdf = fs::read_to_string("./tests/resources/simple1-rsa.trig")?; let profile = NpProfile::new(&get_test_key(), "", "", None)?; let np = Nanopub::new(&np_rdf)? - .publish(&profile, Some("failing")) + .publish(Some(&profile), Some("failing")) .await; assert!(np.is_err()); Ok(()) @@ -116,7 +116,7 @@ fn test_get_np_server() -> Result<(), Box> { async fn publish_jsonld() -> Result<(), Box> { let np_rdf = fs::read_to_string("./tests/resources/nanopub.jsonld")?; let profile = NpProfile::new(&get_test_key(), "", "", None)?; - let np = Nanopub::new(&np_rdf)?.publish(&profile, None).await?; + let np = Nanopub::new(&np_rdf)?.publish(Some(&profile), None).await?; assert!(np.info.published); Ok(()) } @@ -130,7 +130,7 @@ async fn publish_np_intro() -> Result<(), Box> { None, )?; let np = Nanopub::new_intro(&profile)? - .publish(&profile, None) + .publish(Some(&profile), None) .await?; // println!("{}", np); assert!(np.info.published); @@ -212,7 +212,7 @@ async fn publish_from_scratch() -> Result<(), Box> { Iri::new_unchecked("http://dx.doi.org/10.3233/ISU-2010-0613"), Some(&np.info.prov), )?; - let np = np.publish(&profile, None).await?; + let np = np.publish(Some(&profile), None).await?; println!("DEBUG: SCRATCH 2 {}", np.get_rdf()?); // assert!(res.is_err()); Ok(()) diff --git a/lib/tests/testsuite_test.rs b/lib/tests/testsuite_test.rs index 32235f5..c157531 100644 --- a/lib/tests/testsuite_test.rs +++ b/lib/tests/testsuite_test.rs @@ -15,7 +15,9 @@ async fn testsuite_publish_valid_plain() -> Result<(), Box> { if filename.ends_with("trig\"") { println!("\n☑️ Testing file publish: {}", filename); let np_rdf = fs::read_to_string(file.path())?; - let np = Nanopub::new(&np_rdf)?.publish(&get_profile(), None).await?; + let np = Nanopub::new(&np_rdf)? + .publish(Some(&get_profile()), None) + .await?; assert!(np.info.published); } } @@ -126,7 +128,7 @@ fn testsuite_publish_invalid_plain() -> Result<(), Box> { let result = Nanopub::new(&np_rdf).and_then(|np| { tokio::runtime::Runtime::new() .unwrap() - .block_on(np.publish(&get_profile(), None)) + .block_on(np.publish(Some(&get_profile()), None)) }); assert!( result.is_err(), @@ -141,7 +143,9 @@ fn testsuite_publish_invalid_plain() -> Result<(), Box> { #[tokio::test] async fn testsuite_publish_transform_signed_simple1() -> Result<(), Box> { let np_rdf = fs::read_to_string("./tests/testsuite/transform/signed/rsa-key1/simple1.in.trig")?; - let np = Nanopub::new(&np_rdf)?.publish(&get_profile(), None).await?; + let np = Nanopub::new(&np_rdf)? + .publish(Some(&get_profile()), None) + .await?; assert!(np.info.published); assert_eq!( np.info.trusty_hash, @@ -156,7 +160,9 @@ async fn testsuite_publish_transform_signed_simple1() -> Result<(), Box Result<(), Box> { let np_rdf = fs::read_to_string("./tests/testsuite/transform/trusty/aida1.in.trig")?; - let np = Nanopub::new(&np_rdf)?.publish(&get_profile(), None).await?; + let np = Nanopub::new(&np_rdf)? + .publish(Some(&get_profile()), None) + .await?; // println!("{}", np); assert!(np.info.published); // assert_eq!(np.trusty_hash, "RAPpJU5UOB4pavfWyk7FE3WQiam5yBpmIlviAQWtBSC4M"); @@ -166,7 +172,9 @@ async fn testsuite_publish_transform_trusty_aida() -> Result<(), Box> #[tokio::test] async fn testsuite_publish_transform_trusty_simple1() -> Result<(), Box> { let np_rdf = fs::read_to_string("./tests/testsuite/transform/trusty/simple1.in.trig")?; - let np = Nanopub::new(&np_rdf)?.publish(&get_profile(), None).await?; + let np = Nanopub::new(&np_rdf)? + .publish(Some(&get_profile()), None) + .await?; assert!(np.info.published); // assert_eq!(np.trusty_hash, "RAtAU6U_xKTH016Eoiu11SswQkBu1elB_3_BoDJWH3arA"); Ok(()) diff --git a/python/src/nanopub.rs b/python/src/nanopub.rs index 7c9e13d..597df2c 100644 --- a/python/src/nanopub.rs +++ b/python/src/nanopub.rs @@ -63,7 +63,7 @@ impl NanopubPy { let result = rt.block_on(async move { Nanopub::new(&rdf) .map_err(|e| PyErr::new::(format!("Error Publishing: {e}")))? - .publish(&profile, server_url.as_deref()) + .publish(Some(&profile), server_url.as_deref()) .await .map_err(|e| PyErr::new::(format!("Error Publishing: {e}"))) });