Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #12

Merged
merged 5 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
14 changes: 13 additions & 1 deletion Cargo.lock

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

21 changes: 11 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
[package]
name = "aries-data-generator-toolkit"
name = "aries-cloudagent-controller-ferris"
version = "0.1.0"
edition = "2018"

[[bin]]
name = "adg"
name = "accf"
path = "src/main.rs"

[dependencies]
clap = { version = "2.33.3" , features = ["yaml"] }
serde = { version = "1.0.130", features = ["derive"] }
reqwest = { version = "0.11" , features = ["json"] }
tokio = { version = "1" , features = ["full"] }
serde_json = "1.0.68"
qr2term = "0.2.2"
colored = "2.0.0"
yaml-rust = "0.4.5"
clap = { version = "2.33.3" , features = ["yaml"] }
serde = { version = "1.0.130", features = ["derive"] }
reqwest = { version = "0.11" , features = ["json"] }
tokio = { version = "1" , features = ["full"] }
serde_json = "1.0.68"
qr2term = "0.2.2"
colored = "2.0.0"
yaml-rust = "0.4.5"
async-trait = "0.1.51"
49 changes: 29 additions & 20 deletions cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,37 @@ settings:

# Main command flags
args:
- endpoint:
short: e
long: endpoint
value_name: endpoint
help: cloudagent endpoint
takes_value: true
- endpoint:
help: Required url of the cloudagent
short: e
long: endpoint
takes_value: true
required: true

# Subcommands
subcommands:
- agent:
about: agent
- invite:
about: invitations subcommand
version: "0.1.0"
args:
# A config file with all the data
- config:
short: c
long: config
value_name: FILE
help: Sets a custom config file
takes_value: true
# Wether to create an agent invitation
- create-invitation:
short: i
long: invite
help: create a proper mediation invitation
- auto-accept:
help: Whether the invitation should be auto-accepted
short: a
long: auto-accept
- multi-use:
help: Whether the invitation should be multi-use
short: m
long: multi-use
- toolbox:
help: Whether it should create a default toolbox invitation
short: t
long: toolbox
- qr:
help: Whether it should display a qr code
short: q
long: qr
- alias:
help: Alias for the connection
short: l
long: alias
takes_value: true
101 changes: 0 additions & 101 deletions src/agent.rs

This file was deleted.

15 changes: 15 additions & 0 deletions src/agent/agent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::typing::{Connection, Connections, Invitation, InviteConfiguration, Result};
use async_trait::async_trait;

#[async_trait]
pub trait Agent {
Copy link
Contributor

Choose a reason for hiding this comment

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

nice!

async fn get_connections(&self) -> Connections;
async fn get_connection_by_id(&self, id: String) -> Connection;
async fn create_invitation(&self, config: &InviteConfiguration<'_>) -> Invitation;
}

#[async_trait]
pub trait HttpAgentExtended: Agent {
fn new(endpoint: &str) -> Self;
async fn check_endpoint(&self) -> Result<bool>;
}
127 changes: 127 additions & 0 deletions src/agent/http_agent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use crate::agent::agent::{Agent, HttpAgentExtended};
use crate::error;
use crate::typing;
use crate::utils::http;
use async_trait::async_trait;
use reqwest::Url;
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct HttpAgent {
url: String,
}

// All the available endpoints
struct Endpoint;

// Default value for every endpoint
// TODO: Not the most efficient mehtod (creates a new instance for every function call)
impl Endpoint {
fn connections(agent: &HttpAgent) -> Url {
reqwest::Url::parse(&agent.url)
.expect(&format!("Could not join on {}", agent.url).to_string())
.join("connections")
.expect(&format!("Could not join on connections").to_string())
}
fn get_connection_by_id(agent: &HttpAgent, id: String) -> Url {
reqwest::Url::parse(&agent.url)
.expect(&format!("Could not join on {}", agent.url).to_string())
.join("connections/")
.expect(&format!("Could not join on connections/").to_string())
.join(&id.to_string())
.expect(&format!("Could not join on {}", id).to_string())
}
fn create_invitation(agent: &HttpAgent) -> Url {
reqwest::Url::parse(&agent.url)
Copy link
Contributor

Choose a reason for hiding this comment

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

NOt sure as I'm a total noob here but

reqwest::Url::parse(&agent.url)
            .expect(&format!("Could not join on {}", agent.url).to_string())
            .join("connections/")
            .expect(&format!("Could not join on connections/").to_string())

seems to be the same base route 3 times? Maybe this can be refactored into a base connections route and used in all 3 methods just that get_connection_by_id and create_invitation append sth else as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah definitely agree! The whole endpoint generation needs a refactor as this is an extremely boated way to create urls :)

.expect(&format!("Could not join on {}", agent.url).to_string())
.join("connections/")
.expect(&format!("Could not join on connections/").to_string())
.join("create-invitation")
.expect(&format!("Could not join on create-invitation").to_string())
}
}

#[async_trait]
impl HttpAgentExtended for HttpAgent {
fn new(endpoint: &str) -> Self {
HttpAgent {
url: endpoint.to_owned(),
}
}

async fn check_endpoint(&self) -> typing::Result<bool> {
match reqwest::get(Endpoint::connections(&self)).await {
Ok(res) => {
if res.status().is_success() {
return Err(error::Error::InvalidUrl);
}
Ok(true)
}
Err(_) => Err(error::Error::InvalidUrl),
}
}
}

#[async_trait]
impl Agent for HttpAgent {
async fn get_connections(&self) -> typing::Connections {
match http::get(Endpoint::connections(&self), None).await {
Ok(res) => match res.json().await {
Ok(parsed) => parsed,
Err(_) => error::throw(error::Error::ServerResponseParseError),
},
Err(_) => error::throw(error::Error::ConnectionsUnretrieveable),
}
}

async fn get_connection_by_id(&self, id: String) -> typing::Connection {
match http::get(Endpoint::get_connection_by_id(&self, id), None).await {
Ok(res) => match res.json().await {
Ok(parsed) => parsed,
Err(_) => error::throw(error::Error::ServerResponseParseError),
},
Err(_) => error::throw(error::Error::ConnectionDoesNotExist),
}
}

async fn create_invitation(
&self,
config: &typing::InviteConfiguration<'_>,
) -> typing::Invitation {
let mut query: Vec<(&str, String)> = vec![];
let mut body = None;

if config.toolbox {
query.push(("multi_use", false.to_string()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure I udnerstand this 100%. does false.to_string() mean you're always setting this to false or default value?

Copy link
Member Author

Choose a reason for hiding this comment

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

When we want to create a toolbox invite we don't want multi use. This way we don't pollute the invitations.

false.to_string() just gives back "false". However this is less error-prone as typos cannot occur :)

Copy link
Contributor

Choose a reason for hiding this comment

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

ah ok get it - nice!

query.push(("auto_accept", true.to_string()));
query.push(("alias", String::from("toolbox")));

let mut a = HashMap::new();
let mut b = HashMap::new();

b.insert("group", "admin");
a.insert("metadata", b);

body = Some(a);
Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting! This is how you create

{"metadata": {"group": "admin"}}

?! Just wondering whether tehre is another way of doing this wo having to create two hast maps

Copy link
Contributor

Choose a reason for hiding this comment

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

Just been reading into json in Rust a little bit. and serde seems to be recommended by people to handle json like stuff - and it's in the dependencies. Maybe it makes sense to use that here? Not sure, again, just a noob atm...

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah Serde-json can be used. Serde is a lib that just does SERialization and DEserialization. serde-json is def the way to go. The reqwest json just expected this type so I am not sure wether it'll work.

Will try!

} else {
let multi_use = ("multi_use", config.multi_use.to_string());
let auto_accept = ("auto_accept", config.auto_accept.to_string());

query.push(multi_use);
query.push(auto_accept);

match config.alias {
Some(alias) => query.push(("alias", alias.to_string())),
_ => (),
};
}

match http::post(Endpoint::create_invitation(&self), query, body).await {
Ok(res) => match res.json().await {
Ok(parsed) => parsed,
Err(_) => error::throw(error::Error::ServerResponseParseError),
},
Err(_) => error::throw(error::Error::CannotCreateInvitation),
}
}
}
2 changes: 2 additions & 0 deletions src/agent/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod agent;
pub mod http_agent;
Loading