Skip to content

Commit

Permalink
Refactor messages/agency_comm module, delete legacy proof (#149)
Browse files Browse the repository at this point in the history
* Various messages:: cleanups

- Move messages::proofs to indyvc::proofs, delete legacy code
- Rename module messages to agency_vcx
- Start removing depending on ::settings from ::agency_vcx
- Remove concept of protocol_type from ::agency_vcx
- Ignore legacy tests, fix compile errors

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>

* Use module name 'agency_comm' instead of 'agency_vcx'

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>

* Restructure code related to libindy proofs

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>

* Move module 'utils::indy' to 'indy::utils'

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>

* Scope agency global settings within agency_comm module

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>

* Migrate legacy proof request tests

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>

* Address PR review comments

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>
  • Loading branch information
Patrik-Stas authored Nov 4, 2020
1 parent 639b6d8 commit e0c4d93
Show file tree
Hide file tree
Showing 95 changed files with 1,650 additions and 1,994 deletions.
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!
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

0 comments on commit e0c4d93

Please sign in to comment.