Skip to content

Commit

Permalink
Merge pull request #37 from animo/feat/apikey_header
Browse files Browse the repository at this point in the history
feat: apikey from cli arg or config
  • Loading branch information
berendsliedrecht authored Jan 3, 2022
2 parents 7e51827 + ae5b376 commit 33067c8
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 60 deletions.
5 changes: 5 additions & 0 deletions cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ args:
short: e
long: endpoint
takes_value: true
- apikey:
help: The admin apikey
short: k
long: apikey
takes_value: true

# Subcommands
subcommands:
Expand Down
2 changes: 1 addition & 1 deletion src/agent/agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub trait Agent {
#[async_trait]
pub trait HttpAgentExtended {
/// New http agent instance
fn new(endpoint: String) -> Self;
fn new(endpoint: String, api_key: Option<String>) -> Self;

/// Check if the endpoint is valid
async fn check_endpoint(&self) -> ();
Expand Down
32 changes: 16 additions & 16 deletions src/agent/http_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use crate::typing::{
Connection, Connections, CredentialDefinition, CredentialDefinitionConfig, Features,
Invitation, InvitationConfig, IssueCredentialConfig, MessageConfig, Schema, SchemaConfig,
};
use crate::utils::http;
use crate::utils::logger::Log;
use crate::utils::http::HttpCalls;
use async_trait::async_trait;
use reqwest::Url;
use serde_json::{json, Value};
Expand All @@ -13,7 +12,10 @@ use serde_json::{json, Value};
#[derive(Debug, Clone)]
pub struct HttpAgent {
/// base url of the cloudagent
url: String,
pub url: String,

/// admin Api key for the cloudagent
pub api_key: Option<String>,
}

/// All the available endpoints
Expand Down Expand Up @@ -91,13 +93,13 @@ impl Endpoint {

#[async_trait]
impl HttpAgentExtended for HttpAgent {
fn new(endpoint: String) -> Self {
HttpAgent { url: endpoint }
fn new(endpoint: String, api_key: Option<String>) -> Self {
HttpAgent { url: endpoint, api_key }
}

/// Check if the endpoint is valid
async fn check_endpoint(&self) -> () {
http::get::<Connections>(Endpoint::connections(&self.url), None).await;
self.get::<Connections>(Endpoint::connections(&self.url), None).await;
}
}

Expand All @@ -111,12 +113,12 @@ impl Agent for HttpAgent {
query.push(("alias", alias));
}

http::get::<Connections>(Endpoint::connections(&self.url), Some(query)).await
self.get::<Connections>(Endpoint::connections(&self.url), Some(query)).await
}

/// Get a connection by id
async fn get_connection_by_id(&self, id: String) -> Connection {
http::get::<Connection>(Endpoint::get_connection_by_id(&self.url, &id), None).await
self.get::<Connection>(Endpoint::get_connection_by_id(&self.url, &id), None).await
}

/// Prints an invitation, as url or qr, in stdout
Expand Down Expand Up @@ -146,12 +148,12 @@ impl Agent for HttpAgent {
}
}

http::post(Endpoint::create_invitation(&self.url), Some(query), body).await
self.post(Endpoint::create_invitation(&self.url), Some(query), body).await
}

/// Requests all the features from the cloudagent
async fn discover_features(&self) -> Features {
http::get::<Features>(Endpoint::discover_features(&self.url), None).await
self.get::<Features>(Endpoint::discover_features(&self.url), None).await
}

/// Send a basic message to another agent
Expand All @@ -160,7 +162,7 @@ impl Agent for HttpAgent {
"content": config.message,
});

http::post::<serde_json::Value>(
self.post::<serde_json::Value>(
Endpoint::basic_message(&self.url, &config.connection_id),
None,
Some(body),
Expand All @@ -178,9 +180,7 @@ impl Agent for HttpAgent {
}
});

Log::log_pretty(config);

http::post::<Value>(Endpoint::credential_offer(&self.url), None, Some(body)).await;
self.post::<Value>(Endpoint::credential_offer(&self.url), None, Some(body)).await;
}

async fn schema(&self, config: &SchemaConfig) -> Schema {
Expand All @@ -190,7 +190,7 @@ impl Agent for HttpAgent {
"schema_version": config.version
});

http::post::<Schema>(Endpoint::schema(&self.url), None, Some(body)).await
self.post::<Schema>(Endpoint::schema(&self.url), None, Some(body)).await
}

async fn credential_definition(
Expand All @@ -203,7 +203,7 @@ impl Agent for HttpAgent {
"tag": config.tag
});

http::post::<CredentialDefinition>(
self.post::<CredentialDefinition>(
Endpoint::credential_definition(&self.url),
None,
Some(body),
Expand Down
28 changes: 20 additions & 8 deletions src/cli/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,30 @@ pub async fn register_cli() {
// Takes a path, but prepends the home directory... kinda sketchy
let endpoint_from_config = config::get_value("/.config/accf/ex.ini", "Default", "endpoint");

// create an httpAgent when you supply an endpoint
let agent = match matches.value_of("endpoint") {
Some(endpoint) => HttpAgent::new(endpoint.to_string()),
// Takes a path, but prepends the home directory... kinda sketchy
let api_key_from_config = config::get_value("/.config/accf/ex.ini", "Default", "api_key");

// Get the endpoint when you supply an endpoint
let endpoint = match matches.value_of("endpoint") {
Some(endpoint) => endpoint.to_string(),
None => match endpoint_from_config {
Some(e) => HttpAgent::new(e),
None => match endpoint_from_config {
Some(e) => HttpAgent::new(e),
None => throw(Error::NoSuppliedEndpoint),
},
Some(e) => e,
None => throw(Error::NoSuppliedEndpoint),
},
};

// TODO: Check if this can be refactored
// Get the endpoint when you supply an endpoint
let api_key = match matches.value_of("apikey") {
Some(api_key) => Some(api_key.to_string()),
None => api_key_from_config
};

let agent = HttpAgent {
url: endpoint,
api_key
};

agent.check_endpoint().await;

// Registering the subcommands and their modules
Expand Down
92 changes: 57 additions & 35 deletions src/utils/http.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,71 @@
use reqwest::{Client, RequestBuilder, Url};
use serde::de::DeserializeOwned;
use serde_json::Value;

use async_trait::async_trait;
use crate::agent::http_agent::HttpAgent;
use crate::error::{throw, Error};

/// Builds a get request and calls the sender
pub async fn get<T: DeserializeOwned>(url: Url, query: Option<Vec<(&str, String)>>) -> T {
let client = match query {
Some(q) => Client::new().get(url).query(&q),
None => Client::new().get(url),
};

send::<T>(client).await
/// Interface providing HTTP call methods
#[async_trait]
pub trait HttpCalls {
/// GET method
async fn get<T: DeserializeOwned>(&self, url: Url, query: Option<Vec<(&str, String)>>) -> T;
/// POST method
async fn post<T: DeserializeOwned>(&self, url: Url, query: Option<Vec<(&str, String)>>, body: Option<Value>) -> T;
/// SEND - general method for GET and POST
async fn send<T: DeserializeOwned>(&self, client: RequestBuilder) -> T;
}

/// Builds a post request and calls the sender
pub async fn post<T: DeserializeOwned>(
url: Url,
query: Option<Vec<(&str, String)>>,
body: Option<Value>,
) -> T {
let client = Client::new().post(url).query(&query);
/// Call logic for http calls
#[async_trait]
impl HttpCalls for HttpAgent {
/// Builds a get request and calls the sender
async fn get<T: DeserializeOwned>(&self, url: Url, query: Option<Vec<(&str, String)>>) -> T {
let client = match query {
Some(q) => Client::new().get(url).query(&q),
None => Client::new().get(url),
};

self.send::<T>(client).await
}

let client = match body {
Some(b) => client.json(&b),
None => client,
};
/// Builds a post request and calls the sender
async fn post<T: DeserializeOwned>(
&self,
url: Url,
query: Option<Vec<(&str, String)>>,
body: Option<Value>,
) -> T {
let client = Client::new().post(url).query(&query);

send::<T>(client).await
}
let client = match body {
Some(b) => client.json(&b),
None => client,
};

self.send::<T>(client).await
}

/// Sends any request
async fn send<T: DeserializeOwned>(&self, client: RequestBuilder) -> T {
let client = match &self.api_key {
Some(a) => client.header("X-API-KEY", a),
None => client,
};

let response = client.send().await;

/// Sends any request
async fn send<T: DeserializeOwned>(client: RequestBuilder) -> T {
let response = client.send().await;

match response {
Ok(res) => {
if res.status().is_success() {
return match res.json().await {
Ok(parsed) => parsed,
Err(_) => throw(Error::ServerResponseParseError),
};
match response {
Ok(res) => {
if res.status().is_success() {
return match res.json().await {
Ok(parsed) => parsed,
Err(_) => throw(Error::ServerResponseParseError),
};
}
throw(Error::InternalServerError)
}
throw(Error::InternalServerError)
Err(_) => throw(Error::InternalServerError),
}
Err(_) => throw(Error::InternalServerError),
}
}

0 comments on commit 33067c8

Please sign in to comment.