Skip to content
Snippets Groups Projects
Commit a404efad authored by Cédric Moreau's avatar Cédric Moreau
Browse files

feat: add `adhere` command

parent 1d38e8ae
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,11 @@ struct BmaCertification {
cert: String
}
#[derive(Serialize, Deserialize)]
struct BmaMembership {
membership: String
}
impl Display for BmaCertification {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.cert.as_str())
......@@ -24,6 +29,21 @@ pub fn certify(node: &BmaNode, idty: &String, sig: &String) -> Result<(), String
.send()
.expect("Error during POST /wot/certify");
if resp.status() != 200 {
return Err(format!("KO status : {}, message: {}", resp.status(), resp.text().unwrap()));
}
Ok(())
}
pub fn membership(node: &BmaNode, idty: &String, sig: &String) -> Result<(), String> {
let ms = BmaMembership { membership: format!("{}{}\n", idty, sig) };
let address = node.get_address();
let client = reqwest::blocking::Client::new();
let resp = client.post(format!("{}/blockchain/membership", address))
.json(&ms)
.send()
.expect("Error during POST /blockchain/membership");
if resp.status() != 200 {
return Err(format!("KO status : {}, message: {}", resp.status(), resp.text().unwrap()));
}
......
use crate::bma::BmaNode;
use crate::bma::lookup_identity::{LookupResult, lookup2identities, lookup_print};
use crate::crypto::duniter_key::scrypt_duniter_key::ScryptDuniterKey;
use crate::crypto::duniter_key::ToDuniterKey;
use crate::dubp::documents::membership::Membership;
use crate::dubp::signable::Signable;
pub fn adhere(node: &BmaNode) -> Result<(), String> {
println!("Deriving key for signature...");
let keyring = ScryptDuniterKey::new(String::from("fakesalt"), String::from("fakepasswd")).derive(); // TODO: get salt/passwd from file/cli
let uid_or_pub = keyring.get_public_base58();
let address = node.get_address();
println!("Fetching identity using \"{}\" pattern...", uid_or_pub);
let resp = reqwest::blocking::get(format!("{}/wot/lookup/{}", address, uid_or_pub)).expect("Could not fetch lookup data from distant node");
let res_json = &resp.json().expect("Could not get JSON result from distant node");
let res_json: LookupResult = LookupResult(res_json);
let results = lookup2identities(&res_json);
let idty = match results.len() {
0 => return Err(String::from("No matching identity found")),
1 => &results[0],
_ => {
lookup_print(&res_json);
return Err(format!("Too much identities found ({})", results.len()))
},
};
if idty.revoked {
return Err(format!("Identity {} {} is revoked and cannot be certified anymore.", idty.public, idty.uid))
}
println!("Get current block for blockstamp...");
let current = crate::bma::blockchain::current(&node);
let currency = &current.currency;
let issuer = keyring.get_public_base58();
let current_blockstamp = &current.blockstamp();
let membership = Membership {
version: 10,
currency: currency.clone(),
issuer,
idty_uid: (&idty).uid.clone(),
idty_blockstamp: (&idty).blockstamp.clone(),
adhere_blockstamp: current_blockstamp.clone(),
};
let signature = keyring.sign(&membership);
crate::bma::wot::membership(&node, &membership.to_signable(), &signature.to_string())
}
\ No newline at end of file
......@@ -8,10 +8,15 @@ use crate::crypto::duniter_key::ScryptDuniterKey;
use core::fmt;
pub mod certify;
pub mod adhere;
const DEFAULT_NODE: &str = "https://g1-test.duniter.org";
// TODO: constantize pub, sec, etc
const CMD_PUB: &str = "pub";
const CMD_SEC: &str = "sec";
const CMD_KEYRING: &str = "keyring";
const CMD_LOOKUP: &str = "lookup";
const CMD_CERTIFY: &str = "certify";
const CMD_ADHERE: &str = "adhere";
pub enum Command {
/// Compute the public key from salt/passwd and displays it
......@@ -24,6 +29,8 @@ pub enum Command {
LOOKUP(String, BmaNode, String),
/// Search an identity on a Duniter node (BMA API) and certify it
CERTIFY(String, BmaNode, String),
/// Search an identity matching local pubkey on a Duniter node (BMA API) and send a membership based on it
ADHERE(String, BmaNode),
/// Some unknown command
UNKNOWN(String),
}
......@@ -32,11 +39,12 @@ impl Command {
pub fn name(&self) -> String {
let str_name = match self {
PUB(_, _, _) => "pub",
SEC(_, _, _) => "sec",
KEYRING(_, _, _) => "keyring",
LOOKUP(_, _, _) => "lookup",
CERTIFY(_, _, _) => "certify",
PUB(..) => CMD_PUB,
SEC(..) => CMD_SEC,
KEYRING(..) => CMD_KEYRING,
LOOKUP(..) => CMD_LOOKUP,
CERTIFY(..) => CMD_CERTIFY,
ADHERE(..) => CMD_ADHERE,
UNKNOWN(name) => name.as_str(),
};
str_name.to_string()
......@@ -51,8 +59,8 @@ impl Command {
KEYRING(_, salt, passwd) => println!("{}", compute_key(ScryptDuniterKey::new(salt.to_string(), passwd.to_string()))),
LOOKUP(_, bma_node, uid_or_pub) => bma::lookup_identity::lookup(bma_node, uid_or_pub),
CERTIFY(_, bma_node, uid_or_pub) => cli::certify::certify(bma_node, uid_or_pub).unwrap_or_else(|e| eprintln!("{}", e)),
ADHERE(_, bma_node) => cli::adhere::adhere(bma_node).unwrap_or_else(|e| eprintln!("{}", e)),
UNKNOWN(cmd) => eprintln!("Unknown command {}", cmd),
_ => return Err("Not handled command yet".to_string())
}
Ok(())
}
......@@ -67,33 +75,38 @@ impl Command {
let command = command.as_str();
match command {
"pub" => {
CMD_PUB => {
let salt = args.next().expect("Salt must be provided");
let passwd = args.next().expect("Password must be provided");
Some(PUB(command.to_string(), salt, passwd))
},
"sec" => {
CMD_SEC => {
let salt = args.next().expect("Salt must be provided");
let passwd = args.next().expect("Password must be provided");
Some(SEC(command.to_string(), salt, passwd))
},
"keyring" => {
CMD_KEYRING => {
let salt = args.next().expect("Salt must be provided");
let passwd = args.next().expect("Password must be provided");
Some(KEYRING(command.to_string(), salt, passwd))
},
"lookup" => {
CMD_LOOKUP => {
let uid_or_pub = args.next().expect("UID or pubkey must be provided");
let default = String::from(DEFAULT_NODE);
let bma_node = BmaNode::new(env::var("DUNITER_NODE").unwrap_or(default).as_str());
Some(LOOKUP(command.to_string(), bma_node, uid_or_pub))
},
"cert" => {
CMD_CERTIFY => {
let uid_or_pub = args.next().expect("UID or pubkey must be provided");
let default = String::from(DEFAULT_NODE);
let bma_node = BmaNode::new(env::var("DUNITER_NODE").unwrap_or(default).as_str());
Some(CERTIFY(command.to_string(), bma_node, uid_or_pub))
},
CMD_ADHERE => {
let default = String::from(DEFAULT_NODE);
let bma_node = BmaNode::new(env::var("DUNITER_NODE").unwrap_or(default).as_str());
Some(ADHERE(command.to_string(), bma_node))
},
_ => Some(UNKNOWN(command.to_string())),
}
}
......
#[derive(Debug)]
pub struct Membership {
pub version: u32,
pub currency: String,
pub issuer: String,
pub idty_uid: String,
pub idty_blockstamp: String,
pub adhere_blockstamp: String,
}
impl crate::dubp::signable::Signable for Membership {
fn to_signable(self: &Self) -> String {
format!("Version: {}
Type: Membership
Currency: {}
Issuer: {}
Block: {}
Membership: IN
UserID: {}
CertTS: {}
", self.version, self.currency, self.issuer, self.adhere_blockstamp, self.idty_uid, self.idty_blockstamp)
}
}
\ No newline at end of file
pub mod certification;
\ No newline at end of file
pub mod certification;
pub mod membership;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment