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 messages/agency_comm module, delete legacy proof #149

Merged
merged 7 commits into from
Nov 4, 2020
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
153 changes: 153 additions & 0 deletions libvcx/src/agency_comm/agency_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
use std::borrow::Borrow;
use std::collections::HashMap;
use std::sync::RwLock;

use serde_json::Value;
use url::Url;

use error::{VcxError, VcxErrorKind, VcxResult};
use utils::{error, validation};

pub static CONFIG_AGENCY_ENDPOINT: &str = "agency_endpoint";
pub static CONFIG_AGENCY_DID: &str = "agency_did";
pub static CONFIG_AGENCY_VERKEY: &str = "agency_verkey";
pub static CONFIG_REMOTE_TO_SDK_DID: &str = "remote_to_sdk_did";
pub static CONFIG_REMOTE_TO_SDK_VERKEY: &str = "remote_to_sdk_verkey";
pub static CONFIG_SDK_TO_REMOTE_DID: &str = "sdk_to_remote_did";
pub static CONFIG_SDK_TO_REMOTE_VERKEY: &str = "sdk_to_remote_verkey";
static CONFIG_ENABLE_TEST_MODE: &str = "enable_test_mode";

pub static VALID_AGENCY_CONFIG_KEYS: &[&str] = &[
CONFIG_AGENCY_ENDPOINT,
CONFIG_AGENCY_DID,
CONFIG_AGENCY_VERKEY,
CONFIG_REMOTE_TO_SDK_DID,
CONFIG_REMOTE_TO_SDK_VERKEY,
CONFIG_SDK_TO_REMOTE_DID,
CONFIG_SDK_TO_REMOTE_VERKEY,
CONFIG_ENABLE_TEST_MODE
];

lazy_static! {
static ref AGENCY_SETTINGS: RwLock<HashMap<String, String>> = RwLock::new(HashMap::new());
}


fn validate_mandatory_config_val<F, S, E>(val: Option<&String>, err: VcxErrorKind, closure: F) -> VcxResult<u32>
where F: Fn(&str) -> Result<S, E> {
closure(val.as_ref().ok_or(VcxError::from(err))?)
.or(Err(VcxError::from(err)))?;

Ok(error::SUCCESS.code_num)
}

fn validate_optional_config_val<F, S, E>(val: Option<&String>, err: VcxErrorKind, closure: F) -> VcxResult<u32>
where F: Fn(&str) -> Result<S, E> {
if val.is_none() { return Ok(error::SUCCESS.code_num); }

closure(val.as_ref().ok_or(VcxError::from(VcxErrorKind::InvalidConfiguration))?)
.or(Err(VcxError::from(err)))?;

Ok(error::SUCCESS.code_num)
}

pub fn set_testing_defaults_agency() -> u32 {
trace!("set_testing_defaults_agency >>>");

let DEFAULT_DID= "2hoqvcwupRTUNkXn6ArYzs";
let DEFAULT_VERKEY= "FuN98eH2eZybECWkofW6A9BKJxxnTatBCopfUiNxo6ZB";
let DEFAULT_URL= "http://127.0.0.1:8080";

// if this fails the test should exit
let mut agency_settings = AGENCY_SETTINGS.write().unwrap();

agency_settings.insert(CONFIG_AGENCY_ENDPOINT.to_string(), DEFAULT_URL.to_string());
agency_settings.insert(CONFIG_AGENCY_DID.to_string(), DEFAULT_DID.to_string());
agency_settings.insert(CONFIG_AGENCY_VERKEY.to_string(), DEFAULT_VERKEY.to_string());
agency_settings.insert(CONFIG_REMOTE_TO_SDK_DID.to_string(), DEFAULT_DID.to_string());
agency_settings.insert(CONFIG_REMOTE_TO_SDK_VERKEY.to_string(), DEFAULT_VERKEY.to_string());
agency_settings.insert(CONFIG_SDK_TO_REMOTE_DID.to_string(), DEFAULT_DID.to_string());
agency_settings.insert(CONFIG_SDK_TO_REMOTE_VERKEY.to_string(), DEFAULT_VERKEY.to_string());

error::SUCCESS.code_num
}

pub fn clear_config_agency() {
trace!("clear_config_agency >>>");
let mut config = AGENCY_SETTINGS.write().unwrap();
config.clear();
}

pub fn validate_agency_config(config: &HashMap<String, String>) -> VcxResult<u32> {
trace!("validate_agency_config >>> config: {:?}", config);

// todo: Since we scope these setting to agency module, these are not really optional anymore!
Patrik-Stas marked this conversation as resolved.
Show resolved Hide resolved
validate_optional_config_val(config.get(CONFIG_AGENCY_DID), VcxErrorKind::InvalidDid, validation::validate_did)?;
validate_optional_config_val(config.get(CONFIG_AGENCY_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?;

validate_optional_config_val(config.get(CONFIG_SDK_TO_REMOTE_DID), VcxErrorKind::InvalidDid, validation::validate_did)?;
validate_optional_config_val(config.get(CONFIG_SDK_TO_REMOTE_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?;

validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_DID), VcxErrorKind::InvalidDid, validation::validate_did)?;
validate_optional_config_val(config.get(CONFIG_REMOTE_TO_SDK_VERKEY), VcxErrorKind::InvalidVerkey, validation::validate_verkey)?;

validate_optional_config_val(config.get(CONFIG_AGENCY_ENDPOINT), VcxErrorKind::InvalidUrl, Url::parse)?;

Ok(error::SUCCESS.code_num)
}


pub fn process_agency_config_string(config: &str, do_validation: bool) -> VcxResult<u32> {
trace!("process_config_string >>> config {}", config);

let configuration: Value = serde_json::from_str(config)
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot parse config: {}", err)))?;

if let Value::Object(ref map) = configuration {
for (key, value) in map {
if !VALID_AGENCY_CONFIG_KEYS.contains(&key.as_ref()) {
warn!("Agency settings do not recognize setting key {}. Will be ignored.", key);
} else {
match value {
Value::String(value_) => set_config_value(key, &value_),
Value::Bool(value_) => set_config_value(key, &json!(value_).to_string()),
_ => return Err(VcxError::from_msg(VcxErrorKind::InvalidJson,
format!("Invalid agency config value for key {}", key))),
}
}
}
}

if do_validation {
let setting = AGENCY_SETTINGS.read()
.or(Err(VcxError::from(VcxErrorKind::InvalidConfiguration)))?;
validate_agency_config(&setting.borrow())
} else {
Ok(error::SUCCESS.code_num)
}
}


pub fn get_config_value(key: &str) -> VcxResult<String> {
trace!("get_config_value >>> key: {}", key);

AGENCY_SETTINGS
.read()
.or(Err(VcxError::from_msg(VcxErrorKind::InvalidConfiguration, "Cannot read AGENCY_SETTINGS")))?
.get(key)
.map(|v| v.to_string())
.ok_or(VcxError::from_msg(VcxErrorKind::InvalidConfiguration, format!("Cannot read \"{}\" from AGENCY_SETTINGS", key)))
}

pub fn set_config_value(key: &str, value: &str) {
trace!("set_config_value >>> key: {}, value: {}", key, value);
if !VALID_AGENCY_CONFIG_KEYS.contains(&key) {
warn!("Agency settings do not recognize setting key {}. Will be ignored.", key);
} else {
AGENCY_SETTINGS
.write().unwrap()
.insert(key.to_string(), value.to_string());
}
}


Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use agency_comm::{A2AMessage, A2AMessageKinds, A2AMessageV2, agency_settings, parse_response_from_agency, prepare_message_for_agency};
use agency_comm::message_type::MessageTypes;
use agency_comm::mocking::AgencyMock;
use agency_comm::utils::comm::post_to_agency;
use error::prelude::*;
use messages::{A2AMessage, A2AMessageKinds, A2AMessageV2, parse_response_from_agency, prepare_message_for_agency, validation};
use messages::message_type::MessageTypes;
use settings;
use settings::ProtocolTypes;
use utils::{constants, httpclient};
use utils::httpclient::AgencyMock;
use utils::{constants, httpclient, validation};
use crate::agency_comm::mocking;

#[derive(Deserialize, Serialize, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
Expand All @@ -31,7 +31,6 @@ pub struct CreateKeyResponse {
pub struct CreateKeyBuilder {
for_did: String,
for_verkey: String,
version: ProtocolTypes,
}

impl CreateKeyBuilder {
Expand All @@ -41,7 +40,6 @@ impl CreateKeyBuilder {
CreateKeyBuilder {
for_did: String::new(),
for_verkey: String::new(),
version: settings::get_protocol_type(),
}
}

Expand All @@ -57,55 +55,36 @@ impl CreateKeyBuilder {
Ok(self)
}

pub fn version(&mut self, version: &Option<ProtocolTypes>) -> VcxResult<&mut Self> {
self.version = match version {
Some(version) => version.clone(),
None => settings::get_protocol_type()
};
Ok(self)
}

pub fn send_secure(&self) -> VcxResult<(String, String)> {
trace!("CreateKeyMsg::send >>>");

if settings::agency_mocks_enabled() {
match self.version {
settings::ProtocolTypes::V1 |
settings::ProtocolTypes::V2 |
settings::ProtocolTypes::V3 |
settings::ProtocolTypes::V4 => AgencyMock::set_next_response(constants::CREATE_KEYS_V2_RESPONSE.to_vec()),
}
trace!("CreateKeyBuilder::send_secure >>>");

if mocking::agency_mocks_enabled() {
AgencyMock::set_next_response(constants::CREATE_KEYS_V2_RESPONSE.to_vec());
}

let data = self.prepare_request()?;

let response = httpclient::post_u8(&data)?;
let response = post_to_agency(&data)?;

self.parse_response(&response)
}

fn prepare_request(&self) -> VcxResult<Vec<u8>> {
let message = match self.version {
settings::ProtocolTypes::V1 |
settings::ProtocolTypes::V2 |
settings::ProtocolTypes::V3 |
settings::ProtocolTypes::V4 =>
A2AMessage::Version2(
A2AMessageV2::CreateKey(CreateKey {
msg_type: MessageTypes::MessageTypeV2(MessageTypes::build_v2(A2AMessageKinds::CreateKey)),
for_did: self.for_did.to_string(),
for_verkey: self.for_verkey.to_string(),
})
),
};

let agency_did = settings::get_config_value(settings::CONFIG_REMOTE_TO_SDK_DID)?;

prepare_message_for_agency(&message, &agency_did, &self.version)
let message = A2AMessage::Version2(
A2AMessageV2::CreateKey(CreateKey {
msg_type: MessageTypes::MessageTypeV2(MessageTypes::build_v2(A2AMessageKinds::CreateKey)),
for_did: self.for_did.to_string(),
for_verkey: self.for_verkey.to_string(),
})
);

let agency_did = agency_settings::get_config_value(agency_settings::CONFIG_REMOTE_TO_SDK_DID)?;

prepare_message_for_agency(&message, &agency_did)
}

fn parse_response(&self, response: &Vec<u8>) -> VcxResult<(String, String)> {
let mut response = parse_response_from_agency(response, &self.version)?;
let mut response = parse_response_from_agency(response)?;
match response.remove(0) {
A2AMessage::Version2(A2AMessageV2::CreateKeyResponse(res)) => Ok((res.for_did, res.for_verkey)),
_ => Err(VcxError::from(VcxErrorKind::InvalidHttpResponse))
Expand All @@ -115,10 +94,10 @@ impl CreateKeyBuilder {

#[cfg(test)]
mod tests {
use messages::create_keys;
use agency_comm::create_keys;
use libindy::utils::signus::create_and_store_my_did;
use utils::constants::{CREATE_KEYS_V2_RESPONSE, MY1_SEED, MY2_SEED, MY3_SEED};
use utils::devsetup::*;
use utils::libindy::signus::create_and_store_my_did;

use super::*;

Expand All @@ -144,9 +123,9 @@ mod tests {
let (my_did, my_vk) = create_and_store_my_did(Some(MY1_SEED), None).unwrap();
let (_agency_did, agency_vk) = create_and_store_my_did(Some(MY3_SEED), None).unwrap();

settings::set_config_value(settings::CONFIG_AGENCY_VERKEY, &agency_vk);
settings::set_config_value(settings::CONFIG_REMOTE_TO_SDK_VERKEY, &agent_vk);
settings::set_config_value(settings::CONFIG_SDK_TO_REMOTE_VERKEY, &my_vk);
agency_settings::set_config_value(agency_settings::CONFIG_AGENCY_VERKEY, &agency_vk);
agency_settings::set_config_value(agency_settings::CONFIG_REMOTE_TO_SDK_VERKEY, &agent_vk);
agency_settings::set_config_value(agency_settings::CONFIG_SDK_TO_REMOTE_VERKEY, &my_vk);

let bytes = create_keys()
.for_did(&my_did).unwrap()
Expand All @@ -162,7 +141,7 @@ mod tests {

let mut builder = create_keys();

let (for_did, for_verkey) = builder.version(&Some(ProtocolTypes::V2)).unwrap().parse_response(&CREATE_KEYS_V2_RESPONSE.to_vec()).unwrap();
let (for_did, for_verkey) = builder.parse_response(&CREATE_KEYS_V2_RESPONSE.to_vec()).unwrap();

assert_eq!(for_did, "MNepeSWtGfhnv8jLB1sFZC");
assert_eq!(for_verkey, "C73MRnns4qUjR5N4LRwTyiXVPKPrA5q4LCT8PZzxVdt9");
Expand Down
Loading