Skip to content

Commit

Permalink
WIP refactor to AtomicUrl
Browse files Browse the repository at this point in the history
  • Loading branch information
joepio committed Sep 30, 2022
1 parent adf4990 commit 3b55040
Show file tree
Hide file tree
Showing 21 changed files with 325 additions and 97 deletions.
32 changes: 32 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[build]
rustc-wrapper = '/Users/joep/.cargo/bin/sccache'
[target.x86_64-unknown-linux-gnu]
rustflags = [
'-Clink-arg=-fuse-ld=lld',
'-Zshare-generics=y',
]
linker = '/usr/bin/clang'

[target.x86_64-pc-windows-msvc]
rustflags = ['-Zshare-generics=y']
linker = 'rust-lld.exe'

[target.x86_64-apple-darwin]
rustflags = [
'-C',
'link-arg=-fuse-ld=/usr/local/bin/zld',
'-Zshare-generics=y',
'-Csplit-debuginfo=unpacked',
]
[profile.dev]
opt-level = 0
debug = 2
incremental = true
codegen-units = 512

[profile.release]
opt-level = 3
debug = 0
incremental = false
codegen-units = 256
split-debuginfo = '...'
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn set_agent_config() -> CLIResult<Config> {
"No config found at {:?}. Let's create one!",
&agent_config_path
);
let server = promptly::prompt("What's the base url of your Atomic Server?")?;
let server: String = promptly::prompt("What's the base url of your Atomic Server?")?;
let agent = promptly::prompt("What's the URL of your Agent?")?;
let private_key = promptly::prompt("What's the private key of this Agent?")?;
let config = atomic_lib::config::Config {
Expand Down Expand Up @@ -282,7 +282,7 @@ fn exec_command(context: &mut Context) -> AtomicResult<()> {
fn list(context: &mut Context) {
let mut string = String::new();
for (shortname, url) in context.mapping.lock().unwrap().clone().into_iter() {
string.push_str(&*format!(
string.push_str(&format!(
"{0: <15}{1: <10} \n",
shortname.blue().bold(),
url
Expand All @@ -297,7 +297,7 @@ fn tpf(context: &Context) -> AtomicResult<()> {
let subject = tpf_value(subcommand_matches.value_of("subject").unwrap());
let property = tpf_value(subcommand_matches.value_of("property").unwrap());
let value = tpf_value(subcommand_matches.value_of("value").unwrap());
let endpoint = format!("{}/tpf", &context.get_write_context().server);
let endpoint = context.store.get_server_url().path_tpf().to_string();
let resources =
atomic_lib::client::fetch_tpf(&endpoint, subject, property, value, &context.store)?;
for r in resources {
Expand Down
14 changes: 7 additions & 7 deletions cli/src/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ fn prompt_field(
println!("Only letters, numbers and dashes - no spaces or special characters.");
return Ok(None);
}
None => (return Ok(None)),
None => return Ok(None),
}
}
DataType::Integer => {
Expand All @@ -158,7 +158,7 @@ fn prompt_field(
Some(nr) => {
input = Some(nr.to_string());
}
None => (return Ok(None)),
None => return Ok(None),
}
}
DataType::Float => {
Expand All @@ -168,7 +168,7 @@ fn prompt_field(
Some(nr) => {
input = Some(nr.to_string());
}
None => (return Ok(None)),
None => return Ok(None),
}
}
DataType::Date => {
Expand All @@ -184,7 +184,7 @@ fn prompt_field(
println!("Not a valid date.");
return Ok(None);
}
None => (return Ok(None)),
None => return Ok(None),
}
}
DataType::AtomicUrl => loop {
Expand Down Expand Up @@ -264,7 +264,7 @@ fn prompt_field(
Some(nr) => {
input = Some(nr.to_string());
}
None => (return Ok(None)),
None => return Ok(None),
}
}
DataType::Unsupported(unsup) => {
Expand All @@ -277,7 +277,7 @@ fn prompt_field(
Some(nr) => {
input = Some(nr);
}
None => (return Ok(None)),
None => return Ok(None),
}
}
DataType::Boolean => {
Expand All @@ -290,7 +290,7 @@ fn prompt_field(
}
return Ok(Some("false".to_string()));
}
None => (return Ok(None)),
None => return Ok(None),
}
}
};
Expand Down
14 changes: 7 additions & 7 deletions cli/src/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ pub const SERIALIZE_OPTIONS: [&str; 7] =
pub fn get_serialization(argmatches: &ArgMatches) -> AtomicResult<Format> {
let format = if let Some(preferred_format) = argmatches.value_of("as") {
match preferred_format {
"pretty" => (Format::Pretty),
"json" => (Format::Json),
"jsonld" => (Format::JsonLd),
"jsonad" => (Format::JsonAd),
"nt" => (Format::NTriples),
"turtle" => (Format::NTriples),
"n3" => (Format::NTriples),
"pretty" => Format::Pretty,
"json" => Format::Json,
"jsonld" => Format::JsonLd,
"jsonad" => Format::JsonAd,
"nt" => Format::NTriples,
"turtle" => Format::NTriples,
"n3" => Format::NTriples,
format => {
return Err(
format!("As {} not supported. Try {:?}", format, SERIALIZE_OPTIONS).into(),
Expand Down
18 changes: 12 additions & 6 deletions lib/src/agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,29 @@ impl Agent {
pub fn new(name: Option<&str>, store: &impl Storelike) -> AtomicResult<Agent> {
let keypair = generate_keypair()?;

Ok(Agent::new_from_private_key(name, store, &keypair.private))
Agent::new_from_private_key(name, store, &keypair.private)
}

pub fn new_from_private_key(
name: Option<&str>,
store: &impl Storelike,
private_key: &str,
) -> Agent {
) -> AtomicResult<Agent> {
let keypair = generate_public_key(private_key);
println!("server url: {}", store.get_server_url());
let subject = store
.get_server_url()
.url()
.join(&format!("agents/{}", &keypair.public))?
.to_string();

Agent {
Ok(Agent {
private_key: Some(keypair.private),
public_key: keypair.public.clone(),
subject: format!("{}/agents/{}", store.get_server_url(), keypair.public),
public_key: keypair.public,
subject,
name: name.map(|x| x.to_owned()),
created_at: crate::utils::now(),
}
})
}

pub fn new_from_public_key(store: &impl Storelike, public_key: &str) -> AtomicResult<Agent> {
Expand Down
155 changes: 155 additions & 0 deletions lib/src/atomic_url.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use serde::{Deserialize, Serialize, Serializer};
use url::Url;

use crate::{
errors::AtomicResult,
urls::{PATH_COMMITS, PATH_IMPORT, PATH_PATH, PATH_TPF},
utils::random_string,
};

#[derive(Debug, Clone, PartialEq, Eq)]
/// Wrapper for URLs / subjects.
/// Has a bunch of methods for finding or creating commonly used paths.
pub struct AtomicUrl {
url: Url,
}

impl AtomicUrl {
pub fn new(url: Url) -> Self {
Self { url }
}

pub fn as_str(&self) -> &str {
self.url.as_str()
}

/// Returns the URL to the `/tpf` endpoint
pub fn path_tpf(&self) -> Self {
let mut url = self.url.clone();
url.set_path(PATH_TPF);
Self { url }
}

/// Returns the URL to the `/import` endpoint
pub fn path_import(&self) -> Self {
let mut url = self.url.clone();
url.set_path(PATH_IMPORT);
Self { url }
}
/// Returns the URL to the `/commits` endpoint
pub fn path_commits(&self) -> Self {
let mut url = self.url.clone();
url.set_path(PATH_COMMITS);
Self { url }
}

/// Returns the URL to the `/path` endpoint
pub fn path_path(&self) -> Self {
let mut url = self.url.clone();
url.set_path(PATH_PATH);
Self { url }
}

/// Returns a new URL generated from the provided path_shortname and a random string.
/// ```
/// let url = AtomicUrl::new(Url::parse("https://example.com").unwrap());
/// let generated = url.generate("my-type");
/// assert!(generated.to_string().starts_with("https://example.com/my-type/"));
/// ```
pub fn generate_random(&self, path_shortname: &str) -> Self {
let mut url = self.url.clone();
let path = format!("{path_shortname}/{}", random_string(10));
url.set_path(&path);
Self { url }
}

/// Adds a path to a URL
pub fn join(mut self, path: &str) -> AtomicResult<Self> {
self.url = self.url.join(path)?;
Ok(self)
}

pub fn subdomain(&self) -> Option<String> {
let url = self.url.clone();
let host = url.host_str().unwrap();
let parts: Vec<&str> = host.split('.').collect();
if parts.len() > 2 {
Some(parts[0].to_string())
} else {
None
}
}

/// Returns the inner {url::Url} struct that has a bunch of regular URL methods
/// Useful if you need the host or something.
pub fn url(&self) -> Url {
self.url.clone()
}
}

impl TryFrom<&str> for AtomicUrl {
type Error = url::ParseError;

fn try_from(value: &str) -> Result<Self, Self::Error> {
let url = Url::parse(value)?;
Ok(Self { url })
}
}

impl Serialize for AtomicUrl {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.url.as_str())
}
}

impl<'de> Deserialize<'de> for AtomicUrl {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let url = Url::parse(&s).map_err(serde::de::Error::custom)?;
Ok(Self { url })
}
}

impl std::fmt::Display for AtomicUrl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.url)
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_url() {
let _should_fail = AtomicUrl::try_from("nonsense").unwrap_err();
let _should_succeed = AtomicUrl::try_from("http://localhost/someUrl").unwrap();
}

#[test]
fn join_url() {
let start = "http://localhost/someUrl";
let mut url = AtomicUrl::try_from(start).unwrap();

assert_eq!(url.to_string(), start);
url = url.join("/123").unwrap();
assert_eq!(url.to_string(), "http://localhost/someUrl/123")
}

#[test]
fn subdomain() {
let sub = "http://test.example.com";
assert_eq!(
AtomicUrl::try_from(sub).unwrap().subdomain(),
Some("test".to_string())
);
let no_sub = "http://example.com";
assert_eq!(AtomicUrl::try_from(no_sub).unwrap().subdomain(), None);
}
}
8 changes: 6 additions & 2 deletions lib/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,12 +425,16 @@ impl Commit {
#[tracing::instrument(skip(store))]
pub fn into_resource(self, store: &impl Storelike) -> AtomicResult<Resource> {
let commit_subject = match self.signature.as_ref() {
Some(sig) => format!("{}/commits/{}", store.get_server_url(), sig),
Some(sig) => store.get_server_url().path_commits().join(sig)?.to_string(),
None => {
let now = crate::utils::now();
format!("{}/commitsUnsigned/{}", store.get_server_url(), now)
}
};
println!(
"commit subject: {}",
store.get_server_url().path_commits().join("adwdawawd")?
);
let mut resource = Resource::new_instance(urls::COMMIT, store)?;
resource.set_subject(commit_subject);
resource.set_propval_unsafe(
Expand Down Expand Up @@ -752,7 +756,7 @@ mod test {
let private_key = "CapMWIhFUT+w7ANv9oCPqrHrwZpkP2JhzF9JnyT6WcI=";
let store = crate::Store::init().unwrap();
store.populate().unwrap();
let agent = Agent::new_from_private_key(None, &store, private_key);
let agent = Agent::new_from_private_key(None, &store, private_key).unwrap();
assert_eq!(
&agent.subject,
"local:store/agents/7LsjMW5gOfDdJzK/atgjQ1t20J/rw8MjVg6xwqm+h8U="
Expand Down

0 comments on commit 3b55040

Please sign in to comment.